ARM: Add support for "SUBS PC, LR and related instructions".

This commit is contained in:
Gabe Black 2010-06-02 12:58:04 -05:00
parent 2419903dc0
commit aa45fafb2e
3 changed files with 189 additions and 109 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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)
}};