Initial bits of ARMv4-only support.

Patch by John Tytgat!

llvm-svn: 97886
This commit is contained in:
Anton Korobeynikov 2010-03-06 19:39:36 +00:00
parent 8341c390aa
commit bf16a17fc1
6 changed files with 101 additions and 29 deletions

View File

@ -332,7 +332,7 @@ bool isJumpTableBranchOpcode(int Opc) {
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

View File

@ -1138,7 +1138,7 @@ void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) {
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
if (TID.Opcode == ARM::BX_RET)
if (TID.Opcode == ARM::BX_RET || TID.Opcode == ARM::MOVPCLR)
// The return register is LR.
Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::LR);
else

View File

@ -113,6 +113,8 @@ def ARMrbit : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>;
//===----------------------------------------------------------------------===//
// 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()">;
@ -851,24 +853,50 @@ def LEApcrelJT : AXI1<0x0, (outs GPR:$dst),
// 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.
@ -913,11 +941,22 @@ let isCall = 1,
def BX : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
IIC_Br, "mov\tlr, pc\n\tbx\t$func",
[(ARMcall_nolink tGPR:$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 tGPR:$func, variable_ops),
IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func",
[(ARMcall_nolink tGPR:$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.
@ -950,11 +989,23 @@ let isCall = 1,
// Note: Restrict $func to the tGPR regclass to prevent it being in LR.
def BXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
IIC_Br, "mov\tlr, pc\n\tbx\t$func",
[(ARMcall_nolink tGPR:$func)]>, Requires<[IsARM, IsDarwin]> {
[(ARMcall_nolink tGPR:$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 tGPR:$func, variable_ops),
IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func",
[(ARMcall_nolink tGPR:$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 {

View File

@ -33,7 +33,7 @@ UseMOVT("arm-use-movt",
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 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
// 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 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
}
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) {

View File

@ -26,7 +26,7 @@ class GlobalValue;
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 @@ protected:
Thumb2
};
/// ARMArchVersion - ARM architecture version: V4T (base), V5T, V5TE,
/// ARMArchVersion - ARM architecture version: V4, V4T (base), V5T, V5TE,
/// V6, V6T2, V7A.
ARMArchEnum ARMArchVersion;

View File

@ -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
}