regop.isa revision 5426:0bdcc60ccc45
12292SN/A// Copyright (c) 2007-2008 The Hewlett-Packard Development Company 28733Sgeoffrey.blake@arm.com// All rights reserved. 37597Sminkyu.jeong@arm.com// 47597Sminkyu.jeong@arm.com// Redistribution and use of this software in source and binary forms, 57597Sminkyu.jeong@arm.com// with or without modification, are permitted provided that the 67597Sminkyu.jeong@arm.com// following conditions are met: 77597Sminkyu.jeong@arm.com// 87597Sminkyu.jeong@arm.com// The software must be used only for Non-Commercial Use which means any 97597Sminkyu.jeong@arm.com// use which is NOT directed to receiving any direct monetary 107597Sminkyu.jeong@arm.com// compensation for, or commercial advantage from such use. Illustrative 117597Sminkyu.jeong@arm.com// examples of non-commercial use are academic research, personal study, 127597Sminkyu.jeong@arm.com// teaching, education and corporate research & development. 137597Sminkyu.jeong@arm.com// Illustrative examples of commercial use are distributing products for 142292SN/A// commercial advantage and providing services using the software for 152292SN/A// commercial advantage. 162292SN/A// 172292SN/A// If you wish to use this software or functionality therein that may be 182292SN/A// covered by patents for commercial use, please contact: 192292SN/A// Director of Intellectual Property Licensing 202292SN/A// Office of Strategy and Technology 212292SN/A// Hewlett-Packard Company 222292SN/A// 1501 Page Mill Road 232292SN/A// Palo Alto, California 94304 242292SN/A// 252292SN/A// Redistributions of source code must retain the above copyright notice, 262292SN/A// this list of conditions and the following disclaimer. Redistributions 272292SN/A// in binary form must reproduce the above copyright notice, this list of 282292SN/A// conditions and the following disclaimer in the documentation and/or 292292SN/A// other materials provided with the distribution. Neither the name of 302292SN/A// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its 312292SN/A// contributors may be used to endorse or promote products derived from 322292SN/A// this software without specific prior written permission. No right of 332292SN/A// sublicense is granted herewith. Derivatives of the software and 342292SN/A// output created using the software may be prepared, but only for 352292SN/A// Non-Commercial Uses. Derivatives of the software may be shared with 362292SN/A// others provided: (i) the others agree to abide by the list of 372292SN/A// conditions herein which includes the Non-Commercial Use restrictions; 382292SN/A// and (ii) such Derivatives of the software include the above copyright 392689Sktlim@umich.edu// notice to acknowledge the contribution from this software where 402689Sktlim@umich.edu// applicable, this list of conditions and the disclaimer below. 412689Sktlim@umich.edu// 422292SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 432292SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 448591Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 453326Sktlim@umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 468229Snate@binkert.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 476658Snate@binkert.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 482907Sktlim@umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 492292SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 508232Snate@binkert.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 518232Snate@binkert.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 528232Snate@binkert.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 532722Sktlim@umich.edu// 542669Sktlim@umich.edu// Authors: Gabe Black 552292SN/A 562790Sktlim@umich.edu////////////////////////////////////////////////////////////////////////// 572790Sktlim@umich.edu// 582790Sktlim@umich.edu// RegOp Microop templates 592790Sktlim@umich.edu// 602669Sktlim@umich.edu////////////////////////////////////////////////////////////////////////// 612678Sktlim@umich.edu 622678Sktlim@umich.edudef template MicroRegOpExecute {{ 638581Ssteve.reinhardt@amd.com Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 648581Ssteve.reinhardt@amd.com Trace::InstRecord *traceData) const 652292SN/A { 662292SN/A Fault fault = NoFault; 672292SN/A 682669Sktlim@umich.edu DPRINTF(X86, "The data size is %d\n", dataSize); 692292SN/A %(op_decl)s; 702678Sktlim@umich.edu %(op_rd)s; 712292SN/A 722678Sktlim@umich.edu if(%(cond_check)s) 732678Sktlim@umich.edu { 742678Sktlim@umich.edu %(code)s; 754319Sktlim@umich.edu %(flag_code)s; 764319Sktlim@umich.edu } 774319Sktlim@umich.edu else 784319Sktlim@umich.edu { 794319Sktlim@umich.edu %(else_code)s; 802678Sktlim@umich.edu } 812678Sktlim@umich.edu 822292SN/A //Write the resulting state to the execution context 832678Sktlim@umich.edu if(fault == NoFault) 842678Sktlim@umich.edu { 855336Shines@cs.fsu.edu %(op_wb)s; 862678Sktlim@umich.edu } 874873Sstever@eecs.umich.edu return fault; 882678Sktlim@umich.edu } 892292SN/A}}; 902678Sktlim@umich.edu 912678Sktlim@umich.edudef template MicroRegOpImmExecute {{ 922678Sktlim@umich.edu Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 932678Sktlim@umich.edu Trace::InstRecord *traceData) const 942678Sktlim@umich.edu { 952678Sktlim@umich.edu Fault fault = NoFault; 967852SMatt.Horsnell@arm.com 977852SMatt.Horsnell@arm.com %(op_decl)s; 982344SN/A %(op_rd)s; 992678Sktlim@umich.edu 1002678Sktlim@umich.edu if(%(cond_check)s) 1014986Ssaidi@eecs.umich.edu { 1024986Ssaidi@eecs.umich.edu %(code)s; 1036974Stjones1@inf.ed.ac.uk %(flag_code)s; 1046974Stjones1@inf.ed.ac.uk } 1056974Stjones1@inf.ed.ac.uk else 1066974Stjones1@inf.ed.ac.uk { 1076974Stjones1@inf.ed.ac.uk %(else_code)s; 1086974Stjones1@inf.ed.ac.uk } 1096974Stjones1@inf.ed.ac.uk 1102678Sktlim@umich.edu //Write the resulting state to the execution context 1112820Sktlim@umich.edu if(fault == NoFault) 1122678Sktlim@umich.edu { 1132678Sktlim@umich.edu %(op_wb)s; 1146974Stjones1@inf.ed.ac.uk } 1156974Stjones1@inf.ed.ac.uk return fault; 1166974Stjones1@inf.ed.ac.uk } 1176974Stjones1@inf.ed.ac.uk}}; 1186974Stjones1@inf.ed.ac.uk 1196974Stjones1@inf.ed.ac.ukdef template MicroRegOpDeclare {{ 1202678Sktlim@umich.edu class %(class_name)s : public %(base_class)s 1212678Sktlim@umich.edu { 1222678Sktlim@umich.edu protected: 1232678Sktlim@umich.edu void buildMe(); 1242678Sktlim@umich.edu 1252344SN/A public: 1262307SN/A %(class_name)s(ExtMachInst _machInst, 1276974Stjones1@inf.ed.ac.uk const char * instMnem, 1286974Stjones1@inf.ed.ac.uk bool isMicro, bool isDelayed, bool isFirst, bool isLast, 1296974Stjones1@inf.ed.ac.uk RegIndex _src1, RegIndex _src2, RegIndex _dest, 1306974Stjones1@inf.ed.ac.uk uint8_t _dataSize, uint16_t _ext); 1312678Sktlim@umich.edu 1324032Sktlim@umich.edu %(class_name)s(ExtMachInst _machInst, 1332678Sktlim@umich.edu const char * instMnem, 1342292SN/A RegIndex _src1, RegIndex _src2, RegIndex _dest, 1352292SN/A uint8_t _dataSize, uint16_t _ext); 1362292SN/A 1372292SN/A %(BasicExecDeclare)s 1388545Ssaidi@eecs.umich.edu }; 1392678Sktlim@umich.edu}}; 1408727Snilay@cs.wisc.edu 1412292SN/Adef template MicroRegOpImmDeclare {{ 1422292SN/A 1432292SN/A class %(class_name)s : public %(base_class)s 1442292SN/A { 1452292SN/A protected: 1465529Snate@binkert.org void buildMe(); 1475529Snate@binkert.org 1485529Snate@binkert.org public: 1492292SN/A %(class_name)s(ExtMachInst _machInst, 1504329Sktlim@umich.edu const char * instMnem, 1514329Sktlim@umich.edu bool isMicro, bool isDelayed, bool isFirst, bool isLast, 1524329Sktlim@umich.edu RegIndex _src1, uint16_t _imm8, RegIndex _dest, 1534329Sktlim@umich.edu uint8_t _dataSize, uint16_t _ext); 1542292SN/A 1552307SN/A %(class_name)s(ExtMachInst _machInst, 1562307SN/A const char * instMnem, 1578545Ssaidi@eecs.umich.edu RegIndex _src1, uint16_t _imm8, RegIndex _dest, 1588545Ssaidi@eecs.umich.edu uint8_t _dataSize, uint16_t _ext); 1592907Sktlim@umich.edu 1602907Sktlim@umich.edu %(BasicExecDeclare)s 1612292SN/A }; 1622292SN/A}}; 1632329SN/A 1642329SN/Adef template MicroRegOpConstructor {{ 1652329SN/A 1662292SN/A inline void %(class_name)s::buildMe() 1672292SN/A { 1682292SN/A %(constructor)s; 1692292SN/A } 1708199SAli.Saidi@ARM.com 1718199SAli.Saidi@ARM.com inline %(class_name)s::%(class_name)s( 1728199SAli.Saidi@ARM.com ExtMachInst machInst, const char * instMnem, 1732292SN/A RegIndex _src1, RegIndex _src2, RegIndex _dest, 1742292SN/A uint8_t _dataSize, uint16_t _ext) : 1752292SN/A %(base_class)s(machInst, "%(mnemonic)s", instMnem, 1762292SN/A false, false, false, false, 1772292SN/A _src1, _src2, _dest, _dataSize, _ext, 1782292SN/A %(op_class)s) 1792292SN/A { 1803492Sktlim@umich.edu buildMe(); 1812329SN/A } 1822292SN/A 1832292SN/A inline %(class_name)s::%(class_name)s( 1848727Snilay@cs.wisc.edu ExtMachInst machInst, const char * instMnem, 1852292SN/A bool isMicro, bool isDelayed, bool isFirst, bool isLast, 1862292SN/A RegIndex _src1, RegIndex _src2, RegIndex _dest, 1872292SN/A uint8_t _dataSize, uint16_t _ext) : 1882292SN/A %(base_class)s(machInst, "%(mnemonic)s", instMnem, 1892292SN/A isMicro, isDelayed, isFirst, isLast, 1902292SN/A _src1, _src2, _dest, _dataSize, _ext, 1912292SN/A %(op_class)s) 1922292SN/A { 1932292SN/A buildMe(); 1948247Snate@binkert.org } 1952292SN/A}}; 1962292SN/A 1972292SN/Adef template MicroRegOpImmConstructor {{ 1982292SN/A 1992292SN/A inline void %(class_name)s::buildMe() 2002727Sktlim@umich.edu { 2012727Sktlim@umich.edu %(constructor)s; 2022727Sktlim@umich.edu } 2032727Sktlim@umich.edu 2042727Sktlim@umich.edu inline %(class_name)s::%(class_name)s( 2052727Sktlim@umich.edu ExtMachInst machInst, const char * instMnem, 2062727Sktlim@umich.edu RegIndex _src1, uint16_t _imm8, RegIndex _dest, 2072727Sktlim@umich.edu uint8_t _dataSize, uint16_t _ext) : 2082727Sktlim@umich.edu %(base_class)s(machInst, "%(mnemonic)s", instMnem, 2092727Sktlim@umich.edu false, false, false, false, 2102727Sktlim@umich.edu _src1, _imm8, _dest, _dataSize, _ext, 2112727Sktlim@umich.edu %(op_class)s) 2122727Sktlim@umich.edu { 2132727Sktlim@umich.edu buildMe(); 2142727Sktlim@umich.edu } 2152727Sktlim@umich.edu 2162727Sktlim@umich.edu inline %(class_name)s::%(class_name)s( 2172727Sktlim@umich.edu ExtMachInst machInst, const char * instMnem, 2182361SN/A bool isMicro, bool isDelayed, bool isFirst, bool isLast, 2192361SN/A RegIndex _src1, uint16_t _imm8, RegIndex _dest, 2202361SN/A uint8_t _dataSize, uint16_t _ext) : 2212361SN/A %(base_class)s(machInst, "%(mnemonic)s", instMnem, 2222727Sktlim@umich.edu isMicro, isDelayed, isFirst, isLast, 2232727Sktlim@umich.edu _src1, _imm8, _dest, _dataSize, _ext, 2242727Sktlim@umich.edu %(op_class)s) 2252727Sktlim@umich.edu { 2262727Sktlim@umich.edu buildMe(); 2272727Sktlim@umich.edu } 2282727Sktlim@umich.edu}}; 2292727Sktlim@umich.edu 2302727Sktlim@umich.eduoutput header {{ 2312727Sktlim@umich.edu void 2322727Sktlim@umich.edu divide(uint64_t dividend, uint64_t divisor, 2332727Sktlim@umich.edu uint64_t "ient, uint64_t &remainder); 2342727Sktlim@umich.edu}}; 2352727Sktlim@umich.edu 2362727Sktlim@umich.eduoutput decoder {{ 2372727Sktlim@umich.edu void 2382727Sktlim@umich.edu divide(uint64_t dividend, uint64_t divisor, 2392727Sktlim@umich.edu uint64_t "ient, uint64_t &remainder) 2402727Sktlim@umich.edu { 2412727Sktlim@umich.edu //Check for divide by zero. 2422727Sktlim@umich.edu if (divisor == 0) 2432727Sktlim@umich.edu panic("Divide by zero!\\n"); 2442727Sktlim@umich.edu //If the divisor is bigger than the dividend, don't do anything. 2454329Sktlim@umich.edu if (divisor <= dividend) { 2464329Sktlim@umich.edu //Shift the divisor so it's msb lines up with the dividend. 2474329Sktlim@umich.edu int dividendMsb = findMsbSet(dividend); 2484329Sktlim@umich.edu int divisorMsb = findMsbSet(divisor); 2494329Sktlim@umich.edu int shift = dividendMsb - divisorMsb; 2504329Sktlim@umich.edu divisor <<= shift; 2514329Sktlim@umich.edu //Compute what we'll add to the quotient if the divisor isn't 2522292SN/A //now larger than the dividend. 2532292SN/A uint64_t quotientBit = 1; 2542292SN/A quotientBit <<= shift; 2552292SN/A //If we need to step back a bit (no pun intended) because the 2562292SN/A //divisor got too to large, do that here. This is the "or two" 2572292SN/A //part of one or two bit division. 2582292SN/A if (divisor > dividend) { 2592292SN/A quotientBit >>= 1; 2602292SN/A divisor >>= 1; 2612292SN/A } 2622292SN/A //Decrement the remainder and increment the quotient. 2632292SN/A quotient += quotientBit; 2642292SN/A remainder -= divisor; 2652292SN/A } 2662307SN/A } 2672307SN/A}}; 2682307SN/A 2692367SN/Alet {{ 2702367SN/A # Make these empty strings so that concatenating onto 2712307SN/A # them will always work. 2722367SN/A header_output = "" 2732307SN/A decoder_output = "" 2742329SN/A exec_output = "" 2752307SN/A 2762307SN/A immTemplates = ( 2772307SN/A MicroRegOpImmDeclare, 2782307SN/A MicroRegOpImmConstructor, 2792307SN/A MicroRegOpImmExecute) 2802307SN/A 2812307SN/A regTemplates = ( 2822307SN/A MicroRegOpDeclare, 2832307SN/A MicroRegOpConstructor, 2842307SN/A MicroRegOpExecute) 2852307SN/A 2862307SN/A class RegOpMeta(type): 2872307SN/A def buildCppClasses(self, name, Name, suffix, \ 2882307SN/A code, flag_code, cond_check, else_code): 2892307SN/A 2902329SN/A # Globals to stick the output in 2912307SN/A global header_output 2922307SN/A global decoder_output 2932307SN/A global exec_output 2942307SN/A 2952307SN/A # Stick all the code together so it can be searched at once 2962307SN/A allCode = "|".join((code, flag_code, cond_check, else_code)) 2978545Ssaidi@eecs.umich.edu 2988545Ssaidi@eecs.umich.edu # If op2 is used anywhere, make register and immediate versions 2998545Ssaidi@eecs.umich.edu # of this code. 3002307SN/A matcher = re.compile("(?<!\\w)(?P<prefix>s?)op2(?P<typeQual>\\.\\w+)?") 3012307SN/A match = matcher.search(allCode) 3022307SN/A if match: 3032307SN/A typeQual = "" 3042292SN/A if match.group("typeQual"): 3052292SN/A typeQual = match.group("typeQual") 3062329SN/A src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual) 3072329SN/A self.buildCppClasses(name, Name, suffix, 3082292SN/A matcher.sub(src2_name, code), 3092329SN/A matcher.sub(src2_name, flag_code), 3102329SN/A matcher.sub(src2_name, cond_check), 3112292SN/A matcher.sub(src2_name, else_code)) 3122292SN/A self.buildCppClasses(name + "i", Name, suffix + "Imm", 3132292SN/A matcher.sub("imm8", code), 3142292SN/A matcher.sub("imm8", flag_code), 3152292SN/A matcher.sub("imm8", cond_check), 3162329SN/A matcher.sub("imm8", else_code)) 3172292SN/A return 3182292SN/A 3192292SN/A # If there's something optional to do with flags, generate 3202292SN/A # a version without it and fix up this version to use it. 3212292SN/A if flag_code != "" or cond_check != "true": 3222292SN/A self.buildCppClasses(name, Name, suffix, 3232292SN/A code, "", "true", else_code) 3242292SN/A suffix = "Flags" + suffix 3252329SN/A 3262329SN/A # If psrc1 or psrc2 is used, we need to actually insert code to 3272329SN/A # compute it. 3282292SN/A matcher = re.compile("(?<!\w)psrc1(?!\w)") 3292292SN/A if matcher.search(allCode): 3302292SN/A code = "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);" + code 3312292SN/A matcher = re.compile("(?<!\w)psrc2(?!\w)") 3322292SN/A if matcher.search(allCode): 3332329SN/A code = "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);" + code 3342292SN/A # Also make available versions which do sign extension 3352292SN/A matcher = re.compile("(?<!\w)spsrc1(?!\w)") 3362292SN/A if matcher.search(allCode): 3372292SN/A code = "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);" + code 3382292SN/A matcher = re.compile("(?<!\w)spsrc2(?!\w)") 3392292SN/A if matcher.search(allCode): 3402292SN/A code = "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);" + code 3412292SN/A 3422292SN/A base = "X86ISA::RegOp" 3432292SN/A 3442292SN/A # If imm8 shows up in the code, use the immediate templates, if 3452292SN/A # not, hopefully the register ones will be correct. 3462292SN/A templates = regTemplates 3472292SN/A matcher = re.compile("(?<!\w)imm8(?!\w)") 3482292SN/A if matcher.search(allCode): 3492292SN/A base += "Imm" 3502292SN/A templates = immTemplates 3512292SN/A 3522292SN/A # Get everything ready for the substitution 3532292SN/A iop = InstObjParams(name, Name + suffix, base, 3542292SN/A {"code" : code, 3552292SN/A "flag_code" : flag_code, 3562292SN/A "cond_check" : cond_check, 3572292SN/A "else_code" : else_code}) 3582329SN/A 3592329SN/A # Generate the actual code (finally!) 3602292SN/A header_output += templates[0].subst(iop) 3617720Sgblack@eecs.umich.edu decoder_output += templates[1].subst(iop) 3627720Sgblack@eecs.umich.edu exec_output += templates[2].subst(iop) 3632292SN/A 3642292SN/A 3652292SN/A def __new__(mcls, Name, bases, dict): 3662292SN/A abstract = False 3672292SN/A name = Name.lower() 3682292SN/A if "abstract" in dict: 3692292SN/A abstract = dict['abstract'] 3702292SN/A del dict['abstract'] 3712292SN/A 3722292SN/A cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict) 3732292SN/A if not abstract: 3742292SN/A cls.className = Name 3752292SN/A cls.base_mnemonic = name 3762292SN/A code = cls.code 3772292SN/A flag_code = cls.flag_code 3782292SN/A cond_check = cls.cond_check 3792292SN/A else_code = cls.else_code 3802292SN/A 3812292SN/A # Set up the C++ classes 3822292SN/A mcls.buildCppClasses(cls, name, Name, "", 3832292SN/A code, flag_code, cond_check, else_code) 3842292SN/A 3852292SN/A # Hook into the microassembler dict 3862292SN/A global microopClasses 3877720Sgblack@eecs.umich.edu microopClasses[name] = cls 3887720Sgblack@eecs.umich.edu 3892292SN/A allCode = "|".join((code, flag_code, cond_check, else_code)) 3902292SN/A 3912292SN/A # If op2 is used anywhere, make register and immediate versions 3922292SN/A # of this code. 3932292SN/A matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 3942292SN/A if matcher.search(allCode): 3952292SN/A microopClasses[name + 'i'] = cls 3962292SN/A return cls 3972292SN/A 3982292SN/A 3992292SN/A class RegOp(X86Microop): 4002292SN/A __metaclass__ = RegOpMeta 4012292SN/A # This class itself doesn't act as a microop 4022292SN/A abstract = True 4032292SN/A 4042292SN/A # Default template parameter values 4052292SN/A flag_code = "" 4062292SN/A cond_check = "true" 4072292SN/A else_code = ";" 4082292SN/A 4092292SN/A def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"): 4102292SN/A self.dest = dest 4112292SN/A self.src1 = src1 4122292SN/A self.op2 = op2 4132292SN/A self.flags = flags 4142292SN/A self.dataSize = dataSize 4152292SN/A if flags is None: 4162292SN/A self.ext = 0 4172292SN/A else: 4182292SN/A if not isinstance(flags, (list, tuple)): 4192292SN/A raise Exception, "flags must be a list or tuple of flags" 4202292SN/A self.ext = " | ".join(flags) 4212292SN/A self.className += "Flags" 4222292SN/A 4232292SN/A def getAllocator(self, *microFlags): 4242292SN/A className = self.className 4252292SN/A if self.mnemonic == self.base_mnemonic + 'i': 4262292SN/A className += "Imm" 4272292SN/A allocator = '''new %(class_name)s(machInst, mnemonic 4282292SN/A %(flags)s, %(src1)s, %(op2)s, %(dest)s, 4292292SN/A %(dataSize)s, %(ext)s)''' % { 4302292SN/A "class_name" : className, 4312292SN/A "flags" : self.microFlagsText(microFlags), 4322292SN/A "src1" : self.src1, "op2" : self.op2, 4332292SN/A "dest" : self.dest, 4342292SN/A "dataSize" : self.dataSize, 4352292SN/A "ext" : self.ext} 4362292SN/A return allocator 4372292SN/A 4382292SN/A class LogicRegOp(RegOp): 4392292SN/A abstract = True 4402292SN/A flag_code = ''' 4412292SN/A //Don't have genFlags handle the OF or CF bits 4422292SN/A uint64_t mask = CFBit | ECFBit | OFBit; 4432292SN/A ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, psrc1, op2); 4442292SN/A //If a logic microop wants to set these, it wants to set them to 0. 4452292SN/A ccFlagBits &= ~(CFBit & ext); 4468545Ssaidi@eecs.umich.edu ccFlagBits &= ~(ECFBit & ext); 4478545Ssaidi@eecs.umich.edu ccFlagBits &= ~(OFBit & ext); 4488545Ssaidi@eecs.umich.edu ''' 4498545Ssaidi@eecs.umich.edu 4508545Ssaidi@eecs.umich.edu class FlagRegOp(RegOp): 4518545Ssaidi@eecs.umich.edu abstract = True 4528545Ssaidi@eecs.umich.edu flag_code = \ 4538545Ssaidi@eecs.umich.edu "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);" 4548545Ssaidi@eecs.umich.edu 4558545Ssaidi@eecs.umich.edu class SubRegOp(RegOp): 4568545Ssaidi@eecs.umich.edu abstract = True 4578545Ssaidi@eecs.umich.edu flag_code = \ 4588545Ssaidi@eecs.umich.edu "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);" 4598545Ssaidi@eecs.umich.edu 4608545Ssaidi@eecs.umich.edu class CondRegOp(RegOp): 4618545Ssaidi@eecs.umich.edu abstract = True 4628545Ssaidi@eecs.umich.edu cond_check = "checkCondition(ccFlagBits, ext)" 4638545Ssaidi@eecs.umich.edu 4648545Ssaidi@eecs.umich.edu class RdRegOp(RegOp): 4658545Ssaidi@eecs.umich.edu abstract = True 4668545Ssaidi@eecs.umich.edu def __init__(self, dest, src1=None, dataSize="env.dataSize"): 4678545Ssaidi@eecs.umich.edu if not src1: 4688545Ssaidi@eecs.umich.edu src1 = dest 4698545Ssaidi@eecs.umich.edu super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize) 4708545Ssaidi@eecs.umich.edu 4718545Ssaidi@eecs.umich.edu class WrRegOp(RegOp): 4728545Ssaidi@eecs.umich.edu abstract = True 4738545Ssaidi@eecs.umich.edu def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): 4748545Ssaidi@eecs.umich.edu super(WrRegOp, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize) 4758545Ssaidi@eecs.umich.edu 4768545Ssaidi@eecs.umich.edu class Add(FlagRegOp): 4778545Ssaidi@eecs.umich.edu code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);' 4788545Ssaidi@eecs.umich.edu 4798545Ssaidi@eecs.umich.edu class Or(LogicRegOp): 4808545Ssaidi@eecs.umich.edu code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);' 4818545Ssaidi@eecs.umich.edu 4828545Ssaidi@eecs.umich.edu class Adc(FlagRegOp): 4838545Ssaidi@eecs.umich.edu code = ''' 4848545Ssaidi@eecs.umich.edu CCFlagBits flags = ccFlagBits; 4858545Ssaidi@eecs.umich.edu DestReg = merge(DestReg, psrc1 + op2 + flags.cf, dataSize); 4868545Ssaidi@eecs.umich.edu ''' 4878545Ssaidi@eecs.umich.edu 4888545Ssaidi@eecs.umich.edu class Sbb(SubRegOp): 4898545Ssaidi@eecs.umich.edu code = ''' 4908545Ssaidi@eecs.umich.edu CCFlagBits flags = ccFlagBits; 4918545Ssaidi@eecs.umich.edu DestReg = merge(DestReg, psrc1 - op2 - flags.cf, dataSize); 4928545Ssaidi@eecs.umich.edu ''' 4938545Ssaidi@eecs.umich.edu 4948545Ssaidi@eecs.umich.edu class And(LogicRegOp): 4958545Ssaidi@eecs.umich.edu code = 'DestReg = merge(DestReg, psrc1 & op2, dataSize)' 4968545Ssaidi@eecs.umich.edu 4978545Ssaidi@eecs.umich.edu class Sub(SubRegOp): 4988545Ssaidi@eecs.umich.edu code = 'DestReg = merge(DestReg, psrc1 - op2, dataSize)' 4998545Ssaidi@eecs.umich.edu 5002292SN/A class Xor(LogicRegOp): 5018199SAli.Saidi@ARM.com code = 'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)' 5028199SAli.Saidi@ARM.com 5038199SAli.Saidi@ARM.com # Neither of these is quite correct because it assumes that right shifting 5048199SAli.Saidi@ARM.com # a signed or unsigned value does sign or zero extension respectively. 5058199SAli.Saidi@ARM.com # The C standard says that what happens on a right shift with a 1 in the 5068199SAli.Saidi@ARM.com # MSB position is undefined. On x86 and under likely most compilers the 5078199SAli.Saidi@ARM.com # "right thing" happens, but this isn't a guarantee. 5088199SAli.Saidi@ARM.com class Mul1s(WrRegOp): 5098199SAli.Saidi@ARM.com code = ''' 5108199SAli.Saidi@ARM.com ProdLow = psrc1 * op2; 5118199SAli.Saidi@ARM.com int halfSize = (dataSize * 8) / 2; 5128199SAli.Saidi@ARM.com int64_t spsrc1_h = spsrc1 >> halfSize; 5138199SAli.Saidi@ARM.com int64_t spsrc1_l = spsrc1 & mask(halfSize); 5148199SAli.Saidi@ARM.com int64_t spsrc2_h = sop2 >> halfSize; 5158199SAli.Saidi@ARM.com int64_t spsrc2_l = sop2 & mask(halfSize); 5168199SAli.Saidi@ARM.com ProdHi = ((spsrc1_l * spsrc2_h + spsrc1_h * spsrc2_l + 5178199SAli.Saidi@ARM.com ((spsrc1_l * spsrc2_l) >> halfSize)) >> halfSize) + 5188199SAli.Saidi@ARM.com spsrc1_h * spsrc2_h; 5198199SAli.Saidi@ARM.com ''' 5208199SAli.Saidi@ARM.com 5218199SAli.Saidi@ARM.com class Mul1u(WrRegOp): 5228272SAli.Saidi@ARM.com code = ''' 5238545Ssaidi@eecs.umich.edu ProdLow = psrc1 * op2; 5248545Ssaidi@eecs.umich.edu int halfSize = (dataSize * 8) / 2; 5258545Ssaidi@eecs.umich.edu uint64_t psrc1_h = psrc1 >> halfSize; 5268545Ssaidi@eecs.umich.edu uint64_t psrc1_l = psrc1 & mask(halfSize); 5278545Ssaidi@eecs.umich.edu uint64_t psrc2_h = op2 >> halfSize; 5288545Ssaidi@eecs.umich.edu uint64_t psrc2_l = op2 & mask(halfSize); 5298545Ssaidi@eecs.umich.edu ProdHi = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l + 5308545Ssaidi@eecs.umich.edu ((psrc1_l * psrc2_l) >> halfSize)) >> halfSize) + 5318592Sgblack@eecs.umich.edu psrc1_h * psrc2_h; 5328592Sgblack@eecs.umich.edu ''' 5338545Ssaidi@eecs.umich.edu 5348199SAli.Saidi@ARM.com class Mulel(RdRegOp): 5358545Ssaidi@eecs.umich.edu code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);' 5368199SAli.Saidi@ARM.com 5378591Sgblack@eecs.umich.edu class Muleh(RdRegOp): 5388591Sgblack@eecs.umich.edu def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"): 5398591Sgblack@eecs.umich.edu if not src1: 5408591Sgblack@eecs.umich.edu src1 = dest 5418545Ssaidi@eecs.umich.edu super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", flags, dataSize) 5428545Ssaidi@eecs.umich.edu code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);' 5438199SAli.Saidi@ARM.com flag_code = ''' 5448545Ssaidi@eecs.umich.edu if (ProdHi) 5458545Ssaidi@eecs.umich.edu ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit)); 5468545Ssaidi@eecs.umich.edu else 5478545Ssaidi@eecs.umich.edu ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit)); 5488545Ssaidi@eecs.umich.edu ''' 5498545Ssaidi@eecs.umich.edu 5508545Ssaidi@eecs.umich.edu # One or two bit divide 5518545Ssaidi@eecs.umich.edu class Div1(WrRegOp): 5528545Ssaidi@eecs.umich.edu code = ''' 5538545Ssaidi@eecs.umich.edu //These are temporaries so that modifying them later won't make 5548545Ssaidi@eecs.umich.edu //the ISA parser think they're also sources. 5558545Ssaidi@eecs.umich.edu uint64_t quotient = 0; 5568545Ssaidi@eecs.umich.edu uint64_t remainder = psrc1; 5578592Sgblack@eecs.umich.edu //Similarly, this is a temporary so changing it doesn't make it 5588592Sgblack@eecs.umich.edu //a source. 5598592Sgblack@eecs.umich.edu uint64_t divisor = op2; 5608545Ssaidi@eecs.umich.edu //This is a temporary just for consistency and clarity. 5618545Ssaidi@eecs.umich.edu uint64_t dividend = remainder; 5628545Ssaidi@eecs.umich.edu //Do the division. 5638545Ssaidi@eecs.umich.edu divide(dividend, divisor, quotient, remainder); 5648591Sgblack@eecs.umich.edu //Record the final results. 5658591Sgblack@eecs.umich.edu Remainder = remainder; 5668591Sgblack@eecs.umich.edu Quotient = quotient; 5678545Ssaidi@eecs.umich.edu Divisor = divisor; 5688199SAli.Saidi@ARM.com ''' 5698199SAli.Saidi@ARM.com 5708199SAli.Saidi@ARM.com # Step divide 5718199SAli.Saidi@ARM.com class Div2(RegOp): 5728199SAli.Saidi@ARM.com code = ''' 5738199SAli.Saidi@ARM.com uint64_t dividend = Remainder; 5748199SAli.Saidi@ARM.com uint64_t divisor = Divisor; 5758199SAli.Saidi@ARM.com uint64_t quotient = Quotient; 5768199SAli.Saidi@ARM.com uint64_t remainder = dividend; 5778199SAli.Saidi@ARM.com int remaining = op2; 5788199SAli.Saidi@ARM.com //If we overshot, do nothing. This lets us unrool division loops a 5798199SAli.Saidi@ARM.com //little. 5802292SN/A if (remaining) { 5812292SN/A //Shift in bits from the low order portion of the dividend 5824032Sktlim@umich.edu while(dividend < divisor && remaining) { 5832292SN/A dividend = (dividend << 1) | bits(SrcReg1, remaining - 1); 5842292SN/A quotient <<= 1; 5852292SN/A remaining--; 5867720Sgblack@eecs.umich.edu } 5877944SGiacomo.Gabrielli@arm.com remainder = dividend; 5882292SN/A //Do the division. 5894032Sktlim@umich.edu divide(dividend, divisor, quotient, remainder); 5904032Sktlim@umich.edu } 5912669Sktlim@umich.edu //Keep track of how many bits there are still to pull in. 5922292SN/A DestReg = merge(DestReg, remaining, dataSize); 5937944SGiacomo.Gabrielli@arm.com //Record the final results 5947944SGiacomo.Gabrielli@arm.com Remainder = remainder; 5957944SGiacomo.Gabrielli@arm.com Quotient = quotient; 5967944SGiacomo.Gabrielli@arm.com ''' 5977597Sminkyu.jeong@arm.com flag_code = ''' 5987597Sminkyu.jeong@arm.com if (DestReg == 0) 5997597Sminkyu.jeong@arm.com ccFlagBits = ccFlagBits | (ext & EZFBit); 6002329SN/A else 6012329SN/A ccFlagBits = ccFlagBits & ~(ext & EZFBit); 6022367SN/A ''' 6032367SN/A 6047848SAli.Saidi@ARM.com class Divq(RdRegOp): 6057848SAli.Saidi@ARM.com code = 'DestReg = merge(SrcReg1, Quotient, dataSize);' 6067600Sminkyu.jeong@arm.com 6077600Sminkyu.jeong@arm.com class Divr(RdRegOp): 6087600Sminkyu.jeong@arm.com code = 'DestReg = merge(SrcReg1, Remainder, dataSize);' 6094032Sktlim@umich.edu 6103731Sktlim@umich.edu class Mov(CondRegOp): 6112367SN/A code = 'DestReg = merge(SrcReg1, op2, dataSize)' 6122367SN/A else_code = 'DestReg=DestReg;' 6132292SN/A 6142292SN/A # Shift instructions 6154032Sktlim@umich.edu 6164032Sktlim@umich.edu class Sll(RegOp): 6174032Sktlim@umich.edu code = ''' 6184032Sktlim@umich.edu uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 6194032Sktlim@umich.edu DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize); 6208199SAli.Saidi@ARM.com ''' 6218199SAli.Saidi@ARM.com flag_code = ''' 6222292SN/A // If the shift amount is zero, no flags should be modified. 6232292SN/A if (shiftAmt) { 6242292SN/A //Zero out any flags we might modify. This way we only have to 6252292SN/A //worry about setting them. 6262292SN/A ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 6272292SN/A int CFBits = 0; 6282292SN/A //Figure out if we -would- set the CF bits if requested. 6292292SN/A if (bits(SrcReg1, dataSize * 8 - shiftAmt)) 6302292SN/A CFBits = 1; 6312292SN/A //If some combination of the CF bits need to be set, set them. 6322292SN/A if ((ext & (CFBit | ECFBit)) && CFBits) 6332292SN/A ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 6342292SN/A //Figure out what the OF bit should be. 6352292SN/A if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1))) 6362292SN/A ccFlagBits = ccFlagBits | OFBit; 6377720Sgblack@eecs.umich.edu //Use the regular mechanisms to calculate the other flags. 6387720Sgblack@eecs.umich.edu ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 6392292SN/A DestReg, psrc1, op2); 6404032Sktlim@umich.edu } 6414032Sktlim@umich.edu ''' 6422292SN/A 6432292SN/A class Srl(RegOp): 6442292SN/A code = ''' 6452292SN/A uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 6462292SN/A // Because what happens to the bits shift -in- on a right shift 6472292SN/A // is not defined in the C/C++ standard, we have to mask them out 6487944SGiacomo.Gabrielli@arm.com // to be sure they're zero. 6497944SGiacomo.Gabrielli@arm.com uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); 6507944SGiacomo.Gabrielli@arm.com DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize); 6517944SGiacomo.Gabrielli@arm.com ''' 6527848SAli.Saidi@ARM.com flag_code = ''' 6537848SAli.Saidi@ARM.com // If the shift amount is zero, no flags should be modified. 6547848SAli.Saidi@ARM.com if (shiftAmt) { 6552329SN/A //Zero out any flags we might modify. This way we only have to 6567782Sminkyu.jeong@arm.com //worry about setting them. 6577720Sgblack@eecs.umich.edu ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 6582292SN/A //If some combination of the CF bits need to be set, set them. 6592292SN/A if ((ext & (CFBit | ECFBit)) && bits(SrcReg1, shiftAmt - 1)) 6607782Sminkyu.jeong@arm.com ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 6617782Sminkyu.jeong@arm.com //Figure out what the OF bit should be. 6627782Sminkyu.jeong@arm.com if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1)) 6637782Sminkyu.jeong@arm.com ccFlagBits = ccFlagBits | OFBit; 6642292SN/A //Use the regular mechanisms to calculate the other flags. 6652292SN/A ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 6662292SN/A DestReg, psrc1, op2); 6672292SN/A } 6682336SN/A ''' 6692336SN/A 6702336SN/A class Sra(RegOp): 6712329SN/A code = ''' 6722292SN/A uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 6732329SN/A // Because what happens to the bits shift -in- on a right shift 6742292SN/A // is not defined in the C/C++ standard, we have to sign extend 6752292SN/A // them manually to be sure. 6768199SAli.Saidi@ARM.com uint64_t arithMask = 6772292SN/A -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); 6782292SN/A DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize); 6792292SN/A ''' 6802292SN/A flag_code = ''' 6812292SN/A // If the shift amount is zero, no flags should be modified. 6822292SN/A if (shiftAmt) { 6832292SN/A //Zero out any flags we might modify. This way we only have to 6842292SN/A //worry about setting them. 6852292SN/A ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 6867720Sgblack@eecs.umich.edu //If some combination of the CF bits need to be set, set them. 6877720Sgblack@eecs.umich.edu if ((ext & (CFBit | ECFBit)) && bits(SrcReg1, shiftAmt - 1)) 6882292SN/A ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 6892292SN/A //Use the regular mechanisms to calculate the other flags. 6902292SN/A ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 6912292SN/A DestReg, psrc1, op2); 6922292SN/A } 6932292SN/A ''' 6942292SN/A 6952292SN/A class Ror(RegOp): 6962292SN/A code = ''' 6972292SN/A uint8_t shiftAmt = 6982292SN/A (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 6992292SN/A if(shiftAmt) 7002292SN/A { 7012292SN/A uint64_t top = psrc1 << (dataSize * 8 - shiftAmt); 7022292SN/A uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt); 7032292SN/A DestReg = merge(DestReg, top | bottom, dataSize); 7042292SN/A } 7052292SN/A else 7062292SN/A DestReg = DestReg; 7072292SN/A ''' 7082292SN/A flag_code = ''' 7092292SN/A // If the shift amount is zero, no flags should be modified. 7102292SN/A if (shiftAmt) { 7112292SN/A //Zero out any flags we might modify. This way we only have to 7122292SN/A //worry about setting them. 7132292SN/A ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 7142292SN/A //Find the most and second most significant bits of the result. 7152292SN/A int msb = bits(DestReg, dataSize * 8 - 1); 7162292SN/A int smsb = bits(DestReg, dataSize * 8 - 2); 7172329SN/A //If some combination of the CF bits need to be set, set them. 7182329SN/A if ((ext & (CFBit | ECFBit)) && msb) 7192292SN/A ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 7202292SN/A //Figure out what the OF bit should be. 7212292SN/A if ((ext & OFBit) && (msb ^ smsb)) 7222292SN/A ccFlagBits = ccFlagBits | OFBit; 7232292SN/A //Use the regular mechanisms to calculate the other flags. 7247720Sgblack@eecs.umich.edu ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 7257720Sgblack@eecs.umich.edu DestReg, psrc1, op2); 7262292SN/A } 7272292SN/A ''' 7282292SN/A 7292292SN/A class Rcr(RegOp): 7302292SN/A code = ''' 7312292SN/A uint8_t shiftAmt = 7322292SN/A (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 7332292SN/A if(shiftAmt) 7342292SN/A { 7352292SN/A CCFlagBits flags = ccFlagBits; 7362292SN/A uint64_t top = flags.cf << (dataSize * 8 - shiftAmt); 7372292SN/A if(shiftAmt > 1) 7382292SN/A top |= psrc1 << (dataSize * 8 - shiftAmt - 1); 7396974Stjones1@inf.ed.ac.uk uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt); 7406974Stjones1@inf.ed.ac.uk DestReg = merge(DestReg, top | bottom, dataSize); 7416974Stjones1@inf.ed.ac.uk } 7426974Stjones1@inf.ed.ac.uk else 7436974Stjones1@inf.ed.ac.uk DestReg = DestReg; 7446974Stjones1@inf.ed.ac.uk ''' 7456974Stjones1@inf.ed.ac.uk flag_code = ''' 7466974Stjones1@inf.ed.ac.uk // If the shift amount is zero, no flags should be modified. 7476974Stjones1@inf.ed.ac.uk if (shiftAmt) { 7486974Stjones1@inf.ed.ac.uk //Zero out any flags we might modify. This way we only have to 7496974Stjones1@inf.ed.ac.uk //worry about setting them. 7506974Stjones1@inf.ed.ac.uk ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 7516974Stjones1@inf.ed.ac.uk //Figure out what the OF bit should be. 7526974Stjones1@inf.ed.ac.uk if ((ext & OFBit) && ((ccFlagBits & CFBit) ^ 7536974Stjones1@inf.ed.ac.uk bits(SrcReg1, dataSize * 8 - 1))) 7546974Stjones1@inf.ed.ac.uk ccFlagBits = ccFlagBits | OFBit; 7552292SN/A //If some combination of the CF bits need to be set, set them. 7562292SN/A if ((ext & (CFBit | ECFBit)) && bits(SrcReg1, shiftAmt - 1)) 7576974Stjones1@inf.ed.ac.uk ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 7586974Stjones1@inf.ed.ac.uk //Use the regular mechanisms to calculate the other flags. 7596974Stjones1@inf.ed.ac.uk ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 7606974Stjones1@inf.ed.ac.uk DestReg, psrc1, op2); 7616974Stjones1@inf.ed.ac.uk } 7626974Stjones1@inf.ed.ac.uk ''' 7632292SN/A 7642292SN/A class Rol(RegOp): 7652292SN/A code = ''' 7662292SN/A uint8_t shiftAmt = 7678727Snilay@cs.wisc.edu (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 7682292SN/A if(shiftAmt) 7692292SN/A { 7702907Sktlim@umich.edu uint64_t top = psrc1 << shiftAmt; 7712678Sktlim@umich.edu uint64_t bottom = 7722678Sktlim@umich.edu bits(psrc1, dataSize * 8 - 1, dataSize * 8 - shiftAmt); 7732678Sktlim@umich.edu DestReg = merge(DestReg, top | bottom, dataSize); 7742678Sktlim@umich.edu } 7752678Sktlim@umich.edu else 7762329SN/A DestReg = DestReg; 7772329SN/A ''' 7782292SN/A flag_code = ''' 7792292SN/A // If the shift amount is zero, no flags should be modified. 7802292SN/A if (shiftAmt) { 7812292SN/A //Zero out any flags we might modify. This way we only have to 7822292SN/A //worry about setting them. 7832292SN/A ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 7842292SN/A //The CF bits, if set, would be set to the lsb of the result. 7852678Sktlim@umich.edu int lsb = DestReg & 0x1; 7862292SN/A int msb = bits(DestReg, dataSize * 8 - 1); 7872292SN/A //If some combination of the CF bits need to be set, set them. 7882292SN/A if ((ext & (CFBit | ECFBit)) && lsb) 7892292SN/A ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 7902292SN/A //Figure out what the OF bit should be. 7912292SN/A if ((ext & OFBit) && (msb ^ lsb)) 7922292SN/A ccFlagBits = ccFlagBits | OFBit; 7932292SN/A //Use the regular mechanisms to calculate the other flags. 7942292SN/A ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 7952292SN/A DestReg, psrc1, op2); 7962292SN/A } 7976974Stjones1@inf.ed.ac.uk ''' 7986974Stjones1@inf.ed.ac.uk 7996974Stjones1@inf.ed.ac.uk class Rcl(RegOp): 8006974Stjones1@inf.ed.ac.uk code = ''' 8016974Stjones1@inf.ed.ac.uk uint8_t shiftAmt = 8022669Sktlim@umich.edu (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 8032669Sktlim@umich.edu if(shiftAmt) 8042669Sktlim@umich.edu { 8058481Sgblack@eecs.umich.edu CCFlagBits flags = ccFlagBits; 8068481Sgblack@eecs.umich.edu uint64_t top = psrc1 << shiftAmt; 8078481Sgblack@eecs.umich.edu uint64_t bottom = flags.cf << (shiftAmt - 1); 8082292SN/A if(shiftAmt > 1) 8092292SN/A bottom |= 8102669Sktlim@umich.edu bits(psrc1, dataSize * 8 - 1, 8112669Sktlim@umich.edu dataSize * 8 - shiftAmt + 1); 8123772Sgblack@eecs.umich.edu DestReg = merge(DestReg, top | bottom, dataSize); 8134326Sgblack@eecs.umich.edu } 8142669Sktlim@umich.edu else 8154878Sstever@eecs.umich.edu DestReg = DestReg; 8164878Sstever@eecs.umich.edu ''' 8176102Sgblack@eecs.umich.edu flag_code = ''' 8186974Stjones1@inf.ed.ac.uk // If the shift amount is zero, no flags should be modified. 8196974Stjones1@inf.ed.ac.uk if (shiftAmt) { 8202292SN/A //Zero out any flags we might modify. This way we only have to 8212678Sktlim@umich.edu //worry about setting them. 8222678Sktlim@umich.edu ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 8232678Sktlim@umich.edu int msb = bits(DestReg, dataSize * 8 - 1); 8242678Sktlim@umich.edu int CFBits = bits(SrcReg1, dataSize * 8 - shiftAmt); 8256974Stjones1@inf.ed.ac.uk //If some combination of the CF bits need to be set, set them. 8266974Stjones1@inf.ed.ac.uk if ((ext & (CFBit | ECFBit)) && CFBits) 8276974Stjones1@inf.ed.ac.uk ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 8286974Stjones1@inf.ed.ac.uk //Figure out what the OF bit should be. 8296974Stjones1@inf.ed.ac.uk if ((ext & OFBit) && (msb ^ CFBits)) 8306974Stjones1@inf.ed.ac.uk ccFlagBits = ccFlagBits | OFBit; 8316974Stjones1@inf.ed.ac.uk //Use the regular mechanisms to calculate the other flags. 8326974Stjones1@inf.ed.ac.uk ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 8336974Stjones1@inf.ed.ac.uk DestReg, psrc1, op2); 8346974Stjones1@inf.ed.ac.uk } 8356974Stjones1@inf.ed.ac.uk ''' 8366974Stjones1@inf.ed.ac.uk 8376974Stjones1@inf.ed.ac.uk class Wrip(WrRegOp, CondRegOp): 8386974Stjones1@inf.ed.ac.uk code = 'RIP = psrc1 + sop2 + CSBase' 8396974Stjones1@inf.ed.ac.uk else_code="RIP = RIP;" 8406974Stjones1@inf.ed.ac.uk 8416974Stjones1@inf.ed.ac.uk class Br(WrRegOp, CondRegOp): 8426974Stjones1@inf.ed.ac.uk code = 'nuIP = psrc1 + op2;' 8436974Stjones1@inf.ed.ac.uk else_code='nuIP = nuIP;' 8446974Stjones1@inf.ed.ac.uk 8456974Stjones1@inf.ed.ac.uk class Wruflags(WrRegOp): 8466974Stjones1@inf.ed.ac.uk code = 'ccFlagBits = psrc1 ^ op2' 8476974Stjones1@inf.ed.ac.uk 8486974Stjones1@inf.ed.ac.uk class Wrflags(WrRegOp): 8496974Stjones1@inf.ed.ac.uk code = ''' 8502678Sktlim@umich.edu MiscReg newFlags = psrc1 ^ op2; 8517720Sgblack@eecs.umich.edu MiscReg userFlagMask = 0xDD5; 8522292SN/A // Get only the user flags 8537720Sgblack@eecs.umich.edu ccFlagBits = newFlags & userFlagMask; 8543797Sgblack@eecs.umich.edu // Get everything else 8553221Sktlim@umich.edu nccFlagBits = newFlags & ~userFlagMask; 8562292SN/A ''' 8572693Sktlim@umich.edu 8584350Sgblack@eecs.umich.edu class Rdip(RdRegOp): 8596974Stjones1@inf.ed.ac.uk code = 'DestReg = RIP - CSBase' 8603326Sktlim@umich.edu 8613326Sktlim@umich.edu class Ruflags(RdRegOp): 8623326Sktlim@umich.edu code = 'DestReg = ccFlagBits' 8633326Sktlim@umich.edu 8643326Sktlim@umich.edu class Rflags(RdRegOp): 8653326Sktlim@umich.edu code = 'DestReg = ccFlagBits | nccFlagBits' 8663326Sktlim@umich.edu 8673326Sktlim@umich.edu class Ruflag(RegOp): 8683326Sktlim@umich.edu code = ''' 8693326Sktlim@umich.edu int flag = bits(ccFlagBits, imm8); 8703326Sktlim@umich.edu DestReg = merge(DestReg, flag, dataSize); 8713326Sktlim@umich.edu ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) : 8723326Sktlim@umich.edu (ccFlagBits & ~EZFBit); 8737823Ssteve.reinhardt@amd.com ''' 8748733Sgeoffrey.blake@arm.com def __init__(self, dest, imm, flags=None, \ 8758733Sgeoffrey.blake@arm.com dataSize="env.dataSize"): 8768733Sgeoffrey.blake@arm.com super(Ruflag, self).__init__(dest, \ 8778733Sgeoffrey.blake@arm.com "NUM_INTREGS", imm, flags, dataSize) 8788733Sgeoffrey.blake@arm.com 8793326Sktlim@umich.edu class Rflag(RegOp): 8803326Sktlim@umich.edu code = ''' 8813326Sktlim@umich.edu MiscReg flagMask = 0x3F7FDD5; 8822693Sktlim@umich.edu MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask; 8832693Sktlim@umich.edu int flag = bits(flags, imm8); 8842693Sktlim@umich.edu DestReg = merge(DestReg, flag, dataSize); 8852693Sktlim@umich.edu ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) : 8862693Sktlim@umich.edu (ccFlagBits & ~EZFBit); 8872693Sktlim@umich.edu ''' 8888481Sgblack@eecs.umich.edu def __init__(self, dest, imm, flags=None, \ 8898481Sgblack@eecs.umich.edu dataSize="env.dataSize"): 8908481Sgblack@eecs.umich.edu super(Rflag, self).__init__(dest, \ 8918481Sgblack@eecs.umich.edu "NUM_INTREGS", imm, flags, dataSize) 8928481Sgblack@eecs.umich.edu 8938481Sgblack@eecs.umich.edu class Sext(RegOp): 8948481Sgblack@eecs.umich.edu code = ''' 8958481Sgblack@eecs.umich.edu IntReg val = psrc1; 8968481Sgblack@eecs.umich.edu // Mask the bit position so that it wraps. 8978481Sgblack@eecs.umich.edu int bitPos = op2 & (dataSize * 8 - 1); 8988481Sgblack@eecs.umich.edu int sign_bit = bits(val, bitPos, bitPos); 8998481Sgblack@eecs.umich.edu uint64_t maskVal = mask(bitPos+1); 9008481Sgblack@eecs.umich.edu val = sign_bit ? (val | ~maskVal) : (val & maskVal); 9018481Sgblack@eecs.umich.edu DestReg = merge(DestReg, val, dataSize); 9028481Sgblack@eecs.umich.edu ''' 9038481Sgblack@eecs.umich.edu flag_code = ''' 9048481Sgblack@eecs.umich.edu if (!sign_bit) 9058481Sgblack@eecs.umich.edu ccFlagBits = ccFlagBits & 9068481Sgblack@eecs.umich.edu ~(ext & (CFBit | ECFBit | ZFBit | EZFBit)); 9078481Sgblack@eecs.umich.edu else 9088481Sgblack@eecs.umich.edu ccFlagBits = ccFlagBits | 9094032Sktlim@umich.edu (ext & (CFBit | ECFBit | ZFBit | EZFBit)); 9103221Sktlim@umich.edu ''' 9113221Sktlim@umich.edu 9126974Stjones1@inf.ed.ac.uk class Zext(RegOp): 9136974Stjones1@inf.ed.ac.uk code = 'DestReg = bits(psrc1, op2, 0);' 9148481Sgblack@eecs.umich.edu 9156974Stjones1@inf.ed.ac.uk class Rdcr(RegOp): 9166974Stjones1@inf.ed.ac.uk def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 9176974Stjones1@inf.ed.ac.uk super(Rdcr, self).__init__(dest, \ 9182669Sktlim@umich.edu src1, "NUM_INTREGS", flags, dataSize) 9196974Stjones1@inf.ed.ac.uk code = ''' 9206974Stjones1@inf.ed.ac.uk if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) { 9218481Sgblack@eecs.umich.edu fault = new InvalidOpcode(); 9226974Stjones1@inf.ed.ac.uk } else { 9236974Stjones1@inf.ed.ac.uk DestReg = ControlSrc1; 9246974Stjones1@inf.ed.ac.uk } 9256974Stjones1@inf.ed.ac.uk ''' 9266974Stjones1@inf.ed.ac.uk 9276974Stjones1@inf.ed.ac.uk class Wrcr(RegOp): 9286974Stjones1@inf.ed.ac.uk def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 9296974Stjones1@inf.ed.ac.uk super(Wrcr, self).__init__(dest, \ 9306974Stjones1@inf.ed.ac.uk src1, "NUM_INTREGS", flags, dataSize) 9316974Stjones1@inf.ed.ac.uk code = ''' 9326974Stjones1@inf.ed.ac.uk if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) { 9336974Stjones1@inf.ed.ac.uk fault = new InvalidOpcode(); 9346974Stjones1@inf.ed.ac.uk } else { 9356974Stjones1@inf.ed.ac.uk // There are *s in the line below so it doesn't confuse the 9366974Stjones1@inf.ed.ac.uk // parser. They may be unnecessary. 9376974Stjones1@inf.ed.ac.uk //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize); 9386974Stjones1@inf.ed.ac.uk MiscReg newVal = psrc1; 9396974Stjones1@inf.ed.ac.uk 9406974Stjones1@inf.ed.ac.uk // Check for any modifications that would cause a fault. 9416974Stjones1@inf.ed.ac.uk switch(dest) { 9426974Stjones1@inf.ed.ac.uk case 0: 9436974Stjones1@inf.ed.ac.uk { 9446974Stjones1@inf.ed.ac.uk Efer efer = EferOp; 9456974Stjones1@inf.ed.ac.uk CR0 cr0 = newVal; 9462292SN/A CR4 oldCr4 = CR4Op; 9472292SN/A if (bits(newVal, 63, 32) || 9482292SN/A (!cr0.pe && cr0.pg) || 9492292SN/A (!cr0.cd && cr0.nw) || 9502292SN/A (cr0.pg && efer.lme && !oldCr4.pae)) 9512292SN/A fault = new GeneralProtection(0); 9522292SN/A } 9532292SN/A break; 9542292SN/A case 2: 9552292SN/A break; 9562292SN/A case 3: 9572292SN/A break; 9582292SN/A case 4: 9592292SN/A { 9602292SN/A CR4 cr4 = newVal; 9612292SN/A // PAE can't be disabled in long mode. 9622292SN/A if (bits(newVal, 63, 11) || 9632292SN/A (machInst.mode.mode == LongMode && !cr4.pae)) 9642292SN/A fault = new GeneralProtection(0); 9652292SN/A } 9662292SN/A break; 9672292SN/A case 8: 9682292SN/A { 9692292SN/A if (bits(newVal, 63, 4)) 9702292SN/A fault = new GeneralProtection(0); 9712292SN/A } 9722292SN/A default: 9732292SN/A panic("Unrecognized control register %d.\\n", dest); 9742329SN/A } 9752292SN/A ControlDest = newVal; 9762292SN/A } 9772292SN/A ''' 9782292SN/A 9792292SN/A # Microops for manipulating segmentation registers 9807720Sgblack@eecs.umich.edu class SegOp(RegOp): 9812292SN/A abstract = True 9827720Sgblack@eecs.umich.edu def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 9832292SN/A super(SegOp, self).__init__(dest, \ 9842292SN/A src1, "NUM_INTREGS", flags, dataSize) 9852292SN/A 9862292SN/A class Wrbase(SegOp): 9872292SN/A code = ''' 9882292SN/A SegBaseDest = psrc1; 9892292SN/A ''' 9902292SN/A 9912329SN/A class Wrlimit(SegOp): 9922731Sktlim@umich.edu code = ''' 9932292SN/A SegLimitDest = psrc1; 9942292SN/A ''' 9952292SN/A 9962292SN/A class Wrsel(SegOp): 9972292SN/A code = ''' 9982292SN/A SegSelDest = psrc1; 9992292SN/A ''' 10002727Sktlim@umich.edu 10012292SN/A class Rdbase(SegOp): 10022292SN/A code = ''' 10032292SN/A DestReg = SegBaseDest; 10042292SN/A ''' 10052292SN/A 10062292SN/A class Rdlimit(SegOp): 10072292SN/A code = ''' 10082292SN/A DestReg = SegLimitSrc1; 10092292SN/A ''' 10102292SN/A 10114032Sktlim@umich.edu class Rdsel(SegOp): 10124032Sktlim@umich.edu code = ''' 10134032Sktlim@umich.edu DestReg = SegSelSrc1; 10144032Sktlim@umich.edu ''' 10152292SN/A 10162292SN/A class Chks(SegOp): 10172292SN/A code = ''' 10182292SN/A // The selector is in source 1 and can be at most 16 bits. 10192292SN/A SegSelector selector = psrc1; 10202329SN/A 10212292SN/A // Compute the address of the descriptor and set DestReg to it. 10222292SN/A if (selector.ti) { 10232292SN/A // A descriptor in the LDT 10242292SN/A Addr target = (selector.si << 3) + LDTRBase; 10257720Sgblack@eecs.umich.edu if (!LDTRSel || (selector.si << 3) + dataSize > LDTRLimit) 10262292SN/A fault = new GeneralProtection(selector & mask(16)); 10277720Sgblack@eecs.umich.edu DestReg = target; 10282292SN/A } else { 10292292SN/A // A descriptor in the GDT 10302329SN/A Addr target = (selector.si << 3) + GDTRBase; 10312329SN/A if ((selector.si << 3) + dataSize > GDTRLimit) 10322292SN/A fault = new GeneralProtection(selector & mask(16)); 10332292SN/A DestReg = target; 10342292SN/A } 10352292SN/A ''' 10362292SN/A flag_code = ''' 10372292SN/A // Check for a NULL selector and set ZF,EZF appropriately. 10382292SN/A ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit)); 10392329SN/A if (!selector.si && !selector.ti) 10402731Sktlim@umich.edu ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit)); 10412292SN/A ''' 10422292SN/A 10432292SN/A class Wrdh(RegOp): 10444032Sktlim@umich.edu code = ''' 10454032Sktlim@umich.edu 10464032Sktlim@umich.edu ''' 10474032Sktlim@umich.edu 10486974Stjones1@inf.ed.ac.uk class Wrtsc(WrRegOp): 10496974Stjones1@inf.ed.ac.uk code = ''' 10506974Stjones1@inf.ed.ac.uk TscOp = psrc1; 10516974Stjones1@inf.ed.ac.uk ''' 10526974Stjones1@inf.ed.ac.uk 10536974Stjones1@inf.ed.ac.uk class Rdtsc(RdRegOp): 10546974Stjones1@inf.ed.ac.uk code = ''' 10554032Sktlim@umich.edu DestReg = TscOp; 10562292SN/A ''' 10572292SN/A 10582292SN/A class Wrdl(RegOp): 10592292SN/A code = ''' 10602292SN/A SegDescriptor desc = SrcReg1; 10612292SN/A SegAttr attr = 0; 10622292SN/A attr.dpl = desc.dpl; 10632727Sktlim@umich.edu attr.defaultSize = desc.d; 10642292SN/A if (!desc.s) { 10652292SN/A SegBaseDest = SegBaseDest; 10662292SN/A SegLimitDest = SegLimitDest; 10672292SN/A SegAttrDest = SegAttrDest; 10682292SN/A panic("System segment encountered.\\n"); 10693349Sbinkertn@umich.edu } else { 10702693Sktlim@umich.edu if (!desc.p) 10712693Sktlim@umich.edu panic("Segment not present.\\n"); 10722693Sktlim@umich.edu if (desc.type.codeOrData) { 10732693Sktlim@umich.edu attr.readable = desc.type.r; 10742693Sktlim@umich.edu attr.longMode = desc.l; 10752693Sktlim@umich.edu } else { 10762693Sktlim@umich.edu attr.expandDown = desc.type.e; 10772693Sktlim@umich.edu attr.readable = 1; 10782693Sktlim@umich.edu attr.writable = desc.type.w; 10792693Sktlim@umich.edu } 10802693Sktlim@umich.edu Addr base = desc.baseLow | (desc.baseHigh << 24); 10812693Sktlim@umich.edu Addr limit = desc.limitLow | (desc.limitHigh << 16); 10822693Sktlim@umich.edu if (desc.g) 10832693Sktlim@umich.edu limit = (limit << 12) | mask(12); 10842693Sktlim@umich.edu SegBaseDest = base; 10852693Sktlim@umich.edu SegLimitDest = limit; 10862733Sktlim@umich.edu SegAttrDest = attr; 10872693Sktlim@umich.edu } 10882732Sktlim@umich.edu ''' 10892693Sktlim@umich.edu}}; 10902733Sktlim@umich.edu