// -*- mode:c++ -*- // Copyright (c) 2010 ARM Limited // All rights reserved // // The license below extends only to copyright in the software and shall // not be construed as granting a license to any other intellectual // property including but not limited to intellectual property relating // to a hardware implementation of the functionality of the software // licensed hereunder. You may use the software subject to the license // terms below provided that you ensure that this notice is replicated // unmodified and in its entirety in all distributions of the software, // modified or unmodified, in source code or in binary form. // // 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 let {{ header_output = "" decoder_output = "" exec_output = "" calcGECode = ''' CondCodes = insertBits(CondCodes, 19, 16, resTemp); ''' calcQCode = ''' CondCodes = CondCodes | ((resTemp & 1) << 27); ''' calcCcCode = ''' uint16_t _ic, _iv, _iz, _in; _in = (resTemp >> %(negBit)d) & 1; _iz = (resTemp == 0); _iv = %(ivValue)s & 1; _ic = %(icValue)s & 1; CondCodes = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 | (CondCodes & 0x0FFFFFFF); DPRINTF(Arm, "(in, iz, ic, iv) = (%%d, %%d, %%d, %%d)\\n", _in, _iz, _ic, _iv); ''' # Dict of code to set the carry flag. (imm, reg, reg-reg) oldC = 'CondCodes<29:>' oldV = 'CondCodes<28:>' carryCode = { "none": (oldC, oldC, oldC), "llbit": (oldC, oldC, oldC), "saturate": ('0', '0', '0'), "overflow": ('0', '0', '0'), "ge": ('0', '0', '0'), "add": ('findCarry(32, resTemp, Op1, secondOp)', 'findCarry(32, resTemp, Op1, secondOp)', 'findCarry(32, resTemp, Op1, secondOp)'), "sub": ('findCarry(32, resTemp, Op1, ~secondOp)', 'findCarry(32, resTemp, Op1, ~secondOp)', 'findCarry(32, resTemp, Op1, ~secondOp)'), "rsb": ('findCarry(32, resTemp, secondOp, ~Op1)', 'findCarry(32, resTemp, secondOp, ~Op1)', 'findCarry(32, resTemp, secondOp, ~Op1)'), "logic": ('(rotC ? bits(secondOp, 31) : %s)' % oldC, 'shift_carry_imm(Op2, shiftAmt, shiftType, %s)' % oldC, 'shift_carry_rs(Op2, Shift<7:0>, shiftType, %s)' % oldC) } # Dict of code to set the overflow flag. overflowCode = { "none": oldV, "llbit": oldV, "saturate": '0', "overflow": '0', "ge": '0', "add": 'findOverflow(32, resTemp, Op1, secondOp)', "sub": 'findOverflow(32, resTemp, Op1, ~secondOp)', "rsb": 'findOverflow(32, resTemp, secondOp, ~Op1)', "logic": oldV } secondOpRe = re.compile("secondOp") immOp2 = "imm" regOp2 = "shift_rm_imm(Op2, shiftAmt, shiftType, CondCodes<29:>)" regRegOp2 = "shift_rm_rs(Op2, Shift<7:0>, shiftType, CondCodes<29:>)" def buildImmDataInst(mnem, code, flagType = "logic", suffix = "Imm", \ buildCc = True, buildNonCc = True): cCode = carryCode[flagType] vCode = overflowCode[flagType] negBit = 31 if flagType == "llbit": negBit = 63 if flagType == "saturate": immCcCode = calcQCode elif flagType == "ge": immCcCode = calcGECode else: immCcCode = calcCcCode % { "icValue": secondOpRe.sub(immOp2, cCode[0]), "ivValue": secondOpRe.sub(immOp2, vCode), "negBit": negBit } immCode = secondOpRe.sub(immOp2, code) immIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataImmOp", {"code" : immCode, "predicate_test": predicateTest}) immIopCc = InstObjParams(mnem + "s", mnem.capitalize() + suffix + "Cc", "DataImmOp", {"code" : immCode + immCcCode, "predicate_test": predicateTest}) def subst(iop): global header_output, decoder_output, exec_output header_output += DataImmDeclare.subst(iop) decoder_output += DataImmConstructor.subst(iop) exec_output += PredOpExecute.subst(iop) if buildNonCc: subst(immIop) if buildCc: subst(immIopCc) def buildRegDataInst(mnem, code, flagType = "logic", suffix = "Reg", \ buildCc = True, buildNonCc = True): cCode = carryCode[flagType] vCode = overflowCode[flagType] negBit = 31 if flagType == "llbit": negBit = 63 if flagType == "saturate": regCcCode = calcQCode elif flagType == "ge": regCcCode = calcGECode else: regCcCode = calcCcCode % { "icValue": secondOpRe.sub(regOp2, cCode[1]), "ivValue": secondOpRe.sub(regOp2, vCode), "negBit": negBit } regCode = secondOpRe.sub(regOp2, code) regIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataRegOp", {"code" : regCode, "predicate_test": predicateTest}) regIopCc = InstObjParams(mnem + "s", mnem.capitalize() + suffix + "Cc", "DataRegOp", {"code" : regCode + regCcCode, "predicate_test": predicateTest}) def subst(iop): global header_output, decoder_output, exec_output header_output += DataRegDeclare.subst(iop) decoder_output += DataRegConstructor.subst(iop) exec_output += PredOpExecute.subst(iop) if buildNonCc: subst(regIop) if buildCc: subst(regIopCc) def buildRegRegDataInst(mnem, code, flagType = "logic", \ suffix = "RegReg", \ buildCc = True, buildNonCc = True): cCode = carryCode[flagType] vCode = overflowCode[flagType] negBit = 31 if flagType == "llbit": negBit = 63 if flagType == "saturate": regRegCcCode = calcQCode elif flagType == "ge": regRegCcCode = calcGECode else: regRegCcCode = calcCcCode % { "icValue": secondOpRe.sub(regRegOp2, cCode[2]), "ivValue": secondOpRe.sub(regRegOp2, vCode), "negBit": negBit } regRegCode = secondOpRe.sub(regRegOp2, code) regRegIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataRegRegOp", {"code" : regRegCode, "predicate_test": predicateTest}) regRegIopCc = InstObjParams(mnem + "s", mnem.capitalize() + suffix + "Cc", "DataRegRegOp", {"code" : regRegCode + regRegCcCode, "predicate_test": predicateTest}) def subst(iop): global header_output, decoder_output, exec_output header_output += DataRegRegDeclare.subst(iop) decoder_output += DataRegRegConstructor.subst(iop) exec_output += PredOpExecute.subst(iop) if buildNonCc: subst(regRegIop) if buildCc: subst(regRegIopCc) def buildDataInst(mnem, code, flagType = "logic", \ aiw = True, regRegAiw = True, subsPcLr = True): regRegCode = instCode = code if aiw: instCode = "AIW" + instCode if regRegAiw: regRegCode = "AIW" + regRegCode buildImmDataInst(mnem, instCode, flagType) buildRegDataInst(mnem, instCode, flagType) buildRegRegDataInst(mnem, regRegCode, flagType) if subsPcLr: code += ''' uint32_t newCpsr = cpsrWriteByInstr(Cpsr | CondCodes, Spsr, 0xF, true); Cpsr = ~CondCodesMask & newCpsr; CondCodes = CondCodesMask & newCpsr; ''' buildImmDataInst(mnem + 's', code, flagType, suffix = "ImmPclr", buildCc = False) buildRegDataInst(mnem + 's', code, flagType, suffix = "RegPclr", buildCc = False) buildDataInst("and", "Dest = resTemp = Op1 & secondOp;") buildDataInst("eor", "Dest = resTemp = Op1 ^ secondOp;") buildDataInst("sub", "Dest = resTemp = Op1 - secondOp;", "sub") buildDataInst("rsb", "Dest = resTemp = secondOp - Op1;", "rsb") buildDataInst("add", "Dest = resTemp = Op1 + secondOp;", "add") buildImmDataInst("adr", ''' Dest = resTemp = (readPC(xc) & ~0x3) + (op1 ? secondOp : -secondOp); ''') buildDataInst("adc", "Dest = resTemp = Op1 + secondOp + %s;" % oldC, "add") buildDataInst("sbc", "Dest = resTemp = Op1 - secondOp - !%s;" % oldC, "sub") buildDataInst("rsc", "Dest = resTemp = secondOp - Op1 - !%s;" % oldC, "rsb") buildDataInst("tst", "resTemp = Op1 & secondOp;", aiw = False) buildDataInst("teq", "resTemp = Op1 ^ secondOp;", aiw = False) buildDataInst("cmp", "resTemp = Op1 - secondOp;", "sub", aiw = False) buildDataInst("cmn", "resTemp = Op1 + secondOp;", "add", aiw = False) buildDataInst("orr", "Dest = resTemp = Op1 | secondOp;") buildDataInst("orn", "Dest = resTemp = Op1 | ~secondOp;", aiw = False) buildDataInst("mov", "Dest = resTemp = secondOp;", regRegAiw = False) buildDataInst("bic", "Dest = resTemp = Op1 & ~secondOp;") buildDataInst("mvn", "Dest = resTemp = ~secondOp;") buildDataInst("movt", "Dest = resTemp = insertBits(Op1, 31, 16, secondOp);", aiw = False) buildRegDataInst("qadd", ''' int32_t midRes; resTemp = saturateOp<32>(midRes, Op1.sw, Op2.sw); Dest = midRes; ''', flagType="saturate", buildNonCc=False) buildRegDataInst("qadd16", ''' int32_t midRes; for (unsigned i = 0; i < 2; i++) { int high = (i + 1) * 16 - 1; int low = i * 16; int64_t arg1 = sext<16>(bits(Op1.sw, high, low)); int64_t arg2 = sext<16>(bits(Op2.sw, high, low)); saturateOp<16>(midRes, arg1, arg2); replaceBits(resTemp, high, low, midRes); } Dest = resTemp; ''', flagType="none", buildCc=False) buildRegDataInst("qadd8", ''' int32_t midRes; for (unsigned i = 0; i < 4; i++) { int high = (i + 1) * 8 - 1; int low = i * 8; int64_t arg1 = sext<8>(bits(Op1.sw, high, low)); int64_t arg2 = sext<8>(bits(Op2.sw, high, low)); saturateOp<8>(midRes, arg1, arg2); replaceBits(resTemp, high, low, midRes); } Dest = resTemp; ''', flagType="none", buildCc=False) buildRegDataInst("qdadd", ''' int32_t midRes; resTemp = saturateOp<32>(midRes, Op2.sw, Op2.sw) | saturateOp<32>(midRes, Op1.sw, midRes); Dest = midRes; ''', flagType="saturate", buildNonCc=False) buildRegDataInst("qsub", ''' int32_t midRes; resTemp = saturateOp<32>(midRes, Op1.sw, Op2.sw, true); Dest = midRes; ''', flagType="saturate") buildRegDataInst("qsub16", ''' int32_t midRes; for (unsigned i = 0; i < 2; i++) { int high = (i + 1) * 16 - 1; int low = i * 16; int64_t arg1 = sext<16>(bits(Op1.sw, high, low)); int64_t arg2 = sext<16>(bits(Op2.sw, high, low)); saturateOp<16>(midRes, arg1, arg2, true); replaceBits(resTemp, high, low, midRes); } Dest = resTemp; ''', flagType="none", buildCc=False) buildRegDataInst("qsub8", ''' int32_t midRes; for (unsigned i = 0; i < 4; i++) { int high = (i + 1) * 8 - 1; int low = i * 8; int64_t arg1 = sext<8>(bits(Op1.sw, high, low)); int64_t arg2 = sext<8>(bits(Op2.sw, high, low)); saturateOp<8>(midRes, arg1, arg2, true); replaceBits(resTemp, high, low, midRes); } Dest = resTemp; ''', flagType="none", buildCc=False) buildRegDataInst("qdsub", ''' int32_t midRes; resTemp = saturateOp<32>(midRes, Op2.sw, Op2.sw) | saturateOp<32>(midRes, Op1.sw, midRes, true); Dest = midRes; ''', flagType="saturate", buildNonCc=False) buildRegDataInst("qasx", ''' int32_t midRes; int64_t arg1Low = sext<16>(bits(Op1.sw, 15, 0)); int64_t arg1High = sext<16>(bits(Op1.sw, 31, 16)); int64_t arg2Low = sext<16>(bits(Op2.sw, 15, 0)); int64_t arg2High = sext<16>(bits(Op2.sw, 31, 16)); saturateOp<16>(midRes, arg1Low, arg2High, true); replaceBits(resTemp, 15, 0, midRes); saturateOp<16>(midRes, arg1High, arg2Low); replaceBits(resTemp, 31, 16, midRes); Dest = resTemp; ''', flagType="none", buildCc=False) buildRegDataInst("qsax", ''' int32_t midRes; int64_t arg1Low = sext<16>(bits(Op1.sw, 15, 0)); int64_t arg1High = sext<16>(bits(Op1.sw, 31, 16)); int64_t arg2Low = sext<16>(bits(Op2.sw, 15, 0)); int64_t arg2High = sext<16>(bits(Op2.sw, 31, 16)); saturateOp<16>(midRes, arg1Low, arg2High); replaceBits(resTemp, 15, 0, midRes); saturateOp<16>(midRes, arg1High, arg2Low, true); replaceBits(resTemp, 31, 16, midRes); Dest = resTemp; ''', flagType="none", buildCc=False) buildRegDataInst("sadd8", ''' uint32_t geBits = 0; resTemp = 0; for (unsigned i = 0; i < 4; i++) { int high = (i + 1) * 8 - 1; int low = i * 8; int32_t midRes = sext<8>(bits(Op1.sw, high, low)) + sext<8>(bits(Op2.sw, high, low)); replaceBits(resTemp, high, low, midRes); if (midRes >= 0) { geBits = geBits | (1 << i); } } Dest = resTemp; resTemp = geBits; ''', flagType="ge", buildNonCc=False) buildRegDataInst("sadd16", ''' uint32_t geBits = 0; resTemp = 0; for (unsigned i = 0; i < 2; i++) { int high = (i + 1) * 16 - 1; int low = i * 16; int32_t midRes = sext<16>(bits(Op1.sw, high, low)) + sext<16>(bits(Op2.sw, high, low)); replaceBits(resTemp, high, low, midRes); if (midRes >= 0) { geBits = geBits | (0x3 << (i * 2)); } } Dest = resTemp; resTemp = geBits; ''', flagType="ge", buildNonCc=False) buildRegDataInst("ssub8", ''' uint32_t geBits = 0; resTemp = 0; for (unsigned i = 0; i < 4; i++) { int high = (i + 1) * 8 - 1; int low = i * 8; int32_t midRes = sext<8>(bits(Op1.sw, high, low)) - sext<8>(bits(Op2.sw, high, low)); replaceBits(resTemp, high, low, midRes); if (midRes >= 0) { geBits = geBits | (1 << i); } } Dest = resTemp; resTemp = geBits; ''', flagType="ge", buildNonCc=False) buildRegDataInst("ssub16", ''' uint32_t geBits = 0; resTemp = 0; for (unsigned i = 0; i < 2; i++) { int high = (i + 1) * 16 - 1; int low = i * 16; int32_t midRes = sext<16>(bits(Op1.sw, high, low)) - sext<16>(bits(Op2.sw, high, low)); replaceBits(resTemp, high, low, midRes); if (midRes >= 0) { geBits = geBits | (0x3 << (i * 2)); } } Dest = resTemp; resTemp = geBits; ''', flagType="ge", buildNonCc=False) buildRegDataInst("sasx", ''' int32_t midRes, geBits = 0; resTemp = 0; int64_t arg1Low = sext<16>(bits(Op1.sw, 15, 0)); int64_t arg1High = sext<16>(bits(Op1.sw, 31, 16)); int64_t arg2Low = sext<16>(bits(Op2.sw, 15, 0)); int64_t arg2High = sext<16>(bits(Op2.sw, 31, 16)); midRes = arg1Low - arg2High; if (midRes >= 0) { geBits = geBits | 0x3; } replaceBits(resTemp, 15, 0, midRes); midRes = arg1High + arg2Low; if (midRes >= 0) { geBits = geBits | 0xc; } replaceBits(resTemp, 31, 16, midRes); Dest = resTemp; resTemp = geBits; ''', flagType="ge", buildNonCc=True) buildRegDataInst("ssax", ''' int32_t midRes, geBits = 0; resTemp = 0; int64_t arg1Low = sext<16>(bits(Op1.sw, 15, 0)); int64_t arg1High = sext<16>(bits(Op1.sw, 31, 16)); int64_t arg2Low = sext<16>(bits(Op2.sw, 15, 0)); int64_t arg2High = sext<16>(bits(Op2.sw, 31, 16)); midRes = arg1Low + arg2High; if (midRes >= 0) { geBits = geBits | 0x3; } replaceBits(resTemp, 15, 0, midRes); midRes = arg1High - arg2Low; if (midRes >= 0) { geBits = geBits | 0xc; } replaceBits(resTemp, 31, 16, midRes); Dest = resTemp; resTemp = geBits; ''', flagType="ge", buildNonCc=True) buildRegDataInst("uqadd16", ''' uint32_t midRes; for (unsigned i = 0; i < 2; i++) { int high = (i + 1) * 16 - 1; int low = i * 16; uint64_t arg1 = bits(Op1, high, low); uint64_t arg2 = bits(Op2, high, low); uSaturateOp<16>(midRes, arg1, arg2); replaceBits(resTemp, high, low, midRes); } Dest = resTemp; ''', flagType="none", buildCc=False) buildRegDataInst("uqadd8", ''' uint32_t midRes; for (unsigned i = 0; i < 4; i++) { int high = (i + 1) * 8 - 1; int low = i * 8; uint64_t arg1 = bits(Op1, high, low); uint64_t arg2 = bits(Op2, high, low); uSaturateOp<8>(midRes, arg1, arg2); replaceBits(resTemp, high, low, midRes); } Dest = resTemp; ''', flagType="none", buildCc=False) buildRegDataInst("uqsub16", ''' uint32_t midRes; for (unsigned i = 0; i < 2; i++) { int high = (i + 1) * 16 - 1; int low = i * 16; uint64_t arg1 = bits(Op1, high, low); uint64_t arg2 = bits(Op2, high, low); uSaturateOp<16>(midRes, arg1, arg2, true); replaceBits(resTemp, high, low, midRes); } Dest = resTemp; ''', flagType="none", buildCc=False) buildRegDataInst("uqsub8", ''' uint32_t midRes; for (unsigned i = 0; i < 4; i++) { int high = (i + 1) * 8 - 1; int low = i * 8; uint64_t arg1 = bits(Op1, high, low); uint64_t arg2 = bits(Op2, high, low); uSaturateOp<8>(midRes, arg1, arg2, true); replaceBits(resTemp, high, low, midRes); } Dest = resTemp; ''', flagType="none", buildCc=False) buildRegDataInst("uqasx", ''' uint32_t midRes; uint64_t arg1Low = bits(Op1.sw, 15, 0); uint64_t arg1High = bits(Op1.sw, 31, 16); uint64_t arg2Low = bits(Op2.sw, 15, 0); uint64_t arg2High = bits(Op2.sw, 31, 16); uSaturateOp<16>(midRes, arg1Low, arg2High, true); replaceBits(resTemp, 15, 0, midRes); uSaturateOp<16>(midRes, arg1High, arg2Low); replaceBits(resTemp, 31, 16, midRes); Dest = resTemp; ''', flagType="none", buildCc=False) buildRegDataInst("uqsax", ''' uint32_t midRes; uint64_t arg1Low = bits(Op1.sw, 15, 0); uint64_t arg1High = bits(Op1.sw, 31, 16); uint64_t arg2Low = bits(Op2.sw, 15, 0); uint64_t arg2High = bits(Op2.sw, 31, 16); uSaturateOp<16>(midRes, arg1Low, arg2High); replaceBits(resTemp, 15, 0, midRes); uSaturateOp<16>(midRes, arg1High, arg2Low, true); replaceBits(resTemp, 31, 16, midRes); Dest = resTemp; ''', flagType="none", buildCc=False) buildRegDataInst("uadd16", ''' uint32_t geBits = 0; resTemp = 0; for (unsigned i = 0; i < 2; i++) { int high = (i + 1) * 16 - 1; int low = i * 16; int32_t midRes = bits(Op1, high, low) + bits(Op2, high, low); if (midRes >= 0x10000) { geBits = geBits | (0x3 << (i * 2)); } replaceBits(resTemp, high, low, midRes); } Dest = resTemp; resTemp = geBits; ''', flagType="ge", buildNonCc=False) buildRegDataInst("uadd8", ''' uint32_t geBits = 0; resTemp = 0; for (unsigned i = 0; i < 4; i++) { int high = (i + 1) * 8 - 1; int low = i * 8; int32_t midRes = bits(Op1, high, low) + bits(Op2, high, low); if (midRes >= 0x100) { geBits = geBits | (1 << i); } replaceBits(resTemp, high, low, midRes); } Dest = resTemp; resTemp = geBits; ''', flagType="ge", buildNonCc=False) buildRegDataInst("usub16", ''' uint32_t geBits = 0; resTemp = 0; for (unsigned i = 0; i < 2; i++) { int high = (i + 1) * 16 - 1; int low = i * 16; int32_t midRes = bits(Op1, high, low) - bits(Op2, high, low); if (midRes >= 0) { geBits = geBits | (0x3 << (i * 2)); } replaceBits(resTemp, high, low, midRes); } Dest = resTemp; resTemp = geBits; ''', flagType="ge", buildNonCc=False) buildRegDataInst("usub8", ''' uint32_t geBits = 0; resTemp = 0; for (unsigned i = 0; i < 4; i++) { int high = (i + 1) * 8 - 1; int low = i * 8; int32_t midRes = bits(Op1, high, low) - bits(Op2, high, low); if (midRes >= 0) { geBits = geBits | (1 << i); } replaceBits(resTemp, high, low, midRes); } Dest = resTemp; resTemp = geBits; ''', flagType="ge", buildNonCc=False) buildRegDataInst("uasx", ''' int32_t midRes, geBits = 0; resTemp = 0; int64_t arg1Low = bits(Op1.sw, 15, 0); int64_t arg1High = bits(Op1.sw, 31, 16); int64_t arg2Low = bits(Op2.sw, 15, 0); int64_t arg2High = bits(Op2.sw, 31, 16); midRes = arg1Low - arg2High; if (midRes >= 0) { geBits = geBits | 0x3; } replaceBits(resTemp, 15, 0, midRes); midRes = arg1High + arg2Low; if (midRes >= 0x10000) { geBits = geBits | 0xc; } replaceBits(resTemp, 31, 16, midRes); Dest = resTemp; resTemp = geBits; ''', flagType="ge", buildNonCc=False) buildRegDataInst("usax", ''' int32_t midRes, geBits = 0; resTemp = 0; int64_t arg1Low = bits(Op1.sw, 15, 0); int64_t arg1High = bits(Op1.sw, 31, 16); int64_t arg2Low = bits(Op2.sw, 15, 0); int64_t arg2High = bits(Op2.sw, 31, 16); midRes = arg1Low + arg2High; if (midRes >= 0x10000) { geBits = geBits | 0x3; } replaceBits(resTemp, 15, 0, midRes); midRes = arg1High - arg2Low; if (midRes >= 0) { geBits = geBits | 0xc; } replaceBits(resTemp, 31, 16, midRes); Dest = resTemp; resTemp = geBits; ''', flagType="ge", buildNonCc=False) }};