regop.isa revision 4712
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 71 if(%(cond_check)s) 72 { 73 %(code)s; 74 %(flag_code)s; 75 } 76 else 77 { 78 %(else_code)s; 79 } 80 81 //Write the resulting state to the execution context 82 if(fault == NoFault) 83 { 84 %(op_wb)s; 85 } 86 return fault; 87 } 88}}; 89 90def template MicroRegOpImmExecute {{ 91 Fault %(class_name)sImm::execute(%(CPU_exec_context)s *xc, 92 Trace::InstRecord *traceData) const 93 { 94 Fault fault = NoFault; 95 96 %(op_decl)s; 97 %(op_rd)s; 98 99 if(%(cond_check)s) 100 { 101 %(code)s; 102 %(flag_code)s; 103 } 104 else 105 { 106 %(else_code)s; 107 } 108 109 //Write the resulting state to the execution context 110 if(fault == NoFault) 111 { 112 %(op_wb)s; 113 } 114 return fault; 115 } 116}}; 117 118def template MicroRegOpDeclare {{ 119 class %(class_name)s : public %(base_class)s 120 { 121 protected: 122 void buildMe(); 123 124 public: 125 %(class_name)s(ExtMachInst _machInst, 126 const char * instMnem, 127 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 128 RegIndex _src1, RegIndex _src2, RegIndex _dest, 129 uint8_t _dataSize, uint16_t _ext); 130 131 %(class_name)s(ExtMachInst _machInst, 132 const char * instMnem, 133 RegIndex _src1, RegIndex _src2, RegIndex _dest, 134 uint8_t _dataSize, uint16_t _ext); 135 136 %(BasicExecDeclare)s 137 }; 138}}; 139 140def template MicroRegOpImmDeclare {{ 141 142 class %(class_name)sImm : public %(base_class)s 143 { 144 protected: 145 void buildMe(); 146 147 public: 148 %(class_name)sImm(ExtMachInst _machInst, 149 const char * instMnem, 150 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 151 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 152 uint8_t _dataSize, uint16_t _ext); 153 154 %(class_name)sImm(ExtMachInst _machInst, 155 const char * instMnem, 156 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 157 uint8_t _dataSize, uint16_t _ext); 158 159 %(BasicExecDeclare)s 160 }; 161}}; 162 163def template MicroRegOpConstructor {{ 164 165 inline void %(class_name)s::buildMe() 166 { 167 %(constructor)s; 168 } 169 170 inline %(class_name)s::%(class_name)s( 171 ExtMachInst machInst, const char * instMnem, 172 RegIndex _src1, RegIndex _src2, RegIndex _dest, 173 uint8_t _dataSize, uint16_t _ext) : 174 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 175 false, false, false, false, 176 _src1, _src2, _dest, _dataSize, _ext, 177 %(op_class)s) 178 { 179 buildMe(); 180 } 181 182 inline %(class_name)s::%(class_name)s( 183 ExtMachInst machInst, const char * instMnem, 184 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 185 RegIndex _src1, RegIndex _src2, RegIndex _dest, 186 uint8_t _dataSize, uint16_t _ext) : 187 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 188 isMicro, isDelayed, isFirst, isLast, 189 _src1, _src2, _dest, _dataSize, _ext, 190 %(op_class)s) 191 { 192 buildMe(); 193 } 194}}; 195 196def template MicroRegOpImmConstructor {{ 197 198 inline void %(class_name)sImm::buildMe() 199 { 200 %(constructor)s; 201 } 202 203 inline %(class_name)sImm::%(class_name)sImm( 204 ExtMachInst machInst, const char * instMnem, 205 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 206 uint8_t _dataSize, uint16_t _ext) : 207 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 208 false, false, false, false, 209 _src1, _imm8, _dest, _dataSize, _ext, 210 %(op_class)s) 211 { 212 buildMe(); 213 } 214 215 inline %(class_name)sImm::%(class_name)sImm( 216 ExtMachInst machInst, const char * instMnem, 217 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 218 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 219 uint8_t _dataSize, uint16_t _ext) : 220 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 221 isMicro, isDelayed, isFirst, isLast, 222 _src1, _imm8, _dest, _dataSize, _ext, 223 %(op_class)s) 224 { 225 buildMe(); 226 } 227}}; 228 229let {{ 230 class X86MicroMeta(type): 231 def __new__(mcls, name, bases, dict): 232 abstract = False 233 if "abstract" in dict: 234 abstract = dict['abstract'] 235 del dict['abstract'] 236 237 cls = type.__new__(mcls, name, bases, dict) 238 if not abstract: 239 allClasses[name] = cls 240 return cls 241 242 class XXX86Microop(object): 243 __metaclass__ = X86MicroMeta 244 abstract = True 245 246 class RegOp(X86Microop): 247 abstract = True 248 def __init__(self, dest, src1, src2, flags, dataSize): 249 self.dest = dest 250 self.src1 = src1 251 self.src2 = src2 252 self.flags = flags 253 self.dataSize = dataSize 254 if flags is None: 255 self.ext = 0 256 else: 257 if not isinstance(flags, (list, tuple)): 258 raise Exception, "flags must be a list or tuple of flags" 259 self.ext = " | ".join(flags) 260 self.className += "Flags" 261 262 def getAllocator(self, *microFlags): 263 allocator = '''new %(class_name)s(machInst, mnemonic 264 %(flags)s, %(src1)s, %(src2)s, %(dest)s, 265 %(dataSize)s, %(ext)s)''' % { 266 "class_name" : self.className, 267 "flags" : self.microFlagsText(microFlags), 268 "src1" : self.src1, "src2" : self.src2, 269 "dest" : self.dest, 270 "dataSize" : self.dataSize, 271 "ext" : self.ext} 272 return allocator 273 274 class RegOpImm(X86Microop): 275 abstract = True 276 def __init__(self, dest, src1, imm8, flags, dataSize): 277 self.dest = dest 278 self.src1 = src1 279 self.imm8 = imm8 280 self.flags = flags 281 self.dataSize = dataSize 282 if flags is None: 283 self.ext = 0 284 else: 285 if not isinstance(flags, (list, tuple)): 286 raise Exception, "flags must be a list or tuple of flags" 287 self.ext = " | ".join(flags) 288 self.className += "Flags" 289 290 def getAllocator(self, *microFlags): 291 allocator = '''new %(class_name)s(machInst, mnemonic 292 %(flags)s, %(src1)s, %(imm8)s, %(dest)s, 293 %(dataSize)s, %(ext)s)''' % { 294 "class_name" : self.className, 295 "flags" : self.microFlagsText(microFlags), 296 "src1" : self.src1, "imm8" : self.imm8, 297 "dest" : self.dest, 298 "dataSize" : self.dataSize, 299 "ext" : self.ext} 300 return allocator 301}}; 302 303let {{ 304 305 # Make these empty strings so that concatenating onto 306 # them will always work. 307 header_output = "" 308 decoder_output = "" 309 exec_output = "" 310 311 # A function which builds the C++ classes that implement the microops 312 def setUpMicroRegOp(name, Name, base, code, flagCode, condCheck, elseCode): 313 global header_output 314 global decoder_output 315 global exec_output 316 global microopClasses 317 318 iop = InstObjParams(name, Name, base, 319 {"code" : code, 320 "flag_code" : flagCode, 321 "cond_check" : condCheck, 322 "else_code" : elseCode}) 323 header_output += MicroRegOpDeclare.subst(iop) 324 decoder_output += MicroRegOpConstructor.subst(iop) 325 exec_output += MicroRegOpExecute.subst(iop) 326 327 328 checkCCFlagBits = "checkCondition(ccFlagBits)" 329 genCCFlagBits = "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, SrcReg1, %s);" 330 331 332 # This creates a python representations of a microop which are a cross 333 # product of reg/immediate and flag/no flag versions. 334 def defineMicroRegOp(mnemonic, code, secondSrc = "op2", cc=False, elseCode=";"): 335 Name = mnemonic 336 name = mnemonic.lower() 337 338 # Find op2 in each of the instruction definitions. Create two versions 339 # of the code, one with an integer operand, and one with an immediate 340 # operand. 341 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 342 regCode = matcher.sub("SrcReg2", code) 343 immCode = matcher.sub("imm8", code) 344 345 if not cc: 346 flagCode = genCCFlagBits % secondSrc 347 condCode = "true" 348 else: 349 flagCode = "" 350 condCode = checkCCFlagBits 351 352 regFlagCode = matcher.sub("SrcReg2", flagCode) 353 immFlagCode = matcher.sub("imm8", flagCode) 354 355 class RegOpChild(RegOp): 356 mnemonic = name 357 className = Name 358 def __init__(self, dest, src1, src2, flags=None, dataSize="env.dataSize"): 359 super(RegOpChild, self).__init__(dest, src1, src2, flags, dataSize) 360 361 microopClasses[name] = RegOpChild 362 363 setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode, "", "true", elseCode); 364 setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode, regFlagCode, condCode, elseCode); 365 366 class RegOpChildImm(RegOpImm): 367 mnemonic = name + 'i' 368 className = Name + 'Imm' 369 def __init__(self, dest, src1, src2, flags=None, dataSize="env.dataSize"): 370 super(RegOpChildImm, self).__init__(dest, src1, src2, flags, dataSize) 371 372 microopClasses[name + 'i'] = RegOpChildImm 373 374 setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", immCode, "", "true", elseCode); 375 setUpMicroRegOp(name + "i", Name + "ImmFlags", "X86ISA::RegOpImm", immCode, immFlagCode, condCode, elseCode); 376 377 defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') 378 defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)') 379 defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') 380 defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', '-op2') 381 defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)') 382 defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', '-op2') 383 defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)') 384 defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', '-op2') 385 defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', 386 elseCode='DestReg=DestReg;', cc=True) 387 388 # This has it's own function because Wr ops have implicit destinations 389 def defineMicroRegOpWr(mnemonic, code, elseCode=";"): 390 Name = mnemonic 391 name = mnemonic.lower() 392 393 # Find op2 in each of the instruction definitions. Create two versions 394 # of the code, one with an integer operand, and one with an immediate 395 # operand. 396 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 397 regCode = matcher.sub("SrcReg2", code) 398 immCode = matcher.sub("imm8", code) 399 400 class RegOpChild(RegOp): 401 mnemonic = name 402 className = Name 403 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): 404 super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize) 405 406 microopClasses[name] = RegOpChild 407 408 setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode, "", "true", elseCode); 409 setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode, "", checkCCFlagBits, elseCode); 410 411 class RegOpChildImm(RegOpImm): 412 mnemonic = name + 'i' 413 className = Name + 'Imm' 414 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): 415 super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize) 416 417 microopClasses[name + 'i'] = RegOpChildImm 418 419 setUpMicroRegOp(name + 'i', Name + "Imm", "X86ISA::RegOpImm", immCode, "", "true", elseCode); 420 setUpMicroRegOp(name + 'i', Name + "ImmFlags", "X86ISA::RegOpImm", immCode, "", checkCCFlagBits, elseCode); 421 422 defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2', elseCode="RIP = RIP;") 423 424 # This has it's own function because Rd ops don't always have two parameters 425 def defineMicroRegOpRd(mnemonic, code): 426 Name = mnemonic 427 name = mnemonic.lower() 428 429 class RegOpChild(RegOp): 430 def __init__(self, dest, src1 = "NUM_INTREGS", dataSize="env.dataSize"): 431 super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize) 432 self.className = Name 433 self.mnemonic = name 434 435 microopClasses[name] = RegOpChild 436 437 setUpMicroRegOp(name, Name, "X86ISA::RegOp", code, "", "true", ";"); 438 439 defineMicroRegOpRd('Rdip', 'DestReg = RIP') 440 441 def defineMicroRegOpImm(mnemonic, code): 442 Name = mnemonic 443 name = mnemonic.lower() 444 445 class RegOpChild(RegOpImm): 446 def __init__(self, dest, src1, src2, dataSize="env.dataSize"): 447 super(RegOpChild, self).__init__(dest, src1, src2, None, dataSize) 448 self.className = Name 449 self.mnemonic = name 450 451 microopClasses[name] = RegOpChild 452 453 setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code, "", "true", ";"); 454 455 defineMicroRegOpImm('Sext', ''' 456 IntReg val = SrcReg1; 457 int sign_bit = bits(val, imm8-1, imm8-1); 458 val = sign_bit ? (val | ~mask(imm8)) : val; 459 DestReg = merge(DestReg, val, dataSize);''') 460}}; 461