blockmem.isa revision 3379
1//////////////////////////////////////////////////////////////////// 2// 3// Block Memory instructions 4// 5 6output header {{ 7 8 class BlockMem : public SparcMacroInst 9 { 10 protected: 11 12 // Constructor 13 // We make the assumption that all block memory operations 14 // Will take 8 instructions to execute 15 BlockMem(const char *mnem, 16 ExtMachInst _machInst, OpClass __opClass) : 17 SparcMacroInst(mnem, _machInst, __opClass, 8) 18 {} 19 }; 20 21 class BlockMemImm : public BlockMem 22 { 23 protected: 24 25 // Constructor 26 BlockMemImm(const char *mnem, 27 ExtMachInst _machInst, OpClass __opClass) : 28 BlockMem(mnem, _machInst, __opClass), 29 imm(sext<13>(SIMM13)) 30 {} 31 32 const int32_t imm; 33 }; 34 35 class BlockMemMicro : public SparcDelayedMicroInst 36 { 37 protected: 38 39 // Constructor 40 BlockMemMicro(const char *mnem, ExtMachInst _machInst, 41 OpClass __opClass, int8_t _offset) : 42 SparcDelayedMicroInst(mnem, _machInst, __opClass), 43 offset(_offset) 44 {} 45 46 std::string generateDisassembly(Addr pc, 47 const SymbolTable *symtab) const; 48 49 const int8_t offset; 50 }; 51 52 class BlockMemImmMicro : public BlockMemMicro 53 { 54 protected: 55 56 // Constructor 57 BlockMemImmMicro(const char *mnem, ExtMachInst _machInst, 58 OpClass __opClass, int8_t _offset) : 59 BlockMemMicro(mnem, _machInst, __opClass, _offset), 60 imm(sext<13>(SIMM13)) 61 {} 62 63 std::string generateDisassembly(Addr pc, 64 const SymbolTable *symtab) const; 65 66 const int32_t imm; 67 }; 68}}; 69 70output decoder {{ 71 std::string BlockMemMicro::generateDisassembly(Addr pc, 72 const SymbolTable *symtab) const 73 { 74 std::stringstream response; 75 bool load = flags[IsLoad]; 76 bool save = flags[IsStore]; 77 78 printMnemonic(response, mnemonic); 79 if(save) 80 { 81 printReg(response, _srcRegIdx[0]); 82 ccprintf(response, ", "); 83 } 84 ccprintf(response, "[ "); 85 printReg(response, _srcRegIdx[!save ? 0 : 1]); 86 ccprintf(response, " + "); 87 printReg(response, _srcRegIdx[!save ? 1 : 2]); 88 ccprintf(response, " ]"); 89 if(load) 90 { 91 ccprintf(response, ", "); 92 printReg(response, _destRegIdx[0]); 93 } 94 95 return response.str(); 96 } 97 98 std::string BlockMemImmMicro::generateDisassembly(Addr pc, 99 const SymbolTable *symtab) const 100 { 101 std::stringstream response; 102 bool load = flags[IsLoad]; 103 bool save = flags[IsStore]; 104 105 printMnemonic(response, mnemonic); 106 if(save) 107 { 108 printReg(response, _srcRegIdx[1]); 109 ccprintf(response, ", "); 110 } 111 ccprintf(response, "[ "); 112 printReg(response, _srcRegIdx[0]); 113 if(imm >= 0) 114 ccprintf(response, " + 0x%x ]", imm); 115 else 116 ccprintf(response, " + -0x%x ]", -imm); 117 if(load) 118 { 119 ccprintf(response, ", "); 120 printReg(response, _destRegIdx[0]); 121 } 122 123 return response.str(); 124 } 125 126}}; 127 128def template LoadStoreExecute {{ 129 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 130 Trace::InstRecord *traceData) const 131 { 132 Fault fault = NoFault; 133 uint64_t write_result = 0; 134 Addr EA; 135 %(op_decl)s; 136 %(op_rd)s; 137 %(priv_check)s; 138 %(ea_code)s; 139 DPRINTF(Sparc, "The address is 0x%x\n", EA); 140 xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); 141 %(code)s; 142 143 if(fault == NoFault) 144 { 145 xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); 146 //Write the resulting state to the execution context 147 %(op_wb)s; 148 } 149 150 return fault; 151 } 152}}; 153 154def template BlockMemDeclare {{ 155 /** 156 * Static instruction class for a block memory operation 157 */ 158 class %(class_name)s : public %(base_class)s 159 { 160 public: 161 //Constructor 162 %(class_name)s(ExtMachInst machInst); 163 164 protected: 165 class %(class_name)s_0 : public %(base_class)sMicro 166 { 167 public: 168 //Constructor 169 %(class_name)s_0(ExtMachInst machInst); 170 %(BasicExecDeclare)s 171 }; 172 173 class %(class_name)s_1 : public %(base_class)sMicro 174 { 175 public: 176 //Constructor 177 %(class_name)s_1(ExtMachInst machInst); 178 %(BasicExecDeclare)s 179 }; 180 181 class %(class_name)s_2 : public %(base_class)sMicro 182 { 183 public: 184 //Constructor 185 %(class_name)s_2(ExtMachInst machInst); 186 %(BasicExecDeclare)s 187 }; 188 189 class %(class_name)s_3 : public %(base_class)sMicro 190 { 191 public: 192 //Constructor 193 %(class_name)s_3(ExtMachInst machInst); 194 %(BasicExecDeclare)s 195 }; 196 197 class %(class_name)s_4 : public %(base_class)sMicro 198 { 199 public: 200 //Constructor 201 %(class_name)s_4(ExtMachInst machInst); 202 %(BasicExecDeclare)s 203 }; 204 205 class %(class_name)s_5 : public %(base_class)sMicro 206 { 207 public: 208 //Constructor 209 %(class_name)s_5(ExtMachInst machInst); 210 %(BasicExecDeclare)s 211 }; 212 213 class %(class_name)s_6 : public %(base_class)sMicro 214 { 215 public: 216 //Constructor 217 %(class_name)s_6(ExtMachInst machInst); 218 %(BasicExecDeclare)s 219 }; 220 221 class %(class_name)s_7 : public %(base_class)sMicro 222 { 223 public: 224 //Constructor 225 %(class_name)s_7(ExtMachInst machInst); 226 %(BasicExecDeclare)s 227 }; 228 }; 229}}; 230 231// Basic instruction class constructor template. 232def template BlockMemConstructor {{ 233 inline %(class_name)s::%(class_name)s(ExtMachInst machInst) 234 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 235 { 236 %(constructor)s; 237 microOps[0] = new %(class_name)s_0(machInst); 238 microOps[1] = new %(class_name)s_1(machInst); 239 microOps[2] = new %(class_name)s_2(machInst); 240 microOps[3] = new %(class_name)s_3(machInst); 241 microOps[4] = new %(class_name)s_4(machInst); 242 microOps[5] = new %(class_name)s_5(machInst); 243 microOps[6] = new %(class_name)s_6(machInst); 244 microOps[7] = new %(class_name)s_7(machInst); 245 } 246}}; 247 248def template BlockMemMicroConstructor {{ 249 inline %(class_name)s:: 250 %(class_name)s_%(micro_pc)s:: 251 %(class_name)s_%(micro_pc)s(ExtMachInst machInst) : 252 %(base_class)sMicro("%(mnemonic)s[%(micro_pc)s]", 253 machInst, %(op_class)s, %(micro_pc)s * 8) 254 { 255 %(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