blockmem.isa revision 3379
16145Snate@binkert.org//////////////////////////////////////////////////////////////////// 26145Snate@binkert.org// 36145Snate@binkert.org// Block Memory instructions 46145Snate@binkert.org// 56145Snate@binkert.org 66145Snate@binkert.orgoutput header {{ 76145Snate@binkert.org 86145Snate@binkert.org class BlockMem : public SparcMacroInst 96145Snate@binkert.org { 106145Snate@binkert.org protected: 116145Snate@binkert.org 126145Snate@binkert.org // Constructor 136145Snate@binkert.org // We make the assumption that all block memory operations 146145Snate@binkert.org // Will take 8 instructions to execute 156145Snate@binkert.org BlockMem(const char *mnem, 166145Snate@binkert.org ExtMachInst _machInst, OpClass __opClass) : 176145Snate@binkert.org SparcMacroInst(mnem, _machInst, __opClass, 8) 186145Snate@binkert.org {} 196145Snate@binkert.org }; 206145Snate@binkert.org 216145Snate@binkert.org class BlockMemImm : public BlockMem 226145Snate@binkert.org { 236145Snate@binkert.org protected: 246145Snate@binkert.org 256145Snate@binkert.org // Constructor 266145Snate@binkert.org BlockMemImm(const char *mnem, 276145Snate@binkert.org ExtMachInst _machInst, OpClass __opClass) : 286154Snate@binkert.org BlockMem(mnem, _machInst, __opClass), 296154Snate@binkert.org imm(sext<13>(SIMM13)) 306154Snate@binkert.org {} 316154Snate@binkert.org 326145Snate@binkert.org const int32_t imm; 336145Snate@binkert.org }; 346145Snate@binkert.org 356145Snate@binkert.org class BlockMemMicro : public SparcDelayedMicroInst 366145Snate@binkert.org { 376145Snate@binkert.org protected: 386145Snate@binkert.org 396145Snate@binkert.org // Constructor 406145Snate@binkert.org BlockMemMicro(const char *mnem, ExtMachInst _machInst, 416145Snate@binkert.org OpClass __opClass, int8_t _offset) : 426145Snate@binkert.org SparcDelayedMicroInst(mnem, _machInst, __opClass), 436145Snate@binkert.org offset(_offset) 446145Snate@binkert.org {} 456145Snate@binkert.org 466145Snate@binkert.org std::string generateDisassembly(Addr pc, 476145Snate@binkert.org const SymbolTable *symtab) const; 486145Snate@binkert.org 496145Snate@binkert.org const int8_t offset; 506145Snate@binkert.org }; 516145Snate@binkert.org 526145Snate@binkert.org class BlockMemImmMicro : public BlockMemMicro 536145Snate@binkert.org { 546145Snate@binkert.org protected: 556145Snate@binkert.org 566145Snate@binkert.org // Constructor 576145Snate@binkert.org BlockMemImmMicro(const char *mnem, ExtMachInst _machInst, 586145Snate@binkert.org OpClass __opClass, int8_t _offset) : 596145Snate@binkert.org BlockMemMicro(mnem, _machInst, __opClass, _offset), 606145Snate@binkert.org imm(sext<13>(SIMM13)) 616145Snate@binkert.org {} 626145Snate@binkert.org 636145Snate@binkert.org std::string generateDisassembly(Addr pc, 646145Snate@binkert.org const SymbolTable *symtab) const; 656145Snate@binkert.org 666145Snate@binkert.org const int32_t imm; 676145Snate@binkert.org }; 686145Snate@binkert.org}}; 696145Snate@binkert.org 706145Snate@binkert.orgoutput decoder {{ 716145Snate@binkert.org std::string BlockMemMicro::generateDisassembly(Addr pc, 726145Snate@binkert.org const SymbolTable *symtab) const 736145Snate@binkert.org { 746145Snate@binkert.org std::stringstream response; 756145Snate@binkert.org bool load = flags[IsLoad]; 766145Snate@binkert.org bool save = flags[IsStore]; 776145Snate@binkert.org 786145Snate@binkert.org printMnemonic(response, mnemonic); 796145Snate@binkert.org if(save) 806145Snate@binkert.org { 816145Snate@binkert.org printReg(response, _srcRegIdx[0]); 826145Snate@binkert.org ccprintf(response, ", "); 836145Snate@binkert.org } 846145Snate@binkert.org ccprintf(response, "[ "); 856145Snate@binkert.org printReg(response, _srcRegIdx[!save ? 0 : 1]); 866145Snate@binkert.org ccprintf(response, " + "); 876145Snate@binkert.org printReg(response, _srcRegIdx[!save ? 1 : 2]); 886145Snate@binkert.org ccprintf(response, " ]"); 896145Snate@binkert.org if(load) 906145Snate@binkert.org { 916145Snate@binkert.org ccprintf(response, ", "); 926145Snate@binkert.org printReg(response, _destRegIdx[0]); 936145Snate@binkert.org } 946145Snate@binkert.org 956145Snate@binkert.org return response.str(); 966145Snate@binkert.org } 976145Snate@binkert.org 986145Snate@binkert.org std::string BlockMemImmMicro::generateDisassembly(Addr pc, 996145Snate@binkert.org const SymbolTable *symtab) const 1006145Snate@binkert.org { 1016145Snate@binkert.org std::stringstream response; 1026145Snate@binkert.org bool load = flags[IsLoad]; 1036145Snate@binkert.org bool save = flags[IsStore]; 1046145Snate@binkert.org 1056145Snate@binkert.org printMnemonic(response, mnemonic); 1066145Snate@binkert.org if(save) 1076145Snate@binkert.org { 1086145Snate@binkert.org printReg(response, _srcRegIdx[1]); 1096145Snate@binkert.org ccprintf(response, ", "); 1106145Snate@binkert.org } 1116145Snate@binkert.org ccprintf(response, "[ "); 1126145Snate@binkert.org printReg(response, _srcRegIdx[0]); 1136145Snate@binkert.org if(imm >= 0) 1146145Snate@binkert.org ccprintf(response, " + 0x%x ]", imm); 1156145Snate@binkert.org else 1166145Snate@binkert.org ccprintf(response, " + -0x%x ]", -imm); 1176145Snate@binkert.org if(load) 1186145Snate@binkert.org { 1196145Snate@binkert.org ccprintf(response, ", "); 1206145Snate@binkert.org printReg(response, _destRegIdx[0]); 1216145Snate@binkert.org } 1226145Snate@binkert.org 1236145Snate@binkert.org return response.str(); 1246145Snate@binkert.org } 1256145Snate@binkert.org 1266145Snate@binkert.org}}; 1276145Snate@binkert.org 1286145Snate@binkert.orgdef template LoadStoreExecute {{ 1296145Snate@binkert.org Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 1306145Snate@binkert.org Trace::InstRecord *traceData) const 1316145Snate@binkert.org { 1326145Snate@binkert.org Fault fault = NoFault; 1336145Snate@binkert.org uint64_t write_result = 0; 1346145Snate@binkert.org Addr EA; 1356145Snate@binkert.org %(op_decl)s; 1366145Snate@binkert.org %(op_rd)s; 1376145Snate@binkert.org %(priv_check)s; 1386145Snate@binkert.org %(ea_code)s; 1396145Snate@binkert.org DPRINTF(Sparc, "The address is 0x%x\n", EA); 1406145Snate@binkert.org xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); 1416145Snate@binkert.org %(code)s; 1426145Snate@binkert.org 1436145Snate@binkert.org if(fault == NoFault) 1446145Snate@binkert.org { 1456145Snate@binkert.org xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); 1466145Snate@binkert.org //Write the resulting state to the execution context 1476145Snate@binkert.org %(op_wb)s; 1486145Snate@binkert.org } 1496145Snate@binkert.org 1506145Snate@binkert.org return fault; 1516145Snate@binkert.org } 1526145Snate@binkert.org}}; 1536145Snate@binkert.org 1546145Snate@binkert.orgdef template BlockMemDeclare {{ 1556145Snate@binkert.org /** 1566145Snate@binkert.org * Static instruction class for a block memory operation 1576145Snate@binkert.org */ 1586145Snate@binkert.org class %(class_name)s : public %(base_class)s 1596145Snate@binkert.org { 1606145Snate@binkert.org public: 1616145Snate@binkert.org //Constructor 1626145Snate@binkert.org %(class_name)s(ExtMachInst machInst); 1636145Snate@binkert.org 1646145Snate@binkert.org protected: 1656145Snate@binkert.org class %(class_name)s_0 : public %(base_class)sMicro 1666145Snate@binkert.org { 1676145Snate@binkert.org public: 1686145Snate@binkert.org //Constructor 1696145Snate@binkert.org %(class_name)s_0(ExtMachInst machInst); 1706145Snate@binkert.org %(BasicExecDeclare)s 1716145Snate@binkert.org }; 1726145Snate@binkert.org 1736145Snate@binkert.org class %(class_name)s_1 : public %(base_class)sMicro 1746145Snate@binkert.org { 1756145Snate@binkert.org public: 1766145Snate@binkert.org //Constructor 1776145Snate@binkert.org %(class_name)s_1(ExtMachInst machInst); 1786145Snate@binkert.org %(BasicExecDeclare)s 1796145Snate@binkert.org }; 1806145Snate@binkert.org 1816145Snate@binkert.org class %(class_name)s_2 : public %(base_class)sMicro 1826145Snate@binkert.org { 1836145Snate@binkert.org public: 1846145Snate@binkert.org //Constructor 1856145Snate@binkert.org %(class_name)s_2(ExtMachInst machInst); 1866145Snate@binkert.org %(BasicExecDeclare)s 1876145Snate@binkert.org }; 1886145Snate@binkert.org 1896145Snate@binkert.org class %(class_name)s_3 : public %(base_class)sMicro 1906145Snate@binkert.org { 1916145Snate@binkert.org public: 1926145Snate@binkert.org //Constructor 1936145Snate@binkert.org %(class_name)s_3(ExtMachInst machInst); 1946145Snate@binkert.org %(BasicExecDeclare)s 1956145Snate@binkert.org }; 1966145Snate@binkert.org 1976145Snate@binkert.org class %(class_name)s_4 : public %(base_class)sMicro 1986145Snate@binkert.org { 1996145Snate@binkert.org public: 2006145Snate@binkert.org //Constructor 2016145Snate@binkert.org %(class_name)s_4(ExtMachInst machInst); 2026145Snate@binkert.org %(BasicExecDeclare)s 2036145Snate@binkert.org }; 2046145Snate@binkert.org 2056145Snate@binkert.org class %(class_name)s_5 : public %(base_class)sMicro 2066145Snate@binkert.org { 2076145Snate@binkert.org public: 2086145Snate@binkert.org //Constructor 2096145Snate@binkert.org %(class_name)s_5(ExtMachInst machInst); 2106145Snate@binkert.org %(BasicExecDeclare)s 2116145Snate@binkert.org }; 2126145Snate@binkert.org 2136145Snate@binkert.org class %(class_name)s_6 : public %(base_class)sMicro 2146145Snate@binkert.org { 2156145Snate@binkert.org public: 2166145Snate@binkert.org //Constructor 2176145Snate@binkert.org %(class_name)s_6(ExtMachInst machInst); 2186145Snate@binkert.org %(BasicExecDeclare)s 2196145Snate@binkert.org }; 2206145Snate@binkert.org 2216145Snate@binkert.org class %(class_name)s_7 : public %(base_class)sMicro 2226145Snate@binkert.org { 2236145Snate@binkert.org public: 2246145Snate@binkert.org //Constructor 2256145Snate@binkert.org %(class_name)s_7(ExtMachInst machInst); 2266145Snate@binkert.org %(BasicExecDeclare)s 2276145Snate@binkert.org }; 2286145Snate@binkert.org }; 2296145Snate@binkert.org}}; 2306145Snate@binkert.org 2316145Snate@binkert.org// Basic instruction class constructor template. 2326145Snate@binkert.orgdef template BlockMemConstructor {{ 2336145Snate@binkert.org inline %(class_name)s::%(class_name)s(ExtMachInst machInst) 2346145Snate@binkert.org : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 2356145Snate@binkert.org { 2366145Snate@binkert.org %(constructor)s; 2376145Snate@binkert.org microOps[0] = new %(class_name)s_0(machInst); 2386145Snate@binkert.org microOps[1] = new %(class_name)s_1(machInst); 2396145Snate@binkert.org microOps[2] = new %(class_name)s_2(machInst); 2406145Snate@binkert.org microOps[3] = new %(class_name)s_3(machInst); 2416145Snate@binkert.org microOps[4] = new %(class_name)s_4(machInst); 2426145Snate@binkert.org microOps[5] = new %(class_name)s_5(machInst); 2436145Snate@binkert.org microOps[6] = new %(class_name)s_6(machInst); 2446145Snate@binkert.org microOps[7] = new %(class_name)s_7(machInst); 2456145Snate@binkert.org } 2466145Snate@binkert.org}}; 2476145Snate@binkert.org 2486145Snate@binkert.orgdef template BlockMemMicroConstructor {{ 2496145Snate@binkert.org inline %(class_name)s:: 2506145Snate@binkert.org %(class_name)s_%(micro_pc)s:: 2516145Snate@binkert.org %(class_name)s_%(micro_pc)s(ExtMachInst machInst) : 2526145Snate@binkert.org %(base_class)sMicro("%(mnemonic)s[%(micro_pc)s]", 2536145Snate@binkert.org machInst, %(op_class)s, %(micro_pc)s * 8) 2546145Snate@binkert.org { 2556145Snate@binkert.org %(constructor)s; 256 %(set_flags)s; 257 } 258}}; 259 260def template MicroLoadExecute {{ 261 Fault %(class_name)s::%(class_name)s_%(micro_pc)s::execute( 262 %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const 263 { 264 Fault fault = NoFault; 265 Addr EA; 266 %(op_decl)s; 267 %(op_rd)s; 268 %(ea_code)s; 269 %(fault_check)s; 270 DPRINTF(Sparc, "The address is 0x%x\n", EA); 271 xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); 272 %(code)s; 273 274 if(fault == NoFault) 275 { 276 //Write the resulting state to the execution context 277 %(op_wb)s; 278 } 279 280 return fault; 281 } 282}}; 283 284def template MicroStoreExecute {{ 285 Fault %(class_name)s::%(class_name)s_%(micro_pc)s::execute( 286 %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const 287 { 288 Fault fault = NoFault; 289 uint64_t write_result = 0; 290 Addr EA; 291 %(op_decl)s; 292 %(op_rd)s; 293 %(ea_code)s; 294 %(fault_check)s; 295 DPRINTF(Sparc, "The address is 0x%x\n", EA); 296 %(code)s; 297 298 if(fault == NoFault) 299 { 300 xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); 301 //Write the resulting state to the execution context 302 %(op_wb)s; 303 } 304 305 return fault; 306 } 307}}; 308 309let {{ 310 311 def doBlockMemFormat(code, execute, name, Name, opt_flags): 312 # XXX Need to take care of pstate.hpriv as well. The lower ASIs 313 # are split into ones that are available in priv and hpriv, and 314 # those that are only available in hpriv 315 faultCheck = '''if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0) 316 return new PrivilegedAction; 317 if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2)) 318 return new PrivilegedAction; 319 //The LSB can be zero, since it's really the MSB in doubles 320 //and quads 321 if(RD & 0xe) 322 return new IllegalInstruction; 323 if(EA & 0x3f) 324 return new MemAddressNotAligned; 325 ''' 326 addrCalcReg = 'EA = Rs1 + Rs2 + offset;' 327 addrCalcImm = 'EA = Rs1 + imm + offset;' 328 iop = InstObjParams(name, Name, 'BlockMem', code, opt_flags) 329 iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', code, opt_flags) 330 header_output = BlockMemDeclare.subst(iop) + BlockMemDeclare.subst(iop_imm) 331 decoder_output = BlockMemConstructor.subst(iop) + BlockMemConstructor.subst(iop_imm) 332 decode_block = ROrImmDecode.subst(iop) 333 matcher = re.compile(r'Frd_N') 334 exec_output = '' 335 for microPC in range(8): 336 flag_code = '' 337 if (microPC == 7): 338 flag_code = "flags[IsLastMicroOp] = true" 339 pcedCode = matcher.sub("Frd_%d" % microPC, code) 340 iop = InstObjParams(name, Name, 'BlockMem', pcedCode, 341 opt_flags, {"ea_code": addrCalcReg, 342 "fault_check": faultCheck, "micro_pc": microPC, 343 "set_flags": flag_code}) 344 iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', pcedCode, 345 opt_flags, {"ea_code": addrCalcImm, 346 "fault_check": faultCheck, "micro_pc": microPC, 347 "set_flags": flag_code}) 348 exec_output += execute.subst(iop) 349 exec_output += execute.subst(iop_imm) 350 decoder_output += BlockMemMicroConstructor.subst(iop) 351 decoder_output += BlockMemMicroConstructor.subst(iop_imm) 352 faultCheck = '' 353 return (header_output, decoder_output, exec_output, decode_block) 354}}; 355 356def format BlockLoad(code, *opt_flags) {{ 357 (header_output, 358 decoder_output, 359 exec_output, 360 decode_block) = doBlockMemFormat(code, MicroLoadExecute, 361 name, Name, opt_flags) 362}}; 363 364def format BlockStore(code, *opt_flags) {{ 365 (header_output, 366 decoder_output, 367 exec_output, 368 decode_block) = doBlockMemFormat(code, MicroStoreExecute, 369 name, Name, opt_flags) 370}}; 371