ARM: Add support for "SUBS PC, LR and related instructions".
This commit is contained in:
parent
2419903dc0
commit
aa45fafb2e
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
}};
|
||||
|
|
Loading…
Reference in a new issue