mem.isa revision 2742
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// Authors: Gabe Black 30// Korey Sewell 31 32//////////////////////////////////////////////////////////////////// 33// 34// Memory-format instructions 35// 36 37output header {{ 38 /** 39 * Base class for general Mips memory-format instructions. 40 */ 41 class Memory : public MipsStaticInst 42 { 43 protected: 44 45 /// Memory request flags. See mem_req_base.hh. 46 unsigned memAccessFlags; 47 /// Pointer to EAComp object. 48 const StaticInstPtr eaCompPtr; 49 /// Pointer to MemAcc object. 50 const StaticInstPtr memAccPtr; 51 52 /// Displacement for EA calculation (signed). 53 int32_t disp; 54 55 /// Constructor 56 Memory(const char *mnem, MachInst _machInst, OpClass __opClass, 57 StaticInstPtr _eaCompPtr = nullStaticInstPtr, 58 StaticInstPtr _memAccPtr = nullStaticInstPtr) 59 : MipsStaticInst(mnem, _machInst, __opClass), 60 memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), 61 disp(sext<16>(OFFSET)) 62 { 63 } 64 65 std::string 66 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 67 68 public: 69 70 const StaticInstPtr &eaCompInst() const { return eaCompPtr; } 71 const StaticInstPtr &memAccInst() const { return memAccPtr; } 72 }; 73 74 /** 75 * Base class for a few miscellaneous memory-format insts 76 * that don't interpret the disp field 77 */ 78 class MemoryNoDisp : public Memory 79 { 80 protected: 81 /// Constructor 82 MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 83 StaticInstPtr _eaCompPtr = nullStaticInstPtr, 84 StaticInstPtr _memAccPtr = nullStaticInstPtr) 85 : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr) 86 { 87 } 88 89 std::string 90 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 91 }; 92}}; 93 94 95output decoder {{ 96 std::string 97 Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const 98 { 99 return csprintf("%-10s %c%d, %d(r%d)", mnemonic, 100 flags[IsFloating] ? 'f' : 'r', RT, disp, RS); 101 } 102 103 std::string 104 MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 105 { 106 return csprintf("%-10s %c%d, r%d(r%d)", mnemonic, 107 flags[IsFloating] ? 'f' : 'r', 108 flags[IsFloating] ? FD : RD, 109 RS, RT); 110 } 111}}; 112 113def template LoadStoreDeclare {{ 114 /** 115 * Static instruction class for "%(mnemonic)s". 116 */ 117 class %(class_name)s : public %(base_class)s 118 { 119 protected: 120 121 /** 122 * "Fake" effective address computation class for "%(mnemonic)s". 123 */ 124 class EAComp : public %(base_class)s 125 { 126 public: 127 /// Constructor 128 EAComp(MachInst machInst); 129 130 %(BasicExecDeclare)s 131 }; 132 133 /** 134 * "Fake" memory access instruction class for "%(mnemonic)s". 135 */ 136 class MemAcc : public %(base_class)s 137 { 138 public: 139 /// Constructor 140 MemAcc(MachInst machInst); 141 142 %(BasicExecDeclare)s 143 }; 144 145 public: 146 147 /// Constructor. 148 %(class_name)s(MachInst machInst); 149 150 %(BasicExecDeclare)s 151 152 %(InitiateAccDeclare)s 153 154 %(CompleteAccDeclare)s 155 }; 156}}; 157 158 159def template InitiateAccDeclare {{ 160 Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; 161}}; 162 163 164def template CompleteAccDeclare {{ 165 Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const; 166}}; 167 168 169def template LoadStoreConstructor {{ 170 /** TODO: change op_class to AddrGenOp or something (requires 171 * creating new member of OpClass enum in op_class.hh, updating 172 * config files, etc.). */ 173 inline %(class_name)s::EAComp::EAComp(MachInst machInst) 174 : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) 175 { 176 %(ea_constructor)s; 177 } 178 179 inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) 180 : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) 181 { 182 %(memacc_constructor)s; 183 } 184 185 inline %(class_name)s::%(class_name)s(MachInst machInst) 186 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 187 new EAComp(machInst), new MemAcc(machInst)) 188 { 189 %(constructor)s; 190 } 191}}; 192 193 194def template EACompExecute {{ 195 Fault 196 %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, 197 Trace::InstRecord *traceData) const 198 { 199 Addr EA; 200 Fault fault = NoFault; 201 202 %(fp_enable_check)s; 203 %(op_decl)s; 204 %(op_rd)s; 205 %(code)s; 206 207 if (fault == NoFault) { 208 %(op_wb)s; 209 xc->setEA(EA); 210 } 211 212 return fault; 213 } 214}}; 215 216def template LoadMemAccExecute {{ 217 Fault 218 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 219 Trace::InstRecord *traceData) const 220 { 221 Addr EA; 222 Fault fault = NoFault; 223 224 %(fp_enable_check)s; 225 %(op_decl)s; 226 %(op_rd)s; 227 EA = xc->getEA(); 228 229 if (fault == NoFault) { 230 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 231 %(code)s; 232 } 233 234 if (fault == NoFault) { 235 %(op_wb)s; 236 } 237 238 return fault; 239 } 240}}; 241 242 243def template LoadExecute {{ 244 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 245 Trace::InstRecord *traceData) const 246 { 247 Addr EA; 248 Fault fault = NoFault; 249 250 %(fp_enable_check)s; 251 %(op_decl)s; 252 %(op_rd)s; 253 %(ea_code)s; 254 255 if (fault == NoFault) { 256 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 257 %(memacc_code)s; 258 } 259 260 if (fault == NoFault) { 261 %(op_wb)s; 262 } 263 264 return fault; 265 } 266}}; 267 268 269def template LoadInitiateAcc {{ 270 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 271 Trace::InstRecord *traceData) const 272 { 273 Addr EA; 274 Fault fault = NoFault; 275 276 %(fp_enable_check)s; 277 %(op_src_decl)s; 278 %(op_rd)s; 279 %(ea_code)s; 280 281 if (fault == NoFault) { 282 fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); 283 } 284 285 return fault; 286 } 287}}; 288 289 290def template LoadCompleteAcc {{ 291 Fault %(class_name)s::completeAcc(uint8_t *data, 292 %(CPU_exec_context)s *xc, 293 Trace::InstRecord *traceData) const 294 { 295 Fault fault = NoFault; 296 297 %(fp_enable_check)s; 298 %(op_decl)s; 299 300 memcpy(&Mem, data, sizeof(Mem)); 301 302 if (fault == NoFault) { 303 %(memacc_code)s; 304 } 305 306 if (fault == NoFault) { 307 %(op_wb)s; 308 } 309 310 return fault; 311 } 312}}; 313 314 315def template StoreMemAccExecute {{ 316 Fault 317 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 318 Trace::InstRecord *traceData) const 319 { 320 Addr EA; 321 Fault fault = NoFault; 322 uint64_t write_result = 0; 323 324 %(fp_enable_check)s; 325 %(op_decl)s; 326 %(op_rd)s; 327 EA = xc->getEA(); 328 329 if (fault == NoFault) { 330 %(code)s; 331 } 332 333 if (fault == NoFault) { 334 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 335 memAccessFlags, &write_result); 336 if (traceData) { traceData->setData(Mem); } 337 } 338 339 if (fault == NoFault) { 340 %(postacc_code)s; 341 } 342 343 if (fault == NoFault) { 344 %(op_wb)s; 345 } 346 347 return fault; 348 } 349}}; 350 351 352def template StoreExecute {{ 353 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 354 Trace::InstRecord *traceData) const 355 { 356 Addr EA; 357 Fault fault = NoFault; 358 uint64_t write_result = 0; 359 360 %(fp_enable_check)s; 361 %(op_decl)s; 362 %(op_rd)s; 363 %(ea_code)s; 364 365 if (fault == NoFault) { 366 %(memacc_code)s; 367 } 368 369 if (fault == NoFault) { 370 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 371 memAccessFlags, &write_result); 372 if (traceData) { traceData->setData(Mem); } 373 } 374 375 if (fault == NoFault) { 376 %(postacc_code)s; 377 } 378 379 if (fault == NoFault) { 380 %(op_wb)s; 381 } 382 383 return fault; 384 } 385}}; 386 387def template StoreInitiateAcc {{ 388 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 389 Trace::InstRecord *traceData) const 390 { 391 Addr EA; 392 Fault fault = NoFault; 393 uint64_t write_result = 0; 394 395 %(fp_enable_check)s; 396 %(op_decl)s; 397 %(op_rd)s; 398 %(ea_code)s; 399 400 if (fault == NoFault) { 401 %(memacc_code)s; 402 } 403 404 if (fault == NoFault) { 405 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 406 memAccessFlags, &write_result); 407 if (traceData) { traceData->setData(Mem); } 408 } 409 410 return fault; 411 } 412}}; 413 414 415def template StoreCompleteAcc {{ 416 Fault %(class_name)s::completeAcc(uint8_t *data, 417 %(CPU_exec_context)s *xc, 418 Trace::InstRecord *traceData) const 419 { 420 Fault fault = NoFault; 421 uint64_t write_result = 0; 422 423 %(fp_enable_check)s; 424 %(op_dest_decl)s; 425 426 memcpy(&write_result, data, sizeof(write_result)); 427 428 if (fault == NoFault) { 429 %(postacc_code)s; 430 } 431 432 if (fault == NoFault) { 433 %(op_wb)s; 434 } 435 436 return fault; 437 } 438}}; 439 440 441def template MiscMemAccExecute {{ 442 Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 443 Trace::InstRecord *traceData) const 444 { 445 Addr EA; 446 Fault fault = NoFault; 447 448 %(fp_enable_check)s; 449 %(op_decl)s; 450 %(op_rd)s; 451 EA = xc->getEA(); 452 453 if (fault == NoFault) { 454 %(code)s; 455 } 456 457 return NoFault; 458 } 459}}; 460 461def template MiscExecute {{ 462 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 463 Trace::InstRecord *traceData) const 464 { 465 Addr EA; 466 Fault fault = NoFault; 467 468 %(fp_enable_check)s; 469 %(op_decl)s; 470 %(op_rd)s; 471 %(ea_code)s; 472 473 if (fault == NoFault) { 474 %(memacc_code)s; 475 } 476 477 return NoFault; 478 } 479}}; 480 481def template MiscInitiateAcc {{ 482 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 483 Trace::InstRecord *traceData) const 484 { 485 panic("Misc instruction does not support split access method!"); 486 return NoFault; 487 } 488}}; 489 490 491def template MiscCompleteAcc {{ 492 Fault %(class_name)s::completeAcc(uint8_t *data, 493 %(CPU_exec_context)s *xc, 494 Trace::InstRecord *traceData) const 495 { 496 panic("Misc instruction does not support split access method!"); 497 498 return NoFault; 499 } 500}}; 501 502// load instructions use Rt as dest, so check for 503// Rt == 0 to detect nops 504def template LoadNopCheckDecode {{ 505 { 506 MipsStaticInst *i = new %(class_name)s(machInst); 507 if (RT == 0) { 508 i = makeNop(i); 509 } 510 return i; 511 } 512}}; 513 514def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, 515 mem_flags = [], inst_flags = []) {{ 516 (header_output, decoder_output, decode_block, exec_output) = \ 517 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 518 decode_template = LoadNopCheckDecode, 519 exec_template_base = 'Load') 520}}; 521 522def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, 523 mem_flags = [], inst_flags = []) {{ 524 (header_output, decoder_output, decode_block, exec_output) = \ 525 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 526 exec_template_base = 'Store') 527}}; 528 529def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }}, 530 mem_flags = [], inst_flags = []) {{ 531 (header_output, decoder_output, decode_block, exec_output) = \ 532 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 533 decode_template = LoadNopCheckDecode, 534 exec_template_base = 'Load') 535}}; 536 537def format StoreIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }}, 538 mem_flags = [], inst_flags = []) {{ 539 (header_output, decoder_output, decode_block, exec_output) = \ 540 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 541 exec_template_base = 'Store') 542}}; 543 544def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }}, 545 mem_flags = [], inst_flags = []) {{ 546 decl_code = 'uint32_t mem_word = Mem.uw;\n' 547 decl_code += 'uint32_t unalign_addr = Rs + disp;\n' 548 decl_code += 'uint32_t byte_offset = unalign_addr & 3;\n' 549 decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n' 550 decl_code += '\tbyte_offset ^= 3;\n' 551 decl_code += '#endif\n' 552 553 memacc_code = decl_code + memacc_code 554 555 (header_output, decoder_output, decode_block, exec_output) = \ 556 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 557 decode_template = LoadNopCheckDecode, 558 exec_template_base = 'Load') 559}}; 560 561def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }}, 562 mem_flags = [], inst_flags = []) {{ 563 decl_code = 'uint32_t mem_word = 0;\n' 564 decl_code += 'uint32_t unaligned_addr = Rs + disp;\n' 565 decl_code += 'uint32_t byte_offset = unaligned_addr & 3;\n' 566 decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n' 567 decl_code += '\tbyte_offset ^= 3;\n' 568 decl_code += '#endif\n' 569 decl_code += 'fault = xc->read(EA, (uint32_t&)mem_word, memAccessFlags);\n' 570 memacc_code = decl_code + memacc_code + '\nMem = mem_word;\n' 571 572 (header_output, decoder_output, decode_block, exec_output) = \ 573 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 574 decode_template = LoadNopCheckDecode, 575 exec_template_base = 'Store') 576}}; 577 578def format Prefetch(ea_code = {{ EA = Rs + disp; }}, 579 mem_flags = [], pf_flags = [], inst_flags = []) {{ 580 pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT'] 581 pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad', 582 'IsDataPrefetch', 'MemReadOp'] 583 584 (header_output, decoder_output, decode_block, exec_output) = \ 585 LoadStoreBase(name, Name, ea_code, 586 'xc->prefetch(EA, memAccessFlags);', 587 pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc') 588 589}}; 590 591def format StoreCond(memacc_code, postacc_code, 592 ea_code = {{ EA = Rs + disp; }}, 593 mem_flags = [], inst_flags = []) {{ 594 (header_output, decoder_output, decode_block, exec_output) = \ 595 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 596 postacc_code, exec_template_base = 'Store') 597}}; 598