blockmem.isa revision 3852:b91ce3d7d236
1// Copyright (c) 2006 The Regents of The University of Michigan 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer; 8// redistributions in binary form must reproduce the above copyright 9// notice, this list of conditions and the following disclaimer in the 10// documentation and/or other materials provided with the distribution; 11// neither the name of the copyright holders nor the names of its 12// contributors may be used to endorse or promote products derived from 13// this software without specific prior written permission. 14// 15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26// 27// Authors: Ali Saidi 28// Gabe Black 29 30//////////////////////////////////////////////////////////////////// 31// 32// Block Memory instructions 33// 34 35output header {{ 36 37 class BlockMem : public SparcMacroInst 38 { 39 protected: 40 41 // Constructor 42 // We make the assumption that all block memory operations 43 // Will take 8 instructions to execute 44 BlockMem(const char *mnem, ExtMachInst _machInst) : 45 SparcMacroInst(mnem, _machInst, No_OpClass, 8) 46 {} 47 }; 48 49 class BlockMemImm : public BlockMem 50 { 51 protected: 52 53 // Constructor 54 BlockMemImm(const char *mnem, ExtMachInst _machInst) : 55 BlockMem(mnem, _machInst) 56 {} 57 }; 58 59 class BlockMemMicro : public SparcMicroInst 60 { 61 protected: 62 63 // Constructor 64 BlockMemMicro(const char *mnem, ExtMachInst _machInst, 65 OpClass __opClass, int8_t _offset) : 66 SparcMicroInst(mnem, _machInst, __opClass), 67 offset(_offset) 68 {} 69 70 std::string generateDisassembly(Addr pc, 71 const SymbolTable *symtab) const; 72 73 const int8_t offset; 74 }; 75 76 class BlockMemImmMicro : public BlockMemMicro 77 { 78 protected: 79 80 // Constructor 81 BlockMemImmMicro(const char *mnem, ExtMachInst _machInst, 82 OpClass __opClass, int8_t _offset) : 83 BlockMemMicro(mnem, _machInst, __opClass, _offset), 84 imm(sext<13>(SIMM13)) 85 {} 86 87 std::string generateDisassembly(Addr pc, 88 const SymbolTable *symtab) const; 89 90 const int32_t imm; 91 }; 92}}; 93 94output header {{ 95 96 class TwinMem : public SparcMacroInst 97 { 98 protected: 99 100 // Constructor 101 // We make the assumption that all block memory operations 102 // Will take 8 instructions to execute 103 TwinMem(const char *mnem, ExtMachInst _machInst) : 104 SparcMacroInst(mnem, _machInst, No_OpClass, 8) 105 {} 106 }; 107 108 class TwinMemImm : public BlockMem 109 { 110 protected: 111 112 // Constructor 113 TwinMemImm(const char *mnem, ExtMachInst _machInst) : 114 BlockMem(mnem, _machInst) 115 {} 116 }; 117 118 class TwinMemMicro : public SparcMicroInst 119 { 120 protected: 121 122 // Constructor 123 TwinMemMicro(const char *mnem, ExtMachInst _machInst, 124 OpClass __opClass, int8_t _offset) : 125 SparcMicroInst(mnem, _machInst, __opClass), 126 offset(_offset) 127 {} 128 129 std::string generateDisassembly(Addr pc, 130 const SymbolTable *symtab) const; 131 132 const int8_t offset; 133 }; 134 135 class TwinMemImmMicro : public BlockMemMicro 136 { 137 protected: 138 139 // Constructor 140 TwinMemImmMicro(const char *mnem, ExtMachInst _machInst, 141 OpClass __opClass, int8_t _offset) : 142 BlockMemMicro(mnem, _machInst, __opClass, _offset), 143 imm(sext<13>(SIMM13)) 144 {} 145 146 std::string generateDisassembly(Addr pc, 147 const SymbolTable *symtab) const; 148 149 const int32_t imm; 150 }; 151}}; 152 153output decoder {{ 154 std::string BlockMemMicro::generateDisassembly(Addr pc, 155 const SymbolTable *symtab) const 156 { 157 std::stringstream response; 158 bool load = flags[IsLoad]; 159 bool save = flags[IsStore]; 160 161 printMnemonic(response, mnemonic); 162 if(save) 163 { 164 printReg(response, _srcRegIdx[0]); 165 ccprintf(response, ", "); 166 } 167 ccprintf(response, "[ "); 168 printReg(response, _srcRegIdx[!save ? 0 : 1]); 169 ccprintf(response, " + "); 170 printReg(response, _srcRegIdx[!save ? 1 : 2]); 171 ccprintf(response, " ]"); 172 if(load) 173 { 174 ccprintf(response, ", "); 175 printReg(response, _destRegIdx[0]); 176 } 177 178 return response.str(); 179 } 180 181 std::string BlockMemImmMicro::generateDisassembly(Addr pc, 182 const SymbolTable *symtab) const 183 { 184 std::stringstream response; 185 bool load = flags[IsLoad]; 186 bool save = flags[IsStore]; 187 188 printMnemonic(response, mnemonic); 189 if(save) 190 { 191 printReg(response, _srcRegIdx[1]); 192 ccprintf(response, ", "); 193 } 194 ccprintf(response, "[ "); 195 printReg(response, _srcRegIdx[0]); 196 if(imm >= 0) 197 ccprintf(response, " + 0x%x ]", imm); 198 else 199 ccprintf(response, " + -0x%x ]", -imm); 200 if(load) 201 { 202 ccprintf(response, ", "); 203 printReg(response, _destRegIdx[0]); 204 } 205 206 return response.str(); 207 } 208 209}}; 210 211output decoder {{ 212 std::string TwinMemMicro::generateDisassembly(Addr pc, 213 const SymbolTable *symtab) const 214 { 215 std::stringstream response; 216 bool load = flags[IsLoad]; 217 bool save = flags[IsStore]; 218 219 printMnemonic(response, mnemonic); 220 if(save) 221 { 222 printReg(response, _srcRegIdx[0]); 223 ccprintf(response, ", "); 224 } 225 ccprintf(response, "[ "); 226 printReg(response, _srcRegIdx[!save ? 0 : 1]); 227 ccprintf(response, " + "); 228 printReg(response, _srcRegIdx[!save ? 1 : 2]); 229 ccprintf(response, " ]"); 230 if(load) 231 { 232 ccprintf(response, ", "); 233 printReg(response, _destRegIdx[0]); 234 } 235 236 return response.str(); 237 } 238 239 std::string TwinMemImmMicro::generateDisassembly(Addr pc, 240 const SymbolTable *symtab) const 241 { 242 std::stringstream response; 243 bool load = flags[IsLoad]; 244 bool save = flags[IsStore]; 245 246 printMnemonic(response, mnemonic); 247 if(save) 248 { 249 printReg(response, _srcRegIdx[1]); 250 ccprintf(response, ", "); 251 } 252 ccprintf(response, "[ "); 253 printReg(response, _srcRegIdx[0]); 254 if(imm >= 0) 255 ccprintf(response, " + 0x%x ]", imm); 256 else 257 ccprintf(response, " + -0x%x ]", -imm); 258 if(load) 259 { 260 ccprintf(response, ", "); 261 printReg(response, _destRegIdx[0]); 262 } 263 264 return response.str(); 265 } 266 267}}; 268 269def template BlockMemDeclare {{ 270 /** 271 * Static instruction class for a block memory operation 272 */ 273 class %(class_name)s : public %(base_class)s 274 { 275 public: 276 //Constructor 277 %(class_name)s(ExtMachInst machInst); 278 279 protected: 280 class %(class_name)s_0 : public %(base_class)sMicro 281 { 282 public: 283 //Constructor 284 %(class_name)s_0(ExtMachInst machInst); 285 %(BasicExecDeclare)s 286 %(InitiateAccDeclare)s 287 %(CompleteAccDeclare)s 288 }; 289 290 class %(class_name)s_1 : public %(base_class)sMicro 291 { 292 public: 293 //Constructor 294 %(class_name)s_1(ExtMachInst machInst); 295 %(BasicExecDeclare)s 296 %(InitiateAccDeclare)s 297 %(CompleteAccDeclare)s 298 }; 299 300 class %(class_name)s_2 : public %(base_class)sMicro 301 { 302 public: 303 //Constructor 304 %(class_name)s_2(ExtMachInst machInst); 305 %(BasicExecDeclare)s 306 %(InitiateAccDeclare)s 307 %(CompleteAccDeclare)s 308 }; 309 310 class %(class_name)s_3 : public %(base_class)sMicro 311 { 312 public: 313 //Constructor 314 %(class_name)s_3(ExtMachInst machInst); 315 %(BasicExecDeclare)s 316 %(InitiateAccDeclare)s 317 %(CompleteAccDeclare)s 318 }; 319 320 class %(class_name)s_4 : public %(base_class)sMicro 321 { 322 public: 323 //Constructor 324 %(class_name)s_4(ExtMachInst machInst); 325 %(BasicExecDeclare)s 326 %(InitiateAccDeclare)s 327 %(CompleteAccDeclare)s 328 }; 329 330 class %(class_name)s_5 : public %(base_class)sMicro 331 { 332 public: 333 //Constructor 334 %(class_name)s_5(ExtMachInst machInst); 335 %(BasicExecDeclare)s 336 %(InitiateAccDeclare)s 337 %(CompleteAccDeclare)s 338 }; 339 340 class %(class_name)s_6 : public %(base_class)sMicro 341 { 342 public: 343 //Constructor 344 %(class_name)s_6(ExtMachInst machInst); 345 %(BasicExecDeclare)s 346 %(InitiateAccDeclare)s 347 %(CompleteAccDeclare)s 348 }; 349 350 class %(class_name)s_7 : public %(base_class)sMicro 351 { 352 public: 353 //Constructor 354 %(class_name)s_7(ExtMachInst machInst); 355 %(BasicExecDeclare)s 356 %(InitiateAccDeclare)s 357 %(CompleteAccDeclare)s 358 }; 359 }; 360}}; 361 362def template TwinMemDeclare {{ 363 /** 364 * Static instruction class for a block memory operation 365 */ 366 class %(class_name)s : public %(base_class)s 367 { 368 public: 369 //Constructor 370 %(class_name)s(ExtMachInst machInst); 371 372 protected: 373 class %(class_name)s_0 : public %(base_class)sMicro 374 { 375 public: 376 //Constructor 377 %(class_name)s_0(ExtMachInst machInst); 378 %(BasicExecDeclare)s 379 %(InitiateAccDeclare)s 380 %(CompleteAccDeclare)s 381 }; 382 383 class %(class_name)s_1 : public %(base_class)sMicro 384 { 385 public: 386 //Constructor 387 %(class_name)s_1(ExtMachInst machInst); 388 %(BasicExecDeclare)s 389 %(InitiateAccDeclare)s 390 %(CompleteAccDeclare)s 391 }; 392 }; 393}}; 394 395// Basic instruction class constructor template. 396def template BlockMemConstructor {{ 397 inline %(class_name)s::%(class_name)s(ExtMachInst machInst) 398 : %(base_class)s("%(mnemonic)s", machInst) 399 { 400 %(constructor)s; 401 microOps[0] = new %(class_name)s_0(machInst); 402 microOps[1] = new %(class_name)s_1(machInst); 403 microOps[2] = new %(class_name)s_2(machInst); 404 microOps[3] = new %(class_name)s_3(machInst); 405 microOps[4] = new %(class_name)s_4(machInst); 406 microOps[5] = new %(class_name)s_5(machInst); 407 microOps[6] = new %(class_name)s_6(machInst); 408 microOps[7] = new %(class_name)s_7(machInst); 409 } 410}}; 411 412// Basic instruction class constructor template. 413def template TwinMemConstructor {{ 414 inline %(class_name)s::%(class_name)s(ExtMachInst machInst) 415 : %(base_class)s("%(mnemonic)s", machInst) 416 { 417 %(constructor)s; 418 microOps[0] = new %(class_name)s_0(machInst); 419 microOps[1] = new %(class_name)s_1(machInst); 420 } 421}}; 422 423def template BlockMemMicroConstructor {{ 424 inline %(class_name)s:: 425 %(class_name)s_%(micro_pc)s:: 426 %(class_name)s_%(micro_pc)s(ExtMachInst machInst) : 427 %(base_class)sMicro("%(mnemonic)s[%(micro_pc)s]", 428 machInst, %(op_class)s, %(micro_pc)s * 8) 429 { 430 %(constructor)s; 431 %(set_flags)s; 432 } 433}}; 434 435let {{ 436 437 def doBlockMemFormat(code, faultCode, execute, name, Name, asi, opt_flags): 438 # XXX Need to take care of pstate.hpriv as well. The lower ASIs 439 # are split into ones that are available in priv and hpriv, and 440 # those that are only available in hpriv 441 addrCalcReg = 'EA = Rs1 + Rs2 + offset;' 442 addrCalcImm = 'EA = Rs1 + imm + offset;' 443 iop = InstObjParams(name, Name, 'BlockMem', code, opt_flags) 444 iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', code, opt_flags) 445 header_output = BlockMemDeclare.subst(iop) + BlockMemDeclare.subst(iop_imm) 446 decoder_output = BlockMemConstructor.subst(iop) + BlockMemConstructor.subst(iop_imm) 447 decode_block = ROrImmDecode.subst(iop) 448 matcher = re.compile(r'Frd_N') 449 exec_output = '' 450 for microPc in range(8): 451 flag_code = '' 452 if (microPc == 7): 453 flag_code = "flags[IsLastMicroOp] = true;" 454 else: 455 flag_code = "flags[IsDelayedCommit] = true;" 456 pcedCode = matcher.sub("Frd_%d" % microPc, code) 457 iop = InstObjParams(name, Name, 'BlockMem', pcedCode, 458 opt_flags, {"ea_code": addrCalcReg, 459 "fault_check": faultCode, "micro_pc": microPc, 460 "set_flags": flag_code}) 461 iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', pcedCode, 462 opt_flags, {"ea_code": addrCalcImm, 463 "fault_check": faultCode, "micro_pc": microPc, 464 "set_flags": flag_code}) 465 decoder_output += BlockMemMicroConstructor.subst(iop) 466 decoder_output += BlockMemMicroConstructor.subst(iop_imm) 467 exec_output += doDualSplitExecute( 468 pcedCode, addrCalcReg, addrCalcImm, execute, faultCode, 469 makeMicroName(name, microPc), 470 makeMicroName(name + "Imm", microPc), 471 makeMicroName(Name, microPc), 472 makeMicroName(Name + "Imm", microPc), 473 asi, opt_flags); 474 faultCode = '' 475 return (header_output, decoder_output, exec_output, decode_block) 476 477 478 def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags): 479 addrCalcReg = 'EA = Rs1 + Rs2 + offset;' 480 addrCalcImm = 'EA = Rs1 + imm + offset;' 481 iop = InstObjParams(name, Name, 'TwinMem', code, opt_flags) 482 iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', code, opt_flags) 483 header_output = TwinMemDeclare.subst(iop) + TwinMemDeclare.subst(iop_imm) 484 decoder_output = TwinMemConstructor.subst(iop) + TwinMemConstructor.subst(iop_imm) 485 decode_block = ROrImmDecode.subst(iop) 486 matcher = re.compile(r'RdTwin') 487 exec_output = '' 488 for microPc in range(2): 489 flag_code = '' 490 pcedCode = '' 491 if (microPc == 1): 492 flag_code = "flags[IsLastMicroOp] = true;" 493 pcedCode = matcher.sub("RdHigh", code) 494 else: 495 flag_code = "flags[IsDelayedCommit] = true;" 496 pcedCode = matcher.sub("RdLow", code) 497 iop = InstObjParams(name, Name, 'TwinMem', pcedCode, 498 opt_flags, {"ea_code": addrCalcReg, 499 "fault_check": faultCode, "micro_pc": microPc, 500 "set_flags": flag_code}) 501 iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', pcedCode, 502 opt_flags, {"ea_code": addrCalcImm, 503 "fault_check": faultCode, "micro_pc": microPc, 504 "set_flags": flag_code}) 505 decoder_output += BlockMemMicroConstructor.subst(iop) 506 decoder_output += BlockMemMicroConstructor.subst(iop_imm) 507 exec_output += doDualSplitExecute( 508 pcedCode, addrCalcReg, addrCalcImm, LoadExecute, faultCode, 509 makeMicroName(name, microPc), 510 makeMicroName(name + "Imm", microPc), 511 makeMicroName(Name, microPc), 512 makeMicroName(Name + "Imm", microPc), 513 asi, opt_flags); 514 faultCode = '' 515 return (header_output, decoder_output, exec_output, decode_block) 516 517}}; 518 519def format BlockLoad(code, asi, *opt_flags) {{ 520 # We need to make sure to check the highest priority fault last. 521 # That way, if other faults have been detected, they'll be overwritten 522 # rather than the other way around. 523 faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck 524 (header_output, 525 decoder_output, 526 exec_output, 527 decode_block) = doBlockMemFormat(code, faultCode, 528 LoadExecute, name, Name, asi, opt_flags) 529}}; 530 531def format BlockStore(code, asi, *opt_flags) {{ 532 # We need to make sure to check the highest priority fault last. 533 # That way, if other faults have been detected, they'll be overwritten 534 # rather than the other way around. 535 faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck 536 (header_output, 537 decoder_output, 538 exec_output, 539 decode_block) = doBlockMemFormat(code, faultCode, 540 StoreExecute, name, Name, asi, opt_flags) 541}}; 542 543def format TwinLoad(code, asi, *opt_flags) {{ 544 faultCode = AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck 545 (header_output, 546 decoder_output, 547 exec_output, 548 decode_block) = doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags) 549}}; 550