mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
Initial bits of ARMv4-only support.
Patch by John Tytgat! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97886 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
043f3c2a0e
commit
ce7bf1c55f
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
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