regop.isa revision 4679:0b39fa8f5eb8
1// Copyright (c) 2007 The Hewlett-Packard Development Company 2// All rights reserved. 3// 4// Redistribution and use of this software in source and binary forms, 5// with or without modification, are permitted provided that the 6// following conditions are met: 7// 8// The software must be used only for Non-Commercial Use which means any 9// use which is NOT directed to receiving any direct monetary 10// compensation for, or commercial advantage from such use. Illustrative 11// examples of non-commercial use are academic research, personal study, 12// teaching, education and corporate research & development. 13// Illustrative examples of commercial use are distributing products for 14// commercial advantage and providing services using the software for 15// commercial advantage. 16// 17// If you wish to use this software or functionality therein that may be 18// covered by patents for commercial use, please contact: 19// Director of Intellectual Property Licensing 20// Office of Strategy and Technology 21// Hewlett-Packard Company 22// 1501 Page Mill Road 23// Palo Alto, California 94304 24// 25// Redistributions of source code must retain the above copyright notice, 26// this list of conditions and the following disclaimer. Redistributions 27// in binary form must reproduce the above copyright notice, this list of 28// conditions and the following disclaimer in the documentation and/or 29// other materials provided with the distribution. Neither the name of 30// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its 31// contributors may be used to endorse or promote products derived from 32// this software without specific prior written permission. No right of 33// sublicense is granted herewith. Derivatives of the software and 34// output created using the software may be prepared, but only for 35// Non-Commercial Uses. Derivatives of the software may be shared with 36// others provided: (i) the others agree to abide by the list of 37// conditions herein which includes the Non-Commercial Use restrictions; 38// and (ii) such Derivatives of the software include the above copyright 39// notice to acknowledge the contribution from this software where 40// applicable, this list of conditions and the disclaimer below. 41// 42// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 43// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 44// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 45// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 46// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 47// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 48// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 52// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53// 54// Authors: Gabe Black 55 56////////////////////////////////////////////////////////////////////////// 57// 58// RegOp Microop templates 59// 60////////////////////////////////////////////////////////////////////////// 61 62def template MicroRegOpExecute {{ 63 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 64 Trace::InstRecord *traceData) const 65 { 66 Fault fault = NoFault; 67 68 %(op_decl)s; 69 %(op_rd)s; 70 %(code)s; 71 %(flag_code)s; 72 73 //Write the resulting state to the execution context 74 if(fault == NoFault) 75 { 76 %(op_wb)s; 77 } 78 return fault; 79 } 80}}; 81 82def template MicroRegOpImmExecute {{ 83 Fault %(class_name)sImm::execute(%(CPU_exec_context)s *xc, 84 Trace::InstRecord *traceData) const 85 { 86 Fault fault = NoFault; 87 88 %(op_decl)s; 89 %(op_rd)s; 90 %(code)s; 91 %(flag_code)s; 92 93 //Write the resulting state to the execution context 94 if(fault == NoFault) 95 { 96 %(op_wb)s; 97 } 98 return fault; 99 } 100}}; 101 102def template MicroRegOpDeclare {{ 103 class %(class_name)s : public %(base_class)s 104 { 105 protected: 106 void buildMe(); 107 108 public: 109 %(class_name)s(ExtMachInst _machInst, 110 const char * instMnem, 111 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 112 RegIndex _src1, RegIndex _src2, RegIndex _dest, 113 bool _setStatus, uint8_t _dataSize, uint8_t _ext); 114 115 %(class_name)s(ExtMachInst _machInst, 116 const char * instMnem, 117 RegIndex _src1, RegIndex _src2, RegIndex _dest, 118 bool _setStatus, uint8_t _dataSize, uint8_t _ext); 119 120 %(BasicExecDeclare)s 121 }; 122}}; 123 124def template MicroRegOpImmDeclare {{ 125 126 class %(class_name)sImm : public %(base_class)s 127 { 128 protected: 129 void buildMe(); 130 131 public: 132 %(class_name)sImm(ExtMachInst _machInst, 133 const char * instMnem, 134 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 135 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 136 bool _setStatus, uint8_t _dataSize, uint8_t _ext); 137 138 %(class_name)sImm(ExtMachInst _machInst, 139 const char * instMnem, 140 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 141 bool _setStatus, uint8_t _dataSize, uint8_t _ext); 142 143 %(BasicExecDeclare)s 144 }; 145}}; 146 147def template MicroRegOpConstructor {{ 148 149 inline void %(class_name)s::buildMe() 150 { 151 %(constructor)s; 152 } 153 154 inline %(class_name)s::%(class_name)s( 155 ExtMachInst machInst, const char * instMnem, 156 RegIndex _src1, RegIndex _src2, RegIndex _dest, 157 bool _setStatus, uint8_t _dataSize, uint8_t _ext) : 158 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 159 false, false, false, false, 160 _src1, _src2, _dest, _setStatus, _dataSize, _ext, 161 %(op_class)s) 162 { 163 buildMe(); 164 } 165 166 inline %(class_name)s::%(class_name)s( 167 ExtMachInst machInst, const char * instMnem, 168 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 169 RegIndex _src1, RegIndex _src2, RegIndex _dest, 170 bool _setStatus, uint8_t _dataSize, uint8_t _ext) : 171 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 172 isMicro, isDelayed, isFirst, isLast, 173 _src1, _src2, _dest, _setStatus, _dataSize, _ext, 174 %(op_class)s) 175 { 176 buildMe(); 177 } 178}}; 179 180def template MicroRegOpImmConstructor {{ 181 182 inline void %(class_name)sImm::buildMe() 183 { 184 %(constructor)s; 185 } 186 187 inline %(class_name)sImm::%(class_name)sImm( 188 ExtMachInst machInst, const char * instMnem, 189 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 190 bool _setStatus, uint8_t _dataSize, uint8_t _ext) : 191 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 192 false, false, false, false, 193 _src1, _imm8, _dest, _setStatus, _dataSize, _ext, 194 %(op_class)s) 195 { 196 buildMe(); 197 } 198 199 inline %(class_name)sImm::%(class_name)sImm( 200 ExtMachInst machInst, const char * instMnem, 201 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 202 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 203 bool _setStatus, uint8_t _dataSize, uint8_t _ext) : 204 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 205 isMicro, isDelayed, isFirst, isLast, 206 _src1, _imm8, _dest, _setStatus, _dataSize, _ext, 207 %(op_class)s) 208 { 209 buildMe(); 210 } 211}}; 212 213let {{ 214 class RegOp(X86Microop): 215 def __init__(self, dest, src1, src2, setStatus): 216 self.dest = dest 217 self.src1 = src1 218 self.src2 = src2 219 self.setStatus = setStatus 220 self.dataSize = "env.dataSize" 221 self.ext = 0 222 223 def getAllocator(self, *microFlags): 224 allocator = '''new %(class_name)s(machInst, mnemonic 225 %(flags)s, %(src1)s, %(src2)s, %(dest)s, 226 %(setStatus)s, %(dataSize)s, %(ext)s)''' % { 227 "class_name" : self.className, 228 "flags" : self.microFlagsText(microFlags), 229 "src1" : self.src1, "src2" : self.src2, 230 "dest" : self.dest, 231 "setStatus" : self.cppBool(self.setStatus), 232 "dataSize" : self.dataSize, 233 "ext" : self.ext} 234 return allocator 235 236 class RegOpImm(X86Microop): 237 def __init__(self, dest, src1, imm8, setStatus): 238 self.dest = dest 239 self.src1 = src1 240 self.imm8 = imm8 241 self.setStatus = setStatus 242 self.dataSize = "env.dataSize" 243 self.ext = 0 244 245 def getAllocator(self, *microFlags): 246 allocator = '''new %(class_name)s(machInst, mnemonic 247 %(flags)s, %(src1)s, %(imm8)s, %(dest)s, 248 %(setStatus)s, %(dataSize)s, %(ext)s)''' % { 249 "class_name" : self.className, 250 "flags" : self.microFlagsText(microFlags), 251 "src1" : self.src1, "imm8" : self.imm8, 252 "dest" : self.dest, 253 "setStatus" : self.cppBool(self.setStatus), 254 "dataSize" : self.dataSize, 255 "ext" : self.ext} 256 return allocator 257}}; 258 259let {{ 260 261 # Make these empty strings so that concatenating onto 262 # them will always work. 263 header_output = "" 264 decoder_output = "" 265 exec_output = "" 266 267 def setUpMicroRegOp(name, Name, base, code, child, flagCode): 268 global header_output 269 global decoder_output 270 global exec_output 271 global microopClasses 272 273 iop = InstObjParams(name, Name, base, 274 {"code" : code, 275 "flag_code" : flagCode}) 276 header_output += MicroRegOpDeclare.subst(iop) 277 decoder_output += MicroRegOpConstructor.subst(iop) 278 exec_output += MicroRegOpExecute.subst(iop) 279 280 microopClasses[name] = child 281 282 def defineMicroRegOp(mnemonic, code, flagCode): 283 Name = mnemonic 284 name = mnemonic.lower() 285 286 # Find op2 in each of the instruction definitions. Create two versions 287 # of the code, one with an integer operand, and one with an immediate 288 # operand. 289 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 290 regCode = matcher.sub("SrcReg2", code) 291 immCode = matcher.sub("imm8", code) 292 293 # Build the all register version of this micro op 294 class RegOpChild(RegOp): 295 def __init__(self, dest, src1, src2, setStatus=False): 296 super(RegOpChild, self).__init__(dest, src1, src2, setStatus) 297 self.className = Name 298 self.mnemonic = name 299 300 setUpMicroRegOp(name, Name, "X86ISA::RegOp", \ 301 regCode, RegOpChild, flagCode); 302 303 # Build the immediate version of this micro op 304 class RegOpChildImm(RegOpImm): 305 def __init__(self, dest, src1, src2, setStatus=False): 306 super(RegOpChildImm, self).__init__(dest, src1, src2, setStatus) 307 self.className = Name + "Imm" 308 self.mnemonic = name + "i" 309 310 setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", \ 311 immCode, RegOpChildImm, flagCode); 312 313 defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to set OF,CF,SF 314 defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)', "") 315 defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to add in CF, set OF,CF,SF 316 defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to subtract CF, set OF,CF,SF 317 defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)', "") 318 defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to set OF,CF,SF 319 defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)', "") 320 defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', "") #Needs to set OF,CF,SF and not DestReg 321 defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', "") 322 323 # This has it's own function because Wr ops have implicit destinations 324 def defineMicroRegOpWr(mnemonic, code): 325 Name = mnemonic 326 name = mnemonic.lower() 327 328 # Find op2 in each of the instruction definitions. Create two versions 329 # of the code, one with an integer operand, and one with an immediate 330 # operand. 331 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 332 regCode = matcher.sub("SrcReg2", code) 333 immCode = matcher.sub("imm8", code) 334 335 # Build the all register version of this micro op 336 class RegOpChild(RegOp): 337 def __init__(self, src1, src2): 338 super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, False) 339 self.className = Name 340 self.mnemonic = name 341 342 setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode, RegOpChild, ""); 343 344 # Build the immediate version of this micro op 345 class RegOpChildImm(RegOpImm): 346 def __init__(self, src1, src2): 347 super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, False) 348 self.className = Name + "Imm" 349 self.mnemonic = name + "i" 350 351 setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", \ 352 immCode, RegOpChildImm, ""); 353 354 defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2') 355 356 # This has it's own function because Rd ops don't always have two parameters 357 def defineMicroRegOpRd(mnemonic, code): 358 Name = mnemonic 359 name = mnemonic.lower() 360 361 class RegOpChild(RegOp): 362 def __init__(self, dest, src1 = "NUM_INTREGS"): 363 super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", False) 364 self.className = Name 365 self.mnemonic = name 366 367 setUpMicroRegOp(name, Name, "X86ISA::RegOp", code, RegOpChild, ""); 368 369 defineMicroRegOpRd('Rdip', 'DestReg = RIP') 370 371 def defineMicroRegOpImm(mnemonic, code): 372 Name = mnemonic 373 name = mnemonic.lower() 374 375 class RegOpChild(RegOpImm): 376 def __init__(self, dest, src1, src2): 377 super(RegOpChild, self).__init__(dest, src1, src2, False) 378 self.className = Name 379 self.mnemonic = name 380 381 setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code, RegOpChild, ""); 382 383 defineMicroRegOpImm('Sext', ''' 384 IntReg val = SrcReg1; 385 int sign_bit = bits(val, imm8-1, imm8-1); 386 val = sign_bit ? (val | ~mask(imm8)) : val; 387 DestReg = merge(DestReg, val, dataSize);''') 388}}; 389