mem.isa revision 2068
16691Stjones1@inf.ed.ac.uk// -*- mode:c++ -*- 26691Stjones1@inf.ed.ac.uk 36691Stjones1@inf.ed.ac.uk// Copyright (c) 2003-2005 The Regents of The University of Michigan 46691Stjones1@inf.ed.ac.uk// All rights reserved. 56691Stjones1@inf.ed.ac.uk// 66691Stjones1@inf.ed.ac.uk// Redistribution and use in source and binary forms, with or without 76691Stjones1@inf.ed.ac.uk// modification, are permitted provided that the following conditions are 86691Stjones1@inf.ed.ac.uk// met: redistributions of source code must retain the above copyright 96691Stjones1@inf.ed.ac.uk// notice, this list of conditions and the following disclaimer; 106691Stjones1@inf.ed.ac.uk// redistributions in binary form must reproduce the above copyright 116691Stjones1@inf.ed.ac.uk// notice, this list of conditions and the following disclaimer in the 126691Stjones1@inf.ed.ac.uk// documentation and/or other materials provided with the distribution; 136691Stjones1@inf.ed.ac.uk// neither the name of the copyright holders nor the names of its 146691Stjones1@inf.ed.ac.uk// contributors may be used to endorse or promote products derived from 156691Stjones1@inf.ed.ac.uk// this software without specific prior written permission. 166691Stjones1@inf.ed.ac.uk// 176691Stjones1@inf.ed.ac.uk// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186691Stjones1@inf.ed.ac.uk// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196691Stjones1@inf.ed.ac.uk// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206691Stjones1@inf.ed.ac.uk// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216691Stjones1@inf.ed.ac.uk// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226691Stjones1@inf.ed.ac.uk// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236691Stjones1@inf.ed.ac.uk// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246691Stjones1@inf.ed.ac.uk// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256691Stjones1@inf.ed.ac.uk// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266691Stjones1@inf.ed.ac.uk// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276691Stjones1@inf.ed.ac.uk// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286691Stjones1@inf.ed.ac.uk 296691Stjones1@inf.ed.ac.ukoutput header {{ 306691Stjones1@inf.ed.ac.uk /** 316691Stjones1@inf.ed.ac.uk * Base class for general Alpha memory-format instructions. 326691Stjones1@inf.ed.ac.uk */ 336691Stjones1@inf.ed.ac.uk class Memory : public AlphaStaticInst 346691Stjones1@inf.ed.ac.uk { 356691Stjones1@inf.ed.ac.uk protected: 366691Stjones1@inf.ed.ac.uk 376691Stjones1@inf.ed.ac.uk /// Memory request flags. See mem_req_base.hh. 386691Stjones1@inf.ed.ac.uk unsigned memAccessFlags; 396691Stjones1@inf.ed.ac.uk /// Pointer to EAComp object. 406691Stjones1@inf.ed.ac.uk const StaticInstPtr<AlphaISA> eaCompPtr; 416691Stjones1@inf.ed.ac.uk /// Pointer to MemAcc object. 426691Stjones1@inf.ed.ac.uk const StaticInstPtr<AlphaISA> memAccPtr; 436691Stjones1@inf.ed.ac.uk 446691Stjones1@inf.ed.ac.uk /// Constructor 456691Stjones1@inf.ed.ac.uk Memory(const char *mnem, MachInst _machInst, OpClass __opClass, 466691Stjones1@inf.ed.ac.uk StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr, 476691Stjones1@inf.ed.ac.uk StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr) 486691Stjones1@inf.ed.ac.uk : AlphaStaticInst(mnem, _machInst, __opClass), 496691Stjones1@inf.ed.ac.uk memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr) 506691Stjones1@inf.ed.ac.uk { 516691Stjones1@inf.ed.ac.uk } 526691Stjones1@inf.ed.ac.uk 536691Stjones1@inf.ed.ac.uk std::string 546691Stjones1@inf.ed.ac.uk generateDisassembly(Addr pc, const SymbolTable *symtab) const; 556691Stjones1@inf.ed.ac.uk 566691Stjones1@inf.ed.ac.uk public: 576691Stjones1@inf.ed.ac.uk 586691Stjones1@inf.ed.ac.uk const StaticInstPtr<AlphaISA> &eaCompInst() const { return eaCompPtr; } 596691Stjones1@inf.ed.ac.uk const StaticInstPtr<AlphaISA> &memAccInst() const { return memAccPtr; } 606691Stjones1@inf.ed.ac.uk }; 616691Stjones1@inf.ed.ac.uk 626691Stjones1@inf.ed.ac.uk /** 636691Stjones1@inf.ed.ac.uk * Base class for memory-format instructions using a 32-bit 646691Stjones1@inf.ed.ac.uk * displacement (i.e. most of them). 656691Stjones1@inf.ed.ac.uk */ 666691Stjones1@inf.ed.ac.uk class MemoryDisp32 : public Memory 676691Stjones1@inf.ed.ac.uk { 686691Stjones1@inf.ed.ac.uk protected: 696691Stjones1@inf.ed.ac.uk /// Displacement for EA calculation (signed). 706691Stjones1@inf.ed.ac.uk int32_t disp; 716691Stjones1@inf.ed.ac.uk 726691Stjones1@inf.ed.ac.uk /// Constructor. 736691Stjones1@inf.ed.ac.uk MemoryDisp32(const char *mnem, MachInst _machInst, OpClass __opClass, 746691Stjones1@inf.ed.ac.uk StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr, 756691Stjones1@inf.ed.ac.uk StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr) 766691Stjones1@inf.ed.ac.uk : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr), 776691Stjones1@inf.ed.ac.uk disp(MEMDISP) 786691Stjones1@inf.ed.ac.uk { 796972Stjones1@inf.ed.ac.uk } 806972Stjones1@inf.ed.ac.uk }; 816972Stjones1@inf.ed.ac.uk 826972Stjones1@inf.ed.ac.uk 836972Stjones1@inf.ed.ac.uk /** 846972Stjones1@inf.ed.ac.uk * Base class for a few miscellaneous memory-format insts 856972Stjones1@inf.ed.ac.uk * that don't interpret the disp field: wh64, fetch, fetch_m, ecb. 866972Stjones1@inf.ed.ac.uk * None of these instructions has a destination register either. 876972Stjones1@inf.ed.ac.uk */ 886972Stjones1@inf.ed.ac.uk class MemoryNoDisp : public Memory 896972Stjones1@inf.ed.ac.uk { 906972Stjones1@inf.ed.ac.uk protected: 916972Stjones1@inf.ed.ac.uk /// Constructor 926972Stjones1@inf.ed.ac.uk MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass, 936972Stjones1@inf.ed.ac.uk StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr, 946972Stjones1@inf.ed.ac.uk StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr) 956691Stjones1@inf.ed.ac.uk : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr) 966691Stjones1@inf.ed.ac.uk { 976691Stjones1@inf.ed.ac.uk } 986691Stjones1@inf.ed.ac.uk 996691Stjones1@inf.ed.ac.uk std::string 1006691Stjones1@inf.ed.ac.uk generateDisassembly(Addr pc, const SymbolTable *symtab) const; 1016691Stjones1@inf.ed.ac.uk }; 1026691Stjones1@inf.ed.ac.uk}}; 1036691Stjones1@inf.ed.ac.uk 104 105output decoder {{ 106 std::string 107 Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const 108 { 109 return csprintf("%-10s %c%d,%d(r%d)", mnemonic, 110 flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB); 111 } 112 113 std::string 114 MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 115 { 116 return csprintf("%-10s (r%d)", mnemonic, RB); 117 } 118}}; 119 120def format LoadAddress(code) {{ 121 iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code)) 122 header_output = BasicDeclare.subst(iop) 123 decoder_output = BasicConstructor.subst(iop) 124 decode_block = BasicDecode.subst(iop) 125 exec_output = BasicExecute.subst(iop) 126}}; 127 128 129def template LoadStoreDeclare {{ 130 /** 131 * Static instruction class for "%(mnemonic)s". 132 */ 133 class %(class_name)s : public %(base_class)s 134 { 135 protected: 136 137 /** 138 * "Fake" effective address computation class for "%(mnemonic)s". 139 */ 140 class EAComp : public %(base_class)s 141 { 142 public: 143 /// Constructor 144 EAComp(MachInst machInst); 145 146 %(BasicExecDeclare)s 147 }; 148 149 /** 150 * "Fake" memory access instruction class for "%(mnemonic)s". 151 */ 152 class MemAcc : public %(base_class)s 153 { 154 public: 155 /// Constructor 156 MemAcc(MachInst machInst); 157 158 %(BasicExecDeclare)s 159 }; 160 161 public: 162 163 /// Constructor. 164 %(class_name)s(MachInst machInst); 165 166 %(BasicExecDeclare)s 167 }; 168}}; 169 170def template LoadStoreConstructor {{ 171 /** TODO: change op_class to AddrGenOp or something (requires 172 * creating new member of OpClass enum in op_class.hh, updating 173 * config files, etc.). */ 174 inline %(class_name)s::EAComp::EAComp(MachInst machInst) 175 : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) 176 { 177 %(ea_constructor)s; 178 } 179 180 inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) 181 : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) 182 { 183 %(memacc_constructor)s; 184 } 185 186 inline %(class_name)s::%(class_name)s(MachInst machInst) 187 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 188 new EAComp(machInst), new MemAcc(machInst)) 189 { 190 %(constructor)s; 191 } 192}}; 193 194 195def template EACompExecute {{ 196 Fault 197 %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, 198 Trace::InstRecord *traceData) const 199 { 200 Addr EA; 201 Fault fault = No_Fault; 202 203 %(fp_enable_check)s; 204 %(op_decl)s; 205 %(op_rd)s; 206 %(code)s; 207 208 if (fault == No_Fault) { 209 %(op_wb)s; 210 xc->setEA(EA); 211 } 212 213 return fault; 214 } 215}}; 216 217def template MemAccExecute {{ 218 Fault 219 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 220 Trace::InstRecord *traceData) const 221 { 222 Addr EA; 223 Fault fault = No_Fault; 224 225 %(fp_enable_check)s; 226 %(op_decl)s; 227 %(op_nonmem_rd)s; 228 EA = xc->getEA(); 229 230 if (fault == No_Fault) { 231 %(op_mem_rd)s; 232 %(code)s; 233 } 234 235 if (fault == No_Fault) { 236 %(op_mem_wb)s; 237 } 238 239 if (fault == No_Fault) { 240 %(postacc_code)s; 241 } 242 243 if (fault == No_Fault) { 244 %(op_nonmem_wb)s; 245 } 246 247 return fault; 248 } 249}}; 250 251 252def template LoadStoreExecute {{ 253 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 254 Trace::InstRecord *traceData) const 255 { 256 Addr EA; 257 Fault fault = No_Fault; 258 259 %(fp_enable_check)s; 260 %(op_decl)s; 261 %(op_nonmem_rd)s; 262 %(ea_code)s; 263 264 if (fault == No_Fault) { 265 %(op_mem_rd)s; 266 %(memacc_code)s; 267 } 268 269 if (fault == No_Fault) { 270 %(op_mem_wb)s; 271 } 272 273 if (fault == No_Fault) { 274 %(postacc_code)s; 275 } 276 277 if (fault == No_Fault) { 278 %(op_nonmem_wb)s; 279 } 280 281 return fault; 282 } 283}}; 284 285 286def template PrefetchExecute {{ 287 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 288 Trace::InstRecord *traceData) const 289 { 290 Addr EA; 291 Fault fault = No_Fault; 292 293 %(fp_enable_check)s; 294 %(op_decl)s; 295 %(op_nonmem_rd)s; 296 %(ea_code)s; 297 298 if (fault == No_Fault) { 299 xc->prefetch(EA, memAccessFlags); 300 } 301 302 return No_Fault; 303 } 304}}; 305 306// load instructions use Ra as dest, so check for 307// Ra == 31 to detect nops 308def template LoadNopCheckDecode {{ 309 { 310 AlphaStaticInst *i = new %(class_name)s(machInst); 311 if (RA == 31) { 312 i = makeNop(i); 313 } 314 return i; 315 } 316}}; 317 318 319// for some load instructions, Ra == 31 indicates a prefetch (not a nop) 320def template LoadPrefetchCheckDecode {{ 321 { 322 if (RA != 31) { 323 return new %(class_name)s(machInst); 324 } 325 else { 326 return new %(class_name)sPrefetch(machInst); 327 } 328 } 329}}; 330 331 332let {{ 333def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '', 334 base_class = 'MemoryDisp32', flags = [], 335 decode_template = BasicDecode, 336 exec_template = LoadStoreExecute): 337 # Segregate flags into instruction flags (handled by InstObjParams) 338 # and memory access flags (handled here). 339 340 # Would be nice to autogenerate this list, but oh well. 341 valid_mem_flags = ['LOCKED', 'NO_FAULT', 'EVICT_NEXT', 'PF_EXCLUSIVE'] 342 mem_flags = [f for f in flags if f in valid_mem_flags] 343 inst_flags = [f for f in flags if f not in valid_mem_flags] 344 345 # add hook to get effective addresses into execution trace output. 346 ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' 347 348 # generate code block objects 349 ea_cblk = CodeBlock(ea_code) 350 memacc_cblk = CodeBlock(memacc_code) 351 postacc_cblk = CodeBlock(postacc_code) 352 353 # Some CPU models execute the memory operation as an atomic unit, 354 # while others want to separate them into an effective address 355 # computation and a memory access operation. As a result, we need 356 # to generate three StaticInst objects. Note that the latter two 357 # are nested inside the larger "atomic" one. 358 359 # generate InstObjParams for EAComp object 360 ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags) 361 362 # generate InstObjParams for MemAcc object 363 memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags) 364 # in the split execution model, the MemAcc portion is responsible 365 # for the post-access code. 366 memacc_iop.postacc_code = postacc_cblk.code 367 368 # generate InstObjParams for unified execution 369 cblk = CodeBlock(ea_code + memacc_code + postacc_code) 370 iop = InstObjParams(name, Name, base_class, cblk, inst_flags) 371 372 iop.ea_constructor = ea_cblk.constructor 373 iop.ea_code = ea_cblk.code 374 iop.memacc_constructor = memacc_cblk.constructor 375 iop.memacc_code = memacc_cblk.code 376 iop.postacc_code = postacc_cblk.code 377 378 if mem_flags: 379 s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' 380 iop.constructor += s 381 memacc_iop.constructor += s 382 383 # (header_output, decoder_output, decode_block, exec_output) 384 return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop), 385 decode_template.subst(iop), 386 EACompExecute.subst(ea_iop) 387 + MemAccExecute.subst(memacc_iop) 388 + exec_template.subst(iop)) 389}}; 390 391 392def format LoadOrNop(ea_code, memacc_code, *flags) {{ 393 (header_output, decoder_output, decode_block, exec_output) = \ 394 LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags, 395 decode_template = LoadNopCheckDecode) 396}}; 397 398 399// Note that the flags passed in apply only to the prefetch version 400def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{ 401 # declare the load instruction object and generate the decode block 402 (header_output, decoder_output, decode_block, exec_output) = \ 403 LoadStoreBase(name, Name, ea_code, memacc_code, 404 decode_template = LoadPrefetchCheckDecode) 405 406 # Declare the prefetch instruction object. 407 408 # convert flags from tuple to list to make them mutable 409 pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp', 'NO_FAULT'] 410 411 (pf_header_output, pf_decoder_output, _, pf_exec_output) = \ 412 LoadStoreBase(name, Name + 'Prefetch', ea_code, '', 413 flags = pf_flags, exec_template = PrefetchExecute) 414 415 header_output += pf_header_output 416 decoder_output += pf_decoder_output 417 exec_output += pf_exec_output 418}}; 419 420 421def format Store(ea_code, memacc_code, *flags) {{ 422 (header_output, decoder_output, decode_block, exec_output) = \ 423 LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags) 424}}; 425 426 427def format StoreCond(ea_code, memacc_code, postacc_code, *flags) {{ 428 (header_output, decoder_output, decode_block, exec_output) = \ 429 LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code, 430 flags = flags) 431}}; 432 433 434// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb 435def format MiscPrefetch(ea_code, memacc_code, *flags) {{ 436 (header_output, decoder_output, decode_block, exec_output) = \ 437 LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags, 438 base_class = 'MemoryNoDisp') 439}}; 440 441 442