mem.isa revision 3953
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: Steve Reinhardt 30// Kevin Lim 31 32//////////////////////////////////////////////////////////////////// 33// 34// Memory-format instructions: LoadAddress, Load, Store 35// 36 37output header {{ 38 /** 39 * Base class for general Alpha memory-format instructions. 40 */ 41 class Memory : public AlphaStaticInst 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 /// Constructor 53 Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 54 StaticInstPtr _eaCompPtr = nullStaticInstPtr, 55 StaticInstPtr _memAccPtr = nullStaticInstPtr) 56 : AlphaStaticInst(mnem, _machInst, __opClass), 57 memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr) 58 { 59 } 60 61 std::string 62 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 63 64 public: 65 66 const StaticInstPtr &eaCompInst() const { return eaCompPtr; } 67 const StaticInstPtr &memAccInst() const { return memAccPtr; } 68 }; 69 70 /** 71 * Base class for memory-format instructions using a 32-bit 72 * displacement (i.e. most of them). 73 */ 74 class MemoryDisp32 : public Memory 75 { 76 protected: 77 /// Displacement for EA calculation (signed). 78 int32_t disp; 79 80 /// Constructor. 81 MemoryDisp32(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 82 StaticInstPtr _eaCompPtr = nullStaticInstPtr, 83 StaticInstPtr _memAccPtr = nullStaticInstPtr) 84 : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr), 85 disp(MEMDISP) 86 { 87 } 88 }; 89 90 91 /** 92 * Base class for a few miscellaneous memory-format insts 93 * that don't interpret the disp field: wh64, fetch, fetch_m, ecb. 94 * None of these instructions has a destination register either. 95 */ 96 class MemoryNoDisp : public Memory 97 { 98 protected: 99 /// Constructor 100 MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 101 StaticInstPtr _eaCompPtr = nullStaticInstPtr, 102 StaticInstPtr _memAccPtr = nullStaticInstPtr) 103 : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr) 104 { 105 } 106 107 std::string 108 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 109 }; 110}}; 111 112 113output decoder {{ 114 std::string 115 Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const 116 { 117 return csprintf("%-10s %c%d,%d(r%d)", mnemonic, 118 flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB); 119 } 120 121 std::string 122 MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 123 { 124 return csprintf("%-10s (r%d)", mnemonic, RB); 125 } 126}}; 127 128def format LoadAddress(code) {{ 129 iop = InstObjParams(name, Name, 'MemoryDisp32', code) 130 header_output = BasicDeclare.subst(iop) 131 decoder_output = BasicConstructor.subst(iop) 132 decode_block = BasicDecode.subst(iop) 133 exec_output = BasicExecute.subst(iop) 134}}; 135 136 137def template LoadStoreDeclare {{ 138 /** 139 * Static instruction class for "%(mnemonic)s". 140 */ 141 class %(class_name)s : public %(base_class)s 142 { 143 protected: 144 145 /** 146 * "Fake" effective address computation class for "%(mnemonic)s". 147 */ 148 class EAComp : public %(base_class)s 149 { 150 public: 151 /// Constructor 152 EAComp(ExtMachInst machInst); 153 154 %(BasicExecDeclare)s 155 }; 156 157 /** 158 * "Fake" memory access instruction class for "%(mnemonic)s". 159 */ 160 class MemAcc : public %(base_class)s 161 { 162 public: 163 /// Constructor 164 MemAcc(ExtMachInst machInst); 165 166 %(BasicExecDeclare)s 167 }; 168 169 public: 170 171 /// Constructor. 172 %(class_name)s(ExtMachInst machInst); 173 174 %(BasicExecDeclare)s 175 176 %(InitiateAccDeclare)s 177 178 %(CompleteAccDeclare)s 179 }; 180}}; 181 182 183def template InitiateAccDeclare {{ 184 Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; 185}}; 186 187 188def template CompleteAccDeclare {{ 189 Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, 190 Trace::InstRecord *) const; 191}}; 192 193 194def template EACompConstructor {{ 195 /** TODO: change op_class to AddrGenOp or something (requires 196 * creating new member of OpClass enum in op_class.hh, updating 197 * config files, etc.). */ 198 inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst) 199 : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) 200 { 201 %(constructor)s; 202 } 203}}; 204 205 206def template MemAccConstructor {{ 207 inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst) 208 : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) 209 { 210 %(constructor)s; 211 } 212}}; 213 214 215def template LoadStoreConstructor {{ 216 inline %(class_name)s::%(class_name)s(ExtMachInst machInst) 217 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 218 new EAComp(machInst), new MemAcc(machInst)) 219 { 220 %(constructor)s; 221 } 222}}; 223 224 225def template EACompExecute {{ 226 Fault 227 %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, 228 Trace::InstRecord *traceData) const 229 { 230 Addr EA; 231 Fault fault = NoFault; 232 233 %(fp_enable_check)s; 234 %(op_decl)s; 235 %(op_rd)s; 236 %(ea_code)s; 237 238 if (fault == NoFault) { 239 %(op_wb)s; 240 xc->setEA(EA); 241 } 242 243 return fault; 244 } 245}}; 246 247def template LoadMemAccExecute {{ 248 Fault 249 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 250 Trace::InstRecord *traceData) const 251 { 252 Addr EA; 253 Fault fault = NoFault; 254 255 %(fp_enable_check)s; 256 %(op_decl)s; 257 %(op_rd)s; 258 EA = xc->getEA(); 259 260 if (fault == NoFault) { 261 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 262 %(memacc_code)s; 263 } 264 265 if (fault == NoFault) { 266 %(op_wb)s; 267 } 268 269 return fault; 270 } 271}}; 272 273 274def template LoadExecute {{ 275 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 276 Trace::InstRecord *traceData) const 277 { 278 Addr EA; 279 Fault fault = NoFault; 280 281 %(fp_enable_check)s; 282 %(op_decl)s; 283 %(op_rd)s; 284 %(ea_code)s; 285 286 if (fault == NoFault) { 287 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 288 %(memacc_code)s; 289 } 290 291 if (fault == NoFault) { 292 %(op_wb)s; 293 } 294 295 return fault; 296 } 297}}; 298 299 300def template LoadInitiateAcc {{ 301 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 302 Trace::InstRecord *traceData) const 303 { 304 Addr EA; 305 Fault fault = NoFault; 306 307 %(fp_enable_check)s; 308 %(op_src_decl)s; 309 %(op_rd)s; 310 %(ea_code)s; 311 312 if (fault == NoFault) { 313 fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); 314 } 315 316 return fault; 317 } 318}}; 319 320 321def template LoadCompleteAcc {{ 322 Fault %(class_name)s::completeAcc(PacketPtr pkt, 323 %(CPU_exec_context)s *xc, 324 Trace::InstRecord *traceData) const 325 { 326 Fault fault = NoFault; 327 328 %(fp_enable_check)s; 329 %(op_decl)s; 330 331 Mem = pkt->get<typeof(Mem)>(); 332 333 if (fault == NoFault) { 334 %(memacc_code)s; 335 } 336 337 if (fault == NoFault) { 338 %(op_wb)s; 339 } 340 341 return fault; 342 } 343}}; 344 345 346def template StoreMemAccExecute {{ 347 Fault 348 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 349 Trace::InstRecord *traceData) const 350 { 351 Addr EA; 352 Fault fault = NoFault; 353 uint64_t write_result = 0; 354 355 %(fp_enable_check)s; 356 %(op_decl)s; 357 %(op_rd)s; 358 EA = xc->getEA(); 359 360 if (fault == NoFault) { 361 %(memacc_code)s; 362 } 363 364 if (fault == NoFault) { 365 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 366 memAccessFlags, &write_result); 367 if (traceData) { traceData->setData(Mem); } 368 } 369 370 if (fault == NoFault) { 371 %(postacc_code)s; 372 } 373 374 if (fault == NoFault) { 375 %(op_wb)s; 376 } 377 378 return fault; 379 } 380}}; 381 382 383def template StoreExecute {{ 384 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 385 Trace::InstRecord *traceData) const 386 { 387 Addr EA; 388 Fault fault = NoFault; 389 uint64_t write_result = 0; 390 391 %(fp_enable_check)s; 392 %(op_decl)s; 393 %(op_rd)s; 394 %(ea_code)s; 395 396 if (fault == NoFault) { 397 %(memacc_code)s; 398 } 399 400 if (fault == NoFault) { 401 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 402 memAccessFlags, &write_result); 403 if (traceData) { traceData->setData(Mem); } 404 } 405 406 if (fault == NoFault) { 407 %(postacc_code)s; 408 } 409 410 if (fault == NoFault) { 411 %(op_wb)s; 412 } 413 414 return fault; 415 } 416}}; 417 418def template StoreInitiateAcc {{ 419 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 420 Trace::InstRecord *traceData) const 421 { 422 Addr EA; 423 Fault fault = NoFault; 424 425 %(fp_enable_check)s; 426 %(op_decl)s; 427 %(op_rd)s; 428 %(ea_code)s; 429 430 if (fault == NoFault) { 431 %(memacc_code)s; 432 } 433 434 if (fault == NoFault) { 435 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 436 memAccessFlags, NULL); 437 if (traceData) { traceData->setData(Mem); } 438 } 439 440 return fault; 441 } 442}}; 443 444 445def template StoreCompleteAcc {{ 446 Fault %(class_name)s::completeAcc(PacketPtr pkt, 447 %(CPU_exec_context)s *xc, 448 Trace::InstRecord *traceData) const 449 { 450 Fault fault = NoFault; 451 452 %(fp_enable_check)s; 453 %(op_dest_decl)s; 454 455 if (fault == NoFault) { 456 %(postacc_code)s; 457 } 458 459 if (fault == NoFault) { 460 %(op_wb)s; 461 } 462 463 return fault; 464 } 465}}; 466 467 468def template StoreCondCompleteAcc {{ 469 Fault %(class_name)s::completeAcc(PacketPtr pkt, 470 %(CPU_exec_context)s *xc, 471 Trace::InstRecord *traceData) const 472 { 473 Fault fault = NoFault; 474 475 %(fp_enable_check)s; 476 %(op_dest_decl)s; 477 478 uint64_t write_result = pkt->req->getScResult(); 479 480 if (fault == NoFault) { 481 %(postacc_code)s; 482 } 483 484 if (fault == NoFault) { 485 %(op_wb)s; 486 } 487 488 return fault; 489 } 490}}; 491 492 493def template MiscMemAccExecute {{ 494 Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 495 Trace::InstRecord *traceData) const 496 { 497 Addr EA; 498 Fault fault = NoFault; 499 500 %(fp_enable_check)s; 501 %(op_decl)s; 502 %(op_rd)s; 503 EA = xc->getEA(); 504 505 if (fault == NoFault) { 506 %(memacc_code)s; 507 } 508 509 return NoFault; 510 } 511}}; 512 513def template MiscExecute {{ 514 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 515 Trace::InstRecord *traceData) const 516 { 517 Addr EA; 518 Fault fault = NoFault; 519 520 %(fp_enable_check)s; 521 %(op_decl)s; 522 %(op_rd)s; 523 %(ea_code)s; 524 525 if (fault == NoFault) { 526 %(memacc_code)s; 527 } 528 529 return NoFault; 530 } 531}}; 532 533def template MiscInitiateAcc {{ 534 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 535 Trace::InstRecord *traceData) const 536 { 537 warn("Misc instruction does not support split access method!"); 538 return NoFault; 539 } 540}}; 541 542 543def template MiscCompleteAcc {{ 544 Fault %(class_name)s::completeAcc(PacketPtr pkt, 545 %(CPU_exec_context)s *xc, 546 Trace::InstRecord *traceData) const 547 { 548 warn("Misc instruction does not support split access method!"); 549 550 return NoFault; 551 } 552}}; 553 554// load instructions use Ra as dest, so check for 555// Ra == 31 to detect nops 556def template LoadNopCheckDecode {{ 557 { 558 AlphaStaticInst *i = new %(class_name)s(machInst); 559 if (RA == 31) { 560 i = makeNop(i); 561 } 562 return i; 563 } 564}}; 565 566 567// for some load instructions, Ra == 31 indicates a prefetch (not a nop) 568def template LoadPrefetchCheckDecode {{ 569 { 570 if (RA != 31) { 571 return new %(class_name)s(machInst); 572 } 573 else { 574 return new %(class_name)sPrefetch(machInst); 575 } 576 } 577}}; 578 579 580let {{ 581def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 582 postacc_code = '', base_class = 'MemoryDisp32', 583 decode_template = BasicDecode, exec_template_base = ''): 584 # Make sure flags are in lists (convert to lists if not). 585 mem_flags = makeList(mem_flags) 586 inst_flags = makeList(inst_flags) 587 588 # add hook to get effective addresses into execution trace output. 589 ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' 590 591 # Some CPU models execute the memory operation as an atomic unit, 592 # while others want to separate them into an effective address 593 # computation and a memory access operation. As a result, we need 594 # to generate three StaticInst objects. Note that the latter two 595 # are nested inside the larger "atomic" one. 596 597 # Generate InstObjParams for each of the three objects. Note that 598 # they differ only in the set of code objects contained (which in 599 # turn affects the object's overall operand list). 600 iop = InstObjParams(name, Name, base_class, 601 { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code }, 602 inst_flags) 603 ea_iop = InstObjParams(name, Name, base_class, 604 { 'ea_code':ea_code }, 605 inst_flags) 606 memacc_iop = InstObjParams(name, Name, base_class, 607 { 'memacc_code':memacc_code, 'postacc_code':postacc_code }, 608 inst_flags) 609 610 if mem_flags: 611 s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' 612 iop.constructor += s 613 memacc_iop.constructor += s 614 615 # select templates 616 617 # define aliases... most StoreCond templates are the same as the 618 # corresponding Store templates (only CompleteAcc is different). 619 StoreCondMemAccExecute = StoreMemAccExecute 620 StoreCondExecute = StoreExecute 621 StoreCondInitiateAcc = StoreInitiateAcc 622 623 memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') 624 fullExecTemplate = eval(exec_template_base + 'Execute') 625 initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') 626 completeAccTemplate = eval(exec_template_base + 'CompleteAcc') 627 628 # (header_output, decoder_output, decode_block, exec_output) 629 return (LoadStoreDeclare.subst(iop), 630 EACompConstructor.subst(ea_iop) 631 + MemAccConstructor.subst(memacc_iop) 632 + LoadStoreConstructor.subst(iop), 633 decode_template.subst(iop), 634 EACompExecute.subst(ea_iop) 635 + memAccExecTemplate.subst(memacc_iop) 636 + fullExecTemplate.subst(iop) 637 + initiateAccTemplate.subst(iop) 638 + completeAccTemplate.subst(iop)) 639}}; 640 641def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }}, 642 mem_flags = [], inst_flags = []) {{ 643 (header_output, decoder_output, decode_block, exec_output) = \ 644 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 645 decode_template = LoadNopCheckDecode, 646 exec_template_base = 'Load') 647}}; 648 649 650// Note that the flags passed in apply only to the prefetch version 651def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }}, 652 mem_flags = [], pf_flags = [], inst_flags = []) {{ 653 # declare the load instruction object and generate the decode block 654 (header_output, decoder_output, decode_block, exec_output) = \ 655 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 656 decode_template = LoadPrefetchCheckDecode, 657 exec_template_base = 'Load') 658 659 # Declare the prefetch instruction object. 660 661 # Make sure flag args are lists so we can mess with them. 662 mem_flags = makeList(mem_flags) 663 pf_flags = makeList(pf_flags) 664 inst_flags = makeList(inst_flags) 665 666 pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT'] 667 pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad', 668 'IsDataPrefetch', 'MemReadOp'] 669 670 (pf_header_output, pf_decoder_output, _, pf_exec_output) = \ 671 LoadStoreBase(name, Name + 'Prefetch', ea_code, 672 'xc->prefetch(EA, memAccessFlags);', 673 pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc') 674 675 header_output += pf_header_output 676 decoder_output += pf_decoder_output 677 exec_output += pf_exec_output 678}}; 679 680 681def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }}, 682 mem_flags = [], inst_flags = []) {{ 683 (header_output, decoder_output, decode_block, exec_output) = \ 684 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 685 exec_template_base = 'Store') 686}}; 687 688 689def format StoreCond(memacc_code, postacc_code, 690 ea_code = {{ EA = Rb + disp; }}, 691 mem_flags = [], inst_flags = []) {{ 692 (header_output, decoder_output, decode_block, exec_output) = \ 693 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 694 postacc_code, exec_template_base = 'StoreCond') 695}}; 696 697 698// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb 699def format MiscPrefetch(ea_code, memacc_code, 700 mem_flags = [], inst_flags = []) {{ 701 (header_output, decoder_output, decode_block, exec_output) = \ 702 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 703 base_class = 'MemoryNoDisp', exec_template_base = 'Misc') 704}}; 705 706 707