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