ARM: Respect the E bit of the CPSR when doing loads and stores.
This commit is contained in:
@@ -231,6 +231,17 @@ class ArmStaticInst : public StaticInst
|
||||
(val & ~PcModeMask));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static T
|
||||
cSwap(T val, bool big)
|
||||
{
|
||||
if (big) {
|
||||
return gtobe(val);
|
||||
} else {
|
||||
return gtole(val);
|
||||
}
|
||||
}
|
||||
|
||||
// Perform an interworking branch.
|
||||
template<class XC>
|
||||
static void
|
||||
|
||||
@@ -104,7 +104,8 @@ let {{
|
||||
if ldrex:
|
||||
memFlags.append("Request::LLSC")
|
||||
Name = "%s_%s" % (mnem.upper(), Name)
|
||||
accCode = "IWDest = Mem%s;\n" % buildMemSuffix(sign, size)
|
||||
accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);" % \
|
||||
buildMemSuffix(sign, size)
|
||||
|
||||
if not prefetch and not ldrex:
|
||||
memFlags.append("ArmISA::TLB::AllowUnaligned")
|
||||
@@ -131,10 +132,12 @@ let {{
|
||||
if add:
|
||||
wbDiff = 8
|
||||
accCode = '''
|
||||
NPC = bits(Mem.ud, 31, 0);
|
||||
uint32_t newCpsr = cpsrWriteByInstr(Cpsr | CondCodes,
|
||||
bits(Mem.ud, 63, 32),
|
||||
0xF, true);
|
||||
CPSR cpsr = Cpsr;
|
||||
NPC = cSwap<uint32_t>(Mem.ud, cpsr.e);
|
||||
uint32_t newCpsr =
|
||||
cpsrWriteByInstr(cpsr | CondCodes,
|
||||
cSwap<uint32_t>(Mem.ud >> 32, cpsr.e),
|
||||
0xF, true);
|
||||
Cpsr = ~CondCodesMask & newCpsr;
|
||||
CondCodes = CondCodesMask & newCpsr;
|
||||
'''
|
||||
@@ -179,7 +182,8 @@ let {{
|
||||
temp = temp;
|
||||
''' % buildMemSuffix(sign, size)
|
||||
else:
|
||||
accCode = "IWDest = Mem%s;\n" % buildMemSuffix(sign, size)
|
||||
accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);" % \
|
||||
buildMemSuffix(sign, size)
|
||||
if writeback:
|
||||
accCode += "Base = Base %s;\n" % offset
|
||||
|
||||
@@ -207,8 +211,9 @@ let {{
|
||||
eaCode += ";"
|
||||
|
||||
accCode = '''
|
||||
Dest = bits(Mem.ud, 31, 0);
|
||||
Dest2 = bits(Mem.ud, 63, 32);
|
||||
CPSR cpsr = Cpsr;
|
||||
Dest = cSwap<uint32_t>(Mem.ud, cpsr.e);
|
||||
Dest2 = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
|
||||
'''
|
||||
if ldrex:
|
||||
memFlags = ["Request::LLSC"]
|
||||
@@ -242,8 +247,9 @@ let {{
|
||||
eaCode += ";"
|
||||
|
||||
accCode = '''
|
||||
Dest = bits(Mem.ud, 31, 0);
|
||||
Dest2 = bits(Mem.ud, 63, 32);
|
||||
CPSR cpsr = Cpsr;
|
||||
Dest = cSwap<uint32_t>(Mem.ud, cpsr.e);
|
||||
Dest2 = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
|
||||
'''
|
||||
if writeback:
|
||||
accCode += "Base = Base %s;\n" % offset
|
||||
|
||||
@@ -51,26 +51,29 @@ let {{
|
||||
}};
|
||||
|
||||
let {{
|
||||
microLdrUopCode = "IWRa = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
|
||||
microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
|
||||
'MicroMemOp',
|
||||
{'memacc_code': 'IWRa = Mem;',
|
||||
{'memacc_code': microLdrUopCode,
|
||||
'ea_code': 'EA = Rb + (up ? imm : -imm);',
|
||||
'predicate_test': predicateTest},
|
||||
['IsMicroop'])
|
||||
|
||||
microLdrFpUopCode = "Fa = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
|
||||
microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop',
|
||||
'MicroMemOp',
|
||||
{'memacc_code': 'Fa = Mem;',
|
||||
{'memacc_code': microLdrFpUopCode,
|
||||
'ea_code': 'EA = Rb + (up ? imm : -imm);',
|
||||
'predicate_test': predicateTest},
|
||||
['IsMicroop'])
|
||||
|
||||
microLdrRetUopCode = '''
|
||||
CPSR cpsr = Cpsr;
|
||||
uint32_t newCpsr =
|
||||
cpsrWriteByInstr(Cpsr | CondCodes, Spsr, 0xF, true);
|
||||
cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true);
|
||||
Cpsr = ~CondCodesMask & newCpsr;
|
||||
CondCodes = CondCodesMask & newCpsr;
|
||||
IWNPC = Mem | ((Spsr & 0x20) ? 1 : 0);
|
||||
IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
|
||||
'''
|
||||
microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
|
||||
'MicroMemOp',
|
||||
@@ -80,16 +83,18 @@ let {{
|
||||
'predicate_test': predicateTest},
|
||||
['IsMicroop'])
|
||||
|
||||
microStrUopCode = "Mem = cSwap(Ra.uw, ((CPSR)Cpsr).e);"
|
||||
microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
|
||||
'MicroMemOp',
|
||||
{'memacc_code': 'Mem = Ra;',
|
||||
{'memacc_code': microStrUopCode,
|
||||
'ea_code': 'EA = Rb + (up ? imm : -imm);',
|
||||
'predicate_test': predicateTest},
|
||||
['IsMicroop'])
|
||||
|
||||
microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
|
||||
microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop',
|
||||
'MicroMemOp',
|
||||
{'memacc_code': 'Mem = Fa;',
|
||||
{'memacc_code': microStrFpUopCode,
|
||||
'ea_code': 'EA = Rb + (up ? imm : -imm);',
|
||||
'predicate_test': predicateTest},
|
||||
['IsMicroop'])
|
||||
|
||||
@@ -93,7 +93,8 @@ let {{
|
||||
eaCode += offset
|
||||
eaCode += ";"
|
||||
|
||||
accCode = "Mem%s = Dest;\n" % buildMemSuffix(sign, size)
|
||||
accCode = "Mem%(suffix)s = cSwap(Dest%(suffix)s, ((CPSR)Cpsr).e);" % \
|
||||
{ "suffix" : buildMemSuffix(sign, size) }
|
||||
if writeback:
|
||||
accCode += "Base = Base %s;\n" % offset
|
||||
base = buildMemBase("MemoryImm", post, writeback)
|
||||
@@ -121,7 +122,8 @@ let {{
|
||||
eaCode += offset
|
||||
eaCode += ";"
|
||||
|
||||
accCode = "Mem%s = Dest;\n" % buildMemSuffix(sign, size)
|
||||
accCode = "Mem%(suffix)s = cSwap(Dest%(suffix)s, ((CPSR)Cpsr).e);" % \
|
||||
{ "suffix" : buildMemSuffix(sign, size) }
|
||||
if writeback:
|
||||
accCode += "Base = Base %s;\n" % offset
|
||||
base = buildMemBase("MemoryReg", post, writeback)
|
||||
@@ -146,7 +148,11 @@ let {{
|
||||
eaCode += offset
|
||||
eaCode += ";"
|
||||
|
||||
accCode = 'Mem.ud = (Dest.ud & mask(32)) | (Dest2.ud << 32);'
|
||||
accCode = '''
|
||||
CPSR cpsr = Cpsr;
|
||||
Mem.ud = (uint64_t)cSwap(Dest.uw, cpsr.e) |
|
||||
((uint64_t)cSwap(Dest2.uw, cpsr.e) << 32);
|
||||
'''
|
||||
if writeback:
|
||||
accCode += "Base = Base %s;\n" % offset
|
||||
base = buildMemBase("MemoryDImm", post, writeback)
|
||||
@@ -171,7 +177,11 @@ let {{
|
||||
eaCode += offset
|
||||
eaCode += ";"
|
||||
|
||||
accCode = 'Mem.ud = (Dest.ud & mask(32)) | (Dest2.ud << 32);'
|
||||
accCode = '''
|
||||
CPSR cpsr = Cpsr;
|
||||
Mem.ud = (uint64_t)cSwap(Dest.uw, cpsr.e) |
|
||||
((uint64_t)cSwap(Dest2.uw, cpsr.e) << 32);
|
||||
'''
|
||||
if writeback:
|
||||
accCode += "Base = Base %s;\n" % offset
|
||||
base = buildMemBase("MemoryDReg", post, writeback)
|
||||
|
||||
@@ -44,7 +44,8 @@ let {{
|
||||
(newHeader,
|
||||
newDecoder,
|
||||
newExec) = SwapBase("swp", "Swp", "EA = Base;",
|
||||
"Mem = Op1;", "Dest = memData;",
|
||||
"Mem = cSwap(Op1.uw, ((CPSR)Cpsr).e);",
|
||||
"Dest = cSwap((uint32_t)memData, ((CPSR)Cpsr).e);",
|
||||
["Request::MEM_SWAP",
|
||||
"ArmISA::TLB::AlignWord",
|
||||
"ArmISA::TLB::MustBeOne"], [])
|
||||
@@ -55,7 +56,8 @@ let {{
|
||||
(newHeader,
|
||||
newDecoder,
|
||||
newExec) = SwapBase("swpb", "Swpb", "EA = Base;",
|
||||
"Mem.ub = Op1.ub;", "Dest.ub = (uint8_t)memData;",
|
||||
"Mem.ub = cSwap(Op1.ub, ((CPSR)Cpsr).e);",
|
||||
"Dest.ub = cSwap((uint8_t)memData, ((CPSR)Cpsr).e);",
|
||||
["Request::MEM_SWAP",
|
||||
"ArmISA::TLB::AlignByte",
|
||||
"ArmISA::TLB::MustBeOne"], [])
|
||||
|
||||
Reference in New Issue
Block a user