1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00

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 74dea2d5cb
commit e0e616a74d
6 changed files with 101 additions and 29 deletions

View File

@ -332,7 +332,7 @@ bool isJumpTableBranchOpcode(int Opc) {
static inline static inline
bool isIndirectBranchOpcode(int Opc) { 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 /// 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 // Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift; 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. // The return register is LR.
Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::LR); Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::LR);
else else

View File

@ -113,6 +113,8 @@ def ARMrbit : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ARM Instruction Predicate Definitions. // ARM Instruction Predicate Definitions.
// //
def HasV4T : Predicate<"Subtarget->hasV4TOps()">;
def NoV4T : Predicate<"!Subtarget->hasV4TOps()">;
def HasV5T : Predicate<"Subtarget->hasV5TOps()">; def HasV5T : Predicate<"Subtarget->hasV5TOps()">;
def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">; def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">;
def HasV6 : Predicate<"Subtarget->hasV6Ops()">; def HasV6 : Predicate<"Subtarget->hasV6Ops()">;
@ -851,24 +853,50 @@ def LEApcrelJT : AXI1<0x0, (outs GPR:$dst),
// Control Flow Instructions. // 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, def BX_RET : AI<(outs), (ins), BrMiscFrm, IIC_Br,
"bx", "\tlr", [(ARMretflag)]> { "bx", "\tlr", [(ARMretflag)]>,
let Inst{3-0} = 0b1110; Requires<[IsARM, HasV4T]> {
let Inst{7-4} = 0b0001; let Inst{3-0} = 0b1110;
let Inst{19-8} = 0b111111111111; let Inst{7-4} = 0b0001;
let Inst{27-20} = 0b00010010; 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 // Indirect branches
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 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", 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{7-4} = 0b0001;
let Inst{19-8} = 0b111111111111; let Inst{19-8} = 0b111111111111;
let Inst{27-20} = 0b00010010; let Inst{27-20} = 0b00010010;
let Inst{31-28} = 0b1110; 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. // 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), def BX : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
IIC_Br, "mov\tlr, pc\n\tbx\t$func", IIC_Br, "mov\tlr, pc\n\tbx\t$func",
[(ARMcall_nolink tGPR:$func)]>, [(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, IsNotDarwin]> { Requires<[IsARM, HasV4T, IsNotDarwin]> {
let Inst{7-4} = 0b0001; let Inst{7-4} = 0b0001;
let Inst{19-8} = 0b111111111111; let Inst{19-8} = 0b111111111111;
let Inst{27-20} = 0b00010010; 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. // 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. // Note: Restrict $func to the tGPR regclass to prevent it being in LR.
def BXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops), def BXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
IIC_Br, "mov\tlr, pc\n\tbx\t$func", 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{7-4} = 0b0001;
let Inst{19-8} = 0b111111111111; let Inst{19-8} = 0b111111111111;
let Inst{27-20} = 0b00010010; 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 { 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, ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
bool isT) bool isT)
: ARMArchVersion(V4T) : ARMArchVersion(V4)
, ARMFPUType(None) , ARMFPUType(None)
, UseNEONForSinglePrecisionFP(UseNEONFP) , UseNEONForSinglePrecisionFP(UseNEONFP)
, IsThumb(isT) , IsThumb(isT)
@ -54,6 +54,11 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
// Parse features string. // Parse features string.
CPUString = ParseSubtargetFeatures(FS, CPUString); 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 // Set the boolean corresponding to the current target triple, or the default
// if one cannot be determined, to true. // if one cannot be determined, to true.
unsigned Len = TT.length(); unsigned Len = TT.length();
@ -68,25 +73,28 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
} }
if (Idx) { if (Idx) {
unsigned SubVer = TT[Idx]; unsigned SubVer = TT[Idx];
if (SubVer > '4' && SubVer <= '9') { if (SubVer >= '7' && SubVer <= '9') {
if (SubVer >= '7') { ARMArchVersion = V7A;
ARMArchVersion = V7A; } else if (SubVer == '6') {
} else if (SubVer == '6') { ARMArchVersion = V6;
ARMArchVersion = V6; if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2')
if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') ARMArchVersion = V6T2;
ARMArchVersion = V6T2; } else if (SubVer == '5') {
} else if (SubVer == '5') { ARMArchVersion = V5T;
ARMArchVersion = V5T; if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e')
if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') ARMArchVersion = V5TE;
ARMArchVersion = V5TE; } else if (SubVer == '4') {
} if (Len >= Idx+2 && TT[Idx+1] == 't')
if (ARMArchVersion >= V6T2) ARMArchVersion = V4T;
ThumbMode = Thumb2; else
ARMArchVersion = V4;
} }
} }
// Thumb2 implies at least V6T2. // Thumb2 implies at least V6T2.
if (ARMArchVersion < V6T2 && ThumbMode >= Thumb2) if (ARMArchVersion >= V6T2)
ThumbMode = Thumb2;
else if (ThumbMode >= Thumb2)
ARMArchVersion = V6T2; ARMArchVersion = V6T2;
if (Len >= 10) { if (Len >= 10) {

View File

@ -26,7 +26,7 @@ class GlobalValue;
class ARMSubtarget : public TargetSubtarget { class ARMSubtarget : public TargetSubtarget {
protected: protected:
enum ARMArchEnum { enum ARMArchEnum {
V4T, V5T, V5TE, V6, V6T2, V7A V4, V4T, V5T, V5TE, V6, V6T2, V7A
}; };
enum ARMFPEnum { enum ARMFPEnum {
@ -38,7 +38,7 @@ protected:
Thumb2 Thumb2
}; };
/// ARMArchVersion - ARM architecture version: V4T (base), V5T, V5TE, /// ARMArchVersion - ARM architecture version: V4, V4T (base), V5T, V5TE,
/// V6, V6T2, V7A. /// V6, V6T2, V7A.
ARMArchEnum ARMArchVersion; ARMArchEnum ARMArchVersion;

13
test/CodeGen/ARM/armv4.ll Normal file
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
}