regop.isa revision 10196:be0e1724eb39
14484Sbinkertn@umich.edu// Copyright (c) 2007-2008 The Hewlett-Packard Development Company 24484Sbinkertn@umich.edu// All rights reserved. 34484Sbinkertn@umich.edu// 44484Sbinkertn@umich.edu// The license below extends only to copyright in the software and shall 54484Sbinkertn@umich.edu// not be construed as granting a license to any other intellectual 64484Sbinkertn@umich.edu// property including but not limited to intellectual property relating 74484Sbinkertn@umich.edu// to a hardware implementation of the functionality of the software 84484Sbinkertn@umich.edu// licensed hereunder. You may use the software subject to the license 94484Sbinkertn@umich.edu// terms below provided that you ensure that this notice is replicated 104484Sbinkertn@umich.edu// unmodified and in its entirety in all distributions of the software, 114484Sbinkertn@umich.edu// modified or unmodified, in source code or in binary form. 124484Sbinkertn@umich.edu// 134484Sbinkertn@umich.edu// Redistribution and use in source and binary forms, with or without 144484Sbinkertn@umich.edu// modification, are permitted provided that the following conditions are 154484Sbinkertn@umich.edu// met: redistributions of source code must retain the above copyright 164484Sbinkertn@umich.edu// notice, this list of conditions and the following disclaimer; 174484Sbinkertn@umich.edu// redistributions in binary form must reproduce the above copyright 184484Sbinkertn@umich.edu// notice, this list of conditions and the following disclaimer in the 194484Sbinkertn@umich.edu// documentation and/or other materials provided with the distribution; 204484Sbinkertn@umich.edu// neither the name of the copyright holders nor the names of its 214484Sbinkertn@umich.edu// contributors may be used to endorse or promote products derived from 224484Sbinkertn@umich.edu// this software without specific prior written permission. 234484Sbinkertn@umich.edu// 244484Sbinkertn@umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 254484Sbinkertn@umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 264484Sbinkertn@umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 274484Sbinkertn@umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 284484Sbinkertn@umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 294484Sbinkertn@umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 304484Sbinkertn@umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 314484Sbinkertn@umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 324484Sbinkertn@umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 334484Sbinkertn@umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 344484Sbinkertn@umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 354484Sbinkertn@umich.edu// 364484Sbinkertn@umich.edu// Authors: Gabe Black 374484Sbinkertn@umich.edu 384484Sbinkertn@umich.edu////////////////////////////////////////////////////////////////////////// 394484Sbinkertn@umich.edu// 404484Sbinkertn@umich.edu// RegOp Microop templates 414484Sbinkertn@umich.edu// 424484Sbinkertn@umich.edu////////////////////////////////////////////////////////////////////////// 434484Sbinkertn@umich.edu 444484Sbinkertn@umich.edudef template MicroRegOpExecute {{ 454484Sbinkertn@umich.edu Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 464484Sbinkertn@umich.edu Trace::InstRecord *traceData) const 474484Sbinkertn@umich.edu { 484484Sbinkertn@umich.edu Fault fault = NoFault; 494484Sbinkertn@umich.edu 504484Sbinkertn@umich.edu DPRINTF(X86, "The data size is %d\n", dataSize); 514484Sbinkertn@umich.edu %(op_decl)s; 524484Sbinkertn@umich.edu %(op_rd)s; 534484Sbinkertn@umich.edu 544484Sbinkertn@umich.edu IntReg result M5_VAR_USED; 554484Sbinkertn@umich.edu 564484Sbinkertn@umich.edu if(%(cond_check)s) 574484Sbinkertn@umich.edu { 584484Sbinkertn@umich.edu %(code)s; 594484Sbinkertn@umich.edu %(flag_code)s; 604484Sbinkertn@umich.edu } 614484Sbinkertn@umich.edu else 624484Sbinkertn@umich.edu { 634484Sbinkertn@umich.edu %(else_code)s; 644484Sbinkertn@umich.edu } 654484Sbinkertn@umich.edu 664484Sbinkertn@umich.edu //Write the resulting state to the execution context 674484Sbinkertn@umich.edu if(fault == NoFault) 684484Sbinkertn@umich.edu { 694484Sbinkertn@umich.edu %(op_wb)s; 704484Sbinkertn@umich.edu } 714484Sbinkertn@umich.edu return fault; 724484Sbinkertn@umich.edu } 734484Sbinkertn@umich.edu}}; 744484Sbinkertn@umich.edu 754484Sbinkertn@umich.edudef template MicroRegOpImmExecute {{ 764484Sbinkertn@umich.edu Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 774484Sbinkertn@umich.edu Trace::InstRecord *traceData) const 784484Sbinkertn@umich.edu { 794484Sbinkertn@umich.edu Fault fault = NoFault; 804484Sbinkertn@umich.edu 814484Sbinkertn@umich.edu %(op_decl)s; 824484Sbinkertn@umich.edu %(op_rd)s; 834484Sbinkertn@umich.edu 844484Sbinkertn@umich.edu IntReg result M5_VAR_USED; 854484Sbinkertn@umich.edu 864484Sbinkertn@umich.edu if(%(cond_check)s) 874484Sbinkertn@umich.edu { 884484Sbinkertn@umich.edu %(code)s; 894484Sbinkertn@umich.edu %(flag_code)s; 904484Sbinkertn@umich.edu } 914484Sbinkertn@umich.edu else 924484Sbinkertn@umich.edu { 934484Sbinkertn@umich.edu %(else_code)s; 944484Sbinkertn@umich.edu } 954484Sbinkertn@umich.edu 964484Sbinkertn@umich.edu //Write the resulting state to the execution context 974484Sbinkertn@umich.edu if(fault == NoFault) 984484Sbinkertn@umich.edu { 994484Sbinkertn@umich.edu %(op_wb)s; 1004484Sbinkertn@umich.edu } 1014484Sbinkertn@umich.edu return fault; 1024484Sbinkertn@umich.edu } 1034484Sbinkertn@umich.edu}}; 1044484Sbinkertn@umich.edu 1054484Sbinkertn@umich.edudef template MicroRegOpDeclare {{ 1064484Sbinkertn@umich.edu class %(class_name)s : public %(base_class)s 1074484Sbinkertn@umich.edu { 1084484Sbinkertn@umich.edu public: 1094484Sbinkertn@umich.edu %(class_name)s(ExtMachInst _machInst, 1104484Sbinkertn@umich.edu const char * instMnem, uint64_t setFlags, 1114484Sbinkertn@umich.edu InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest, 1124484Sbinkertn@umich.edu uint8_t _dataSize, uint16_t _ext); 1134484Sbinkertn@umich.edu 1144484Sbinkertn@umich.edu %(BasicExecDeclare)s 1154484Sbinkertn@umich.edu }; 1164484Sbinkertn@umich.edu}}; 1174484Sbinkertn@umich.edu 1184484Sbinkertn@umich.edudef template MicroRegOpImmDeclare {{ 1194484Sbinkertn@umich.edu 1204484Sbinkertn@umich.edu class %(class_name)s : public %(base_class)s 1214484Sbinkertn@umich.edu { 1224484Sbinkertn@umich.edu public: 1234484Sbinkertn@umich.edu %(class_name)s(ExtMachInst _machInst, 1244484Sbinkertn@umich.edu const char * instMnem, uint64_t setFlags, 1254484Sbinkertn@umich.edu InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest, 1264484Sbinkertn@umich.edu uint8_t _dataSize, uint16_t _ext); 1274484Sbinkertn@umich.edu 1284484Sbinkertn@umich.edu %(BasicExecDeclare)s 1294484Sbinkertn@umich.edu }; 1304484Sbinkertn@umich.edu}}; 1314484Sbinkertn@umich.edu 1324484Sbinkertn@umich.edudef template MicroRegOpConstructor {{ 1334484Sbinkertn@umich.edu %(class_name)s::%(class_name)s( 1344484Sbinkertn@umich.edu ExtMachInst machInst, const char * instMnem, uint64_t setFlags, 1354484Sbinkertn@umich.edu InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest, 1364484Sbinkertn@umich.edu uint8_t _dataSize, uint16_t _ext) : 1374484Sbinkertn@umich.edu %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags, 1384484Sbinkertn@umich.edu _src1, _src2, _dest, _dataSize, _ext, 1394484Sbinkertn@umich.edu %(op_class)s) 1404484Sbinkertn@umich.edu { 1414484Sbinkertn@umich.edu %(constructor)s; 1424484Sbinkertn@umich.edu %(cond_control_flag_init)s; 1434484Sbinkertn@umich.edu } 1444484Sbinkertn@umich.edu}}; 1454484Sbinkertn@umich.edu 1464484Sbinkertn@umich.edudef template MicroRegOpImmConstructor {{ 1474484Sbinkertn@umich.edu %(class_name)s::%(class_name)s( 1484484Sbinkertn@umich.edu ExtMachInst machInst, const char * instMnem, uint64_t setFlags, 1494484Sbinkertn@umich.edu InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest, 1504484Sbinkertn@umich.edu uint8_t _dataSize, uint16_t _ext) : 1514484Sbinkertn@umich.edu %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags, 1524484Sbinkertn@umich.edu _src1, _imm8, _dest, _dataSize, _ext, 1534484Sbinkertn@umich.edu %(op_class)s) 1544484Sbinkertn@umich.edu { 1554484Sbinkertn@umich.edu %(constructor)s; 1564484Sbinkertn@umich.edu %(cond_control_flag_init)s; 1574484Sbinkertn@umich.edu } 1584484Sbinkertn@umich.edu}}; 1594484Sbinkertn@umich.edu 1604484Sbinkertn@umich.eduoutput header {{ 1614484Sbinkertn@umich.edu void 1624484Sbinkertn@umich.edu divide(uint64_t dividend, uint64_t divisor, 1634484Sbinkertn@umich.edu uint64_t "ient, uint64_t &remainder); 1644484Sbinkertn@umich.edu 1654484Sbinkertn@umich.edu enum SegmentSelectorCheck { 1664484Sbinkertn@umich.edu SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck, 1674484Sbinkertn@umich.edu SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck, 1684484Sbinkertn@umich.edu SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck 1694484Sbinkertn@umich.edu }; 1704484Sbinkertn@umich.edu 1714484Sbinkertn@umich.edu enum LongModeDescriptorType { 1724484Sbinkertn@umich.edu LDT64 = 2, 1734484Sbinkertn@umich.edu AvailableTSS64 = 9, 1744484Sbinkertn@umich.edu BusyTSS64 = 0xb, 1754484Sbinkertn@umich.edu CallGate64 = 0xc, 1764484Sbinkertn@umich.edu IntGate64 = 0xe, 1774484Sbinkertn@umich.edu TrapGate64 = 0xf 1784484Sbinkertn@umich.edu }; 1794484Sbinkertn@umich.edu}}; 1804484Sbinkertn@umich.edu 1814484Sbinkertn@umich.eduoutput decoder {{ 1824484Sbinkertn@umich.edu void 1834484Sbinkertn@umich.edu divide(uint64_t dividend, uint64_t divisor, 1844484Sbinkertn@umich.edu uint64_t "ient, uint64_t &remainder) 1854484Sbinkertn@umich.edu { 1864484Sbinkertn@umich.edu //Check for divide by zero. 1874484Sbinkertn@umich.edu assert(divisor != 0); 1884484Sbinkertn@umich.edu //If the divisor is bigger than the dividend, don't do anything. 1894484Sbinkertn@umich.edu if (divisor <= dividend) { 1904484Sbinkertn@umich.edu //Shift the divisor so it's msb lines up with the dividend. 1914484Sbinkertn@umich.edu int dividendMsb = findMsbSet(dividend); 1924484Sbinkertn@umich.edu int divisorMsb = findMsbSet(divisor); 1934484Sbinkertn@umich.edu int shift = dividendMsb - divisorMsb; 1944484Sbinkertn@umich.edu divisor <<= shift; 1954484Sbinkertn@umich.edu //Compute what we'll add to the quotient if the divisor isn't 1964484Sbinkertn@umich.edu //now larger than the dividend. 1974484Sbinkertn@umich.edu uint64_t quotientBit = 1; 1984484Sbinkertn@umich.edu quotientBit <<= shift; 1994484Sbinkertn@umich.edu //If we need to step back a bit (no pun intended) because the 2004484Sbinkertn@umich.edu //divisor got too to large, do that here. This is the "or two" 2014484Sbinkertn@umich.edu //part of one or two bit division. 2024484Sbinkertn@umich.edu if (divisor > dividend) { 2034484Sbinkertn@umich.edu quotientBit >>= 1; 2044484Sbinkertn@umich.edu divisor >>= 1; 2054484Sbinkertn@umich.edu } 2064484Sbinkertn@umich.edu //Decrement the remainder and increment the quotient. 2074484Sbinkertn@umich.edu quotient += quotientBit; 2084484Sbinkertn@umich.edu remainder -= divisor; 2094484Sbinkertn@umich.edu } 2104484Sbinkertn@umich.edu } 2114484Sbinkertn@umich.edu}}; 2124484Sbinkertn@umich.edu 2134484Sbinkertn@umich.edulet {{ 2144484Sbinkertn@umich.edu # Make these empty strings so that concatenating onto 2154484Sbinkertn@umich.edu # them will always work. 2164484Sbinkertn@umich.edu header_output = "" 2174484Sbinkertn@umich.edu decoder_output = "" 2184484Sbinkertn@umich.edu exec_output = "" 2194484Sbinkertn@umich.edu 2204484Sbinkertn@umich.edu immTemplates = ( 2214484Sbinkertn@umich.edu MicroRegOpImmDeclare, 2224484Sbinkertn@umich.edu MicroRegOpImmConstructor, 2234484Sbinkertn@umich.edu MicroRegOpImmExecute) 2244484Sbinkertn@umich.edu 2254484Sbinkertn@umich.edu regTemplates = ( 2264484Sbinkertn@umich.edu MicroRegOpDeclare, 2274484Sbinkertn@umich.edu MicroRegOpConstructor, 2284484Sbinkertn@umich.edu MicroRegOpExecute) 2294484Sbinkertn@umich.edu 2304484Sbinkertn@umich.edu class RegOpMeta(type): 2314484Sbinkertn@umich.edu def buildCppClasses(self, name, Name, suffix, code, big_code, \ 2324484Sbinkertn@umich.edu flag_code, cond_check, else_code, cond_control_flag_init, 2334484Sbinkertn@umich.edu op_class): 2344484Sbinkertn@umich.edu 2354484Sbinkertn@umich.edu # Globals to stick the output in 2364484Sbinkertn@umich.edu global header_output 2374484Sbinkertn@umich.edu global decoder_output 2384484Sbinkertn@umich.edu global exec_output 2394484Sbinkertn@umich.edu 2404484Sbinkertn@umich.edu # Stick all the code together so it can be searched at once 2414484Sbinkertn@umich.edu allCode = "|".join((code, flag_code, cond_check, else_code, 2424484Sbinkertn@umich.edu cond_control_flag_init)) 2434484Sbinkertn@umich.edu allBigCode = "|".join((big_code, flag_code, cond_check, else_code, 2444484Sbinkertn@umich.edu cond_control_flag_init)) 2454484Sbinkertn@umich.edu 2464484Sbinkertn@umich.edu # If op2 is used anywhere, make register and immediate versions 2474484Sbinkertn@umich.edu # of this code. 2484484Sbinkertn@umich.edu matcher = re.compile(r"(?<!\w)(?P<prefix>s?)op2(?P<typeQual>_[^\W_]+)?") 2494484Sbinkertn@umich.edu match = matcher.search(allCode + allBigCode) 250 if match: 251 typeQual = "" 252 if match.group("typeQual"): 253 typeQual = match.group("typeQual") 254 src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual) 255 self.buildCppClasses(name, Name, suffix, 256 matcher.sub(src2_name, code), 257 matcher.sub(src2_name, big_code), 258 matcher.sub(src2_name, flag_code), 259 matcher.sub(src2_name, cond_check), 260 matcher.sub(src2_name, else_code), 261 matcher.sub(src2_name, cond_control_flag_init), 262 op_class) 263 imm_name = "%simm8" % match.group("prefix") 264 self.buildCppClasses(name + "i", Name, suffix + "Imm", 265 matcher.sub(imm_name, code), 266 matcher.sub(imm_name, big_code), 267 matcher.sub(imm_name, flag_code), 268 matcher.sub(imm_name, cond_check), 269 matcher.sub(imm_name, else_code), 270 matcher.sub(imm_name, cond_control_flag_init), 271 op_class) 272 return 273 274 # If there's something optional to do with flags, generate 275 # a version without it and fix up this version to use it. 276 if flag_code != "" or cond_check != "true": 277 self.buildCppClasses(name, Name, suffix, 278 code, big_code, "", "true", else_code, "", op_class) 279 suffix = "Flags" + suffix 280 281 # If psrc1 or psrc2 is used, we need to actually insert code to 282 # compute it. 283 for (big, all) in ((False, allCode), (True, allBigCode)): 284 prefix = "" 285 for (rex, decl) in ( 286 ("(?<!\w)psrc1(?!\w)", 287 "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);"), 288 ("(?<!\w)psrc2(?!\w)", 289 "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);"), 290 ("(?<!\w)spsrc1(?!\w)", 291 "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);"), 292 ("(?<!\w)spsrc2(?!\w)", 293 "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);"), 294 ("(?<!\w)simm8(?!\w)", 295 "int8_t simm8 = imm8;")): 296 matcher = re.compile(rex) 297 if matcher.search(all): 298 prefix += decl + "\n" 299 if big: 300 if big_code != "": 301 big_code = prefix + big_code 302 else: 303 code = prefix + code 304 305 base = "X86ISA::RegOp" 306 307 # If imm8 shows up in the code, use the immediate templates, if 308 # not, hopefully the register ones will be correct. 309 templates = regTemplates 310 matcher = re.compile("(?<!\w)s?imm8(?!\w)") 311 if matcher.search(allCode): 312 base += "Imm" 313 templates = immTemplates 314 315 # Get everything ready for the substitution 316 iops = [InstObjParams(name, Name + suffix, base, 317 {"code" : code, 318 "flag_code" : flag_code, 319 "cond_check" : cond_check, 320 "else_code" : else_code, 321 "cond_control_flag_init" : cond_control_flag_init, 322 "op_class" : op_class})] 323 if big_code != "": 324 iops += [InstObjParams(name, Name + suffix + "Big", base, 325 {"code" : big_code, 326 "flag_code" : flag_code, 327 "cond_check" : cond_check, 328 "else_code" : else_code, 329 "cond_control_flag_init" : cond_control_flag_init, 330 "op_class" : op_class})] 331 332 # Generate the actual code (finally!) 333 for iop in iops: 334 header_output += templates[0].subst(iop) 335 decoder_output += templates[1].subst(iop) 336 exec_output += templates[2].subst(iop) 337 338 339 def __new__(mcls, Name, bases, dict): 340 abstract = False 341 name = Name.lower() 342 if "abstract" in dict: 343 abstract = dict['abstract'] 344 del dict['abstract'] 345 346 cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict) 347 if not abstract: 348 cls.className = Name 349 cls.base_mnemonic = name 350 code = cls.code 351 big_code = cls.big_code 352 flag_code = cls.flag_code 353 cond_check = cls.cond_check 354 else_code = cls.else_code 355 cond_control_flag_init = cls.cond_control_flag_init 356 op_class = cls.op_class 357 358 # Set up the C++ classes 359 mcls.buildCppClasses(cls, name, Name, "", code, big_code, 360 flag_code, cond_check, else_code, 361 cond_control_flag_init, op_class) 362 363 # Hook into the microassembler dict 364 global microopClasses 365 microopClasses[name] = cls 366 367 allCode = "|".join((code, flag_code, cond_check, else_code, 368 cond_control_flag_init)) 369 370 # If op2 is used anywhere, make register and immediate versions 371 # of this code. 372 matcher = re.compile(r"op2(?P<typeQual>_[^\W_]+)?") 373 if matcher.search(allCode): 374 microopClasses[name + 'i'] = cls 375 return cls 376 377 378 class RegOp(X86Microop): 379 __metaclass__ = RegOpMeta 380 # This class itself doesn't act as a microop 381 abstract = True 382 383 # Default template parameter values 384 big_code = "" 385 flag_code = "" 386 cond_check = "true" 387 else_code = ";" 388 cond_control_flag_init = "" 389 op_class = "IntAluOp" 390 391 def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"): 392 self.dest = dest 393 self.src1 = src1 394 self.op2 = op2 395 self.flags = flags 396 self.dataSize = dataSize 397 if flags is None: 398 self.ext = 0 399 else: 400 if not isinstance(flags, (list, tuple)): 401 raise Exception, "flags must be a list or tuple of flags" 402 self.ext = " | ".join(flags) 403 self.className += "Flags" 404 405 def getAllocator(self, microFlags): 406 if self.big_code != "": 407 className = self.className 408 if self.mnemonic == self.base_mnemonic + 'i': 409 className += "Imm" 410 allocString = ''' 411 (%(dataSize)s >= 4) ? 412 (StaticInstPtr)(new %(class_name)sBig(machInst, 413 macrocodeBlock, %(flags)s, %(src1)s, %(op2)s, 414 %(dest)s, %(dataSize)s, %(ext)s)) : 415 (StaticInstPtr)(new %(class_name)s(machInst, 416 macrocodeBlock, %(flags)s, %(src1)s, %(op2)s, 417 %(dest)s, %(dataSize)s, %(ext)s)) 418 ''' 419 allocator = allocString % { 420 "class_name" : className, 421 "flags" : self.microFlagsText(microFlags), 422 "src1" : self.src1, "op2" : self.op2, 423 "dest" : self.dest, 424 "dataSize" : self.dataSize, 425 "ext" : self.ext} 426 return allocator 427 else: 428 className = self.className 429 if self.mnemonic == self.base_mnemonic + 'i': 430 className += "Imm" 431 allocator = '''new %(class_name)s(machInst, macrocodeBlock, 432 %(flags)s, %(src1)s, %(op2)s, %(dest)s, 433 %(dataSize)s, %(ext)s)''' % { 434 "class_name" : className, 435 "flags" : self.microFlagsText(microFlags), 436 "src1" : self.src1, "op2" : self.op2, 437 "dest" : self.dest, 438 "dataSize" : self.dataSize, 439 "ext" : self.ext} 440 return allocator 441 442 class LogicRegOp(RegOp): 443 abstract = True 444 flag_code = ''' 445 //Don't have genFlags handle the OF or CF bits 446 uint64_t mask = CFBit | ECFBit | OFBit; 447 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 448 PredezfBit, ext & ~mask, result, psrc1, op2); 449 PredezfBit = newFlags & EZFBit; 450 PreddfBit = newFlags & DFBit; 451 PredccFlagBits = newFlags & ccFlagMask; 452 453 //If a logic microop wants to set these, it wants to set them to 0. 454 PredcfofBits = PredcfofBits & ~((CFBit | OFBit) & ext); 455 PredecfBit = PredecfBit & ~(ECFBit & ext); 456 ''' 457 458 class FlagRegOp(RegOp): 459 abstract = True 460 flag_code = ''' 461 uint64_t newFlags = genFlags(PredccFlagBits | PredcfofBits | 462 PreddfBit | PredecfBit | PredezfBit, 463 ext, result, psrc1, op2); 464 465 PredcfofBits = newFlags & cfofMask; 466 PredecfBit = newFlags & ECFBit; 467 PredezfBit = newFlags & EZFBit; 468 PreddfBit = newFlags & DFBit; 469 PredccFlagBits = newFlags & ccFlagMask; 470 ''' 471 472 class SubRegOp(RegOp): 473 abstract = True 474 flag_code = ''' 475 uint64_t newFlags = genFlags(PredccFlagBits | PredcfofBits | 476 PreddfBit | PredecfBit | PredezfBit, 477 ext, result, psrc1, ~op2, true); 478 479 PredcfofBits = newFlags & cfofMask; 480 PredecfBit = newFlags & ECFBit; 481 PredezfBit = newFlags & EZFBit; 482 PreddfBit = newFlags & DFBit; 483 PredccFlagBits = newFlags & ccFlagMask; 484 ''' 485 486 class CondRegOp(RegOp): 487 abstract = True 488 cond_check = "checkCondition(ccFlagBits | cfofBits | dfBit | ecfBit | \ 489 ezfBit, ext)" 490 cond_control_flag_init = "flags[IsCondControl] = flags[IsControl];" 491 492 class RdRegOp(RegOp): 493 abstract = True 494 def __init__(self, dest, src1=None, dataSize="env.dataSize"): 495 if not src1: 496 src1 = dest 497 super(RdRegOp, self).__init__(dest, src1, \ 498 "InstRegIndex(NUM_INTREGS)", None, dataSize) 499 500 class WrRegOp(RegOp): 501 abstract = True 502 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): 503 super(WrRegOp, self).__init__("InstRegIndex(NUM_INTREGS)", \ 504 src1, src2, flags, dataSize) 505 506 class Add(FlagRegOp): 507 code = 'DestReg = merge(DestReg, result = (psrc1 + op2), dataSize);' 508 big_code = 'DestReg = result = (psrc1 + op2) & mask(dataSize * 8);' 509 510 class Or(LogicRegOp): 511 code = 'DestReg = merge(DestReg, result = (psrc1 | op2), dataSize);' 512 big_code = 'DestReg = result = (psrc1 | op2) & mask(dataSize * 8);' 513 514 class Adc(FlagRegOp): 515 code = ''' 516 CCFlagBits flags = cfofBits; 517 DestReg = merge(DestReg, result = (psrc1 + op2 + flags.cf), dataSize); 518 ''' 519 big_code = ''' 520 CCFlagBits flags = cfofBits; 521 DestReg = result = (psrc1 + op2 + flags.cf) & mask(dataSize * 8); 522 ''' 523 524 class Sbb(SubRegOp): 525 code = ''' 526 CCFlagBits flags = cfofBits; 527 DestReg = merge(DestReg, result = (psrc1 - op2 - flags.cf), dataSize); 528 ''' 529 big_code = ''' 530 CCFlagBits flags = cfofBits; 531 DestReg = result = (psrc1 - op2 - flags.cf) & mask(dataSize * 8); 532 ''' 533 534 class And(LogicRegOp): 535 code = 'DestReg = merge(DestReg, result = (psrc1 & op2), dataSize)' 536 big_code = 'DestReg = result = (psrc1 & op2) & mask(dataSize * 8)' 537 538 class Sub(SubRegOp): 539 code = 'DestReg = merge(DestReg, result = (psrc1 - op2), dataSize)' 540 big_code = 'DestReg = result = (psrc1 - op2) & mask(dataSize * 8)' 541 542 class Xor(LogicRegOp): 543 code = 'DestReg = merge(DestReg, result = (psrc1 ^ op2), dataSize)' 544 big_code = 'DestReg = result = (psrc1 ^ op2) & mask(dataSize * 8)' 545 546 class Mul1s(WrRegOp): 547 op_class = 'IntMultOp' 548 549 code = ''' 550 ProdLow = psrc1 * op2; 551 int halfSize = (dataSize * 8) / 2; 552 uint64_t shifter = (ULL(1) << halfSize); 553 uint64_t hiResult; 554 uint64_t psrc1_h = psrc1 / shifter; 555 uint64_t psrc1_l = psrc1 & mask(halfSize); 556 uint64_t psrc2_h = (op2 / shifter) & mask(halfSize); 557 uint64_t psrc2_l = op2 & mask(halfSize); 558 hiResult = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l + 559 ((psrc1_l * psrc2_l) / shifter)) /shifter) + 560 psrc1_h * psrc2_h; 561 if (bits(psrc1, dataSize * 8 - 1)) 562 hiResult -= op2; 563 if (bits(op2, dataSize * 8 - 1)) 564 hiResult -= psrc1; 565 ProdHi = hiResult; 566 ''' 567 flag_code = ''' 568 if ((-ProdHi & mask(dataSize * 8)) != 569 bits(ProdLow, dataSize * 8 - 1)) { 570 PredcfofBits = PredcfofBits | (ext & (CFBit | OFBit)); 571 PredecfBit = PredecfBit | (ext & ECFBit); 572 } else { 573 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 574 PredecfBit = PredecfBit & ~(ext & ECFBit); 575 } 576 ''' 577 578 class Mul1u(WrRegOp): 579 op_class = 'IntMultOp' 580 581 code = ''' 582 ProdLow = psrc1 * op2; 583 int halfSize = (dataSize * 8) / 2; 584 uint64_t shifter = (ULL(1) << halfSize); 585 uint64_t psrc1_h = psrc1 / shifter; 586 uint64_t psrc1_l = psrc1 & mask(halfSize); 587 uint64_t psrc2_h = (op2 / shifter) & mask(halfSize); 588 uint64_t psrc2_l = op2 & mask(halfSize); 589 ProdHi = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l + 590 ((psrc1_l * psrc2_l) / shifter)) / shifter) + 591 psrc1_h * psrc2_h; 592 ''' 593 flag_code = ''' 594 if (ProdHi) { 595 PredcfofBits = PredcfofBits | (ext & (CFBit | OFBit)); 596 PredecfBit = PredecfBit | (ext & ECFBit); 597 } else { 598 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 599 PredecfBit = PredecfBit & ~(ext & ECFBit); 600 } 601 ''' 602 603 class Mulel(RdRegOp): 604 code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);' 605 big_code = 'DestReg = ProdLow & mask(dataSize * 8);' 606 607 class Muleh(RdRegOp): 608 def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"): 609 if not src1: 610 src1 = dest 611 super(RdRegOp, self).__init__(dest, src1, \ 612 "InstRegIndex(NUM_INTREGS)", flags, dataSize) 613 code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);' 614 big_code = 'DestReg = ProdHi & mask(dataSize * 8);' 615 616 # One or two bit divide 617 class Div1(WrRegOp): 618 op_class = 'IntDivOp' 619 620 code = ''' 621 //These are temporaries so that modifying them later won't make 622 //the ISA parser think they're also sources. 623 uint64_t quotient = 0; 624 uint64_t remainder = psrc1; 625 //Similarly, this is a temporary so changing it doesn't make it 626 //a source. 627 uint64_t divisor = op2; 628 //This is a temporary just for consistency and clarity. 629 uint64_t dividend = remainder; 630 //Do the division. 631 if (divisor == 0) { 632 fault = new DivideByZero; 633 } else { 634 divide(dividend, divisor, quotient, remainder); 635 //Record the final results. 636 Remainder = remainder; 637 Quotient = quotient; 638 Divisor = divisor; 639 } 640 ''' 641 642 # Step divide 643 class Div2(RegOp): 644 op_class = 'IntDivOp' 645 646 divCode = ''' 647 uint64_t dividend = Remainder; 648 uint64_t divisor = Divisor; 649 uint64_t quotient = Quotient; 650 uint64_t remainder = dividend; 651 int remaining = op2; 652 //If we overshot, do nothing. This lets us unrool division loops a 653 //little. 654 if (divisor == 0) { 655 fault = new DivideByZero; 656 } else if (remaining) { 657 if (divisor & (ULL(1) << 63)) { 658 while (remaining && !(dividend & (ULL(1) << 63))) { 659 dividend = (dividend << 1) | 660 bits(SrcReg1, remaining - 1); 661 quotient <<= 1; 662 remaining--; 663 } 664 if (dividend & (ULL(1) << 63)) { 665 bool highBit = false; 666 if (dividend < divisor && remaining) { 667 highBit = true; 668 dividend = (dividend << 1) | 669 bits(SrcReg1, remaining - 1); 670 quotient <<= 1; 671 remaining--; 672 } 673 if (highBit || divisor <= dividend) { 674 quotient++; 675 dividend -= divisor; 676 } 677 } 678 remainder = dividend; 679 } else { 680 //Shift in bits from the low order portion of the dividend 681 while (dividend < divisor && remaining) { 682 dividend = (dividend << 1) | 683 bits(SrcReg1, remaining - 1); 684 quotient <<= 1; 685 remaining--; 686 } 687 remainder = dividend; 688 //Do the division. 689 divide(dividend, divisor, quotient, remainder); 690 } 691 } 692 //Keep track of how many bits there are still to pull in. 693 %s 694 //Record the final results 695 Remainder = remainder; 696 Quotient = quotient; 697 ''' 698 code = divCode % "DestReg = merge(DestReg, remaining, dataSize);" 699 big_code = divCode % "DestReg = remaining & mask(dataSize * 8);" 700 flag_code = ''' 701 if (remaining == 0) 702 PredezfBit = PredezfBit | (ext & EZFBit); 703 else 704 PredezfBit = PredezfBit & ~(ext & EZFBit); 705 ''' 706 707 class Divq(RdRegOp): 708 code = 'DestReg = merge(SrcReg1, Quotient, dataSize);' 709 big_code = 'DestReg = Quotient & mask(dataSize * 8);' 710 711 class Divr(RdRegOp): 712 code = 'DestReg = merge(SrcReg1, Remainder, dataSize);' 713 big_code = 'DestReg = Remainder & mask(dataSize * 8);' 714 715 class Mov(CondRegOp): 716 code = 'DestReg = merge(SrcReg1, op2, dataSize)' 717 else_code = 'DestReg = DestReg;' 718 719 # Shift instructions 720 721 class Sll(RegOp): 722 code = ''' 723 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 724 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize); 725 ''' 726 big_code = ''' 727 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 728 DestReg = (psrc1 << shiftAmt) & mask(dataSize * 8); 729 ''' 730 flag_code = ''' 731 // If the shift amount is zero, no flags should be modified. 732 if (shiftAmt) { 733 //Zero out any flags we might modify. This way we only have to 734 //worry about setting them. 735 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 736 PredecfBit = PredecfBit & ~(ext & ECFBit); 737 738 int CFBits = 0; 739 //Figure out if we -would- set the CF bits if requested. 740 if (shiftAmt <= dataSize * 8 && 741 bits(SrcReg1, dataSize * 8 - shiftAmt)) { 742 CFBits = 1; 743 } 744 745 //If some combination of the CF bits need to be set, set them. 746 if ((ext & (CFBit | ECFBit)) && CFBits) { 747 PredcfofBits = PredcfofBits | (ext & CFBit); 748 PredecfBit = PredecfBit | (ext & ECFBit); 749 } 750 751 //Figure out what the OF bit should be. 752 if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1))) 753 PredcfofBits = PredcfofBits | OFBit; 754 755 //Use the regular mechanisms to calculate the other flags. 756 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 757 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 758 DestReg, psrc1, op2); 759 760 PredezfBit = newFlags & EZFBit; 761 PreddfBit = newFlags & DFBit; 762 PredccFlagBits = newFlags & ccFlagMask; 763 } 764 ''' 765 766 class Srl(RegOp): 767 # Because what happens to the bits shift -in- on a right shift 768 # is not defined in the C/C++ standard, we have to mask them out 769 # to be sure they're zero. 770 code = ''' 771 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 772 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); 773 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize); 774 ''' 775 big_code = ''' 776 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 777 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); 778 DestReg = (psrc1 >> shiftAmt) & logicalMask; 779 ''' 780 flag_code = ''' 781 // If the shift amount is zero, no flags should be modified. 782 if (shiftAmt) { 783 //Zero out any flags we might modify. This way we only have to 784 //worry about setting them. 785 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 786 PredecfBit = PredecfBit & ~(ext & ECFBit); 787 788 //If some combination of the CF bits need to be set, set them. 789 if ((ext & (CFBit | ECFBit)) && 790 shiftAmt <= dataSize * 8 && 791 bits(SrcReg1, shiftAmt - 1)) { 792 PredcfofBits = PredcfofBits | (ext & CFBit); 793 PredecfBit = PredecfBit | (ext & ECFBit); 794 } 795 796 //Figure out what the OF bit should be. 797 if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1)) 798 PredcfofBits = PredcfofBits | OFBit; 799 800 //Use the regular mechanisms to calculate the other flags. 801 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 802 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 803 DestReg, psrc1, op2); 804 805 PredezfBit = newFlags & EZFBit; 806 PreddfBit = newFlags & DFBit; 807 PredccFlagBits = newFlags & ccFlagMask; 808 } 809 ''' 810 811 class Sra(RegOp): 812 # Because what happens to the bits shift -in- on a right shift 813 # is not defined in the C/C++ standard, we have to sign extend 814 # them manually to be sure. 815 code = ''' 816 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 817 uint64_t arithMask = (shiftAmt == 0) ? 0 : 818 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); 819 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize); 820 ''' 821 big_code = ''' 822 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 823 uint64_t arithMask = (shiftAmt == 0) ? 0 : 824 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); 825 DestReg = ((psrc1 >> shiftAmt) | arithMask) & mask(dataSize * 8); 826 ''' 827 flag_code = ''' 828 // If the shift amount is zero, no flags should be modified. 829 if (shiftAmt) { 830 //Zero out any flags we might modify. This way we only have to 831 //worry about setting them. 832 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 833 PredecfBit = PredecfBit & ~(ext & ECFBit); 834 835 //If some combination of the CF bits need to be set, set them. 836 uint8_t effectiveShift = 837 (shiftAmt <= dataSize * 8) ? shiftAmt : (dataSize * 8); 838 if ((ext & (CFBit | ECFBit)) && 839 bits(SrcReg1, effectiveShift - 1)) { 840 PredcfofBits = PredcfofBits | (ext & CFBit); 841 PredecfBit = PredecfBit | (ext & ECFBit); 842 } 843 844 //Use the regular mechanisms to calculate the other flags. 845 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 846 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 847 DestReg, psrc1, op2); 848 849 PredezfBit = newFlags & EZFBit; 850 PreddfBit = newFlags & DFBit; 851 PredccFlagBits = newFlags & ccFlagMask; 852 } 853 ''' 854 855 class Ror(RegOp): 856 code = ''' 857 uint8_t shiftAmt = 858 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 859 uint8_t realShiftAmt = shiftAmt % (dataSize * 8); 860 if (realShiftAmt) { 861 uint64_t top = psrc1 << (dataSize * 8 - realShiftAmt); 862 uint64_t bottom = bits(psrc1, dataSize * 8, realShiftAmt); 863 DestReg = merge(DestReg, top | bottom, dataSize); 864 } else 865 DestReg = merge(DestReg, DestReg, dataSize); 866 ''' 867 flag_code = ''' 868 // If the shift amount is zero, no flags should be modified. 869 if (shiftAmt) { 870 //Zero out any flags we might modify. This way we only have to 871 //worry about setting them. 872 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 873 PredecfBit = PredecfBit & ~(ext & ECFBit); 874 875 //Find the most and second most significant bits of the result. 876 int msb = bits(DestReg, dataSize * 8 - 1); 877 int smsb = bits(DestReg, dataSize * 8 - 2); 878 //If some combination of the CF bits need to be set, set them. 879 if ((ext & (CFBit | ECFBit)) && msb) { 880 PredcfofBits = PredcfofBits | (ext & CFBit); 881 PredecfBit = PredecfBit | (ext & ECFBit); 882 } 883 884 //Figure out what the OF bit should be. 885 if ((ext & OFBit) && (msb ^ smsb)) 886 PredcfofBits = PredcfofBits | OFBit; 887 888 //Use the regular mechanisms to calculate the other flags. 889 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 890 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 891 DestReg, psrc1, op2); 892 893 PredezfBit = newFlags & EZFBit; 894 PreddfBit = newFlags & DFBit; 895 PredccFlagBits = newFlags & ccFlagMask; 896 } 897 ''' 898 899 class Rcr(RegOp): 900 code = ''' 901 uint8_t shiftAmt = 902 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 903 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1); 904 if (realShiftAmt) { 905 CCFlagBits flags = cfofBits; 906 uint64_t top = flags.cf << (dataSize * 8 - realShiftAmt); 907 if (realShiftAmt > 1) 908 top |= psrc1 << (dataSize * 8 - realShiftAmt + 1); 909 uint64_t bottom = bits(psrc1, dataSize * 8 - 1, realShiftAmt); 910 DestReg = merge(DestReg, top | bottom, dataSize); 911 } else 912 DestReg = merge(DestReg, DestReg, dataSize); 913 ''' 914 flag_code = ''' 915 // If the shift amount is zero, no flags should be modified. 916 if (shiftAmt) { 917 int origCFBit = (cfofBits & CFBit) ? 1 : 0; 918 //Zero out any flags we might modify. This way we only have to 919 //worry about setting them. 920 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 921 PredecfBit = PredecfBit & ~(ext & ECFBit); 922 923 //Figure out what the OF bit should be. 924 if ((ext & OFBit) && (origCFBit ^ 925 bits(SrcReg1, dataSize * 8 - 1))) { 926 PredcfofBits = PredcfofBits | OFBit; 927 } 928 //If some combination of the CF bits need to be set, set them. 929 if ((ext & (CFBit | ECFBit)) && 930 (realShiftAmt == 0) ? origCFBit : 931 bits(SrcReg1, realShiftAmt - 1)) { 932 PredcfofBits = PredcfofBits | (ext & CFBit); 933 PredecfBit = PredecfBit | (ext & ECFBit); 934 } 935 936 //Use the regular mechanisms to calculate the other flags. 937 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 938 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 939 DestReg, psrc1, op2); 940 941 PredezfBit = newFlags & EZFBit; 942 PreddfBit = newFlags & DFBit; 943 PredccFlagBits = newFlags & ccFlagMask; 944 } 945 ''' 946 947 class Rol(RegOp): 948 code = ''' 949 uint8_t shiftAmt = 950 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 951 uint8_t realShiftAmt = shiftAmt % (dataSize * 8); 952 if (realShiftAmt) { 953 uint64_t top = psrc1 << realShiftAmt; 954 uint64_t bottom = 955 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - realShiftAmt); 956 DestReg = merge(DestReg, top | bottom, dataSize); 957 } else 958 DestReg = merge(DestReg, DestReg, dataSize); 959 ''' 960 flag_code = ''' 961 // If the shift amount is zero, no flags should be modified. 962 if (shiftAmt) { 963 //Zero out any flags we might modify. This way we only have to 964 //worry about setting them. 965 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 966 PredecfBit = PredecfBit & ~(ext & ECFBit); 967 968 //The CF bits, if set, would be set to the lsb of the result. 969 int lsb = DestReg & 0x1; 970 int msb = bits(DestReg, dataSize * 8 - 1); 971 //If some combination of the CF bits need to be set, set them. 972 if ((ext & (CFBit | ECFBit)) && lsb) { 973 PredcfofBits = PredcfofBits | (ext & CFBit); 974 PredecfBit = PredecfBit | (ext & ECFBit); 975 } 976 977 //Figure out what the OF bit should be. 978 if ((ext & OFBit) && (msb ^ lsb)) 979 PredcfofBits = PredcfofBits | OFBit; 980 981 //Use the regular mechanisms to calculate the other flags. 982 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 983 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 984 DestReg, psrc1, op2); 985 986 PredezfBit = newFlags & EZFBit; 987 PreddfBit = newFlags & DFBit; 988 PredccFlagBits = newFlags & ccFlagMask; 989 } 990 ''' 991 992 class Rcl(RegOp): 993 code = ''' 994 uint8_t shiftAmt = 995 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 996 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1); 997 if (realShiftAmt) { 998 CCFlagBits flags = cfofBits; 999 uint64_t top = psrc1 << realShiftAmt; 1000 uint64_t bottom = flags.cf << (realShiftAmt - 1); 1001 if(shiftAmt > 1) 1002 bottom |= 1003 bits(psrc1, dataSize * 8 - 1, 1004 dataSize * 8 - realShiftAmt + 1); 1005 DestReg = merge(DestReg, top | bottom, dataSize); 1006 } else 1007 DestReg = merge(DestReg, DestReg, dataSize); 1008 ''' 1009 flag_code = ''' 1010 // If the shift amount is zero, no flags should be modified. 1011 if (shiftAmt) { 1012 int origCFBit = (cfofBits & CFBit) ? 1 : 0; 1013 //Zero out any flags we might modify. This way we only have to 1014 //worry about setting them. 1015 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 1016 PredecfBit = PredecfBit & ~(ext & ECFBit); 1017 1018 int msb = bits(DestReg, dataSize * 8 - 1); 1019 int CFBits = bits(SrcReg1, dataSize * 8 - realShiftAmt); 1020 //If some combination of the CF bits need to be set, set them. 1021 if ((ext & (CFBit | ECFBit)) && 1022 (realShiftAmt == 0) ? origCFBit : CFBits) { 1023 PredcfofBits = PredcfofBits | (ext & CFBit); 1024 PredecfBit = PredecfBit | (ext & ECFBit); 1025 } 1026 1027 //Figure out what the OF bit should be. 1028 if ((ext & OFBit) && (msb ^ CFBits)) 1029 PredcfofBits = PredcfofBits | OFBit; 1030 1031 //Use the regular mechanisms to calculate the other flags. 1032 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 1033 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 1034 DestReg, psrc1, op2); 1035 1036 PredezfBit = newFlags & EZFBit; 1037 PreddfBit = newFlags & DFBit; 1038 PredccFlagBits = newFlags & ccFlagMask; 1039 } 1040 ''' 1041 1042 class Sld(RegOp): 1043 sldCode = ''' 1044 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 1045 uint8_t dataBits = dataSize * 8; 1046 uint8_t realShiftAmt = shiftAmt %% (2 * dataBits); 1047 uint64_t result; 1048 if (realShiftAmt == 0) { 1049 result = psrc1; 1050 } else if (realShiftAmt < dataBits) { 1051 result = (psrc1 << realShiftAmt) | 1052 (DoubleBits >> (dataBits - realShiftAmt)); 1053 } else { 1054 result = (DoubleBits << (realShiftAmt - dataBits)) | 1055 (psrc1 >> (2 * dataBits - realShiftAmt)); 1056 } 1057 %s 1058 ''' 1059 code = sldCode % "DestReg = merge(DestReg, result, dataSize);" 1060 big_code = sldCode % "DestReg = result & mask(dataSize * 8);" 1061 flag_code = ''' 1062 // If the shift amount is zero, no flags should be modified. 1063 if (shiftAmt) { 1064 //Zero out any flags we might modify. This way we only have to 1065 //worry about setting them. 1066 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 1067 PredecfBit = PredecfBit & ~(ext & ECFBit); 1068 int CFBits = 0; 1069 1070 //Figure out if we -would- set the CF bits if requested. 1071 if ((realShiftAmt == 0 && 1072 bits(DoubleBits, 0)) || 1073 (realShiftAmt <= dataBits && 1074 bits(SrcReg1, dataBits - realShiftAmt)) || 1075 (realShiftAmt > dataBits && 1076 bits(DoubleBits, 2 * dataBits - realShiftAmt))) { 1077 CFBits = 1; 1078 } 1079 1080 //If some combination of the CF bits need to be set, set them. 1081 if ((ext & (CFBit | ECFBit)) && CFBits) { 1082 PredcfofBits = PredcfofBits | (ext & CFBit); 1083 PredecfBit = PredecfBit | (ext & ECFBit); 1084 } 1085 1086 //Figure out what the OF bit should be. 1087 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^ 1088 bits(result, dataBits - 1))) 1089 PredcfofBits = PredcfofBits | OFBit; 1090 1091 //Use the regular mechanisms to calculate the other flags. 1092 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 1093 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 1094 DestReg, psrc1, op2); 1095 1096 PredezfBit = newFlags & EZFBit; 1097 PreddfBit = newFlags & DFBit; 1098 PredccFlagBits = newFlags & ccFlagMask; 1099 } 1100 ''' 1101 1102 class Srd(RegOp): 1103 srdCode = ''' 1104 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 1105 uint8_t dataBits = dataSize * 8; 1106 uint8_t realShiftAmt = shiftAmt %% (2 * dataBits); 1107 uint64_t result; 1108 if (realShiftAmt == 0) { 1109 result = psrc1; 1110 } else if (realShiftAmt < dataBits) { 1111 // Because what happens to the bits shift -in- on a right 1112 // shift is not defined in the C/C++ standard, we have to 1113 // mask them out to be sure they're zero. 1114 uint64_t logicalMask = mask(dataBits - realShiftAmt); 1115 result = ((psrc1 >> realShiftAmt) & logicalMask) | 1116 (DoubleBits << (dataBits - realShiftAmt)); 1117 } else { 1118 uint64_t logicalMask = mask(2 * dataBits - realShiftAmt); 1119 result = ((DoubleBits >> (realShiftAmt - dataBits)) & 1120 logicalMask) | 1121 (psrc1 << (2 * dataBits - realShiftAmt)); 1122 } 1123 %s 1124 ''' 1125 code = srdCode % "DestReg = merge(DestReg, result, dataSize);" 1126 big_code = srdCode % "DestReg = result & mask(dataSize * 8);" 1127 flag_code = ''' 1128 // If the shift amount is zero, no flags should be modified. 1129 if (shiftAmt) { 1130 //Zero out any flags we might modify. This way we only have to 1131 //worry about setting them. 1132 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 1133 PredecfBit = PredecfBit & ~(ext & ECFBit); 1134 int CFBits = 0; 1135 1136 //If some combination of the CF bits need to be set, set them. 1137 if ((realShiftAmt == 0 && 1138 bits(DoubleBits, dataBits - 1)) || 1139 (realShiftAmt <= dataBits && 1140 bits(SrcReg1, realShiftAmt - 1)) || 1141 (realShiftAmt > dataBits && 1142 bits(DoubleBits, realShiftAmt - dataBits - 1))) { 1143 CFBits = 1; 1144 } 1145 1146 //If some combination of the CF bits need to be set, set them. 1147 if ((ext & (CFBit | ECFBit)) && CFBits) { 1148 PredcfofBits = PredcfofBits | (ext & CFBit); 1149 PredecfBit = PredecfBit | (ext & ECFBit); 1150 } 1151 1152 //Figure out what the OF bit should be. 1153 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^ 1154 bits(result, dataBits - 1))) 1155 PredcfofBits = PredcfofBits | OFBit; 1156 1157 //Use the regular mechanisms to calculate the other flags. 1158 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 1159 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 1160 DestReg, psrc1, op2); 1161 1162 PredezfBit = newFlags & EZFBit; 1163 PreddfBit = newFlags & DFBit; 1164 PredccFlagBits = newFlags & ccFlagMask; 1165 } 1166 ''' 1167 1168 class Mdb(WrRegOp): 1169 code = 'DoubleBits = psrc1 ^ op2;' 1170 1171 class Wrip(WrRegOp, CondRegOp): 1172 code = 'NRIP = psrc1 + sop2 + CSBase;' 1173 else_code = "NRIP = NRIP;" 1174 1175 class Wruflags(WrRegOp): 1176 code = ''' 1177 uint64_t newFlags = psrc1 ^ op2; 1178 cfofBits = newFlags & cfofMask; 1179 ecfBit = newFlags & ECFBit; 1180 ezfBit = newFlags & EZFBit; 1181 dfBit = newFlags & DFBit; 1182 ccFlagBits = newFlags & ccFlagMask; 1183 ''' 1184 1185 class Wrflags(WrRegOp): 1186 code = ''' 1187 MiscReg newFlags = psrc1 ^ op2; 1188 MiscReg userFlagMask = 0xDD5; 1189 1190 // Get only the user flags 1191 ccFlagBits = newFlags & ccFlagMask; 1192 dfBit = newFlags & DFBit; 1193 cfofBits = newFlags & cfofMask; 1194 ecfBit = 0; 1195 ezfBit = 0; 1196 1197 // Get everything else 1198 nccFlagBits = newFlags & ~userFlagMask; 1199 ''' 1200 1201 class Rdip(RdRegOp): 1202 code = 'DestReg = NRIP - CSBase;' 1203 1204 class Ruflags(RdRegOp): 1205 code = 'DestReg = ccFlagBits | cfofBits | dfBit | ecfBit | ezfBit;' 1206 1207 class Rflags(RdRegOp): 1208 code = ''' 1209 DestReg = ccFlagBits | cfofBits | dfBit | 1210 ecfBit | ezfBit | nccFlagBits; 1211 ''' 1212 1213 class Ruflag(RegOp): 1214 code = ''' 1215 int flag = bits(ccFlagBits | cfofBits | dfBit | 1216 ecfBit | ezfBit, imm8); 1217 DestReg = merge(DestReg, flag, dataSize); 1218 ezfBit = (flag == 0) ? EZFBit : 0; 1219 ''' 1220 1221 big_code = ''' 1222 int flag = bits(ccFlagBits | cfofBits | dfBit | 1223 ecfBit | ezfBit, imm8); 1224 DestReg = flag & mask(dataSize * 8); 1225 ezfBit = (flag == 0) ? EZFBit : 0; 1226 ''' 1227 1228 def __init__(self, dest, imm, flags=None, \ 1229 dataSize="env.dataSize"): 1230 super(Ruflag, self).__init__(dest, \ 1231 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize) 1232 1233 class Rflag(RegOp): 1234 code = ''' 1235 MiscReg flagMask = 0x3F7FDD5; 1236 MiscReg flags = (nccFlagBits | ccFlagBits | cfofBits | dfBit | 1237 ecfBit | ezfBit) & flagMask; 1238 1239 int flag = bits(flags, imm8); 1240 DestReg = merge(DestReg, flag, dataSize); 1241 ezfBit = (flag == 0) ? EZFBit : 0; 1242 ''' 1243 1244 big_code = ''' 1245 MiscReg flagMask = 0x3F7FDD5; 1246 MiscReg flags = (nccFlagBits | ccFlagBits | cfofBits | dfBit | 1247 ecfBit | ezfBit) & flagMask; 1248 1249 int flag = bits(flags, imm8); 1250 DestReg = flag & mask(dataSize * 8); 1251 ezfBit = (flag == 0) ? EZFBit : 0; 1252 ''' 1253 1254 def __init__(self, dest, imm, flags=None, \ 1255 dataSize="env.dataSize"): 1256 super(Rflag, self).__init__(dest, \ 1257 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize) 1258 1259 class Sext(RegOp): 1260 code = ''' 1261 IntReg val = psrc1; 1262 // Mask the bit position so that it wraps. 1263 int bitPos = op2 & (dataSize * 8 - 1); 1264 int sign_bit = bits(val, bitPos, bitPos); 1265 uint64_t maskVal = mask(bitPos+1); 1266 val = sign_bit ? (val | ~maskVal) : (val & maskVal); 1267 DestReg = merge(DestReg, val, dataSize); 1268 ''' 1269 1270 big_code = ''' 1271 IntReg val = psrc1; 1272 // Mask the bit position so that it wraps. 1273 int bitPos = op2 & (dataSize * 8 - 1); 1274 int sign_bit = bits(val, bitPos, bitPos); 1275 uint64_t maskVal = mask(bitPos+1); 1276 val = sign_bit ? (val | ~maskVal) : (val & maskVal); 1277 DestReg = val & mask(dataSize * 8); 1278 ''' 1279 1280 flag_code = ''' 1281 if (!sign_bit) { 1282 PredccFlagBits = PredccFlagBits & ~(ext & (ZFBit)); 1283 PredcfofBits = PredcfofBits & ~(ext & (CFBit)); 1284 PredecfBit = PredecfBit & ~(ext & ECFBit); 1285 PredezfBit = PredezfBit & ~(ext & EZFBit); 1286 } else { 1287 PredccFlagBits = PredccFlagBits | (ext & (ZFBit)); 1288 PredcfofBits = PredcfofBits | (ext & (CFBit)); 1289 PredecfBit = PredecfBit | (ext & ECFBit); 1290 PredezfBit = PredezfBit | (ext & EZFBit); 1291 } 1292 ''' 1293 1294 class Zext(RegOp): 1295 code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);' 1296 big_code = 'DestReg = bits(psrc1, op2, 0) & mask(dataSize * 8);' 1297 1298 class Rddr(RegOp): 1299 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1300 super(Rddr, self).__init__(dest, \ 1301 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1302 rdrCode = ''' 1303 CR4 cr4 = CR4Op; 1304 DR7 dr7 = DR7Op; 1305 if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) { 1306 fault = new InvalidOpcode(); 1307 } else if (dr7.gd) { 1308 fault = new DebugException(); 1309 } else { 1310 %s 1311 } 1312 ''' 1313 code = rdrCode % "DestReg = merge(DestReg, DebugSrc1, dataSize);" 1314 big_code = rdrCode % "DestReg = DebugSrc1 & mask(dataSize * 8);" 1315 1316 class Wrdr(RegOp): 1317 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1318 super(Wrdr, self).__init__(dest, \ 1319 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1320 code = ''' 1321 CR4 cr4 = CR4Op; 1322 DR7 dr7 = DR7Op; 1323 if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) { 1324 fault = new InvalidOpcode(); 1325 } else if ((dest == 6 || dest == 7) && bits(psrc1, 63, 32) && 1326 machInst.mode.mode == LongMode) { 1327 fault = new GeneralProtection(0); 1328 } else if (dr7.gd) { 1329 fault = new DebugException(); 1330 } else { 1331 DebugDest = psrc1; 1332 } 1333 ''' 1334 1335 class Rdcr(RegOp): 1336 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1337 super(Rdcr, self).__init__(dest, \ 1338 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1339 rdcrCode = ''' 1340 if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) { 1341 fault = new InvalidOpcode(); 1342 } else { 1343 %s 1344 } 1345 ''' 1346 code = rdcrCode % "DestReg = merge(DestReg, ControlSrc1, dataSize);" 1347 big_code = rdcrCode % "DestReg = ControlSrc1 & mask(dataSize * 8);" 1348 1349 class Wrcr(RegOp): 1350 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1351 super(Wrcr, self).__init__(dest, \ 1352 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1353 code = ''' 1354 if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) { 1355 fault = new InvalidOpcode(); 1356 } else { 1357 // There are *s in the line below so it doesn't confuse the 1358 // parser. They may be unnecessary. 1359 //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize); 1360 MiscReg newVal = psrc1; 1361 1362 // Check for any modifications that would cause a fault. 1363 switch(dest) { 1364 case 0: 1365 { 1366 Efer efer = EferOp; 1367 CR0 cr0 = newVal; 1368 CR4 oldCr4 = CR4Op; 1369 if (bits(newVal, 63, 32) || 1370 (!cr0.pe && cr0.pg) || 1371 (!cr0.cd && cr0.nw) || 1372 (cr0.pg && efer.lme && !oldCr4.pae)) 1373 fault = new GeneralProtection(0); 1374 } 1375 break; 1376 case 2: 1377 break; 1378 case 3: 1379 break; 1380 case 4: 1381 { 1382 CR4 cr4 = newVal; 1383 // PAE can't be disabled in long mode. 1384 if (bits(newVal, 63, 11) || 1385 (machInst.mode.mode == LongMode && !cr4.pae)) 1386 fault = new GeneralProtection(0); 1387 } 1388 break; 1389 case 8: 1390 { 1391 if (bits(newVal, 63, 4)) 1392 fault = new GeneralProtection(0); 1393 } 1394 default: 1395 fault = new GenericISA::M5PanicFault( 1396 "Unrecognized control register %d.\\n", dest); 1397 } 1398 ControlDest = newVal; 1399 } 1400 ''' 1401 1402 # Microops for manipulating segmentation registers 1403 class SegOp(CondRegOp): 1404 abstract = True 1405 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1406 super(SegOp, self).__init__(dest, \ 1407 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1408 1409 class Wrbase(SegOp): 1410 code = ''' 1411 SegBaseDest = psrc1; 1412 ''' 1413 1414 class Wrlimit(SegOp): 1415 code = ''' 1416 SegLimitDest = psrc1; 1417 ''' 1418 1419 class Wrsel(SegOp): 1420 code = ''' 1421 SegSelDest = psrc1; 1422 ''' 1423 1424 class WrAttr(SegOp): 1425 code = ''' 1426 SegAttrDest = psrc1; 1427 ''' 1428 1429 class Rdbase(SegOp): 1430 code = 'DestReg = merge(DestReg, SegBaseSrc1, dataSize);' 1431 big_code = 'DestReg = SegBaseSrc1 & mask(dataSize * 8);' 1432 1433 class Rdlimit(SegOp): 1434 code = 'DestReg = merge(DestReg, SegLimitSrc1, dataSize);' 1435 big_code = 'DestReg = SegLimitSrc1 & mask(dataSize * 8);' 1436 1437 class RdAttr(SegOp): 1438 code = 'DestReg = merge(DestReg, SegAttrSrc1, dataSize);' 1439 big_code = 'DestReg = SegAttrSrc1 & mask(dataSize * 8);' 1440 1441 class Rdsel(SegOp): 1442 code = 'DestReg = merge(DestReg, SegSelSrc1, dataSize);' 1443 big_code = 'DestReg = SegSelSrc1 & mask(dataSize * 8);' 1444 1445 class Rdval(RegOp): 1446 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1447 super(Rdval, self).__init__(dest, src1, \ 1448 "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1449 code = ''' 1450 DestReg = MiscRegSrc1; 1451 ''' 1452 1453 class Wrval(RegOp): 1454 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1455 super(Wrval, self).__init__(dest, src1, \ 1456 "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1457 code = ''' 1458 MiscRegDest = SrcReg1; 1459 ''' 1460 1461 class Chks(RegOp): 1462 def __init__(self, dest, src1, src2=0, 1463 flags=None, dataSize="env.dataSize"): 1464 super(Chks, self).__init__(dest, 1465 src1, src2, flags, dataSize) 1466 code = ''' 1467 // The selector is in source 1 and can be at most 16 bits. 1468 SegSelector selector = DestReg; 1469 SegDescriptor desc = SrcReg1; 1470 HandyM5Reg m5reg = M5Reg; 1471 1472 switch (imm8) 1473 { 1474 case SegNoCheck: 1475 break; 1476 case SegCSCheck: 1477 // Make sure it's the right type 1478 if (desc.s == 0 || desc.type.codeOrData != 1) { 1479 fault = new GeneralProtection(0); 1480 } else if (m5reg.cpl != desc.dpl) { 1481 fault = new GeneralProtection(0); 1482 } 1483 break; 1484 case SegCallGateCheck: 1485 fault = new GenericISA::M5PanicFault("CS checks for far " 1486 "calls/jumps through call gates not implemented.\\n"); 1487 break; 1488 case SegSoftIntGateCheck: 1489 // Check permissions. 1490 if (desc.dpl < m5reg.cpl) { 1491 fault = new GeneralProtection(selector); 1492 break; 1493 } 1494 // Fall through on purpose 1495 case SegIntGateCheck: 1496 // Make sure the gate's the right type. 1497 if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) || 1498 ((desc.type & 0x6) != 0x6)) { 1499 fault = new GeneralProtection(0); 1500 } 1501 break; 1502 case SegSSCheck: 1503 if (selector.si || selector.ti) { 1504 if (!desc.p) { 1505 fault = new StackFault(selector); 1506 } else if (!(desc.s == 1 && desc.type.codeOrData == 0 && 1507 desc.type.w) || 1508 (desc.dpl != m5reg.cpl) || 1509 (selector.rpl != m5reg.cpl)) { 1510 fault = new GeneralProtection(selector); 1511 } 1512 } else if (m5reg.submode != SixtyFourBitMode || 1513 m5reg.cpl == 3) { 1514 fault = new GeneralProtection(selector); 1515 } 1516 break; 1517 case SegIretCheck: 1518 { 1519 if ((!selector.si && !selector.ti) || 1520 (selector.rpl < m5reg.cpl) || 1521 !(desc.s == 1 && desc.type.codeOrData == 1) || 1522 (!desc.type.c && desc.dpl != selector.rpl) || 1523 (desc.type.c && desc.dpl > selector.rpl)) { 1524 fault = new GeneralProtection(selector); 1525 } else if (!desc.p) { 1526 fault = new SegmentNotPresent(selector); 1527 } 1528 break; 1529 } 1530 case SegIntCSCheck: 1531 if (m5reg.mode == LongMode) { 1532 if (desc.l != 1 || desc.d != 0) { 1533 fault = new GeneralProtection(selector); 1534 } 1535 } else { 1536 fault = new GenericISA::M5PanicFault("Interrupt CS " 1537 "checks not implemented in legacy mode.\\n"); 1538 } 1539 break; 1540 case SegTRCheck: 1541 if (!selector.si || selector.ti) { 1542 fault = new GeneralProtection(selector); 1543 } 1544 break; 1545 case SegTSSCheck: 1546 if (!desc.p) { 1547 fault = new SegmentNotPresent(selector); 1548 } else if (!(desc.type == 0x9 || 1549 (desc.type == 1 && 1550 m5reg.mode != LongMode))) { 1551 fault = new GeneralProtection(selector); 1552 } 1553 break; 1554 case SegInGDTCheck: 1555 if (selector.ti) { 1556 fault = new GeneralProtection(selector); 1557 } 1558 break; 1559 case SegLDTCheck: 1560 if (!desc.p) { 1561 fault = new SegmentNotPresent(selector); 1562 } else if (desc.type != 0x2) { 1563 fault = new GeneralProtection(selector); 1564 } 1565 break; 1566 default: 1567 fault = new GenericISA::M5PanicFault( 1568 "Undefined segment check type.\\n"); 1569 } 1570 ''' 1571 flag_code = ''' 1572 // Check for a NULL selector and set ZF,EZF appropriately. 1573 PredccFlagBits = PredccFlagBits & ~(ext & ZFBit); 1574 PredezfBit = PredezfBit & ~(ext & EZFBit); 1575 1576 if (!selector.si && !selector.ti) { 1577 PredccFlagBits = PredccFlagBits | (ext & ZFBit); 1578 PredezfBit = PredezfBit | (ext & EZFBit); 1579 } 1580 ''' 1581 1582 class Wrdh(RegOp): 1583 code = ''' 1584 SegDescriptor desc = SrcReg1; 1585 1586 uint64_t target = bits(SrcReg2, 31, 0) << 32; 1587 switch(desc.type) { 1588 case LDT64: 1589 case AvailableTSS64: 1590 case BusyTSS64: 1591 replaceBits(target, 23, 0, desc.baseLow); 1592 replaceBits(target, 31, 24, desc.baseHigh); 1593 break; 1594 case CallGate64: 1595 case IntGate64: 1596 case TrapGate64: 1597 replaceBits(target, 15, 0, bits(desc, 15, 0)); 1598 replaceBits(target, 31, 16, bits(desc, 63, 48)); 1599 break; 1600 default: 1601 fault = new GenericISA::M5PanicFault( 1602 "Wrdh used with wrong descriptor type!\\n"); 1603 } 1604 DestReg = target; 1605 ''' 1606 1607 class Wrtsc(WrRegOp): 1608 code = ''' 1609 TscOp = psrc1; 1610 ''' 1611 1612 class Rdtsc(RdRegOp): 1613 code = ''' 1614 DestReg = TscOp; 1615 ''' 1616 1617 class Rdm5reg(RdRegOp): 1618 code = ''' 1619 DestReg = M5Reg; 1620 ''' 1621 1622 class Wrdl(RegOp): 1623 code = ''' 1624 SegDescriptor desc = SrcReg1; 1625 SegSelector selector = SrcReg2; 1626 // This while loop is so we can use break statements in the code 1627 // below to skip the rest of this section without a bunch of 1628 // nesting. 1629 while (true) { 1630 if (selector.si || selector.ti) { 1631 if (!desc.p) { 1632 fault = new GenericISA::M5PanicFault( 1633 "Segment not present.\\n"); 1634 break; 1635 } 1636 SegAttr attr = 0; 1637 attr.dpl = desc.dpl; 1638 attr.unusable = 0; 1639 attr.defaultSize = desc.d; 1640 attr.longMode = desc.l; 1641 attr.avl = desc.avl; 1642 attr.granularity = desc.g; 1643 attr.present = desc.p; 1644 attr.system = desc.s; 1645 attr.type = desc.type; 1646 if (!desc.s) { 1647 // The expand down bit happens to be set for gates. 1648 if (desc.type.e) { 1649 fault = new GenericISA::M5PanicFault( 1650 "Gate descriptor encountered.\\n"); 1651 break; 1652 } 1653 attr.readable = 1; 1654 attr.writable = 1; 1655 attr.expandDown = 0; 1656 } else { 1657 if (desc.type.codeOrData) { 1658 attr.expandDown = 0; 1659 attr.readable = desc.type.r; 1660 attr.writable = 0; 1661 } else { 1662 attr.expandDown = desc.type.e; 1663 attr.readable = 1; 1664 attr.writable = desc.type.w; 1665 } 1666 } 1667 Addr base = desc.baseLow | (desc.baseHigh << 24); 1668 Addr limit = desc.limitLow | (desc.limitHigh << 16); 1669 if (desc.g) 1670 limit = (limit << 12) | mask(12); 1671 SegBaseDest = base; 1672 SegLimitDest = limit; 1673 SegAttrDest = attr; 1674 } else { 1675 SegBaseDest = SegBaseDest; 1676 SegLimitDest = SegLimitDest; 1677 SegAttrDest = SegAttrDest; 1678 } 1679 break; 1680 } 1681 ''' 1682 1683 class Wrxftw(WrRegOp): 1684 def __init__(self, src1, **kwargs): 1685 super(Wrxftw, self).__init__(src1, "InstRegIndex(NUM_INTREGS)", \ 1686 **kwargs) 1687 1688 code = ''' 1689 FTW = X86ISA::convX87XTagsToTags(SrcReg1); 1690 ''' 1691 1692 class Rdxftw(RdRegOp): 1693 code = ''' 1694 DestReg = X86ISA::convX87TagsToXTags(FTW); 1695 ''' 1696}}; 1697