blockmem.isa revision 3274
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 std::string generateDisassembly(Addr pc, 21 const SymbolTable *symtab) const; 22 }; 23 24 class BlockMemImm : public BlockMem 25 { 26 protected: 27 28 // Constructor 29 BlockMemImm(const char *mnem, 30 ExtMachInst _machInst, OpClass __opClass) : 31 BlockMem(mnem, _machInst, __opClass), 32 imm(sext<13>(SIMM13)) 33 {} 34 35 std::string generateDisassembly(Addr pc, 36 const SymbolTable *symtab) const; 37 38 const int32_t imm; 39 }; 40 41 class BlockMemMicro : public SparcDelayedMicroInst 42 { 43 protected: 44 45 // Constructor 46 BlockMemMicro(const char *mnem, ExtMachInst _machInst, 47 OpClass __opClass, int8_t _offset) : 48 SparcDelayedMicroInst(mnem, _machInst, __opClass), 49 offset(_offset) 50 {} 51 52 std::string generateDisassembly(Addr pc, 53 const SymbolTable *symtab) const; 54 55 const int8_t offset; 56 }; 57 58 class BlockMemImmMicro : public BlockMemMicro 59 { 60 protected: 61 62 // Constructor 63 BlockMemImmMicro(const char *mnem, ExtMachInst _machInst, 64 OpClass __opClass, int8_t _offset) : 65 BlockMemMicro(mnem, _machInst, __opClass, _offset), 66 imm(sext<13>(SIMM13)) 67 {} 68 69 std::string generateDisassembly(Addr pc, 70 const SymbolTable *symtab) const; 71 72 const int32_t imm; 73 }; 74}}; 75 76output decoder {{ 77 std::string BlockMem::generateDisassembly(Addr pc, 78 const SymbolTable *symtab) const 79 { 80 std::stringstream response; 81 bool load = flags[IsLoad]; 82 bool save = flags[IsStore]; 83 84 printMnemonic(response, mnemonic); 85 if(save) 86 { 87 printReg(response, _srcRegIdx[0]); 88 ccprintf(response, ", "); 89 } 90 ccprintf(response, "[ "); 91 printReg(response, _srcRegIdx[!save ? 0 : 1]); 92 ccprintf(response, " + "); 93 printReg(response, _srcRegIdx[!save ? 1 : 2]); 94 ccprintf(response, " ]"); 95 if(load) 96 { 97 ccprintf(response, ", "); 98 printReg(response, _destRegIdx[0]); 99 } 100 101 return response.str(); 102 } 103 104 std::string BlockMemImm::generateDisassembly(Addr pc, 105 const SymbolTable *symtab) const 106 { 107 std::stringstream response; 108 bool load = flags[IsLoad]; 109 bool save = flags[IsStore]; 110 111 printMnemonic(response, mnemonic); 112 if(save) 113 { 114 printReg(response, _srcRegIdx[0]); 115 ccprintf(response, ", "); 116 } 117 ccprintf(response, "[ "); 118 printReg(response, _srcRegIdx[!save ? 0 : 1]); 119 if(imm >= 0) 120 ccprintf(response, " + 0x%x ]", imm); 121 else 122 ccprintf(response, " + -0x%x ]", -imm); 123 if(load) 124 { 125 ccprintf(response, ", "); 126 printReg(response, _destRegIdx[0]); 127 } 128 129 return response.str(); 130 } 131 132}}; 133 134def template LoadStoreExecute {{ 135 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 136 Trace::InstRecord *traceData) const 137 { 138 Fault fault = NoFault; 139 uint64_t write_result = 0; 140 Addr EA; 141 %(op_decl)s; 142 %(op_rd)s; 143 %(priv_check)s; 144 %(ea_code)s; 145 DPRINTF(Sparc, "The address is 0x%x\n", EA); 146 xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); 147 %(code)s; 148 149 if(fault == NoFault) 150 { 151 xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); 152 //Write the resulting state to the execution context 153 %(op_wb)s; 154 } 155 156 return fault; 157 } 158}}; 159 160def template BlockMemDeclare {{ 161 /** 162 * Static instruction class for a block memory operation 163 */ 164 class %(class_name)s : public %(base_class)s 165 { 166 public: 167 //Constructor 168 %(class_name)s(MachInst machInst); 169 170 protected: 171 class %(class_name)s_0 : public %(base_class)sMicro 172 { 173 public: 174 //Constructor 175 %(class_name)s_0(MachInst machInst) : 176 %(base_class)sMicro("%(mnemonic)s[0]", 177 machInst, %(op_class)s, 0*8) 178 {;} 179 %(BasicExecDeclare)s 180 }; 181 182 class %(class_name)s_1 : public %(base_class)sMicro 183 { 184 public: 185 //Constructor 186 %(class_name)s_1(MachInst machInst) : 187 %(base_class)sMicro("%(mnemonic)s[1]", 188 machInst, %(op_class)s, 1*8) 189 {;} 190 %(BasicExecDeclare)s 191 }; 192 193 class %(class_name)s_2 : public %(base_class)sMicro 194 { 195 public: 196 //Constructor 197 %(class_name)s_2(MachInst machInst) : 198 %(base_class)sMicro("%(mnemonic)s[2]", 199 machInst, %(op_class)s, 2*8) 200 {;} 201 %(BasicExecDeclare)s 202 }; 203 204 class %(class_name)s_3 : public %(base_class)sMicro 205 { 206 public: 207 //Constructor 208 %(class_name)s_3(MachInst machInst) : 209 %(base_class)sMicro("%(mnemonic)s[3]", 210 machInst, %(op_class)s, 3*8) 211 {;} 212 %(BasicExecDeclare)s 213 }; 214 215 class %(class_name)s_4 : public %(base_class)sMicro 216 { 217 public: 218 //Constructor 219 %(class_name)s_4(MachInst machInst) : 220 %(base_class)sMicro("%(mnemonic)s[4]", 221 machInst, %(op_class)s, 4*8) 222 {;} 223 %(BasicExecDeclare)s 224 }; 225 226 class %(class_name)s_5 : public %(base_class)sMicro 227 { 228 public: 229 //Constructor 230 %(class_name)s_5(MachInst machInst) : 231 %(base_class)sMicro("%(mnemonic)s[5]", 232 machInst, %(op_class)s, 5*8) 233 {;} 234 %(BasicExecDeclare)s 235 }; 236 237 class %(class_name)s_6 : public %(base_class)sMicro 238 { 239 public: 240 //Constructor 241 %(class_name)s_6(MachInst machInst) : 242 %(base_class)sMicro("%(mnemonic)s[6]", 243 machInst, %(op_class)s, 6*8) 244 {;} 245 %(BasicExecDeclare)s 246 }; 247 248 class %(class_name)s_7 : public %(base_class)sMicro 249 { 250 public: 251 //Constructor 252 %(class_name)s_7(MachInst machInst) : 253 %(base_class)sMicro("%(mnemonic)s[7]", 254 machInst, %(op_class)s, 7*8) 255 { 256 flags[IsLastMicroOp] = true; 257 } 258 %(BasicExecDeclare)s 259 }; 260 }; 261}}; 262 263// Basic instruction class constructor template. 264def template BlockMemConstructor {{ 265 inline %(class_name)s::%(class_name)s(MachInst machInst) 266 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 267 { 268 %(constructor)s; 269 microOps[0] = new %(class_name)s_0(machInst); 270 microOps[1] = new %(class_name)s_1(machInst); 271 microOps[2] = new %(class_name)s_2(machInst); 272 microOps[3] = new %(class_name)s_3(machInst); 273 microOps[4] = new %(class_name)s_4(machInst); 274 microOps[5] = new %(class_name)s_5(machInst); 275 microOps[6] = new %(class_name)s_6(machInst); 276 microOps[7] = new %(class_name)s_7(machInst); 277 } 278}}; 279 280def template MicroLoadExecute {{ 281 Fault %(class_name)s_%(micro_pc)s::execute(%(CPU_exec_context)s *xc, 282 Trace::InstRecord *traceData) const 283 { 284 Fault fault = NoFault; 285 Addr EA; 286 %(op_decl)s; 287 %(op_rd)s; 288 %(fault_check)s; 289 %(ea_code)s; 290 DPRINTF(Sparc, "The address is 0x%x\n", EA); 291 xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); 292 %(code)s; 293 294 if(fault == NoFault) 295 { 296 //Write the resulting state to the execution context 297 %(op_wb)s; 298 } 299 300 return fault; 301 } 302}}; 303 304def template MicroStoreExecute {{ 305 Fault %(class_name)s_%(micro_pc)s::execute(%(CPU_exec_context)s *xc, 306 Trace::InstRecord *traceData) const 307 { 308 Fault fault = NoFault; 309 uint64_t write_result = 0; 310 Addr EA; 311 %(op_decl)s; 312 %(op_rd)s; 313 %(fault_check)s; 314 %(ea_code)s; 315 DPRINTF(Sparc, "The address is 0x%x\n", EA); 316 %(code)s; 317 318 if(fault == NoFault) 319 { 320 xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); 321 //Write the resulting state to the execution context 322 %(op_wb)s; 323 } 324 325 return fault; 326 } 327}}; 328 329let {{ 330 331 def doBlockMemFormat(code, execute, name, Name, opt_flags): 332 # XXX Need to take care of pstate.hpriv as well. The lower ASIs 333 # are split into ones that are available in priv and hpriv, and 334 # those that are only available in hpriv 335 faultCheck = '''if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0) 336 return new PrivilegedAction; 337 if(AsiIsAsIfUser(EXT_ASI) && !bits(Pstate,2,2)) 338 return new PrivilegedAction; 339 if(RD & 0xf) 340 return new IllegalInstruction; 341 if(EA & 0x3f) 342 return new MemAddressNotAligned;''' 343 addrCalcReg = 'EA = Rs1 + Rs2 + offset;' 344 addrCalcImm = 'EA = Rs1 + imm + offset;' 345 iop = InstObjParams(name, Name, 'BlockMem', code, opt_flags) 346 iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', code, opt_flags) 347 header_output = BlockMemDeclare.subst(iop) + BlockMemDeclare.subst(iop_imm) 348 decoder_output = BlockMemConstructor.subst(iop) + BlockMemConstructor.subst(iop_imm) 349 decode_block = ROrImmDecode.subst(iop) 350 matcher = re.compile(r'Frd_N') 351 exec_output = '' 352 for microPC in range(8): 353 pcedCode = matcher.sub("Frd_%d" % microPC, code) 354 iop = InstObjParams(name, Name, 'BlockMem', pcedCode, 355 opt_flags, {"ea_code": addrCalcReg, 356 "fault_check": faultCheck, "micro_pc": microPC}) 357 iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', pcedCode, 358 opt_flags, {"ea_code": addrCalcImm, 359 "fault_check": faultCheck, "micro_pc": microPC}) 360 exec_output += execute.subst(iop) 361 exec_output += execute.subst(iop_imm) 362 faultCheck = '' 363 return (header_output, decoder_output, exec_output, decode_block) 364}}; 365 366def format BlockLoad(code, *opt_flags) {{ 367 (header_output, 368 decoder_output, 369 exec_output, 370 decode_block) = doBlockMemFormat(code, MicroLoadExecute, 371 name, Name, opt_flags) 372}}; 373 374def format BlockStore(code, *opt_flags) {{ 375 (header_output, 376 decoder_output, 377 exec_output, 378 decode_block) = doBlockMemFormat(code, MicroStoreExecute, 379 name, Name, opt_flags) 380}}; 381