mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-05 02:07:16 +00:00
Fix pre- and post-indexed load / store encoding bugs.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59230 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a6ce05f82a
commit
148cad8b30
@ -312,10 +312,12 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
|
||||
case ARMII::DPSoRegFrm:
|
||||
emitDataProcessingInstruction(MI);
|
||||
break;
|
||||
case ARMII::LdStFrm:
|
||||
case ARMII::LdFrm:
|
||||
case ARMII::StFrm:
|
||||
emitLoadStoreInstruction(MI);
|
||||
break;
|
||||
case ARMII::LdStMiscFrm:
|
||||
case ARMII::LdMiscFrm:
|
||||
case ARMII::StMiscFrm:
|
||||
emitMiscLoadStoreInstruction(MI);
|
||||
break;
|
||||
case ARMII::LdStMulFrm:
|
||||
@ -687,6 +689,8 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
|
||||
unsigned ImplicitRd,
|
||||
unsigned ImplicitRn) {
|
||||
const TargetInstrDesc &TID = MI.getDesc();
|
||||
unsigned Form = TID.TSFlags & ARMII::FormMask;
|
||||
bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0;
|
||||
|
||||
// Part of binary is determined by TableGn.
|
||||
unsigned Binary = getBinaryCodeForInstr(MI);
|
||||
@ -694,8 +698,17 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
|
||||
// Set the conditional execution predicate
|
||||
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
|
||||
|
||||
// Set first operand
|
||||
unsigned OpIdx = 0;
|
||||
|
||||
// Operand 0 of a pre- and post-indexed store is the address base
|
||||
// writeback. Skip it.
|
||||
bool Skipped = false;
|
||||
if (IsPrePost && Form == ARMII::StFrm) {
|
||||
++OpIdx;
|
||||
Skipped = true;
|
||||
}
|
||||
|
||||
// Set first operand
|
||||
if (ImplicitRd)
|
||||
// Special handling for implicit use (e.g. PC).
|
||||
Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRd)
|
||||
@ -712,7 +725,7 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
|
||||
Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift;
|
||||
|
||||
// If this is a two-address operand, skip it. e.g. LDR_PRE.
|
||||
if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
|
||||
if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
|
||||
++OpIdx;
|
||||
|
||||
const MachineOperand &MO2 = MI.getOperand(OpIdx);
|
||||
@ -749,6 +762,8 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
|
||||
void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI,
|
||||
unsigned ImplicitRn) {
|
||||
const TargetInstrDesc &TID = MI.getDesc();
|
||||
unsigned Form = TID.TSFlags & ARMII::FormMask;
|
||||
bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0;
|
||||
|
||||
// Part of binary is determined by TableGn.
|
||||
unsigned Binary = getBinaryCodeForInstr(MI);
|
||||
@ -756,11 +771,20 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI,
|
||||
// Set the conditional execution predicate
|
||||
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
|
||||
|
||||
unsigned OpIdx = 0;
|
||||
|
||||
// Operand 0 of a pre- and post-indexed store is the address base
|
||||
// writeback. Skip it.
|
||||
bool Skipped = false;
|
||||
if (IsPrePost && Form == ARMII::StMiscFrm) {
|
||||
++OpIdx;
|
||||
Skipped = true;
|
||||
}
|
||||
|
||||
// Set first operand
|
||||
Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift;
|
||||
Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift;
|
||||
|
||||
// Set second operand
|
||||
unsigned OpIdx = 1;
|
||||
if (ImplicitRn)
|
||||
// Special handling for implicit use (e.g. PC).
|
||||
Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRn)
|
||||
@ -769,7 +793,7 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI,
|
||||
Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift;
|
||||
|
||||
// If this is a two-address operand, skip it. e.g. LDRH_POST.
|
||||
if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
|
||||
if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
|
||||
++OpIdx;
|
||||
|
||||
const MachineOperand &MO2 = MI.getOperand(OpIdx);
|
||||
|
@ -27,25 +27,27 @@ def BrMiscFrm : Format<4>;
|
||||
def DPFrm : Format<5>;
|
||||
def DPSoRegFrm : Format<6>;
|
||||
|
||||
def LdStFrm : Format<7>;
|
||||
def LdStMiscFrm : Format<8>;
|
||||
def LdStMulFrm : Format<9>;
|
||||
def LdFrm : Format<7>;
|
||||
def StFrm : Format<8>;
|
||||
def LdMiscFrm : Format<9>;
|
||||
def StMiscFrm : Format<10>;
|
||||
def LdStMulFrm : Format<11>;
|
||||
|
||||
def ArithMiscFrm : Format<10>;
|
||||
def ExtFrm : Format<11>;
|
||||
def ArithMiscFrm : Format<12>;
|
||||
def ExtFrm : Format<13>;
|
||||
|
||||
def VFPUnaryFrm : Format<12>;
|
||||
def VFPBinaryFrm : Format<13>;
|
||||
def VFPConv1Frm : Format<14>;
|
||||
def VFPConv2Frm : Format<15>;
|
||||
def VFPConv3Frm : Format<16>;
|
||||
def VFPConv4Frm : Format<17>;
|
||||
def VFPConv5Frm : Format<18>;
|
||||
def VFPLdStFrm : Format<19>;
|
||||
def VFPLdStMulFrm : Format<20>;
|
||||
def VFPMiscFrm : Format<21>;
|
||||
def VFPUnaryFrm : Format<14>;
|
||||
def VFPBinaryFrm : Format<15>;
|
||||
def VFPConv1Frm : Format<16>;
|
||||
def VFPConv2Frm : Format<17>;
|
||||
def VFPConv3Frm : Format<18>;
|
||||
def VFPConv4Frm : Format<19>;
|
||||
def VFPConv5Frm : Format<20>;
|
||||
def VFPLdStFrm : Format<21>;
|
||||
def VFPLdStMulFrm : Format<22>;
|
||||
def VFPMiscFrm : Format<23>;
|
||||
|
||||
def ThumbFrm : Format<22>;
|
||||
def ThumbFrm : Format<24>;
|
||||
|
||||
// Misc flag for data processing instructions that indicates whether
|
||||
// the instruction has a Rn register operand.
|
||||
|
@ -87,30 +87,32 @@ namespace ARMII {
|
||||
DPSoRegFrm = 6 << FormShift,
|
||||
|
||||
// Load and Store
|
||||
LdStFrm = 7 << FormShift,
|
||||
LdStMiscFrm = 8 << FormShift,
|
||||
LdStMulFrm = 9 << FormShift,
|
||||
LdFrm = 7 << FormShift,
|
||||
StFrm = 8 << FormShift,
|
||||
LdMiscFrm = 9 << FormShift,
|
||||
StMiscFrm = 10 << FormShift,
|
||||
LdStMulFrm = 11 << FormShift,
|
||||
|
||||
// Miscellaneous arithmetic instructions
|
||||
ArithMiscFrm = 10 << FormShift,
|
||||
ArithMiscFrm = 12 << FormShift,
|
||||
|
||||
// Extend instructions
|
||||
ExtFrm = 11 << FormShift,
|
||||
ExtFrm = 13 << FormShift,
|
||||
|
||||
// VFP formats
|
||||
VFPUnaryFrm = 12 << FormShift,
|
||||
VFPBinaryFrm = 13 << FormShift,
|
||||
VFPConv1Frm = 14 << FormShift,
|
||||
VFPConv2Frm = 15 << FormShift,
|
||||
VFPConv3Frm = 16 << FormShift,
|
||||
VFPConv4Frm = 17 << FormShift,
|
||||
VFPConv5Frm = 18 << FormShift,
|
||||
VFPLdStFrm = 19 << FormShift,
|
||||
VFPLdStMulFrm = 20 << FormShift,
|
||||
VFPMiscFrm = 21 << FormShift,
|
||||
VFPUnaryFrm = 14 << FormShift,
|
||||
VFPBinaryFrm = 15 << FormShift,
|
||||
VFPConv1Frm = 16 << FormShift,
|
||||
VFPConv2Frm = 17 << FormShift,
|
||||
VFPConv3Frm = 18 << FormShift,
|
||||
VFPConv4Frm = 19 << FormShift,
|
||||
VFPConv5Frm = 20 << FormShift,
|
||||
VFPLdStFrm = 21 << FormShift,
|
||||
VFPLdStMulFrm = 22 << FormShift,
|
||||
VFPMiscFrm = 23 << FormShift,
|
||||
|
||||
// Thumb format
|
||||
ThumbFrm = 22 << FormShift,
|
||||
ThumbFrm = 24 << FormShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Field shifts - such shifts are used to set field while generating
|
||||
|
@ -615,134 +615,134 @@ let isBranch = 1, isTerminator = 1 in {
|
||||
|
||||
// Load
|
||||
let isSimpleLoad = 1 in
|
||||
def LDR : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdStFrm,
|
||||
def LDR : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm,
|
||||
"ldr", " $dst, $addr",
|
||||
[(set GPR:$dst, (load addrmode2:$addr))]>;
|
||||
|
||||
// Special LDR for loads from non-pc-relative constpools.
|
||||
let isSimpleLoad = 1, mayLoad = 1, isReMaterializable = 1 in
|
||||
def LDRcp : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdStFrm,
|
||||
def LDRcp : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm,
|
||||
"ldr", " $dst, $addr", []>;
|
||||
|
||||
// Loads with zero extension
|
||||
def LDRH : AI3ldh<(outs GPR:$dst), (ins addrmode3:$addr), LdStMiscFrm,
|
||||
def LDRH : AI3ldh<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
|
||||
"ldr", "h $dst, $addr",
|
||||
[(set GPR:$dst, (zextloadi16 addrmode3:$addr))]>;
|
||||
|
||||
def LDRB : AI2ldb<(outs GPR:$dst), (ins addrmode2:$addr), LdStFrm,
|
||||
def LDRB : AI2ldb<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm,
|
||||
"ldr", "b $dst, $addr",
|
||||
[(set GPR:$dst, (zextloadi8 addrmode2:$addr))]>;
|
||||
|
||||
// Loads with sign extension
|
||||
def LDRSH : AI3ldsh<(outs GPR:$dst), (ins addrmode3:$addr), LdStMiscFrm,
|
||||
def LDRSH : AI3ldsh<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
|
||||
"ldr", "sh $dst, $addr",
|
||||
[(set GPR:$dst, (sextloadi16 addrmode3:$addr))]>;
|
||||
|
||||
def LDRSB : AI3ldsb<(outs GPR:$dst), (ins addrmode3:$addr), LdStMiscFrm,
|
||||
def LDRSB : AI3ldsb<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
|
||||
"ldr", "sb $dst, $addr",
|
||||
[(set GPR:$dst, (sextloadi8 addrmode3:$addr))]>;
|
||||
|
||||
let mayLoad = 1 in {
|
||||
// Load doubleword
|
||||
def LDRD : AI3ldd<(outs GPR:$dst), (ins addrmode3:$addr), LdStMiscFrm,
|
||||
def LDRD : AI3ldd<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
|
||||
"ldr", "d $dst, $addr",
|
||||
[]>, Requires<[IsARM, HasV5T]>;
|
||||
|
||||
// Indexed loads
|
||||
def LDR_PRE : AI2ldwpr<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins addrmode2:$addr), LdStFrm,
|
||||
(ins addrmode2:$addr), LdFrm,
|
||||
"ldr", " $dst, $addr!", "$addr.base = $base_wb", []>;
|
||||
|
||||
def LDR_POST : AI2ldwpo<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins GPR:$base, am2offset:$offset), LdStFrm,
|
||||
(ins GPR:$base, am2offset:$offset), LdFrm,
|
||||
"ldr", " $dst, [$base], $offset", "$base = $base_wb", []>;
|
||||
|
||||
def LDRH_PRE : AI3ldhpr<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins addrmode3:$addr), LdStMiscFrm,
|
||||
(ins addrmode3:$addr), LdMiscFrm,
|
||||
"ldr", "h $dst, $addr!", "$addr.base = $base_wb", []>;
|
||||
|
||||
def LDRH_POST : AI3ldhpo<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins GPR:$base,am3offset:$offset), LdStMiscFrm,
|
||||
(ins GPR:$base,am3offset:$offset), LdMiscFrm,
|
||||
"ldr", "h $dst, [$base], $offset", "$base = $base_wb", []>;
|
||||
|
||||
def LDRB_PRE : AI2ldbpr<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins addrmode2:$addr), LdStFrm,
|
||||
(ins addrmode2:$addr), LdFrm,
|
||||
"ldr", "b $dst, $addr!", "$addr.base = $base_wb", []>;
|
||||
|
||||
def LDRB_POST : AI2ldbpo<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins GPR:$base,am2offset:$offset), LdStFrm,
|
||||
(ins GPR:$base,am2offset:$offset), LdFrm,
|
||||
"ldr", "b $dst, [$base], $offset", "$base = $base_wb", []>;
|
||||
|
||||
def LDRSH_PRE : AI3ldshpr<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins addrmode3:$addr), LdStMiscFrm,
|
||||
(ins addrmode3:$addr), LdMiscFrm,
|
||||
"ldr", "sh $dst, $addr!", "$addr.base = $base_wb", []>;
|
||||
|
||||
def LDRSH_POST: AI3ldshpo<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins GPR:$base,am3offset:$offset), LdStMiscFrm,
|
||||
"ldr", "sh $dst, [$base], $offset", "$base = $base_wb", []>;
|
||||
(ins GPR:$base,am3offset:$offset), LdMiscFrm,
|
||||
"ldr", "sh $dst, [$base], $offset", "$base = $base_wb", []>;
|
||||
|
||||
def LDRSB_PRE : AI3ldsbpr<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins addrmode3:$addr), LdStMiscFrm,
|
||||
(ins addrmode3:$addr), LdMiscFrm,
|
||||
"ldr", "sb $dst, $addr!", "$addr.base = $base_wb", []>;
|
||||
|
||||
def LDRSB_POST: AI3ldsbpo<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins GPR:$base,am3offset:$offset), LdStMiscFrm,
|
||||
(ins GPR:$base,am3offset:$offset), LdMiscFrm,
|
||||
"ldr", "sb $dst, [$base], $offset", "$base = $base_wb", []>;
|
||||
}
|
||||
|
||||
// Store
|
||||
def STR : AI2stw<(outs), (ins GPR:$src, addrmode2:$addr), LdStFrm,
|
||||
def STR : AI2stw<(outs), (ins GPR:$src, addrmode2:$addr), StFrm,
|
||||
"str", " $src, $addr",
|
||||
[(store GPR:$src, addrmode2:$addr)]>;
|
||||
|
||||
// Stores with truncate
|
||||
def STRH : AI3sth<(outs), (ins GPR:$src, addrmode3:$addr), LdStMiscFrm,
|
||||
def STRH : AI3sth<(outs), (ins GPR:$src, addrmode3:$addr), StMiscFrm,
|
||||
"str", "h $src, $addr",
|
||||
[(truncstorei16 GPR:$src, addrmode3:$addr)]>;
|
||||
|
||||
def STRB : AI2stb<(outs), (ins GPR:$src, addrmode2:$addr), LdStFrm,
|
||||
def STRB : AI2stb<(outs), (ins GPR:$src, addrmode2:$addr), StFrm,
|
||||
"str", "b $src, $addr",
|
||||
[(truncstorei8 GPR:$src, addrmode2:$addr)]>;
|
||||
|
||||
// Store doubleword
|
||||
let mayStore = 1 in
|
||||
def STRD : AI3std<(outs), (ins GPR:$src, addrmode3:$addr), LdStMiscFrm,
|
||||
def STRD : AI3std<(outs), (ins GPR:$src, addrmode3:$addr), StMiscFrm,
|
||||
"str", "d $src, $addr",
|
||||
[]>, Requires<[IsARM, HasV5T]>;
|
||||
|
||||
// Indexed stores
|
||||
def STR_PRE : AI2stwpr<(outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base, am2offset:$offset), LdStFrm,
|
||||
(ins GPR:$src, GPR:$base, am2offset:$offset), StFrm,
|
||||
"str", " $src, [$base, $offset]!", "$base = $base_wb",
|
||||
[(set GPR:$base_wb,
|
||||
(pre_store GPR:$src, GPR:$base, am2offset:$offset))]>;
|
||||
|
||||
def STR_POST : AI2stwpo<(outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base,am2offset:$offset), LdStFrm,
|
||||
(ins GPR:$src, GPR:$base,am2offset:$offset), StFrm,
|
||||
"str", " $src, [$base], $offset", "$base = $base_wb",
|
||||
[(set GPR:$base_wb,
|
||||
(post_store GPR:$src, GPR:$base, am2offset:$offset))]>;
|
||||
|
||||
def STRH_PRE : AI3sthpr<(outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base,am3offset:$offset), LdStMiscFrm,
|
||||
(ins GPR:$src, GPR:$base,am3offset:$offset), StMiscFrm,
|
||||
"str", "h $src, [$base, $offset]!", "$base = $base_wb",
|
||||
[(set GPR:$base_wb,
|
||||
(pre_truncsti16 GPR:$src, GPR:$base,am3offset:$offset))]>;
|
||||
|
||||
def STRH_POST: AI3sthpo<(outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base,am3offset:$offset), LdStMiscFrm,
|
||||
(ins GPR:$src, GPR:$base,am3offset:$offset), StMiscFrm,
|
||||
"str", "h $src, [$base], $offset", "$base = $base_wb",
|
||||
[(set GPR:$base_wb, (post_truncsti16 GPR:$src,
|
||||
GPR:$base, am3offset:$offset))]>;
|
||||
|
||||
def STRB_PRE : AI2stbpr<(outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base,am2offset:$offset), LdStFrm,
|
||||
(ins GPR:$src, GPR:$base,am2offset:$offset), StFrm,
|
||||
"str", "b $src, [$base, $offset]!", "$base = $base_wb",
|
||||
[(set GPR:$base_wb, (pre_truncsti8 GPR:$src,
|
||||
GPR:$base, am2offset:$offset))]>;
|
||||
|
||||
def STRB_POST: AI2stbpo<(outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base,am2offset:$offset), LdStFrm,
|
||||
(ins GPR:$src, GPR:$base,am2offset:$offset), StFrm,
|
||||
"str", "b $src, [$base], $offset", "$base = $base_wb",
|
||||
[(set GPR:$base_wb, (post_truncsti8 GPR:$src,
|
||||
GPR:$base, am2offset:$offset))]>;
|
||||
|
Loading…
Reference in New Issue
Block a user