mem.isa revision 6185:9925b3e83e06
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 LoadStoreMemAccSize {{ 168 int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc) 169 { 170 // Return the memory access size in bytes 171 return (%(mem_acc_size)d / 8); 172 } 173}}; 174 175 176def template LoadStoreConstructor {{ 177 inline %(class_name)s::%(class_name)s(ExtMachInst machInst) 178 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 179 { 180 %(constructor)s; 181 } 182}}; 183 184def template EACompExecute {{ 185 Fault %(class_name)s::eaComp(%(CPU_exec_context)s *xc, 186 Trace::InstRecord *traceData) const 187 { 188 Addr EA; 189 Fault fault = NoFault; 190 191 %(fp_enable_check)s; 192 %(op_decl)s; 193 %(op_rd)s; 194 %(ea_code)s; 195 196 if (fault == NoFault) { 197 %(op_wb)s; 198 xc->setEA(EA); 199 } 200 201 return fault; 202 } 203}}; 204 205 206def template LoadExecute {{ 207 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 208 Trace::InstRecord *traceData) const 209 { 210 Addr EA; 211 Fault fault = NoFault; 212 213 %(fp_enable_check)s; 214 %(op_decl)s; 215 %(op_rd)s; 216 %(ea_code)s; 217 218 if (fault == NoFault) { 219 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 220 %(memacc_code)s; 221 } 222 223 if (fault == NoFault) { 224 %(op_wb)s; 225 } 226 227 return fault; 228 } 229}}; 230 231 232def template LoadInitiateAcc {{ 233 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 234 Trace::InstRecord *traceData) const 235 { 236 Addr EA; 237 Fault fault = NoFault; 238 239 %(fp_enable_check)s; 240 %(op_src_decl)s; 241 %(op_rd)s; 242 %(ea_code)s; 243 244 if (fault == NoFault) { 245 fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); 246 } 247 248 return fault; 249 } 250}}; 251 252 253def template LoadCompleteAcc {{ 254 Fault %(class_name)s::completeAcc(PacketPtr pkt, 255 %(CPU_exec_context)s *xc, 256 Trace::InstRecord *traceData) const 257 { 258 Fault fault = NoFault; 259 260 %(fp_enable_check)s; 261 %(op_decl)s; 262 263 Mem = pkt->get<typeof(Mem)>(); 264 265 if (fault == NoFault) { 266 %(memacc_code)s; 267 } 268 269 if (fault == NoFault) { 270 %(op_wb)s; 271 } 272 273 return fault; 274 } 275}}; 276 277 278def template StoreExecute {{ 279 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 280 Trace::InstRecord *traceData) const 281 { 282 Addr EA; 283 Fault fault = NoFault; 284 285 %(fp_enable_check)s; 286 %(op_decl)s; 287 %(op_rd)s; 288 %(ea_code)s; 289 290 if (fault == NoFault) { 291 %(memacc_code)s; 292 } 293 294 if (fault == NoFault) { 295 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 296 memAccessFlags, NULL); 297 if (traceData) { traceData->setData(Mem); } 298 } 299 300 if (fault == NoFault) { 301 %(postacc_code)s; 302 } 303 304 if (fault == NoFault) { 305 %(op_wb)s; 306 } 307 308 return fault; 309 } 310}}; 311 312def template StoreCondExecute {{ 313 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 314 Trace::InstRecord *traceData) const 315 { 316 Addr EA; 317 Fault fault = NoFault; 318 uint64_t write_result = 0; 319 320 %(fp_enable_check)s; 321 %(op_decl)s; 322 %(op_rd)s; 323 %(ea_code)s; 324 325 if (fault == NoFault) { 326 %(memacc_code)s; 327 } 328 329 if (fault == NoFault) { 330 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 331 memAccessFlags, &write_result); 332 if (traceData) { traceData->setData(Mem); } 333 } 334 335 if (fault == NoFault) { 336 %(postacc_code)s; 337 } 338 339 if (fault == NoFault) { 340 %(op_wb)s; 341 } 342 343 return fault; 344 } 345}}; 346 347def template StoreInitiateAcc {{ 348 Fault %(class_name)s::initiateAcc(%(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_code)s; 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 return fault; 370 } 371}}; 372 373 374def template StoreCompleteAcc {{ 375 Fault %(class_name)s::completeAcc(PacketPtr pkt, 376 %(CPU_exec_context)s *xc, 377 Trace::InstRecord *traceData) const 378 { 379 Fault fault = NoFault; 380 381 %(fp_enable_check)s; 382 %(op_dest_decl)s; 383 384 if (fault == NoFault) { 385 %(postacc_code)s; 386 } 387 388 if (fault == NoFault) { 389 %(op_wb)s; 390 } 391 392 return fault; 393 } 394}}; 395 396 397def template StoreCondCompleteAcc {{ 398 Fault %(class_name)s::completeAcc(PacketPtr pkt, 399 %(CPU_exec_context)s *xc, 400 Trace::InstRecord *traceData) const 401 { 402 Fault fault = NoFault; 403 404 %(fp_enable_check)s; 405 %(op_dest_decl)s; 406 407 uint64_t write_result = pkt->req->getExtraData(); 408 409 if (fault == NoFault) { 410 %(postacc_code)s; 411 } 412 413 if (fault == NoFault) { 414 %(op_wb)s; 415 } 416 417 return fault; 418 } 419}}; 420 421 422def template MiscExecute {{ 423 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 424 Trace::InstRecord *traceData) const 425 { 426 Addr EA; 427 Fault fault = NoFault; 428 429 %(fp_enable_check)s; 430 %(op_decl)s; 431 %(op_rd)s; 432 %(ea_code)s; 433 434 if (fault == NoFault) { 435 %(memacc_code)s; 436 } 437 438 return NoFault; 439 } 440}}; 441 442def template MiscInitiateAcc {{ 443 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 444 Trace::InstRecord *traceData) const 445 { 446 warn("initiateAcc undefined: Misc instruction does not support split " 447 "access method!"); 448 return NoFault; 449 } 450}}; 451 452 453def template MiscCompleteAcc {{ 454 Fault %(class_name)s::completeAcc(PacketPtr pkt, 455 %(CPU_exec_context)s *xc, 456 Trace::InstRecord *traceData) const 457 { 458 warn("completeAcc undefined: Misc instruction does not support split " 459 "access method!"); 460 461 return NoFault; 462 } 463}}; 464 465def template MiscMemAccSize {{ 466 int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc) 467 { 468 return (%(mem_acc_size)d / 8); 469 panic("memAccSize undefined: Misc instruction does not support split " 470 "access method!"); 471 return 0; 472 } 473}}; 474 475// load instructions use Ra as dest, so check for 476// Ra == 31 to detect nops 477def template LoadNopCheckDecode {{ 478 { 479 AlphaStaticInst *i = new %(class_name)s(machInst); 480 if (RA == 31) { 481 i = makeNop(i); 482 } 483 return i; 484 } 485}}; 486 487 488// for some load instructions, Ra == 31 indicates a prefetch (not a nop) 489def template LoadPrefetchCheckDecode {{ 490 { 491 if (RA != 31) { 492 return new %(class_name)s(machInst); 493 } 494 else { 495 return new %(class_name)sPrefetch(machInst); 496 } 497 } 498}}; 499 500 501let {{ 502def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 503 postacc_code = '', base_class = 'MemoryDisp32', 504 decode_template = BasicDecode, exec_template_base = ''): 505 # Make sure flags are in lists (convert to lists if not). 506 mem_flags = makeList(mem_flags) 507 inst_flags = makeList(inst_flags) 508 509 # add hook to get effective addresses into execution trace output. 510 ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' 511 512 # Some CPU models execute the memory operation as an atomic unit, 513 # while others want to separate them into an effective address 514 # computation and a memory access operation. As a result, we need 515 # to generate three StaticInst objects. Note that the latter two 516 # are nested inside the larger "atomic" one. 517 518 # Generate InstObjParams for each of the three objects. Note that 519 # they differ only in the set of code objects contained (which in 520 # turn affects the object's overall operand list). 521 iop = InstObjParams(name, Name, base_class, 522 { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code }, 523 inst_flags) 524 memacc_iop = InstObjParams(name, Name, base_class, 525 { 'memacc_code':memacc_code, 'postacc_code':postacc_code }, 526 inst_flags) 527 528 if mem_flags: 529 mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] 530 s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' 531 iop.constructor += s 532 memacc_iop.constructor += s 533 534 # select templates 535 536 # The InitiateAcc template is the same for StoreCond templates as the 537 # corresponding Store template.. 538 StoreCondInitiateAcc = StoreInitiateAcc 539 540 fullExecTemplate = eval(exec_template_base + 'Execute') 541 initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') 542 completeAccTemplate = eval(exec_template_base + 'CompleteAcc') 543 544 if (exec_template_base == 'Load' or exec_template_base == 'Store'): 545 memAccSizeTemplate = eval('LoadStoreMemAccSize') 546 else: 547 memAccSizeTemplate = eval('MiscMemAccSize') 548 549 # (header_output, decoder_output, decode_block, exec_output) 550 return (LoadStoreDeclare.subst(iop), 551 LoadStoreConstructor.subst(iop), 552 decode_template.subst(iop), 553 fullExecTemplate.subst(iop) 554 + EACompExecute.subst(iop) 555 + initiateAccTemplate.subst(iop) 556 + completeAccTemplate.subst(iop) 557 + memAccSizeTemplate.subst(memacc_iop)) 558}}; 559 560def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }}, 561 mem_flags = [], inst_flags = []) {{ 562 (header_output, decoder_output, decode_block, exec_output) = \ 563 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 564 decode_template = LoadNopCheckDecode, 565 exec_template_base = 'Load') 566}}; 567 568 569// Note that the flags passed in apply only to the prefetch version 570def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }}, 571 mem_flags = [], pf_flags = [], inst_flags = []) {{ 572 # declare the load instruction object and generate the decode block 573 (header_output, decoder_output, decode_block, exec_output) = \ 574 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 575 decode_template = LoadPrefetchCheckDecode, 576 exec_template_base = 'Load') 577 578 # Declare the prefetch instruction object. 579 580 # Make sure flag args are lists so we can mess with them. 581 mem_flags = makeList(mem_flags) 582 pf_flags = makeList(pf_flags) 583 inst_flags = makeList(inst_flags) 584 585 pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT'] 586 pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad', 587 'IsDataPrefetch', 'MemReadOp'] 588 589 (pf_header_output, pf_decoder_output, _, pf_exec_output) = \ 590 LoadStoreBase(name, Name + 'Prefetch', ea_code, 591 'xc->prefetch(EA, memAccessFlags);', 592 pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc') 593 594 header_output += pf_header_output 595 decoder_output += pf_decoder_output 596 exec_output += pf_exec_output 597}}; 598 599 600def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }}, 601 mem_flags = [], inst_flags = []) {{ 602 (header_output, decoder_output, decode_block, exec_output) = \ 603 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 604 exec_template_base = 'Store') 605}}; 606 607 608def format StoreCond(memacc_code, postacc_code, 609 ea_code = {{ EA = Rb + disp; }}, 610 mem_flags = [], inst_flags = []) {{ 611 (header_output, decoder_output, decode_block, exec_output) = \ 612 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 613 postacc_code, exec_template_base = 'StoreCond') 614}}; 615 616 617// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb 618def format MiscPrefetch(ea_code, memacc_code, 619 mem_flags = [], inst_flags = []) {{ 620 (header_output, decoder_output, decode_block, exec_output) = \ 621 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 622 base_class = 'MemoryNoDisp', exec_template_base = 'Misc') 623}}; 624 625 626