From 148cad8b308c0f8fdb37b368f2c911861dd2421a Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 13 Nov 2008 07:34:59 +0000 Subject: [PATCH] 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 --- lib/Target/ARM/ARMCodeEmitter.cpp | 38 +++++++++++++++++---- lib/Target/ARM/ARMInstrFormats.td | 40 +++++++++++----------- lib/Target/ARM/ARMInstrInfo.h | 34 ++++++++++--------- lib/Target/ARM/ARMInstrInfo.td | 56 +++++++++++++++---------------- 4 files changed, 98 insertions(+), 70 deletions(-) diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index c583ed12def..500d6ac8404 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -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); diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 192dfdf3dba..c2d8df31a60 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -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 ArithMiscFrm : Format<10>; -def ExtFrm : Format<11>; - -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 ThumbFrm : Format<22>; +def LdFrm : Format<7>; +def StFrm : Format<8>; +def LdMiscFrm : Format<9>; +def StMiscFrm : Format<10>; +def LdStMulFrm : Format<11>; + +def ArithMiscFrm : Format<12>; +def ExtFrm : Format<13>; + +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<24>; // Misc flag for data processing instructions that indicates whether // the instruction has a Rn register operand. diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h index 1ef965c5556..476e5fd2542 100644 --- a/lib/Target/ARM/ARMInstrInfo.h +++ b/lib/Target/ARM/ARMInstrInfo.h @@ -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 diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index d4588dd12ef..a437ca7b14c 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -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))]>; -- 2.34.1