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