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:
parent
74dea2d5cb
commit
e0e616a74d
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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) {
|
||||||
|
@ -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
13
test/CodeGen/ARM/armv4.ll
Normal 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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user