[llvm-commits] Support for ARMv4
John Tytgat
john at bass-software.com
Mon Feb 15 15:57:14 PST 2010
In message <30e333ea50.Jo at hobbes.bass-software.com>
John Tytgat <john at bass-software.com> wrote:
> In message <b087fca01002140554i59aed645pf186ca36b5796aab at mail.gmail.com>
> Anton Korobeynikov <anton at korobeynikov.info> wrote:
>
> > Hello, John
> >
> > > No regressions for 'make TESTSUITE=CodeGen/ARM check'.
> > This is pretty expected and necessary thing, but not sufficient.
> >
> > Could you please compile llvm-gcc as a cross-compiler for ARMv4? Even
> > better, with newlib compiled at the same time. This will ensure that
> > the v4 support is indeed real.
>
> Sure, and thanks for this useful suggestion. It allowed me to finetune
> a couple of things ;-) Attached two patches, one for llvm and one for
> llvm-gcc:
>
> llvm-armv4.patch:
> [...]
> - test/CodeGen/ARM/armv4.ll: Added test case.
>
> llvm-gcc-armv4.patch:
Apologies, I just see the armv4.ll testcase wasn't included. Attached
the two patches again with that fixed.
John.
--
John Tytgat
John at bass-software.com
-------------- next part --------------
Index: test/CodeGen/ARM/armv4.ll
===================================================================
--- test/CodeGen/ARM/armv4.ll (revision 0)
+++ test/CodeGen/ARM/armv4.ll (revision 0)
@@ -0,0 +1,13 @@
+; RUN: llc < %s -mtriple=arm-unknown-eabi | FileCheck %s -check-prefix=THUMB
+; RUN: llc < %s -mtriple=arm-unknown-eabi -mcpu=strongarm | FileCheck %s -check-prefix=ARM
+; RUN: llc < %s -mtriple=arm-unknown-eabi -mcpu=cortex-a8 | FileCheck %s -check-prefix=THUMB
+; RUN: llc < %s -mtriple=arm-unknown-eabi -mattr=+v6 | FileCheck %s -check-prefix=THUMB
+; RUN: llc < %s -mtriple=armv4-unknown-eabi | FileCheck %s -check-prefix=ARM
+; RUN: llc < %s -mtriple=armv4t-unknown-eabi | FileCheck %s -check-prefix=THUMB
+
+define arm_aapcscc i32 @test(i32 %a) nounwind readnone {
+entry:
+; ARM: mov pc
+; THUMB: bx
+ ret i32 %a
+}
Index: lib/Target/ARM/ARMSubtarget.cpp
===================================================================
--- lib/Target/ARM/ARMSubtarget.cpp (revision 96176)
+++ lib/Target/ARM/ARMSubtarget.cpp (working copy)
@@ -33,7 +33,7 @@
ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
bool isT)
- : ARMArchVersion(V4T)
+ : ARMArchVersion(V4)
, ARMFPUType(None)
, UseNEONForSinglePrecisionFP(UseNEONFP)
, IsThumb(isT)
@@ -54,6 +54,11 @@
// Parse features string.
CPUString = ParseSubtargetFeatures(FS, CPUString);
+ // When no arch is specified either by CPU or by attributes, make the default
+ // ARMv4T.
+ if (CPUString == "generic" && (FS.empty() || FS == "generic"))
+ ARMArchVersion = V4T;
+
// Set the boolean corresponding to the current target triple, or the default
// if one cannot be determined, to true.
unsigned Len = TT.length();
@@ -68,25 +73,28 @@
}
if (Idx) {
unsigned SubVer = TT[Idx];
- if (SubVer > '4' && SubVer <= '9') {
- if (SubVer >= '7') {
- ARMArchVersion = V7A;
- } else if (SubVer == '6') {
- ARMArchVersion = V6;
- if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2')
- ARMArchVersion = V6T2;
- } else if (SubVer == '5') {
- ARMArchVersion = V5T;
- if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e')
- ARMArchVersion = V5TE;
- }
- if (ARMArchVersion >= V6T2)
- ThumbMode = Thumb2;
+ if (SubVer >= '7' && SubVer <= '9') {
+ ARMArchVersion = V7A;
+ } else if (SubVer == '6') {
+ ARMArchVersion = V6;
+ if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2')
+ ARMArchVersion = V6T2;
+ } else if (SubVer == '5') {
+ ARMArchVersion = V5T;
+ if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e')
+ ARMArchVersion = V5TE;
+ } else if (SubVer == '4') {
+ if (Len >= Idx+2 && TT[Idx+1] == 't')
+ ARMArchVersion = V4T;
+ else
+ ARMArchVersion = V4;
}
}
// Thumb2 implies at least V6T2.
- if (ARMArchVersion < V6T2 && ThumbMode >= Thumb2)
+ if (ARMArchVersion >= V6T2)
+ ThumbMode = Thumb2;
+ else if (ThumbMode >= Thumb2)
ARMArchVersion = V6T2;
if (Len >= 10) {
Index: lib/Target/ARM/ARMInstrInfo.td
===================================================================
--- lib/Target/ARM/ARMInstrInfo.td (revision 96176)
+++ lib/Target/ARM/ARMInstrInfo.td (working copy)
@@ -113,6 +113,8 @@
//===----------------------------------------------------------------------===//
// ARM Instruction Predicate Definitions.
//
+def HasV4T : Predicate<"Subtarget->hasV4TOps()">;
+def NoV4T : Predicate<"!Subtarget->hasV4TOps()">;
def HasV5T : Predicate<"Subtarget->hasV5TOps()">;
def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">;
def HasV6 : Predicate<"Subtarget->hasV6Ops()">;
@@ -770,24 +772,50 @@
// Control Flow Instructions.
//
-let isReturn = 1, isTerminator = 1, isBarrier = 1 in
+let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
+ // ARMV4T and above
def BX_RET : AI<(outs), (ins), BrMiscFrm, IIC_Br,
- "bx", "\tlr", [(ARMretflag)]> {
- let Inst{3-0} = 0b1110;
- let Inst{7-4} = 0b0001;
- let Inst{19-8} = 0b111111111111;
- let Inst{27-20} = 0b00010010;
+ "bx", "\tlr", [(ARMretflag)]>,
+ Requires<[IsARM, HasV4T]> {
+ let Inst{3-0} = 0b1110;
+ let Inst{7-4} = 0b0001;
+ let Inst{19-8} = 0b111111111111;
+ let Inst{27-20} = 0b00010010;
+ }
+
+ // ARMV4 only
+ def MOVPCLR : AI<(outs), (ins), BrMiscFrm, IIC_Br,
+ "mov", "\tpc, lr", [(ARMretflag)]>,
+ Requires<[IsARM, NoV4T]> {
+ let Inst{11-0} = 0b000000001110;
+ let Inst{15-12} = 0b1111;
+ let Inst{19-16} = 0b0000;
+ let Inst{27-20} = 0b00011010;
+ }
}
// Indirect branches
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
+ // ARMV4T and above
def BRIND : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "bx\t$dst",
- [(brind GPR:$dst)]> {
+ [(brind GPR:$dst)]>,
+ Requires<[IsARM, HasV4T]> {
let Inst{7-4} = 0b0001;
let Inst{19-8} = 0b111111111111;
let Inst{27-20} = 0b00010010;
let Inst{31-28} = 0b1110;
}
+
+ // ARMV4 only
+ def MOVPCRX : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "mov\tpc, $dst",
+ [(brind GPR:$dst)]>,
+ Requires<[IsARM, NoV4T]> {
+ let Inst{11-4} = 0b00000000;
+ let Inst{15-12} = 0b1111;
+ let Inst{19-16} = 0b0000;
+ let Inst{27-20} = 0b00011010;
+ let Inst{31-28} = 0b1110;
+ }
}
// FIXME: remove when we have a way to marking a MI with these properties.
@@ -831,11 +859,22 @@
def BX : ABXIx2<(outs), (ins GPR:$func, variable_ops),
IIC_Br, "mov\tlr, pc\n\tbx\t$func",
[(ARMcall_nolink GPR:$func)]>,
- Requires<[IsARM, IsNotDarwin]> {
+ Requires<[IsARM, HasV4T, IsNotDarwin]> {
let Inst{7-4} = 0b0001;
let Inst{19-8} = 0b111111111111;
let Inst{27-20} = 0b00010010;
}
+
+ // ARMv4
+ def BMOVPCRX : ABXIx2<(outs), (ins GPR:$func, variable_ops),
+ IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func",
+ [(ARMcall_nolink GPR:$func)]>,
+ Requires<[IsARM, NoV4T, IsNotDarwin]> {
+ let Inst{11-4} = 0b00000000;
+ let Inst{15-12} = 0b1111;
+ let Inst{19-16} = 0b0000;
+ let Inst{27-20} = 0b00011010;
+ }
}
// On Darwin R9 is call-clobbered.
@@ -867,11 +906,23 @@
// ARMv4T
def BXr9 : ABXIx2<(outs), (ins GPR:$func, variable_ops),
IIC_Br, "mov\tlr, pc\n\tbx\t$func",
- [(ARMcall_nolink GPR:$func)]>, Requires<[IsARM, IsDarwin]> {
+ [(ARMcall_nolink GPR:$func)]>,
+ Requires<[IsARM, HasV4T, IsDarwin]> {
let Inst{7-4} = 0b0001;
let Inst{19-8} = 0b111111111111;
let Inst{27-20} = 0b00010010;
}
+
+ // ARMv4
+ def BMOVPCRXr9 : ABXIx2<(outs), (ins GPR:$func, variable_ops),
+ IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func",
+ [(ARMcall_nolink GPR:$func)]>,
+ Requires<[IsARM, NoV4T, IsDarwin]> {
+ let Inst{11-4} = 0b00000000;
+ let Inst{15-12} = 0b1111;
+ let Inst{19-16} = 0b0000;
+ let Inst{27-20} = 0b00011010;
+ }
}
let isBranch = 1, isTerminator = 1 in {
Index: lib/Target/ARM/ARMCodeEmitter.cpp
===================================================================
--- lib/Target/ARM/ARMCodeEmitter.cpp (revision 96176)
+++ lib/Target/ARM/ARMCodeEmitter.cpp (working copy)
@@ -1138,7 +1138,7 @@
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
- if (TID.Opcode == ARM::BX_RET)
+ if (TID.Opcode == (Subtarget->hasV4TOps() ? ARM::BX_RET : ARM::MOVPCLR))
// The return register is LR.
Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::LR);
else
Index: lib/Target/ARM/ARMSubtarget.h
===================================================================
--- lib/Target/ARM/ARMSubtarget.h (revision 96176)
+++ lib/Target/ARM/ARMSubtarget.h (working copy)
@@ -26,7 +26,7 @@
class ARMSubtarget : public TargetSubtarget {
protected:
enum ARMArchEnum {
- V4T, V5T, V5TE, V6, V6T2, V7A
+ V4, V4T, V5T, V5TE, V6, V6T2, V7A
};
enum ARMFPEnum {
@@ -38,7 +38,7 @@
Thumb2
};
- /// ARMArchVersion - ARM architecture version: V4T (base), V5T, V5TE,
+ /// ARMArchVersion - ARM architecture version: V4, V4T (base), V5T, V5TE,
/// V6, V6T2, V7A.
ARMArchEnum ARMArchVersion;
Index: lib/Target/ARM/ARMBaseInstrInfo.h
===================================================================
--- lib/Target/ARM/ARMBaseInstrInfo.h (revision 96176)
+++ lib/Target/ARM/ARMBaseInstrInfo.h (working copy)
@@ -332,7 +332,7 @@
static inline
bool isIndirectBranchOpcode(int Opc) {
- return Opc == ARM::BRIND || Opc == ARM::tBRIND;
+ return Opc == ARM::BRIND || Opc == ARM::MOVPCRX || Opc == ARM::tBRIND;
}
/// getInstrPredicate - If instruction is predicated, returns its predicate
-------------- next part --------------
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h (revision 96176)
+++ gcc/config/arm/arm.h (working copy)
@@ -3519,7 +3519,9 @@
: (arm_arch5 \
? "armv5" \
: (arm_arch4t \
- ? "armv4t" : "")))))))
+ ? "armv4t" \
+ : (arm_arch4 \
+ ? "armv4" : ""))))))))
#define LLVM_SET_MACHINE_OPTIONS(argvec) \
if (TARGET_SOFT_FLOAT) \
Index: gcc/config/arm/libunwind.S
===================================================================
--- gcc/config/arm/libunwind.S (revision 96176)
+++ gcc/config/arm/libunwind.S (working copy)
@@ -167,21 +167,37 @@
RET
ARM_FUNC_START gnu_Unwind_Restore_WMMXC
+#if __ARM_ARCH__ > 4
/* Use the generic coprocessor form so that gas doesn't complain
on non-iWMMXt targets. */
ldc2 p1, cr8, [r0], #4 /* wldrw wcgr0, [r0], #4 */
ldc2 p1, cr9, [r0], #4 /* wldrw wcgr1, [r0], #4 */
ldc2 p1, cr10, [r0], #4 /* wldrw wcgr2, [r0], #4 */
ldc2 p1, cr11, [r0], #4 /* wldrw wcgr3, [r0], #4 */
+#else
+ /* ldc2 is not valid pre-ARMv5 */
+ .word 0xfcb08101
+ .word 0xfcb09101
+ .word 0xfcb0a101
+ .word 0xfcb0b101
+#endif
RET
ARM_FUNC_START gnu_Unwind_Save_WMMXC
+#if __ARM_ARCH__ > 4
/* Use the generic coprocessor form so that gas doesn't complain
on non-iWMMXt targets. */
stc2 p1, cr8, [r0], #4 /* wstrw wcgr0, [r0], #4 */
stc2 p1, cr9, [r0], #4 /* wstrw wcgr1, [r0], #4 */
stc2 p1, cr10, [r0], #4 /* wstrw wcgr2, [r0], #4 */
stc2 p1, cr11, [r0], #4 /* wstrw wcgr3, [r0], #4 */
+#else
+ /* stc2 is not valid pre-ARMv5 */
+ .word 0xfca08101
+ .word 0xfca09101
+ .word 0xfca0a101
+ .word 0xfca0b101
+#endif
RET
/* APPLE LOCAL end v7 support. Merge from Codesourcery */
More information about the llvm-commits
mailing list