mem.isa revision 2649
1// -*- mode:c++ -*- 2 3// Copyright (c) 2003-2005 The Regents of The University of Michigan 4// All rights reserved. 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer; 10// redistributions in binary form must reproduce the above copyright 11// notice, this list of conditions and the following disclaimer in the 12// documentation and/or other materials provided with the distribution; 13// neither the name of the copyright holders nor the names of its 14// contributors may be used to endorse or promote products derived from 15// this software without specific prior written permission. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29//////////////////////////////////////////////////////////////////// 30// 31// Memory-format instructions: LoadAddress, Load, Store 32// 33 34output header {{ 35 /** 36 * Base class for general Mips memory-format instructions. 37 */ 38 class Memory : public MipsStaticInst 39 { 40 protected: 41 42 /// Memory request flags. See mem_req_base.hh. 43 unsigned memAccessFlags; 44 /// Pointer to EAComp object. 45 const StaticInstPtr eaCompPtr; 46 /// Pointer to MemAcc object. 47 const StaticInstPtr memAccPtr; 48 49 /// Displacement for EA calculation (signed). 50 int32_t disp; 51 52 /// Constructor 53 Memory(const char *mnem, MachInst _machInst, OpClass __opClass, 54 StaticInstPtr _eaCompPtr = nullStaticInstPtr, 55 StaticInstPtr _memAccPtr = nullStaticInstPtr) 56 : MipsStaticInst(mnem, _machInst, __opClass), 57 memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), 58 disp(OFFSET) 59 { 60 //If Bit 15 is 1 then Sign Extend 61 int32_t temp = disp & 0x00008000; 62 63 if (temp > 0) { 64 disp |= 0xFFFF0000; 65 } 66 } 67 68 std::string 69 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 70 71 public: 72 73 const StaticInstPtr &eaCompInst() const { return eaCompPtr; } 74 const StaticInstPtr &memAccInst() const { return memAccPtr; } 75 }; 76 77}}; 78 79 80output decoder {{ 81 std::string 82 Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const 83 { 84 return csprintf("%-10s %c%d,%d(r%d)", mnemonic, 85 flags[IsFloating] ? 'f' : 'r', RT, disp, RS); 86 } 87 88}}; 89 90def format LoadAddress(code) {{ 91 iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code)) 92 header_output = BasicDeclare.subst(iop) 93 decoder_output = BasicConstructor.subst(iop) 94 decode_block = BasicDecode.subst(iop) 95 exec_output = BasicExecute.subst(iop) 96}}; 97 98 99def template LoadStoreDeclare {{ 100 /** 101 * Static instruction class for "%(mnemonic)s". 102 */ 103 class %(class_name)s : public %(base_class)s 104 { 105 protected: 106 107 /** 108 * "Fake" effective address computation class for "%(mnemonic)s". 109 */ 110 class EAComp : public %(base_class)s 111 { 112 public: 113 /// Constructor 114 EAComp(MachInst machInst); 115 116 %(BasicExecDeclare)s 117 }; 118 119 /** 120 * "Fake" memory access instruction class for "%(mnemonic)s". 121 */ 122 class MemAcc : public %(base_class)s 123 { 124 public: 125 /// Constructor 126 MemAcc(MachInst machInst); 127 128 %(BasicExecDeclare)s 129 }; 130 131 public: 132 133 /// Constructor. 134 %(class_name)s(MachInst machInst); 135 136 %(BasicExecDeclare)s 137 138 %(InitiateAccDeclare)s 139 140 %(CompleteAccDeclare)s 141 }; 142}}; 143 144 145def template InitiateAccDeclare {{ 146 Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; 147}}; 148 149 150def template CompleteAccDeclare {{ 151 Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const; 152}}; 153 154 155def template LoadStoreConstructor {{ 156 /** TODO: change op_class to AddrGenOp or something (requires 157 * creating new member of OpClass enum in op_class.hh, updating 158 * config files, etc.). */ 159 inline %(class_name)s::EAComp::EAComp(MachInst machInst) 160 : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) 161 { 162 %(ea_constructor)s; 163 } 164 165 inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) 166 : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) 167 { 168 %(memacc_constructor)s; 169 } 170 171 inline %(class_name)s::%(class_name)s(MachInst machInst) 172 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 173 new EAComp(machInst), new MemAcc(machInst)) 174 { 175 %(constructor)s; 176 } 177}}; 178 179 180def template EACompExecute {{ 181 Fault 182 %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, 183 Trace::InstRecord *traceData) const 184 { 185 Addr EA; 186 Fault fault = NoFault; 187 188 %(fp_enable_check)s; 189 %(op_decl)s; 190 %(op_rd)s; 191 %(code)s; 192 193 if (fault == NoFault) { 194 %(op_wb)s; 195 xc->setEA(EA); 196 } 197 198 return fault; 199 } 200}}; 201 202def template LoadMemAccExecute {{ 203 Fault 204 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 205 Trace::InstRecord *traceData) const 206 { 207 Addr EA; 208 Fault fault = NoFault; 209 210 %(fp_enable_check)s; 211 %(op_decl)s; 212 %(op_rd)s; 213 EA = xc->getEA(); 214 215 if (fault == NoFault) { 216 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 217 %(code)s; 218 } 219 220 if (fault == NoFault) { 221 %(op_wb)s; 222 } 223 224 return fault; 225 } 226}}; 227 228 229def template LoadExecute {{ 230 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 231 Trace::InstRecord *traceData) const 232 { 233 Addr EA; 234 Fault fault = NoFault; 235 236 %(fp_enable_check)s; 237 %(op_decl)s; 238 %(op_rd)s; 239 %(ea_code)s; 240 241 if (fault == NoFault) { 242 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 243 %(memacc_code)s; 244 } 245 246 if (fault == NoFault) { 247 %(op_wb)s; 248 } 249 250 return fault; 251 } 252}}; 253 254 255def template LoadInitiateAcc {{ 256 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 257 Trace::InstRecord *traceData) const 258 { 259 Addr EA; 260 Fault fault = NoFault; 261 262 %(fp_enable_check)s; 263 %(op_src_decl)s; 264 %(op_rd)s; 265 %(ea_code)s; 266 267 if (fault == NoFault) { 268 fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); 269 } 270 271 return fault; 272 } 273}}; 274 275 276def template LoadCompleteAcc {{ 277 Fault %(class_name)s::completeAcc(uint8_t *data, 278 %(CPU_exec_context)s *xc, 279 Trace::InstRecord *traceData) const 280 { 281 Fault fault = NoFault; 282 283 %(fp_enable_check)s; 284 %(op_decl)s; 285 286 memcpy(&Mem, data, sizeof(Mem)); 287 288 if (fault == NoFault) { 289 %(memacc_code)s; 290 } 291 292 if (fault == NoFault) { 293 %(op_wb)s; 294 } 295 296 return fault; 297 } 298}}; 299 300 301def template StoreMemAccExecute {{ 302 Fault 303 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 304 Trace::InstRecord *traceData) const 305 { 306 Addr EA; 307 Fault fault = NoFault; 308 uint64_t write_result = 0; 309 310 %(fp_enable_check)s; 311 %(op_decl)s; 312 %(op_rd)s; 313 EA = xc->getEA(); 314 315 if (fault == NoFault) { 316 %(code)s; 317 } 318 319 if (fault == NoFault) { 320 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 321 memAccessFlags, &write_result); 322 if (traceData) { traceData->setData(Mem); } 323 } 324 325 if (fault == NoFault) { 326 %(postacc_code)s; 327 } 328 329 if (fault == NoFault) { 330 %(op_wb)s; 331 } 332 333 return fault; 334 } 335}}; 336 337 338def template StoreExecute {{ 339 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 340 Trace::InstRecord *traceData) const 341 { 342 Addr EA; 343 Fault fault = NoFault; 344 uint64_t write_result = 0; 345 346 %(fp_enable_check)s; 347 %(op_decl)s; 348 %(op_rd)s; 349 %(ea_code)s; 350 351 if (fault == NoFault) { 352 %(memacc_code)s; 353 } 354 355 if (fault == NoFault) { 356 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 357 memAccessFlags, &write_result); 358 if (traceData) { traceData->setData(Mem); } 359 } 360 361 if (fault == NoFault) { 362 %(postacc_code)s; 363 } 364 365 if (fault == NoFault) { 366 %(op_wb)s; 367 } 368 369 return fault; 370 } 371}}; 372 373def template StoreInitiateAcc {{ 374 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 375 Trace::InstRecord *traceData) const 376 { 377 Addr EA; 378 Fault fault = NoFault; 379 uint64_t write_result = 0; 380 381 %(fp_enable_check)s; 382 %(op_decl)s; 383 %(op_rd)s; 384 %(ea_code)s; 385 386 if (fault == NoFault) { 387 %(memacc_code)s; 388 } 389 390 if (fault == NoFault) { 391 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 392 memAccessFlags, &write_result); 393 if (traceData) { traceData->setData(Mem); } 394 } 395 396 return fault; 397 } 398}}; 399 400 401def template StoreCompleteAcc {{ 402 Fault %(class_name)s::completeAcc(uint8_t *data, 403 %(CPU_exec_context)s *xc, 404 Trace::InstRecord *traceData) const 405 { 406 Fault fault = NoFault; 407 uint64_t write_result = 0; 408 409 %(fp_enable_check)s; 410 %(op_dest_decl)s; 411 412 memcpy(&write_result, data, sizeof(write_result)); 413 414 if (fault == NoFault) { 415 %(postacc_code)s; 416 } 417 418 if (fault == NoFault) { 419 %(op_wb)s; 420 } 421 422 return fault; 423 } 424}}; 425 426// load instructions use Rt as dest, so check for 427// Rt == 31 to detect nops 428def template LoadNopCheckDecode {{ 429 { 430 MipsStaticInst *i = new %(class_name)s(machInst); 431 if (RT == 0) { 432 i = makeNop(i); 433 } 434 return i; 435 } 436}}; 437 438def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, 439 mem_flags = [], inst_flags = []) {{ 440 (header_output, decoder_output, decode_block, exec_output) = \ 441 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 442 decode_template = LoadNopCheckDecode, 443 exec_template_base = 'Load') 444}}; 445 446 447def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, 448 mem_flags = [], inst_flags = []) {{ 449 (header_output, decoder_output, decode_block, exec_output) = \ 450 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 451 exec_template_base = 'Store') 452}}; 453 454//FP loads are offloaded to these formats for now ... 455def format LoadFloatMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, 456 mem_flags = [], inst_flags = []) {{ 457 (header_output, decoder_output, decode_block, exec_output) = \ 458 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 459 decode_template = BasicDecode, 460 exec_template_base = 'Load') 461}}; 462 463 464def format StoreFloatMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, 465 mem_flags = [], inst_flags = []) {{ 466 (header_output, decoder_output, decode_block, exec_output) = \ 467 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 468 exec_template_base = 'Store') 469}}; 470 471 472def format UnalignedStore(memacc_code, postacc_code, 473 ea_code = {{ EA = Rb + disp; }}, 474 mem_flags = [], inst_flags = []) {{ 475 (header_output, decoder_output, decode_block, exec_output) = \ 476 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 477 postacc_code, exec_template_base = 'Store') 478}}; 479