/// Copyright (c) 2009 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer; // redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution; // neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: Gabe Black def template MediaOpExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { Fault fault = NoFault; %(op_decl)s; %(op_rd)s; %(code)s; //Write the resulting state to the execution context if(fault == NoFault) { %(op_wb)s; } return fault; } }}; def template MediaOpRegDeclare {{ class %(class_name)s : public %(base_class)s { protected: void buildMe(); public: %(class_name)s(ExtMachInst _machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest, uint8_t _srcSize, uint8_t _destSize, uint16_t _ext); %(class_name)s(ExtMachInst _machInst, const char * instMnem, InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest, uint8_t _srcSize, uint8_t _destSize, uint16_t _ext); %(BasicExecDeclare)s }; }}; def template MediaOpImmDeclare {{ class %(class_name)s : public %(base_class)s { protected: void buildMe(); public: %(class_name)s(ExtMachInst _machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, InstRegIndex _src1, uint16_t _imm8, InstRegIndex _dest, uint8_t _srcSize, uint8_t _destSize, uint16_t _ext); %(class_name)s(ExtMachInst _machInst, const char * instMnem, InstRegIndex _src1, uint16_t _imm8, InstRegIndex _dest, uint8_t _srcSize, uint8_t _destSize, uint16_t _ext); %(BasicExecDeclare)s }; }}; def template MediaOpRegConstructor {{ inline void %(class_name)s::buildMe() { %(constructor)s; } inline %(class_name)s::%(class_name)s( ExtMachInst machInst, const char * instMnem, InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest, uint8_t _srcSize, uint8_t _destSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, false, false, false, false, _src1, _src2, _dest, _srcSize, _destSize, _ext, %(op_class)s) { buildMe(); } inline %(class_name)s::%(class_name)s( ExtMachInst machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest, uint8_t _srcSize, uint8_t _destSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, isMicro, isDelayed, isFirst, isLast, _src1, _src2, _dest, _srcSize, _destSize, _ext, %(op_class)s) { buildMe(); } }}; def template MediaOpImmConstructor {{ inline void %(class_name)s::buildMe() { %(constructor)s; } inline %(class_name)s::%(class_name)s( ExtMachInst machInst, const char * instMnem, InstRegIndex _src1, uint16_t _imm8, InstRegIndex _dest, uint8_t _srcSize, uint8_t _destSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, false, false, false, false, _src1, _imm8, _dest, _srcSize, _destSize, _ext, %(op_class)s) { buildMe(); } inline %(class_name)s::%(class_name)s( ExtMachInst machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, InstRegIndex _src1, uint16_t _imm8, InstRegIndex _dest, uint8_t _srcSize, uint8_t _destSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, isMicro, isDelayed, isFirst, isLast, _src1, _imm8, _dest, _srcSize, _destSize, _ext, %(op_class)s) { buildMe(); } }}; let {{ # Make these empty strings so that concatenating onto # them will always work. header_output = "" decoder_output = "" exec_output = "" immTemplates = ( MediaOpImmDeclare, MediaOpImmConstructor, MediaOpExecute) regTemplates = ( MediaOpRegDeclare, MediaOpRegConstructor, MediaOpExecute) class MediaOpMeta(type): def buildCppClasses(self, name, Name, suffix, code): # Globals to stick the output in global header_output global decoder_output global exec_output # If op2 is used anywhere, make register and immediate versions # of this code. matcher = re.compile("(?s?)op2(?P\\.\\w+)?") match = matcher.search(code) if match: typeQual = "" if match.group("typeQual"): typeQual = match.group("typeQual") src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual) self.buildCppClasses(name, Name, suffix, matcher.sub(src2_name, code)) self.buildCppClasses(name + "i", Name, suffix + "Imm", matcher.sub("imm8", code)) return base = "X86ISA::MediaOp" # If imm8 shows up in the code, use the immediate templates, if # not, hopefully the register ones will be correct. matcher = re.compile("(?\\.\\w+)?") if matcher.search(code): microopClasses[name + 'i'] = cls return cls class MediaOp(X86Microop): __metaclass__ = MediaOpMeta # This class itself doesn't act as a microop abstract = True def __init__(self, dest, src1, op2, size = None, destSize = None, srcSize = None, ext = None): self.dest = dest self.src1 = src1 self.op2 = op2 if size is not None: self.srcSize = size self.destSize = size if srcSize is not None: self.srcSize = srcSize if destSize is not None: self.destSize = destSize if self.srcSize is None: raise Exception, "Source size not set." if self.destSize is None: raise Exception, "Dest size not set." if ext is None: self.ext = 0 else: self.ext = ext def getAllocator(self, *microFlags): className = self.className if self.mnemonic == self.base_mnemonic + 'i': className += "Imm" allocator = '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(src1)s, %(op2)s, %(dest)s, %(srcSize)s, %(destSize)s, %(ext)s)''' % { "class_name" : className, "flags" : self.microFlagsText(microFlags), "src1" : self.src1, "op2" : self.op2, "dest" : self.dest, "srcSize" : self.srcSize, "destSize" : self.destSize, "ext" : self.ext} return allocator class Mov2int(MediaOp): def __init__(self, dest, src, \ size = None, destSize = None, srcSize = None, ext = None): super(Mov2int, self).__init__(dest, src,\ "InstRegIndex(0)", size, destSize, srcSize, ext) code = ''' uint64_t fpSrcReg1 = bits(FpSrcReg1.uqw, srcSize * 8 - 1, 0); DestReg = merge(DestReg, fpSrcReg1, destSize); ''' class Mov2fp(MediaOp): def __init__(self, dest, src, \ size = None, destSize = None, srcSize = None, ext = None): super(Mov2fp, self).__init__(dest, src,\ "InstRegIndex(0)", size, destSize, srcSize, ext) code = ''' uint64_t srcReg1 = pick(SrcReg1, 0, srcSize); FpDestReg.uqw = insertBits(FpDestReg.uqw, destSize * 8 - 1, 0, srcReg1); ''' class Unpack(MediaOp): code = ''' assert(srcSize == destSize); int size = destSize; int items = (sizeof(FloatRegBits) / size) / 2; int offset = ext ? items : 0; uint64_t result = 0; for (int i = 0; i < items; i++) { uint64_t pickedLow = bits(FpSrcReg1.uqw, (i + offset + 1) * 8 * size - 1, (i + offset) * 8 * size); result = insertBits(result, (2 * i + 1) * 8 * size - 1, (2 * i + 0) * 8 * size, pickedLow); uint64_t pickedHigh = bits(FpSrcReg2.uqw, (i + offset + 1) * 8 * size - 1, (i + offset) * 8 * size); result = insertBits(result, (2 * i + 2) * 8 * size - 1, (2 * i + 1) * 8 * size, pickedHigh); } FpDestReg.uqw = result; ''' class Mxor(MediaOp): def __init__(self, dest, src1, src2): super(Mxor, self).__init__(dest, src1, src2, 1) code = ''' FpDestReg.uqw = FpSrcReg1.uqw ^ FpSrcReg2.uqw; ''' class Mor(MediaOp): def __init__(self, dest, src1, src2): super(Mor, self).__init__(dest, src1, src2, 1) code = ''' FpDestReg.uqw = FpSrcReg1.uqw | FpSrcReg2.uqw; ''' class Mand(MediaOp): def __init__(self, dest, src1, src2): super(Mand, self).__init__(dest, src1, src2, 1) code = ''' FpDestReg.uqw = FpSrcReg1.uqw & FpSrcReg2.uqw; ''' class Mandn(MediaOp): def __init__(self, dest, src1, src2): super(Mandn, self).__init__(dest, src1, src2, 1) code = ''' FpDestReg.uqw = ~FpSrcReg1.uqw & FpSrcReg2.uqw; ''' }};