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