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