mem.isa revision 12236:126ac9da6050
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 Fault execute(ExecContext *, Trace::InstRecord *) const; 133 Fault eaComp(ExecContext *, Trace::InstRecord *) const; 134 Fault initiateAcc(ExecContext *, Trace::InstRecord *) const; 135 Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const; 136 }; 137}}; 138 139def template LoadStoreConstructor {{ 140 %(class_name)s::%(class_name)s(ExtMachInst machInst) 141 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 142 { 143 %(constructor)s; 144 } 145}}; 146 147def template EACompExecute {{ 148 Fault %(class_name)s::eaComp(ExecContext *xc, 149 Trace::InstRecord *traceData) const 150 { 151 Addr EA; 152 Fault fault = NoFault; 153 154 %(fp_enable_check)s; 155 %(op_decl)s; 156 %(op_rd)s; 157 %(ea_code)s; 158 159 if (fault == NoFault) { 160 %(op_wb)s; 161 xc->setEA(EA); 162 } 163 164 return fault; 165 } 166}}; 167 168 169def template LoadExecute {{ 170 Fault %(class_name)s::execute(ExecContext *xc, 171 Trace::InstRecord *traceData) const 172 { 173 Addr EA; 174 Fault fault = NoFault; 175 176 %(fp_enable_check)s; 177 %(op_decl)s; 178 %(op_rd)s; 179 %(ea_code)s; 180 181 if (fault == NoFault) { 182 fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags); 183 %(memacc_code)s; 184 } 185 186 if (fault == NoFault) { 187 %(op_wb)s; 188 } 189 190 return fault; 191 } 192}}; 193 194 195def template LoadInitiateAcc {{ 196 Fault %(class_name)s::initiateAcc(ExecContext *xc, 197 Trace::InstRecord *traceData) const 198 { 199 Addr EA; 200 Fault fault = NoFault; 201 202 %(fp_enable_check)s; 203 %(op_src_decl)s; 204 %(op_rd)s; 205 %(ea_code)s; 206 207 if (fault == NoFault) { 208 fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags); 209 } 210 211 return fault; 212 } 213}}; 214 215 216def template LoadCompleteAcc {{ 217 Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc, 218 Trace::InstRecord *traceData) const 219 { 220 Fault fault = NoFault; 221 222 %(fp_enable_check)s; 223 %(op_decl)s; 224 225 getMem(pkt, Mem, traceData); 226 227 if (fault == NoFault) { 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 StoreExecute {{ 241 Fault %(class_name)s::execute(ExecContext *xc, 242 Trace::InstRecord *traceData) const 243 { 244 Addr EA; 245 Fault fault = NoFault; 246 247 %(fp_enable_check)s; 248 %(op_decl)s; 249 %(op_rd)s; 250 %(ea_code)s; 251 252 if (fault == NoFault) { 253 %(memacc_code)s; 254 } 255 256 if (fault == NoFault) { 257 fault = writeMemAtomic(xc, traceData, Mem, EA, 258 memAccessFlags, NULL); 259 } 260 261 if (fault == NoFault) { 262 %(postacc_code)s; 263 } 264 265 if (fault == NoFault) { 266 %(op_wb)s; 267 } 268 269 return fault; 270 } 271}}; 272 273def template StoreCondExecute {{ 274 Fault %(class_name)s::execute(ExecContext *xc, 275 Trace::InstRecord *traceData) const 276 { 277 Addr EA; 278 Fault fault = NoFault; 279 uint64_t write_result = 0; 280 281 %(fp_enable_check)s; 282 %(op_decl)s; 283 %(op_rd)s; 284 %(ea_code)s; 285 286 if (fault == NoFault) { 287 %(memacc_code)s; 288 } 289 290 if (fault == NoFault) { 291 fault = writeMemAtomic(xc, traceData, Mem, EA, 292 memAccessFlags, &write_result); 293 } 294 295 if (fault == NoFault) { 296 %(postacc_code)s; 297 } 298 299 if (fault == NoFault) { 300 %(op_wb)s; 301 } 302 303 return fault; 304 } 305}}; 306 307def template StoreInitiateAcc {{ 308 Fault %(class_name)s::initiateAcc(ExecContext *xc, 309 Trace::InstRecord *traceData) const 310 { 311 Addr EA; 312 Fault fault = NoFault; 313 314 %(fp_enable_check)s; 315 %(op_decl)s; 316 %(op_rd)s; 317 %(ea_code)s; 318 319 if (fault == NoFault) { 320 %(memacc_code)s; 321 } 322 323 if (fault == NoFault) { 324 fault = writeMemTiming(xc, traceData, Mem, EA, 325 memAccessFlags, NULL); 326 } 327 328 return fault; 329 } 330}}; 331 332 333def template StoreCompleteAcc {{ 334 Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc, 335 Trace::InstRecord *traceData) const 336 { 337 return NoFault; 338 } 339}}; 340 341 342def template StoreCondCompleteAcc {{ 343 Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc, 344 Trace::InstRecord *traceData) const 345 { 346 Fault fault = NoFault; 347 348 %(fp_enable_check)s; 349 %(op_dest_decl)s; 350 351 uint64_t write_result = pkt->req->getExtraData(); 352 353 if (fault == NoFault) { 354 %(postacc_code)s; 355 } 356 357 if (fault == NoFault) { 358 %(op_wb)s; 359 } 360 361 return fault; 362 } 363}}; 364 365 366def template MiscExecute {{ 367 Fault %(class_name)s::execute(ExecContext *xc, 368 Trace::InstRecord *traceData) const 369 { 370 Addr EA M5_VAR_USED; 371 Fault fault = NoFault; 372 373 %(fp_enable_check)s; 374 %(op_decl)s; 375 %(op_rd)s; 376 %(ea_code)s; 377 378 warn_once("Prefetch instructions in Alpha do not do anything\n"); 379 if (fault == NoFault) { 380 %(memacc_code)s; 381 } 382 383 return NoFault; 384 } 385}}; 386 387// Prefetches in Alpha don't actually do anything 388// They just build an effective address and complete 389def template MiscInitiateAcc {{ 390 Fault %(class_name)s::initiateAcc(ExecContext *xc, 391 Trace::InstRecord *traceData) const 392 { 393 warn("initiateAcc undefined: Misc instruction does not support split " 394 "access method!"); 395 return NoFault; 396 } 397}}; 398 399 400def template MiscCompleteAcc {{ 401 Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc, 402 Trace::InstRecord *traceData) const 403 { 404 warn("completeAcc undefined: Misc instruction does not support split " 405 "access method!"); 406 407 return NoFault; 408 } 409}}; 410 411 412// load instructions use Ra as dest, so check for 413// Ra == 31 to detect nops 414def template LoadNopCheckDecode {{ 415 { 416 AlphaStaticInst *i = new %(class_name)s(machInst); 417 if (RA == 31) { 418 i = makeNop(i); 419 } 420 return i; 421 } 422}}; 423 424 425// for some load instructions, Ra == 31 indicates a prefetch (not a nop) 426def template LoadPrefetchCheckDecode {{ 427 { 428 if (RA != 31) { 429 return new %(class_name)s(machInst); 430 } 431 else { 432 return new %(class_name)sPrefetch(machInst); 433 } 434 } 435}}; 436 437 438let {{ 439def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 440 postacc_code = '', base_class = 'MemoryDisp32', 441 decode_template = BasicDecode, exec_template_base = ''): 442 # Make sure flags are in lists (convert to lists if not). 443 mem_flags = makeList(mem_flags) 444 inst_flags = makeList(inst_flags) 445 446 iop = InstObjParams(name, Name, base_class, 447 { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code }, 448 inst_flags) 449 450 if mem_flags: 451 mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] 452 s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' 453 iop.constructor += s 454 455 # select templates 456 457 # The InitiateAcc template is the same for StoreCond templates as the 458 # corresponding Store template.. 459 StoreCondInitiateAcc = StoreInitiateAcc 460 461 fullExecTemplate = eval(exec_template_base + 'Execute') 462 initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') 463 completeAccTemplate = eval(exec_template_base + 'CompleteAcc') 464 465 # (header_output, decoder_output, decode_block, exec_output) 466 return (LoadStoreDeclare.subst(iop), 467 LoadStoreConstructor.subst(iop), 468 decode_template.subst(iop), 469 fullExecTemplate.subst(iop) 470 + EACompExecute.subst(iop) 471 + initiateAccTemplate.subst(iop) 472 + completeAccTemplate.subst(iop)) 473}}; 474 475def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }}, 476 mem_flags = [], inst_flags = []) {{ 477 (header_output, decoder_output, decode_block, exec_output) = \ 478 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 479 decode_template = LoadNopCheckDecode, 480 exec_template_base = 'Load') 481}}; 482 483 484// Note that the flags passed in apply only to the prefetch version 485def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }}, 486 mem_flags = [], pf_flags = [], inst_flags = []) {{ 487 # declare the load instruction object and generate the decode block 488 (header_output, decoder_output, decode_block, exec_output) = \ 489 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 490 decode_template = LoadPrefetchCheckDecode, 491 exec_template_base = 'Load') 492 493 # Declare the prefetch instruction object. 494 495 # Make sure flag args are lists so we can mess with them. 496 mem_flags = makeList(mem_flags) 497 pf_flags = makeList(pf_flags) 498 inst_flags = makeList(inst_flags) 499 500 pf_mem_flags = mem_flags + pf_flags + ['PREFETCH'] 501 pf_inst_flags = inst_flags 502 503 (pf_header_output, pf_decoder_output, _, pf_exec_output) = \ 504 LoadStoreBase(name, Name + 'Prefetch', ea_code, ';', 505 pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc') 506 507 header_output += pf_header_output 508 decoder_output += pf_decoder_output 509 exec_output += pf_exec_output 510}}; 511 512 513def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }}, 514 mem_flags = [], inst_flags = []) {{ 515 (header_output, decoder_output, decode_block, exec_output) = \ 516 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 517 exec_template_base = 'Store') 518}}; 519 520 521def format StoreCond(memacc_code, postacc_code, 522 ea_code = {{ EA = Rb + disp; }}, 523 mem_flags = [], inst_flags = []) {{ 524 (header_output, decoder_output, decode_block, exec_output) = \ 525 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 526 postacc_code, exec_template_base = 'StoreCond') 527}}; 528 529 530// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb 531def format MiscPrefetch(ea_code, memacc_code, 532 mem_flags = [], inst_flags = []) {{ 533 (header_output, decoder_output, decode_block, exec_output) = \ 534 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 535 base_class = 'MemoryNoDisp', exec_template_base = 'Misc') 536}}; 537 538 539