[llvm-commits] Support for ARMv4

John Tytgat john at bass-software.com
Mon Feb 15 15:48:47 PST 2010


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:

- lib/Target/ARM/ARMSubtarget.cpp(ARMSubtarget::ARMSubtarget): Make triple
  armv4-* switch ARMArchVersion to V4, allow CPU selection (like strongarm)
  to switch to V4 as well but keep ARMv4T still as default when no arch
  is specified.
- lib/Target/ARM/ARMSubtarget.h(V4): Defined.
- lib/Target/ARM/ARMInstrInfo.td(HasV4T,NoV4T): Define.
  (BX_RET): Add IsARM and HasV4T requirements.
  (MOVPCLR): Define, is equivalent to BX_RET but for ARMv4 only.
  (BRIND): Add IsARM and HasV4T requirements.
  (MOVPCRX): Define, is equivalent to BRIND but for ARMv4 only.
  (BX, BXr9): Add HasV4T requirements.
  (BMOVPCRX): Define, is equivalent to BX but for ARMv4 only.
  (BMOVPCRXr9): Define, is equivalent to BXr9 but for ARMv4 only.
- lib/Target/ARM/ARMCodeEmitter.cpp(ARMCodeEmitter::emitMiscBranchInstruction):
  Take ARM::MOVPCLR into account.
- lib/Target/ARM/ARMBaseInstrInfo.h(isIndirectBranchOpcode): Take
  ARM::MOVPCRX into account.
- test/CodeGen/ARM/armv4.ll: Added test case.

llvm-gcc-armv4.patch:

- gcc/config/arm/arm.h(LLVM_OVERRIDE_TARGET_ARCH): Add check for arm_arch4.
- gcc/config/arm/libunwind.S(gnu_Unwind_Restore_WMMXC,gnu_Unwind_Save_WMMXC):
  Avoid binutils error when selecting a pre-ARMv5 arch.

No regressions for 'make TESTSUITE=CodeGen/ARM check'.
Tested with llvm-gcc target arm-unknown-eabi + newlib 1.18, binutils 2.20
and configured with --with-arch=armv4

John.
-- 
John Tytgat
John at bass-software.com
-------------- next part --------------
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