/// 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 Pack(MediaOp): code = ''' assert(srcSize == destSize * 2); int items = (sizeof(FloatRegBits) / destSize); int destBits = destSize * 8; int srcBits = srcSize * 8; uint64_t result = 0; int i; for (i = 0; i < items / 2; i++) { uint64_t picked = bits(FpSrcReg1.uqw, (i + 1) * srcBits - 1, (i + 0) * srcBits); unsigned signBit = bits(picked, srcBits - 1); uint64_t overflow = bits(picked, srcBits - 1, destBits - 1); // Handle saturation. if (signBit) { if (overflow != mask(destBits - srcBits + 1)) { if (ext & 0x1) picked = (1 << (destBits - 1)); else picked = 0; } } else { if (overflow != 0) { if (ext & 0x1) picked = mask(destBits - 1); else picked = mask(destBits); } } result = insertBits(result, (i + 1) * destBits - 1, (i + 0) * destBits, picked); } for (;i < items; i++) { uint64_t picked = bits(FpSrcReg2.uqw, (i - items + 1) * srcBits - 1, (i - items + 0) * srcBits); unsigned signBit = bits(picked, srcBits - 1); uint64_t overflow = bits(picked, srcBits - 1, destBits - 1); // Handle saturation. if (signBit) { if (overflow != mask(destBits - srcBits + 1)) { if (ext & 0x1) picked = (1 << (destBits - 1)); else picked = 0; } } else { if (overflow != 0) { if (ext & 0x1) picked = mask(destBits - 1); else picked = mask(destBits); } } result = insertBits(result, (i + 1) * destBits - 1, (i + 0) * destBits, picked); } 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; ''' class Mminf(MediaOp): code = ''' union floatInt { float f; uint32_t i; }; union doubleInt { double d; uint64_t i; }; assert(srcSize == destSize); int size = srcSize; int sizeBits = size * 8; assert(srcSize == 4 || srcSize == 8); int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / size); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { double arg1, arg2; int hiIndex = (i + 1) * sizeBits - 1; int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); if (size == 4) { floatInt fi; fi.i = arg1Bits; arg1 = fi.f; fi.i = arg2Bits; arg2 = fi.f; } else { doubleInt di; di.i = arg1Bits; arg1 = di.d; di.i = arg2Bits; arg2 = di.d; } if (arg1 < arg2) { result = insertBits(result, hiIndex, loIndex, arg1Bits); } else { result = insertBits(result, hiIndex, loIndex, arg2Bits); } } FpDestReg.uqw = result; ''' class Mmaxf(MediaOp): code = ''' union floatInt { float f; uint32_t i; }; union doubleInt { double d; uint64_t i; }; assert(srcSize == destSize); int size = srcSize; int sizeBits = size * 8; assert(srcSize == 4 || srcSize == 8); int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / size); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { double arg1, arg2; int hiIndex = (i + 1) * sizeBits - 1; int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); if (size == 4) { floatInt fi; fi.i = arg1Bits; arg1 = fi.f; fi.i = arg2Bits; arg2 = fi.f; } else { doubleInt di; di.i = arg1Bits; arg1 = di.d; di.i = arg2Bits; arg2 = di.d; } if (arg1 > arg2) { result = insertBits(result, hiIndex, loIndex, arg1Bits); } else { result = insertBits(result, hiIndex, loIndex, arg2Bits); } } FpDestReg.uqw = result; ''' class Mmini(MediaOp): code = ''' assert(srcSize == destSize); int size = srcSize; int sizeBits = size * 8; int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / size); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int hiIndex = (i + 1) * sizeBits - 1; int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); int64_t arg1 = arg1Bits | (0 - (arg1Bits & (1 << (sizeBits - 1)))); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); int64_t arg2 = arg2Bits | (0 - (arg2Bits & (1 << (sizeBits - 1)))); uint64_t resBits; if (ext & 0x2) { if (arg1 < arg2) { resBits = arg1Bits; } else { resBits = arg2Bits; } } else { if (arg1Bits < arg2Bits) { resBits = arg1Bits; } else { resBits = arg2Bits; } } result = insertBits(result, hiIndex, loIndex, resBits); } FpDestReg.uqw = result; ''' class Mmaxi(MediaOp): code = ''' assert(srcSize == destSize); int size = srcSize; int sizeBits = size * 8; int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / size); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int hiIndex = (i + 1) * sizeBits - 1; int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); int64_t arg1 = arg1Bits | (0 - (arg1Bits & (1 << (sizeBits - 1)))); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); int64_t arg2 = arg2Bits | (0 - (arg2Bits & (1 << (sizeBits - 1)))); uint64_t resBits; if (ext & 0x2) { if (arg1 > arg2) { resBits = arg1Bits; } else { resBits = arg2Bits; } } else { if (arg1Bits > arg2Bits) { resBits = arg1Bits; } else { resBits = arg2Bits; } } result = insertBits(result, hiIndex, loIndex, resBits); } FpDestReg.uqw = result; ''' class Msqrt(MediaOp): def __init__(self, dest, src, \ size = None, destSize = None, srcSize = None, ext = None): super(Msqrt, self).__init__(dest, src,\ "InstRegIndex(0)", size, destSize, srcSize, ext) code = ''' union floatInt { float f; uint32_t i; }; union doubleInt { double d; uint64_t i; }; assert(srcSize == destSize); int size = srcSize; int sizeBits = size * 8; assert(srcSize == 4 || srcSize == 8); int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / size); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int hiIndex = (i + 1) * sizeBits - 1; int loIndex = (i + 0) * sizeBits; uint64_t argBits = bits(FpSrcReg1.uqw, hiIndex, loIndex); if (size == 4) { floatInt fi; fi.i = argBits; fi.f = sqrt(fi.f); argBits = fi.i; } else { doubleInt di; di.i = argBits; di.d = sqrt(di.d); argBits = di.i; } result = insertBits(result, hiIndex, loIndex, argBits); } FpDestReg.uqw = result; ''' class Maddf(MediaOp): code = ''' union floatInt { float f; uint32_t i; }; union doubleInt { double d; uint64_t i; }; assert(srcSize == destSize); int size = srcSize; int sizeBits = size * 8; assert(srcSize == 4 || srcSize == 8); int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / size); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int hiIndex = (i + 1) * sizeBits - 1; int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); uint64_t resBits; if (size == 4) { floatInt arg1, arg2, res; arg1.i = arg1Bits; arg2.i = arg2Bits; res.f = arg1.f + arg2.f; resBits = res.i; } else { doubleInt arg1, arg2, res; arg1.i = arg1Bits; arg2.i = arg2Bits; res.d = arg1.d + arg2.d; resBits = res.i; } result = insertBits(result, hiIndex, loIndex, resBits); } FpDestReg.uqw = result; ''' class Msubf(MediaOp): code = ''' union floatInt { float f; uint32_t i; }; union doubleInt { double d; uint64_t i; }; assert(srcSize == destSize); int size = srcSize; int sizeBits = size * 8; assert(srcSize == 4 || srcSize == 8); int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / size); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int hiIndex = (i + 1) * sizeBits - 1; int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); uint64_t resBits; if (size == 4) { floatInt arg1, arg2, res; arg1.i = arg1Bits; arg2.i = arg2Bits; res.f = arg1.f - arg2.f; resBits = res.i; } else { doubleInt arg1, arg2, res; arg1.i = arg1Bits; arg2.i = arg2Bits; res.d = arg1.d - arg2.d; resBits = res.i; } result = insertBits(result, hiIndex, loIndex, resBits); } FpDestReg.uqw = result; ''' class Mmulf(MediaOp): code = ''' union floatInt { float f; uint32_t i; }; union doubleInt { double d; uint64_t i; }; assert(srcSize == destSize); int size = srcSize; int sizeBits = size * 8; assert(srcSize == 4 || srcSize == 8); int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / size); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int hiIndex = (i + 1) * sizeBits - 1; int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); uint64_t resBits; if (size == 4) { floatInt arg1, arg2, res; arg1.i = arg1Bits; arg2.i = arg2Bits; res.f = arg1.f * arg2.f; resBits = res.i; } else { doubleInt arg1, arg2, res; arg1.i = arg1Bits; arg2.i = arg2Bits; res.d = arg1.d * arg2.d; resBits = res.i; } result = insertBits(result, hiIndex, loIndex, resBits); } FpDestReg.uqw = result; ''' class Mdivf(MediaOp): code = ''' union floatInt { float f; uint32_t i; }; union doubleInt { double d; uint64_t i; }; assert(srcSize == destSize); int size = srcSize; int sizeBits = size * 8; assert(srcSize == 4 || srcSize == 8); int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / size); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int hiIndex = (i + 1) * sizeBits - 1; int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); uint64_t resBits; if (size == 4) { floatInt arg1, arg2, res; arg1.i = arg1Bits; arg2.i = arg2Bits; res.f = arg1.f / arg2.f; resBits = res.i; } else { doubleInt arg1, arg2, res; arg1.i = arg1Bits; arg2.i = arg2Bits; res.d = arg1.d / arg2.d; resBits = res.i; } result = insertBits(result, hiIndex, loIndex, resBits); } FpDestReg.uqw = result; ''' class Maddi(MediaOp): code = ''' assert(srcSize == destSize); int size = srcSize; int sizeBits = size * 8; int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / size); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int hiIndex = (i + 1) * sizeBits - 1; int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); uint64_t resBits = arg1Bits + arg2Bits; if (ext & 0x2) { if (findCarry(sizeBits, resBits, arg1Bits, arg2Bits)) resBits = mask(sizeBits); } else if (ext & 0x4) { int arg1Sign = bits(arg1Bits, sizeBits - 1); int arg2Sign = bits(arg2Bits, sizeBits - 1); int resSign = bits(resBits, sizeBits - 1); if ((arg1Sign == arg2Sign) && (arg1Sign != resSign)) { if (resSign == 0) resBits = (1 << (sizeBits - 1)); else resBits = mask(sizeBits - 1); } } result = insertBits(result, hiIndex, loIndex, resBits); } FpDestReg.uqw = result; ''' class Msubi(MediaOp): code = ''' assert(srcSize == destSize); int size = srcSize; int sizeBits = size * 8; int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / size); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int hiIndex = (i + 1) * sizeBits - 1; int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); uint64_t resBits = arg1Bits - arg2Bits; if (ext & 0x2) { if (arg2Bits > arg1Bits) { resBits = 0; } else if (!findCarry(sizeBits, resBits, arg1Bits, ~arg2Bits)) { resBits = mask(sizeBits); } } else if (ext & 0x4) { int arg1Sign = bits(arg1Bits, sizeBits - 1); int arg2Sign = !bits(arg2Bits, sizeBits - 1); int resSign = bits(resBits, sizeBits - 1); if ((arg1Sign == arg2Sign) && (arg1Sign != resSign)) { if (resSign == 0) resBits = (1 << (sizeBits - 1)); else resBits = mask(sizeBits - 1); } } result = insertBits(result, hiIndex, loIndex, resBits); } FpDestReg.uqw = result; ''' class Mmuli(MediaOp): code = ''' int srcBits = srcSize * 8; int destBits = destSize * 8; assert(destBits <= 64); assert(destSize >= srcSize); int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / destSize); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int srcHiIndex = (i + 1) * srcBits - 1; int srcLoIndex = (i + 0) * srcBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, srcHiIndex, srcLoIndex); uint64_t arg2Bits = bits(FpSrcReg2.uqw, srcHiIndex, srcLoIndex); uint64_t resBits; if (ext & 0x2) { int64_t arg1 = arg1Bits | (0 - (arg1Bits & (1 << (srcBits - 1)))); int64_t arg2 = arg2Bits | (0 - (arg2Bits & (1 << (srcBits - 1)))); resBits = (uint64_t)(arg1 * arg2); } else { resBits = arg1Bits * arg2Bits; } if (ext & 0x4) resBits += (1 << (destBits - 1)); if (ext & 0x8) resBits >>= destBits; int destHiIndex = (i + 1) * destBits - 1; int destLoIndex = (i + 0) * destBits; result = insertBits(result, destHiIndex, destLoIndex, resBits); } FpDestReg.uqw = result; ''' class Cvti2f(MediaOp): def __init__(self, dest, src, \ size = None, destSize = None, srcSize = None, ext = None): super(Cvti2f, self).__init__(dest, src,\ "InstRegIndex(0)", size, destSize, srcSize, ext) code = ''' union floatInt { float f; uint32_t i; }; union doubleInt { double d; uint64_t i; }; assert(destSize == 4 || destSize == 8); assert(srcSize == 4 || srcSize == 8); int srcSizeBits = srcSize * 8; int destSizeBits = destSize * 8; int items; int srcStart = 0; int destStart = 0; if (srcSize == 2 * destSize) { items = (ext & 0x1) ? 1: sizeof(FloatRegBits) / srcSize; if (ext & 0x2) destStart = destSizeBits * items; } else if (destSize == 2 * srcSize) { items = (ext & 0x1) ? 1: sizeof(FloatRegBits) / destSize; if (ext & 0x2) srcStart = srcSizeBits * items; } else { items = (ext & 0x1) ? 1: sizeof(FloatRegBits) / destSize; } uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int srcHiIndex = srcStart + (i + 1) * srcSizeBits - 1; int srcLoIndex = srcStart + (i + 0) * srcSizeBits; uint64_t argBits = bits(FpSrcReg1.uqw, srcHiIndex, srcLoIndex); int64_t sArg = argBits | (0 - (argBits & (1 << srcHiIndex))); double arg = sArg; if (destSize == 4) { floatInt fi; fi.f = arg; argBits = fi.i; } else { doubleInt di; di.d = arg; argBits = di.i; } int destHiIndex = destStart + (i + 1) * destSizeBits - 1; int destLoIndex = destStart + (i + 0) * destSizeBits; result = insertBits(result, destHiIndex, destLoIndex, argBits); } FpDestReg.uqw = result; ''' class Cvtf2f(MediaOp): def __init__(self, dest, src, \ size = None, destSize = None, srcSize = None, ext = None): super(Cvtf2f, self).__init__(dest, src,\ "InstRegIndex(0)", size, destSize, srcSize, ext) code = ''' union floatInt { float f; uint32_t i; }; union doubleInt { double d; uint64_t i; }; assert(destSize == 4 || destSize == 8); assert(srcSize == 4 || srcSize == 8); int srcSizeBits = srcSize * 8; int destSizeBits = destSize * 8; int items; int srcStart = 0; int destStart = 0; if (srcSize == 2 * destSize) { items = (ext & 0x1) ? 1: sizeof(FloatRegBits) / srcSize; if (ext & 0x2) destStart = destSizeBits * items; } else if (destSize == 2 * srcSize) { items = (ext & 0x1) ? 1: sizeof(FloatRegBits) / destSize; if (ext & 0x2) srcStart = srcSizeBits * items; } else { items = (ext & 0x1) ? 1: sizeof(FloatRegBits) / destSize; } uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int srcHiIndex = srcStart + (i + 1) * srcSizeBits - 1; int srcLoIndex = srcStart + (i + 0) * srcSizeBits; uint64_t argBits = bits(FpSrcReg1.uqw, srcHiIndex, srcLoIndex); double arg; if (srcSize == 4) { floatInt fi; fi.i = argBits; arg = fi.f; } else { doubleInt di; di.i = argBits; arg = di.d; } if (destSize == 4) { floatInt fi; fi.f = arg; argBits = fi.i; } else { doubleInt di; di.d = arg; argBits = di.i; } int destHiIndex = destStart + (i + 1) * destSizeBits - 1; int destLoIndex = destStart + (i + 0) * destSizeBits; result = insertBits(result, destHiIndex, destLoIndex, argBits); } FpDestReg.uqw = result; ''' class Mcmpi2r(MediaOp): code = ''' union floatInt { float f; uint32_t i; }; union doubleInt { double d; uint64_t i; }; assert(srcSize == destSize); int size = srcSize; int sizeBits = size * 8; int items = (ext & 0x1) ? 1: (sizeof(FloatRegBits) / size); uint64_t result = FpDestReg.uqw; for (int i = 0; i < items; i++) { int hiIndex = (i + 1) * sizeBits - 1; int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); int64_t arg1 = arg1Bits | (0 - (arg1Bits & (1 << (sizeBits - 1)))); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); int64_t arg2 = arg2Bits | (0 - (arg2Bits & (1 << (sizeBits - 1)))); uint64_t resBits = 0; if ((ext & 0x2) == 0 && arg1 == arg2 || (ext & 0x2) == 0x2 && arg1 > arg2) resBits = mask(sizeBits); result = insertBits(result, hiIndex, loIndex, resBits); } FpDestReg.uqw = result; ''' }};