diff --git a/src/arch/arm/isa/formats/branch.isa b/src/arch/arm/isa/formats/branch.isa index caf6f6227..45464018e 100644 --- a/src/arch/arm/isa/formats/branch.isa +++ b/src/arch/arm/isa/formats/branch.isa @@ -192,8 +192,11 @@ def format Thumb32BranchesAndMiscCtrl() {{ case 0x3c: return new WarnUnimplemented("bxj", machInst); case 0x3d: - return new WarnUnimplemented("subs_pc_lr_and_rel_insts", - machInst); + { + const uint32_t imm32 = bits(machInst, 7, 0); + return new SubsImmPclr(machInst, INTREG_PC, INTREG_LR, + imm32, false); + } case 0x3e: case 0x3f: return new WarnUnimplemented("mrs", machInst); diff --git a/src/arch/arm/isa/formats/data.isa b/src/arch/arm/isa/formats/data.isa index 45dedff2c..eb36699c2 100644 --- a/src/arch/arm/isa/formats/data.isa +++ b/src/arch/arm/isa/formats/data.isa @@ -36,12 +36,21 @@ // Authors: Gabe Black def format ArmDataProcReg() {{ + pclr = ''' + return new %(className)ssRegPclr(machInst, %(dest)s, + %(op1)s, rm, imm5, + type); + ''' instDecode = ''' case %(opcode)#x: if (immShift) { if (setCc) { - return new %(className)sRegCc(machInst, %(dest)s, %(op1)s, - rm, imm5, type); + if (%(dest)s == INTREG_PC) { + %(pclr)s + } else { + return new %(className)sRegCc(machInst, %(dest)s, + %(op1)s, rm, imm5, type); + } } else { return new %(className)sReg(machInst, %(dest)s, %(op1)s, rm, imm5, type); @@ -58,12 +67,26 @@ def format ArmDataProcReg() {{ break; ''' - def instCode(opcode, mnem, dest="rd", op1="rn"): - global instDecode - return instDecode % { "className": mnem.capitalize(), - "opcode": opcode, - "dest": dest, - "op1": op1 } + def instCode(opcode, mnem, useDest = True, useOp1 = True): + global pclr + if useDest: + dest = "rd" + else: + dest = "INTREG_ZERO" + if useOp1: + op1 = "rn" + else: + op1 = "INTREG_ZERO" + global instDecode, pclrCode + substDict = { "className": mnem.capitalize(), + "opcode": opcode, + "dest": dest, + "op1": op1 } + if useDest: + substDict["pclr"] = pclr % substDict + else: + substDict["pclr"] = "" + return instDecode % substDict decode_block = ''' { @@ -85,14 +108,14 @@ def format ArmDataProcReg() {{ decode_block += instCode(0x5, "adc") decode_block += instCode(0x6, "sbc") decode_block += instCode(0x7, "rsc") - decode_block += instCode(0x8, "tst", dest="INTREG_ZERO") - decode_block += instCode(0x9, "teq", dest="INTREG_ZERO") - decode_block += instCode(0xa, "cmp", dest="INTREG_ZERO") - decode_block += instCode(0xb, "cmn", dest="INTREG_ZERO") + decode_block += instCode(0x8, "tst", useDest = False) + decode_block += instCode(0x9, "teq", useDest = False) + decode_block += instCode(0xa, "cmp", useDest = False) + decode_block += instCode(0xb, "cmn", useDest = False) decode_block += instCode(0xc, "orr") - decode_block += instCode(0xd, "mov", op1="INTREG_ZERO") + decode_block += instCode(0xd, "mov", useOp1 = False) decode_block += instCode(0xe, "bic") - decode_block += instCode(0xf, "mvn", op1="INTREG_ZERO") + decode_block += instCode(0xf, "mvn", useOp1 = False) decode_block += ''' default: return new Unknown(machInst); @@ -102,43 +125,70 @@ def format ArmDataProcReg() {{ }}; def format ArmDataProcImm() {{ + pclr = ''' + return new %(className)ssImmPclr(machInst, %(dest)s, + %(op1)s, imm, false); + ''' + adr = ''' + return new AdrImm(machInst, %(dest)s, %(add)s, + imm, false); + ''' instDecode = ''' + case %(opcode)#x: if (setCc) { - return new %(className)sImmCc(machInst, %(dest)s, %(op1)s, - imm, rotC); + if (%(pclrInst)s && %(dest)s == INTREG_PC) { + %(pclr)s + } else { + return new %(className)sImmCc(machInst, %(dest)s, %(op1)s, + imm, rotC); + } } else { - return new %(className)sImm(machInst, %(dest)s, %(op1)s, - imm, rotC); + if (%(adrInst)s && %(op1)s == INTREG_PC) { + %(adr)s + } else { + return new %(className)sImm(machInst, %(dest)s, %(op1)s, + imm, rotC); + } } break; ''' - def instCode(opcode, mnem, dest="rd", op1="rn"): - global instDecode - code = ''' - case %(opcode)#x: - ''' + instDecode - return code % { "className": mnem.capitalize(), - "opcode": opcode, - "dest": dest, - "op1": op1 } + def instCode(opcode, mnem, useDest = True, useOp1 = True): + global instDecode, pclr, adr + if useDest: + dest = "rd" + else: + dest = "INTREG_ZERO" + if useOp1: + op1 = "rn" + else: + op1 = "INTREG_ZERO" + substDict = { "className": mnem.capitalize(), + "opcode": opcode, + "dest": dest, + "op1": op1, + "adr": "", + "adrInst": "false" } + if useDest: + substDict["pclrInst"] = "true" + substDict["pclr"] = pclr % substDict + else: + substDict["pclrInst"] = "false" + substDict["pclr"] = "" + return instDecode % substDict - def adrCode(opcode, mnem, dest="rd", op1="rn", add="1"): - global instDecode - code = ''' - case %(opcode)#x: - if (rn == 0xf) { - return new AdrImm(machInst, %(dest)s, %(add)s, - imm, false); - } else { - ''' + instDecode + ''' - } - ''' - return code % { "className": mnem.capitalize(), - "opcode": opcode, - "dest": dest, - "add": add, - "op1": op1 } + def adrCode(opcode, mnem, add="1"): + global instDecode, pclr, adr + substDict = { "className": mnem.capitalize(), + "opcode": opcode, + "dest": "rd", + "op1": "rn", + "add": add, + "pclrInst": "true", + "adrInst": "true" } + substDict["pclr"] = pclr % substDict + substDict["adr"] = adr % substDict + return instDecode % substDict decode_block = ''' { @@ -159,14 +209,14 @@ def format ArmDataProcImm() {{ decode_block += instCode(0x5, "adc") decode_block += instCode(0x6, "sbc") decode_block += instCode(0x7, "rsc") - decode_block += instCode(0x8, "tst", dest="INTREG_ZERO") - decode_block += instCode(0x9, "teq", dest="INTREG_ZERO") - decode_block += instCode(0xa, "cmp", dest="INTREG_ZERO") - decode_block += instCode(0xb, "cmn", dest="INTREG_ZERO") + decode_block += instCode(0x8, "tst", useDest = False) + decode_block += instCode(0x9, "teq", useDest = False) + decode_block += instCode(0xa, "cmp", useDest = False) + decode_block += instCode(0xb, "cmn", useDest = False) decode_block += instCode(0xc, "orr") - decode_block += instCode(0xd, "mov", op1="INTREG_ZERO") + decode_block += instCode(0xd, "mov", useOp1 = False) decode_block += instCode(0xe, "bic") - decode_block += instCode(0xf, "mvn", op1="INTREG_ZERO") + decode_block += instCode(0xf, "mvn", useOp1 = False) decode_block += ''' default: return new Unknown(machInst); diff --git a/src/arch/arm/isa/insts/data.isa b/src/arch/arm/isa/insts/data.isa index 02ecd6b4c..69e813d25 100644 --- a/src/arch/arm/isa/insts/data.isa +++ b/src/arch/arm/isa/insts/data.isa @@ -98,8 +98,8 @@ let {{ 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"): - global header_output, decoder_output, exec_output + def buildImmDataInst(mnem, code, flagType = "logic", \ + suffix = "Imm", buildCc = True): cCode = carryCode[flagType] vCode = overflowCode[flagType] negBit = 31 @@ -114,22 +114,26 @@ let {{ "negBit": negBit } immCode = secondOpRe.sub(immOp2, code) - immIop = InstObjParams(mnem, mnem.capitalize() + "Imm", "DataImmOp", + immIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataImmOp", {"code" : immCode, "predicate_test": predicateTest}) - immIopCc = InstObjParams(mnem + "s", mnem.capitalize() + "ImmCc", + immIopCc = InstObjParams(mnem + "s", mnem.capitalize() + suffix + "Cc", "DataImmOp", {"code" : immCode + immCcCode, "predicate_test": predicateTest}) - header_output += DataImmDeclare.subst(immIop) + \ - DataImmDeclare.subst(immIopCc) - decoder_output += DataImmConstructor.subst(immIop) + \ - DataImmConstructor.subst(immIopCc) - exec_output += PredOpExecute.subst(immIop) + \ - PredOpExecute.subst(immIopCc) - def buildRegDataInst(mnem, code, flagType = "logic"): - global header_output, decoder_output, exec_output + 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) + + subst(immIop) + if buildCc: + subst(immIopCc) + + def buildRegDataInst(mnem, code, flagType = "logic", \ + suffix = "Reg", buildCc = True): cCode = carryCode[flagType] vCode = overflowCode[flagType] negBit = 31 @@ -144,22 +148,26 @@ let {{ "negBit": negBit } regCode = secondOpRe.sub(regOp2, code) - regIop = InstObjParams(mnem, mnem.capitalize() + "Reg", "DataRegOp", + regIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataRegOp", {"code" : regCode, "predicate_test": predicateTest}) - regIopCc = InstObjParams(mnem + "s", mnem.capitalize() + "RegCc", + regIopCc = InstObjParams(mnem + "s", mnem.capitalize() + suffix + "Cc", "DataRegOp", {"code" : regCode + regCcCode, "predicate_test": predicateTest}) - header_output += DataRegDeclare.subst(regIop) + \ - DataRegDeclare.subst(regIopCc) - decoder_output += DataRegConstructor.subst(regIop) + \ - DataRegConstructor.subst(regIopCc) - exec_output += PredOpExecute.subst(regIop) + \ - PredOpExecute.subst(regIopCc) - def buildRegRegDataInst(mnem, code, flagType = "logic"): - global header_output, decoder_output, exec_output + 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) + + subst(regIop) + if buildCc: + subst(regIopCc) + + def buildRegRegDataInst(mnem, code, flagType = "logic", \ + suffix = "RegReg", buildCc = True): cCode = carryCode[flagType] vCode = overflowCode[flagType] negBit = 31 @@ -174,53 +182,72 @@ let {{ "negBit": negBit } regRegCode = secondOpRe.sub(regRegOp2, code) - regRegIop = InstObjParams(mnem, mnem.capitalize() + "RegReg", + regRegIop = InstObjParams(mnem, mnem.capitalize() + suffix, "DataRegRegOp", {"code" : regRegCode, "predicate_test": predicateTest}) regRegIopCc = InstObjParams(mnem + "s", - mnem.capitalize() + "RegRegCc", + mnem.capitalize() + suffix + "Cc", "DataRegRegOp", {"code" : regRegCode + regRegCcCode, "predicate_test": predicateTest}) - header_output += DataRegRegDeclare.subst(regRegIop) + \ - DataRegRegDeclare.subst(regRegIopCc) - decoder_output += DataRegRegConstructor.subst(regRegIop) + \ - DataRegRegConstructor.subst(regRegIopCc) - exec_output += PredOpExecute.subst(regRegIop) + \ - PredOpExecute.subst(regRegIopCc) - def buildDataInst(mnem, code, flagType = "logic"): - buildImmDataInst(mnem, code, flagType) - buildRegDataInst(mnem, code, flagType) - buildRegRegDataInst(mnem, code, flagType) + 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) - buildDataInst("and", "AIWDest = resTemp = Op1 & secondOp;") - buildDataInst("eor", "AIWDest = resTemp = Op1 ^ secondOp;") - buildDataInst("sub", "AIWDest = resTemp = Op1 - secondOp;", "sub") - buildDataInst("rsb", "AIWDest = resTemp = secondOp - Op1;", "rsb") - buildDataInst("add", "AIWDest = resTemp = Op1 + secondOp;", "add") + 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", ''' - AIWDest = resTemp = (readPC(xc) & ~0x3) + + Dest = resTemp = (readPC(xc) & ~0x3) + (op1 ? secondOp : -secondOp); ''') - buildDataInst("adc", "AIWDest = resTemp = Op1 + secondOp + %s;" % oldC, - "add") - buildDataInst("sbc", "AIWDest = resTemp = Op1 - secondOp - !%s;" % oldC, - "sub") - buildDataInst("rsc", "AIWDest = resTemp = secondOp - Op1 - !%s;" % oldC, - "rsb") - buildDataInst("tst", "resTemp = Op1 & secondOp;") - buildDataInst("teq", "resTemp = Op1 ^ secondOp;") - buildDataInst("cmp", "resTemp = Op1 - secondOp;", "sub") - buildDataInst("cmn", "resTemp = Op1 + secondOp;", "add") - buildDataInst("orr", "AIWDest = resTemp = Op1 | secondOp;") - buildDataInst("orn", "Dest = resTemp = Op1 | ~secondOp;") - buildImmDataInst("mov", "AIWDest = resTemp = secondOp;") - buildRegDataInst("mov", "AIWDest = resTemp = secondOp;") - buildRegRegDataInst("mov", "Dest = resTemp = secondOp;") - buildDataInst("bic", "AIWDest = resTemp = Op1 & ~secondOp;") - buildDataInst("mvn", "AIWDest = resTemp = ~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);") + "Dest = resTemp = insertBits(Op1, 31, 16, secondOp);", + aiw = False) }};