mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-27 14:34:58 +00:00
Add support for the PPC isel instruction.
The isel (integer select) instruction is supported on the 440 and A2 embedded cores and on the POWER7. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@159045 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e5457d2116
commit
009f7afbeb
@ -86,8 +86,33 @@ void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
|
|||||||
void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
|
void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
|
||||||
raw_ostream &O,
|
raw_ostream &O,
|
||||||
const char *Modifier) {
|
const char *Modifier) {
|
||||||
assert(Modifier && "Must specify 'cc' or 'reg' as predicate op modifier!");
|
|
||||||
unsigned Code = MI->getOperand(OpNo).getImm();
|
unsigned Code = MI->getOperand(OpNo).getImm();
|
||||||
|
if (!Modifier) {
|
||||||
|
unsigned CCReg = MI->getOperand(OpNo+1).getReg();
|
||||||
|
unsigned RegNo;
|
||||||
|
switch (CCReg) {
|
||||||
|
default: llvm_unreachable("Unknown CR register");
|
||||||
|
case PPC::CR0: RegNo = 0; break;
|
||||||
|
case PPC::CR1: RegNo = 1; break;
|
||||||
|
case PPC::CR2: RegNo = 2; break;
|
||||||
|
case PPC::CR3: RegNo = 3; break;
|
||||||
|
case PPC::CR4: RegNo = 4; break;
|
||||||
|
case PPC::CR5: RegNo = 5; break;
|
||||||
|
case PPC::CR6: RegNo = 6; break;
|
||||||
|
case PPC::CR7: RegNo = 7; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the CR bit number. The Code is ((BI << 5) | BO) for a
|
||||||
|
// BCC, but we must have the positive form here (BO == 12)
|
||||||
|
unsigned BO = Code & 0xF;
|
||||||
|
unsigned BI = Code >> 5;
|
||||||
|
assert(BO == 12 && "BO in predicate bit must have the positive form");
|
||||||
|
|
||||||
|
unsigned Value = 4*RegNo + BI;
|
||||||
|
O << Value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (StringRef(Modifier) == "cc") {
|
if (StringRef(Modifier) == "cc") {
|
||||||
switch ((PPC::Predicate)Code) {
|
switch ((PPC::Predicate)Code) {
|
||||||
case PPC::PRED_ALWAYS: return; // Don't print anything for always.
|
case PPC::PRED_ALWAYS: return; // Don't print anything for always.
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
|
|
||||||
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||||
void printPredicateOperand(const MCInst *MI, unsigned OpNo,
|
void printPredicateOperand(const MCInst *MI, unsigned OpNo,
|
||||||
raw_ostream &O, const char *Modifier);
|
raw_ostream &O, const char *Modifier = 0);
|
||||||
|
|
||||||
|
|
||||||
void printS5ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
void printS5ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||||
|
@ -50,6 +50,8 @@ def FeatureFSqrt : SubtargetFeature<"fsqrt","HasFSQRT", "true",
|
|||||||
"Enable the fsqrt instruction">;
|
"Enable the fsqrt instruction">;
|
||||||
def FeatureSTFIWX : SubtargetFeature<"stfiwx","HasSTFIWX", "true",
|
def FeatureSTFIWX : SubtargetFeature<"stfiwx","HasSTFIWX", "true",
|
||||||
"Enable the stfiwx instruction">;
|
"Enable the stfiwx instruction">;
|
||||||
|
def FeatureISEL : SubtargetFeature<"isel","HasISEL", "true",
|
||||||
|
"Enable the isel instruction">;
|
||||||
def FeatureBookE : SubtargetFeature<"booke", "IsBookE", "true",
|
def FeatureBookE : SubtargetFeature<"booke", "IsBookE", "true",
|
||||||
"Enable Book E instructions">;
|
"Enable Book E instructions">;
|
||||||
|
|
||||||
@ -66,8 +68,10 @@ include "PPCInstrInfo.td"
|
|||||||
//
|
//
|
||||||
|
|
||||||
def : Processor<"generic", G3Itineraries, [Directive32]>;
|
def : Processor<"generic", G3Itineraries, [Directive32]>;
|
||||||
def : Processor<"440", PPC440Itineraries, [Directive440, FeatureBookE]>;
|
def : Processor<"440", PPC440Itineraries, [Directive440, FeatureISEL,
|
||||||
def : Processor<"450", PPC440Itineraries, [Directive440, FeatureBookE]>;
|
FeatureBookE]>;
|
||||||
|
def : Processor<"450", PPC440Itineraries, [Directive440, FeatureISEL,
|
||||||
|
FeatureBookE]>;
|
||||||
def : Processor<"601", G3Itineraries, [Directive601]>;
|
def : Processor<"601", G3Itineraries, [Directive601]>;
|
||||||
def : Processor<"602", G3Itineraries, [Directive602]>;
|
def : Processor<"602", G3Itineraries, [Directive602]>;
|
||||||
def : Processor<"603", G3Itineraries, [Directive603]>;
|
def : Processor<"603", G3Itineraries, [Directive603]>;
|
||||||
@ -90,10 +94,11 @@ def : Processor<"g5", G5Itineraries,
|
|||||||
[Directive970, FeatureAltivec,
|
[Directive970, FeatureAltivec,
|
||||||
FeatureMFOCRF, FeatureFSqrt, FeatureSTFIWX,
|
FeatureMFOCRF, FeatureFSqrt, FeatureSTFIWX,
|
||||||
Feature64Bit /*, Feature64BitRegs */]>;
|
Feature64Bit /*, Feature64BitRegs */]>;
|
||||||
def : Processor<"a2", PPCA2Itineraries, [DirectiveA2, FeatureBookE,
|
def : Processor<"a2", PPCA2Itineraries, [DirectiveA2, FeatureBookE,
|
||||||
FeatureMFOCRF, FeatureFSqrt,
|
FeatureMFOCRF, FeatureFSqrt,
|
||||||
FeatureSTFIWX, Feature64Bit
|
FeatureSTFIWX, FeatureISEL,
|
||||||
/*, Feature64BitRegs */]>;
|
Feature64Bit
|
||||||
|
/*, Feature64BitRegs */]>;
|
||||||
def : Processor<"pwr6", G5Itineraries,
|
def : Processor<"pwr6", G5Itineraries,
|
||||||
[DirectivePwr6, FeatureAltivec,
|
[DirectivePwr6, FeatureAltivec,
|
||||||
FeatureMFOCRF, FeatureFSqrt, FeatureSTFIWX,
|
FeatureMFOCRF, FeatureFSqrt, FeatureSTFIWX,
|
||||||
@ -101,7 +106,7 @@ def : Processor<"pwr6", G5Itineraries,
|
|||||||
def : Processor<"pwr7", G5Itineraries,
|
def : Processor<"pwr7", G5Itineraries,
|
||||||
[DirectivePwr7, FeatureAltivec,
|
[DirectivePwr7, FeatureAltivec,
|
||||||
FeatureMFOCRF, FeatureFSqrt, FeatureSTFIWX,
|
FeatureMFOCRF, FeatureFSqrt, FeatureSTFIWX,
|
||||||
Feature64Bit /*, Feature64BitRegs */]>;
|
FeatureISEL, Feature64Bit /*, Feature64BitRegs */]>;
|
||||||
def : Processor<"ppc", G3Itineraries, [Directive32]>;
|
def : Processor<"ppc", G3Itineraries, [Directive32]>;
|
||||||
def : Processor<"ppc64", G5Itineraries,
|
def : Processor<"ppc64", G5Itineraries,
|
||||||
[Directive64, FeatureAltivec,
|
[Directive64, FeatureAltivec,
|
||||||
|
@ -4937,11 +4937,37 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
|||||||
|
|
||||||
MachineFunction *F = BB->getParent();
|
MachineFunction *F = BB->getParent();
|
||||||
|
|
||||||
if (MI->getOpcode() == PPC::SELECT_CC_I4 ||
|
if (PPCSubTarget.hasISEL() && (MI->getOpcode() == PPC::SELECT_CC_I4 ||
|
||||||
MI->getOpcode() == PPC::SELECT_CC_I8 ||
|
MI->getOpcode() == PPC::SELECT_CC_I8)) {
|
||||||
MI->getOpcode() == PPC::SELECT_CC_F4 ||
|
unsigned OpCode = MI->getOpcode() == PPC::SELECT_CC_I8 ?
|
||||||
MI->getOpcode() == PPC::SELECT_CC_F8 ||
|
PPC::ISEL8 : PPC::ISEL;
|
||||||
MI->getOpcode() == PPC::SELECT_CC_VRRC) {
|
unsigned SelectPred = MI->getOperand(4).getImm();
|
||||||
|
DebugLoc dl = MI->getDebugLoc();
|
||||||
|
|
||||||
|
// The SelectPred is ((BI << 5) | BO) for a BCC
|
||||||
|
unsigned BO = SelectPred & 0xF;
|
||||||
|
assert((BO == 12 || BO == 4) && "invalid predicate BO field for isel");
|
||||||
|
|
||||||
|
unsigned TrueOpNo, FalseOpNo;
|
||||||
|
if (BO == 12) {
|
||||||
|
TrueOpNo = 2;
|
||||||
|
FalseOpNo = 3;
|
||||||
|
} else {
|
||||||
|
TrueOpNo = 3;
|
||||||
|
FalseOpNo = 2;
|
||||||
|
SelectPred = PPC::InvertPredicate((PPC::Predicate)SelectPred);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildMI(*BB, MI, dl, TII->get(OpCode), MI->getOperand(0).getReg())
|
||||||
|
.addReg(MI->getOperand(TrueOpNo).getReg())
|
||||||
|
.addReg(MI->getOperand(FalseOpNo).getReg())
|
||||||
|
.addImm(SelectPred).addReg(MI->getOperand(1).getReg());
|
||||||
|
} else if (MI->getOpcode() == PPC::SELECT_CC_I4 ||
|
||||||
|
MI->getOpcode() == PPC::SELECT_CC_I8 ||
|
||||||
|
MI->getOpcode() == PPC::SELECT_CC_F4 ||
|
||||||
|
MI->getOpcode() == PPC::SELECT_CC_F8 ||
|
||||||
|
MI->getOpcode() == PPC::SELECT_CC_VRRC) {
|
||||||
|
|
||||||
|
|
||||||
// The incoming instruction knows the destination vreg to set, the
|
// The incoming instruction knows the destination vreg to set, the
|
||||||
// condition code register to branch on, the true/false values to
|
// condition code register to branch on, the true/false values to
|
||||||
|
@ -497,6 +497,10 @@ def RLWINM8 : MForm_2<21,
|
|||||||
"rlwinm $rA, $rS, $SH, $MB, $ME", IntGeneral,
|
"rlwinm $rA, $rS, $SH, $MB, $ME", IntGeneral,
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
|
def ISEL8 : AForm_1<31, 15,
|
||||||
|
(outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB, pred:$cond),
|
||||||
|
"isel $rT, $rA, $rB, $cond", IntGeneral,
|
||||||
|
[]>;
|
||||||
} // End FXU Operations.
|
} // End FXU Operations.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1397,6 +1397,13 @@ let Uses = [RM] in {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let PPC970_Unit = 1 in { // FXU Operations.
|
||||||
|
def ISEL : AForm_1<31, 15,
|
||||||
|
(outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB, pred:$cond),
|
||||||
|
"isel $rT, $rA, $rB, $cond", IntGeneral,
|
||||||
|
[]>;
|
||||||
|
}
|
||||||
|
|
||||||
let PPC970_Unit = 1 in { // FXU Operations.
|
let PPC970_Unit = 1 in { // FXU Operations.
|
||||||
// M-Form instructions. rotate and mask instructions.
|
// M-Form instructions. rotate and mask instructions.
|
||||||
//
|
//
|
||||||
|
@ -38,6 +38,7 @@ PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &CPU,
|
|||||||
, HasAltivec(false)
|
, HasAltivec(false)
|
||||||
, HasFSQRT(false)
|
, HasFSQRT(false)
|
||||||
, HasSTFIWX(false)
|
, HasSTFIWX(false)
|
||||||
|
, HasISEL(false)
|
||||||
, IsBookE(false)
|
, IsBookE(false)
|
||||||
, HasLazyResolverStubs(false)
|
, HasLazyResolverStubs(false)
|
||||||
, IsJITCodeModel(false)
|
, IsJITCodeModel(false)
|
||||||
|
@ -70,6 +70,7 @@ protected:
|
|||||||
bool HasAltivec;
|
bool HasAltivec;
|
||||||
bool HasFSQRT;
|
bool HasFSQRT;
|
||||||
bool HasSTFIWX;
|
bool HasSTFIWX;
|
||||||
|
bool HasISEL;
|
||||||
bool IsBookE;
|
bool IsBookE;
|
||||||
bool HasLazyResolverStubs;
|
bool HasLazyResolverStubs;
|
||||||
bool IsJITCodeModel;
|
bool IsJITCodeModel;
|
||||||
@ -141,6 +142,7 @@ public:
|
|||||||
bool hasSTFIWX() const { return HasSTFIWX; }
|
bool hasSTFIWX() const { return HasSTFIWX; }
|
||||||
bool hasAltivec() const { return HasAltivec; }
|
bool hasAltivec() const { return HasAltivec; }
|
||||||
bool hasMFOCRF() const { return HasMFOCRF; }
|
bool hasMFOCRF() const { return HasMFOCRF; }
|
||||||
|
bool hasISEL() const { return HasISEL; }
|
||||||
bool isBookE() const { return IsBookE; }
|
bool isBookE() const { return IsBookE; }
|
||||||
|
|
||||||
const Triple &getTargetTriple() const { return TargetTriple; }
|
const Triple &getTargetTriple() const { return TargetTriple; }
|
||||||
|
23
test/CodeGen/PowerPC/isel.ll
Normal file
23
test/CodeGen/PowerPC/isel.ll
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64"
|
||||||
|
target triple = "powerpc64-unknown-linux-gnu"
|
||||||
|
; RUN: llc -mcpu=a2 < %s | FileCheck %s
|
||||||
|
; RUN: llc -mcpu=pwr7 < %s | FileCheck %s
|
||||||
|
|
||||||
|
define i64 @test1(i64 %a, i64 %b, i64 %c, i64 %d) {
|
||||||
|
entry:
|
||||||
|
%p = icmp uge i64 %a, %b
|
||||||
|
%x = select i1 %p, i64 %c, i64 %d
|
||||||
|
ret i64 %x
|
||||||
|
; CHECK: @test1
|
||||||
|
; CHECK: isel
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @test2(i32 %a, i32 %b, i32 %c, i32 %d) {
|
||||||
|
entry:
|
||||||
|
%p = icmp uge i32 %a, %b
|
||||||
|
%x = select i1 %p, i32 %c, i32 %d
|
||||||
|
ret i32 %x
|
||||||
|
; CHECK: @test2
|
||||||
|
; CHECK: isel
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user