mem.isa revision 4661
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 354 %(fp_enable_check)s; 355 %(op_decl)s; 356 %(op_rd)s; 357 EA = xc->getEA(); 358 359 if (fault == NoFault) { 360 %(memacc_code)s; 361 } 362 363 if (fault == NoFault) { 364 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 365 memAccessFlags, NULL); 366 if (traceData) { traceData->setData(Mem); } 367 } 368 369 if (fault == NoFault) { 370 %(postacc_code)s; 371 } 372 373 if (fault == NoFault) { 374 %(op_wb)s; 375 } 376 377 return fault; 378 } 379}}; 380 381def template StoreCondMemAccExecute {{ 382 Fault 383 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 384 Trace::InstRecord *traceData) const 385 { 386 Addr EA; 387 Fault fault = NoFault; 388 uint64_t write_result = 0; 389 390 %(fp_enable_check)s; 391 %(op_decl)s; 392 %(op_rd)s; 393 EA = xc->getEA(); 394 395 if (fault == NoFault) { 396 %(memacc_code)s; 397 } 398 399 if (fault == NoFault) { 400 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 401 memAccessFlags, &write_result); 402 if (traceData) { traceData->setData(Mem); } 403 } 404 405 if (fault == NoFault) { 406 %(postacc_code)s; 407 } 408 409 if (fault == NoFault) { 410 %(op_wb)s; 411 } 412 413 return fault; 414 } 415}}; 416 417 418def template StoreExecute {{ 419 Fault %(class_name)s::execute(%(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 if (fault == NoFault) { 441 %(postacc_code)s; 442 } 443 444 if (fault == NoFault) { 445 %(op_wb)s; 446 } 447 448 return fault; 449 } 450}}; 451 452def template StoreCondExecute {{ 453 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 454 Trace::InstRecord *traceData) const 455 { 456 Addr EA; 457 Fault fault = NoFault; 458 uint64_t write_result = 0; 459 460 %(fp_enable_check)s; 461 %(op_decl)s; 462 %(op_rd)s; 463 %(ea_code)s; 464 465 if (fault == NoFault) { 466 %(memacc_code)s; 467 } 468 469 if (fault == NoFault) { 470 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 471 memAccessFlags, &write_result); 472 if (traceData) { traceData->setData(Mem); } 473 } 474 475 if (fault == NoFault) { 476 %(postacc_code)s; 477 } 478 479 if (fault == NoFault) { 480 %(op_wb)s; 481 } 482 483 return fault; 484 } 485}}; 486 487def template StoreInitiateAcc {{ 488 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 489 Trace::InstRecord *traceData) const 490 { 491 Addr EA; 492 Fault fault = NoFault; 493 494 %(fp_enable_check)s; 495 %(op_decl)s; 496 %(op_rd)s; 497 %(ea_code)s; 498 499 if (fault == NoFault) { 500 %(memacc_code)s; 501 } 502 503 if (fault == NoFault) { 504 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 505 memAccessFlags, NULL); 506 if (traceData) { traceData->setData(Mem); } 507 } 508 509 return fault; 510 } 511}}; 512 513 514def template StoreCompleteAcc {{ 515 Fault %(class_name)s::completeAcc(PacketPtr pkt, 516 %(CPU_exec_context)s *xc, 517 Trace::InstRecord *traceData) const 518 { 519 Fault fault = NoFault; 520 521 %(fp_enable_check)s; 522 %(op_dest_decl)s; 523 524 if (fault == NoFault) { 525 %(postacc_code)s; 526 } 527 528 if (fault == NoFault) { 529 %(op_wb)s; 530 } 531 532 return fault; 533 } 534}}; 535 536 537def template StoreCondCompleteAcc {{ 538 Fault %(class_name)s::completeAcc(PacketPtr pkt, 539 %(CPU_exec_context)s *xc, 540 Trace::InstRecord *traceData) const 541 { 542 Fault fault = NoFault; 543 544 %(fp_enable_check)s; 545 %(op_dest_decl)s; 546 547 uint64_t write_result = pkt->req->getExtraData(); 548 549 if (fault == NoFault) { 550 %(postacc_code)s; 551 } 552 553 if (fault == NoFault) { 554 %(op_wb)s; 555 } 556 557 return fault; 558 } 559}}; 560 561 562def template MiscMemAccExecute {{ 563 Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 564 Trace::InstRecord *traceData) const 565 { 566 Addr EA; 567 Fault fault = NoFault; 568 569 %(fp_enable_check)s; 570 %(op_decl)s; 571 %(op_rd)s; 572 EA = xc->getEA(); 573 574 if (fault == NoFault) { 575 %(memacc_code)s; 576 } 577 578 return NoFault; 579 } 580}}; 581 582def template MiscExecute {{ 583 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 584 Trace::InstRecord *traceData) const 585 { 586 Addr EA; 587 Fault fault = NoFault; 588 589 %(fp_enable_check)s; 590 %(op_decl)s; 591 %(op_rd)s; 592 %(ea_code)s; 593 594 if (fault == NoFault) { 595 %(memacc_code)s; 596 } 597 598 return NoFault; 599 } 600}}; 601 602def template MiscInitiateAcc {{ 603 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 604 Trace::InstRecord *traceData) const 605 { 606 warn("Misc instruction does not support split access method!"); 607 return NoFault; 608 } 609}}; 610 611 612def template MiscCompleteAcc {{ 613 Fault %(class_name)s::completeAcc(PacketPtr pkt, 614 %(CPU_exec_context)s *xc, 615 Trace::InstRecord *traceData) const 616 { 617 warn("Misc instruction does not support split access method!"); 618 619 return NoFault; 620 } 621}}; 622 623// load instructions use Ra as dest, so check for 624// Ra == 31 to detect nops 625def template LoadNopCheckDecode {{ 626 { 627 AlphaStaticInst *i = new %(class_name)s(machInst); 628 if (RA == 31) { 629 i = makeNop(i); 630 } 631 return i; 632 } 633}}; 634 635 636// for some load instructions, Ra == 31 indicates a prefetch (not a nop) 637def template LoadPrefetchCheckDecode {{ 638 { 639 if (RA != 31) { 640 return new %(class_name)s(machInst); 641 } 642 else { 643 return new %(class_name)sPrefetch(machInst); 644 } 645 } 646}}; 647 648 649let {{ 650def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 651 postacc_code = '', base_class = 'MemoryDisp32', 652 decode_template = BasicDecode, exec_template_base = ''): 653 # Make sure flags are in lists (convert to lists if not). 654 mem_flags = makeList(mem_flags) 655 inst_flags = makeList(inst_flags) 656 657 # add hook to get effective addresses into execution trace output. 658 ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' 659 660 # Some CPU models execute the memory operation as an atomic unit, 661 # while others want to separate them into an effective address 662 # computation and a memory access operation. As a result, we need 663 # to generate three StaticInst objects. Note that the latter two 664 # are nested inside the larger "atomic" one. 665 666 # Generate InstObjParams for each of the three objects. Note that 667 # they differ only in the set of code objects contained (which in 668 # turn affects the object's overall operand list). 669 iop = InstObjParams(name, Name, base_class, 670 { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code }, 671 inst_flags) 672 ea_iop = InstObjParams(name, Name, base_class, 673 { 'ea_code':ea_code }, 674 inst_flags) 675 memacc_iop = InstObjParams(name, Name, base_class, 676 { 'memacc_code':memacc_code, 'postacc_code':postacc_code }, 677 inst_flags) 678 679 if mem_flags: 680 s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' 681 iop.constructor += s 682 memacc_iop.constructor += s 683 684 # select templates 685 686 # The InitiateAcc template is the same for StoreCond templates as the 687 # corresponding Store template.. 688 StoreCondInitiateAcc = StoreInitiateAcc 689 690 memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') 691 fullExecTemplate = eval(exec_template_base + 'Execute') 692 initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') 693 completeAccTemplate = eval(exec_template_base + 'CompleteAcc') 694 695 # (header_output, decoder_output, decode_block, exec_output) 696 return (LoadStoreDeclare.subst(iop), 697 EACompConstructor.subst(ea_iop) 698 + MemAccConstructor.subst(memacc_iop) 699 + LoadStoreConstructor.subst(iop), 700 decode_template.subst(iop), 701 EACompExecute.subst(ea_iop) 702 + memAccExecTemplate.subst(memacc_iop) 703 + fullExecTemplate.subst(iop) 704 + initiateAccTemplate.subst(iop) 705 + completeAccTemplate.subst(iop)) 706}}; 707 708def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }}, 709 mem_flags = [], inst_flags = []) {{ 710 (header_output, decoder_output, decode_block, exec_output) = \ 711 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 712 decode_template = LoadNopCheckDecode, 713 exec_template_base = 'Load') 714}}; 715 716 717// Note that the flags passed in apply only to the prefetch version 718def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }}, 719 mem_flags = [], pf_flags = [], inst_flags = []) {{ 720 # declare the load instruction object and generate the decode block 721 (header_output, decoder_output, decode_block, exec_output) = \ 722 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 723 decode_template = LoadPrefetchCheckDecode, 724 exec_template_base = 'Load') 725 726 # Declare the prefetch instruction object. 727 728 # Make sure flag args are lists so we can mess with them. 729 mem_flags = makeList(mem_flags) 730 pf_flags = makeList(pf_flags) 731 inst_flags = makeList(inst_flags) 732 733 pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT'] 734 pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad', 735 'IsDataPrefetch', 'MemReadOp'] 736 737 (pf_header_output, pf_decoder_output, _, pf_exec_output) = \ 738 LoadStoreBase(name, Name + 'Prefetch', ea_code, 739 'xc->prefetch(EA, memAccessFlags);', 740 pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc') 741 742 header_output += pf_header_output 743 decoder_output += pf_decoder_output 744 exec_output += pf_exec_output 745}}; 746 747 748def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }}, 749 mem_flags = [], inst_flags = []) {{ 750 (header_output, decoder_output, decode_block, exec_output) = \ 751 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 752 exec_template_base = 'Store') 753}}; 754 755 756def format StoreCond(memacc_code, postacc_code, 757 ea_code = {{ EA = Rb + disp; }}, 758 mem_flags = [], inst_flags = []) {{ 759 (header_output, decoder_output, decode_block, exec_output) = \ 760 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 761 postacc_code, exec_template_base = 'StoreCond') 762}}; 763 764 765// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb 766def format MiscPrefetch(ea_code, memacc_code, 767 mem_flags = [], inst_flags = []) {{ 768 (header_output, decoder_output, decode_block, exec_output) = \ 769 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 770 base_class = 'MemoryNoDisp', exec_template_base = 'Misc') 771}}; 772 773 774