llvm-6502/lib/Target/PowerPC/PPCInstrInfo.td
Nate Begeman a07da92624 Use the new predicate support that Evan Cheng added to remove some code
from the DAGToDAG cpp file.  This adds pattern support for vector and
scalar fma, which passes test/Regression/CodeGen/PowerPC/fma.ll, and
does the right thing in the presence of -disable-excess-fp-precision.

Allows us to match:
void %foo(<4 x float> * %a) {
entry:
  %tmp1 = load <4 x float> * %a;
  %tmp2 = mul <4 x float> %tmp1, %tmp1
  %tmp3 = add <4 x float> %tmp2, %tmp1
  store <4 x float> %tmp3, <4 x float> *%a
  ret void
}

As:

_foo:
        li r2, 0
        lvx v0, r2, r3
        vmaddfp v0, v0, v0, v0
        stvx v0, r2, r3
        blr

Or, with llc -disable-excess-fp-precision,

_foo:
        li r2, 0
        lvx v0, r2, r3
        vxor v1, v1, v1
        vmaddfp v1, v0, v0, v1
        vaddfp v0, v1, v0
        stvx v0, r2, r3
        blr


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24719 91177308-0d34-0410-b5e6-96231b3b80d8
2005-12-14 22:54:33 +00:00

1025 lines
47 KiB
TableGen

//===- PPCInstrInfo.td - The PowerPC Instruction Set -------*- tablegen -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the subset of the 32-bit PowerPC instruction set, as used
// by the PowerPC instruction selector.
//
//===----------------------------------------------------------------------===//
include "PPCInstrFormats.td"
//===----------------------------------------------------------------------===//
// PowerPC specific DAG Nodes.
//
def PPCfcfid : SDNode<"PPCISD::FCFID" , SDTFPUnaryOp, []>;
def PPCfctidz : SDNode<"PPCISD::FCTIDZ", SDTFPUnaryOp, []>;
def PPCfctiwz : SDNode<"PPCISD::FCTIWZ", SDTFPUnaryOp, []>;
def PPCfsel : SDNode<"PPCISD::FSEL",
// Type constraint for fsel.
SDTypeProfile<1, 3, [SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>,
SDTCisFP<0>, SDTCisVT<1, f64>]>, []>;
def PPChi : SDNode<"PPCISD::Hi", SDTIntBinOp, []>;
def PPClo : SDNode<"PPCISD::Lo", SDTIntBinOp, []>;
def PPCvmaddfp : SDNode<"PPCISD::VMADDFP", SDTFPTernaryOp, []>;
def PPCvnmsubfp : SDNode<"PPCISD::VNMSUBFP", SDTFPTernaryOp, []>;
// These nodes represent the 32-bit PPC shifts that operate on 6-bit shift
// amounts. These nodes are generated by the multi-precision shift code.
def SDT_PPCShiftOp : SDTypeProfile<1, 2, [ // PPCshl, PPCsra, PPCsrl
SDTCisVT<0, i32>, SDTCisVT<1, i32>, SDTCisVT<2, i32>
]>;
def PPCsrl : SDNode<"PPCISD::SRL" , SDT_PPCShiftOp>;
def PPCsra : SDNode<"PPCISD::SRA" , SDT_PPCShiftOp>;
def PPCshl : SDNode<"PPCISD::SHL" , SDT_PPCShiftOp>;
// These are target-independent nodes, but have target-specific formats.
def SDT_PPCCallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>;
def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PPCCallSeq,[SDNPHasChain]>;
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PPCCallSeq,[SDNPHasChain]>;
//===----------------------------------------------------------------------===//
// PowerPC specific transformation functions and pattern fragments.
//
def SHL32 : SDNodeXForm<imm, [{
// Transformation function: 31 - imm
return getI32Imm(31 - N->getValue());
}]>;
def SHL64 : SDNodeXForm<imm, [{
// Transformation function: 63 - imm
return getI32Imm(63 - N->getValue());
}]>;
def SRL32 : SDNodeXForm<imm, [{
// Transformation function: 32 - imm
return N->getValue() ? getI32Imm(32 - N->getValue()) : getI32Imm(0);
}]>;
def SRL64 : SDNodeXForm<imm, [{
// Transformation function: 64 - imm
return N->getValue() ? getI32Imm(64 - N->getValue()) : getI32Imm(0);
}]>;
def LO16 : SDNodeXForm<imm, [{
// Transformation function: get the low 16 bits.
return getI32Imm((unsigned short)N->getValue());
}]>;
def HI16 : SDNodeXForm<imm, [{
// Transformation function: shift the immediate value down into the low bits.
return getI32Imm((unsigned)N->getValue() >> 16);
}]>;
def HA16 : SDNodeXForm<imm, [{
// Transformation function: shift the immediate value down into the low bits.
signed int Val = N->getValue();
return getI32Imm((Val - (signed short)Val) >> 16);
}]>;
def immSExt16 : PatLeaf<(imm), [{
// immSExt16 predicate - True if the immediate fits in a 16-bit sign extended
// field. Used by instructions like 'addi'.
return (int)N->getValue() == (short)N->getValue();
}]>;
def immZExt16 : PatLeaf<(imm), [{
// immZExt16 predicate - True if the immediate fits in a 16-bit zero extended
// field. Used by instructions like 'ori'.
return (unsigned)N->getValue() == (unsigned short)N->getValue();
}], LO16>;
def imm16Shifted : PatLeaf<(imm), [{
// imm16Shifted predicate - True if only bits in the top 16-bits of the
// immediate are set. Used by instructions like 'addis'.
return ((unsigned)N->getValue() & 0xFFFF0000U) == (unsigned)N->getValue();
}], HI16>;
/*
// Example of a legalize expander: Only for PPC64.
def : Expander<(set i64:$dst, (fp_to_sint f64:$src)),
[(set f64:$tmp , (FCTIDZ f64:$src)),
(set i32:$tmpFI, (CreateNewFrameIndex 8, 8)),
(store f64:$tmp, i32:$tmpFI),
(set i64:$dst, (load i32:$tmpFI))],
Subtarget_PPC64>;
*/
//===----------------------------------------------------------------------===//
// PowerPC Flag Definitions.
class isPPC64 { bit PPC64 = 1; }
class isVMX { bit VMX = 1; }
class isDOT {
list<Register> Defs = [CR0];
bit RC = 1;
}
//===----------------------------------------------------------------------===//
// PowerPC Operand Definitions.
def u5imm : Operand<i32> {
let PrintMethod = "printU5ImmOperand";
}
def u6imm : Operand<i32> {
let PrintMethod = "printU6ImmOperand";
}
def s16imm : Operand<i32> {
let PrintMethod = "printS16ImmOperand";
}
def u16imm : Operand<i32> {
let PrintMethod = "printU16ImmOperand";
}
def s16immX4 : Operand<i32> { // Multiply imm by 4 before printing.
let PrintMethod = "printS16X4ImmOperand";
}
def target : Operand<OtherVT> {
let PrintMethod = "printBranchOperand";
}
def calltarget : Operand<i32> {
let PrintMethod = "printCallOperand";
}
def aaddr : Operand<i32> {
let PrintMethod = "printAbsAddrOperand";
}
def piclabel: Operand<i32> {
let PrintMethod = "printPICLabel";
}
def symbolHi: Operand<i32> {
let PrintMethod = "printSymbolHi";
}
def symbolLo: Operand<i32> {
let PrintMethod = "printSymbolLo";
}
def crbitm: Operand<i8> {
let PrintMethod = "printcrbitm";
}
//===----------------------------------------------------------------------===//
// PowerPC Instruction Predicate Definitions.
def FPContractions : Predicate<"NoExcessFPPrecision">;
//===----------------------------------------------------------------------===//
// PowerPC Instruction Definitions.
// Pseudo-instructions:
def PHI : Pseudo<(ops variable_ops), "; PHI", []>;
let isLoad = 1, hasCtrlDep = 1 in {
def ADJCALLSTACKDOWN : Pseudo<(ops u16imm:$amt),
"; ADJCALLSTACKDOWN",
[(callseq_start imm:$amt)]>;
def ADJCALLSTACKUP : Pseudo<(ops u16imm:$amt),
"; ADJCALLSTACKUP",
[(callseq_end imm:$amt)]>;
}
def IMPLICIT_DEF_GPR : Pseudo<(ops GPRC:$rD), "; $rD = IMPLICIT_DEF_GPRC",
[(set GPRC:$rD, (undef))]>;
def IMPLICIT_DEF_F8 : Pseudo<(ops F8RC:$rD), "; %rD = IMPLICIT_DEF_F8",
[(set F8RC:$rD, (undef))]>;
def IMPLICIT_DEF_F4 : Pseudo<(ops F4RC:$rD), "; %rD = IMPLICIT_DEF_F4",
[(set F4RC:$rD, (undef))]>;
// SELECT_CC_* - Used to implement the SELECT_CC DAG operation. Expanded by the
// scheduler into a branch sequence.
let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler.
def SELECT_CC_Int : Pseudo<(ops GPRC:$dst, CRRC:$cond, GPRC:$T, GPRC:$F,
i32imm:$BROPC), "; SELECT_CC PSEUDO!", []>;
def SELECT_CC_F4 : Pseudo<(ops F4RC:$dst, CRRC:$cond, F4RC:$T, F4RC:$F,
i32imm:$BROPC), "; SELECT_CC PSEUDO!", []>;
def SELECT_CC_F8 : Pseudo<(ops F8RC:$dst, CRRC:$cond, F8RC:$T, F8RC:$F,
i32imm:$BROPC), "; SELECT_CC PSEUDO!", []>;
}
let isTerminator = 1 in {
let isReturn = 1 in
def BLR : XLForm_2_ext<19, 16, 20, 0, 0, (ops), "blr", BrB>;
def BCTR : XLForm_2_ext<19, 528, 20, 0, 0, (ops), "bctr", BrB>;
}
let Defs = [LR] in
def MovePCtoLR : Pseudo<(ops piclabel:$label), "bl $label", []>;
let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in {
def COND_BRANCH : Pseudo<(ops CRRC:$crS, u16imm:$opc,
target:$true, target:$false),
"; COND_BRANCH", []>;
def B : IForm<18, 0, 0, (ops target:$dst),
"b $dst", BrB,
[(br bb:$dst)]>;
// FIXME: 4*CR# needs to be added to the BI field!
// This will only work for CR0 as it stands now
def BLT : BForm<16, 0, 0, 12, 0, (ops CRRC:$crS, target:$block),
"blt $crS, $block", BrB>;
def BLE : BForm<16, 0, 0, 4, 1, (ops CRRC:$crS, target:$block),
"ble $crS, $block", BrB>;
def BEQ : BForm<16, 0, 0, 12, 2, (ops CRRC:$crS, target:$block),
"beq $crS, $block", BrB>;
def BGE : BForm<16, 0, 0, 4, 0, (ops CRRC:$crS, target:$block),
"bge $crS, $block", BrB>;
def BGT : BForm<16, 0, 0, 12, 1, (ops CRRC:$crS, target:$block),
"bgt $crS, $block", BrB>;
def BNE : BForm<16, 0, 0, 4, 2, (ops CRRC:$crS, target:$block),
"bne $crS, $block", BrB>;
def BUN : BForm<16, 0, 0, 12, 3, (ops CRRC:$crS, target:$block),
"bun $crS, $block", BrB>;
def BNU : BForm<16, 0, 0, 4, 3, (ops CRRC:$crS, target:$block),
"bnu $crS, $block", BrB>;
}
let isCall = 1,
// All calls clobber the non-callee saved registers...
Defs = [R0,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,
F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13,
LR,CTR,
CR0,CR1,CR5,CR6,CR7] in {
// Convenient aliases for call instructions
def BL : IForm<18, 0, 1, (ops calltarget:$func, variable_ops),
"bl $func", BrB, []>;
def BLA : IForm<18, 1, 1, (ops aaddr:$func, variable_ops),
"bla $func", BrB, []>;
def BCTRL : XLForm_2_ext<19, 528, 20, 0, 1, (ops variable_ops), "bctrl", BrB>;
}
// D-Form instructions. Most instructions that perform an operation on a
// register and an immediate are of this type.
//
let isLoad = 1 in {
def LBZ : DForm_1<34, (ops GPRC:$rD, symbolLo:$disp, GPRC:$rA),
"lbz $rD, $disp($rA)", LdStGeneral,
[]>;
def LHA : DForm_1<42, (ops GPRC:$rD, symbolLo:$disp, GPRC:$rA),
"lha $rD, $disp($rA)", LdStLHA,
[]>;
def LHZ : DForm_1<40, (ops GPRC:$rD, symbolLo:$disp, GPRC:$rA),
"lhz $rD, $disp($rA)", LdStGeneral,
[]>;
def LMW : DForm_1<46, (ops GPRC:$rD, s16imm:$disp, GPRC:$rA),
"lmw $rD, $disp($rA)", LdStLMW,
[]>;
def LWZ : DForm_1<32, (ops GPRC:$rD, symbolLo:$disp, GPRC:$rA),
"lwz $rD, $disp($rA)", LdStGeneral,
[]>;
def LWZU : DForm_1<35, (ops GPRC:$rD, s16imm:$disp, GPRC:$rA),
"lwzu $rD, $disp($rA)", LdStGeneral,
[]>;
}
def ADDI : DForm_2<14, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
"addi $rD, $rA, $imm", IntGeneral,
[(set GPRC:$rD, (add GPRC:$rA, immSExt16:$imm))]>;
def ADDIC : DForm_2<12, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
"addic $rD, $rA, $imm", IntGeneral,
[]>;
def ADDICo : DForm_2<13, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
"addic. $rD, $rA, $imm", IntGeneral,
[]>;
def ADDIS : DForm_2<15, (ops GPRC:$rD, GPRC:$rA, symbolHi:$imm),
"addis $rD, $rA, $imm", IntGeneral,
[(set GPRC:$rD, (add GPRC:$rA, imm16Shifted:$imm))]>;
def LA : DForm_2<14, (ops GPRC:$rD, GPRC:$rA, symbolLo:$sym),
"la $rD, $sym($rA)", IntGeneral,
[(set GPRC:$rD, (add GPRC:$rA,
(PPClo tglobaladdr:$sym, 0)))]>;
def MULLI : DForm_2< 7, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
"mulli $rD, $rA, $imm", IntMulLI,
[(set GPRC:$rD, (mul GPRC:$rA, immSExt16:$imm))]>;
def SUBFIC : DForm_2< 8, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
"subfic $rD, $rA, $imm", IntGeneral,
[(set GPRC:$rD, (sub immSExt16:$imm, GPRC:$rA))]>;
def LI : DForm_2_r0<14, (ops GPRC:$rD, symbolLo:$imm),
"li $rD, $imm", IntGeneral,
[(set GPRC:$rD, immSExt16:$imm)]>;
def LIS : DForm_2_r0<15, (ops GPRC:$rD, symbolHi:$imm),
"lis $rD, $imm", IntGeneral,
[(set GPRC:$rD, imm16Shifted:$imm)]>;
let isStore = 1 in {
def STMW : DForm_3<47, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA),
"stmw $rS, $disp($rA)", LdStLMW,
[]>;
def STB : DForm_3<38, (ops GPRC:$rS, symbolLo:$disp, GPRC:$rA),
"stb $rS, $disp($rA)", LdStGeneral,
[]>;
def STH : DForm_3<44, (ops GPRC:$rS, symbolLo:$disp, GPRC:$rA),
"sth $rS, $disp($rA)", LdStGeneral,
[]>;
def STW : DForm_3<36, (ops GPRC:$rS, symbolLo:$disp, GPRC:$rA),
"stw $rS, $disp($rA)", LdStGeneral,
[]>;
def STWU : DForm_3<37, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA),
"stwu $rS, $disp($rA)", LdStGeneral,
[]>;
}
def ANDIo : DForm_4<28, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"andi. $dst, $src1, $src2", IntGeneral,
[]>, isDOT;
def ANDISo : DForm_4<29, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"andis. $dst, $src1, $src2", IntGeneral,
[]>, isDOT;
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2", IntGeneral,
[(set GPRC:$dst, (or GPRC:$src1, immZExt16:$src2))]>;
def ORIS : DForm_4<25, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"oris $dst, $src1, $src2", IntGeneral,
[(set GPRC:$dst, (or GPRC:$src1, imm16Shifted:$src2))]>;
def XORI : DForm_4<26, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"xori $dst, $src1, $src2", IntGeneral,
[(set GPRC:$dst, (xor GPRC:$src1, immZExt16:$src2))]>;
def XORIS : DForm_4<27, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"xoris $dst, $src1, $src2", IntGeneral,
[(set GPRC:$dst, (xor GPRC:$src1, imm16Shifted:$src2))]>;
def NOP : DForm_4_zero<24, (ops), "nop", IntGeneral,
[]>;
def CMPI : DForm_5<11, (ops CRRC:$crD, i1imm:$L, GPRC:$rA, s16imm:$imm),
"cmpi $crD, $L, $rA, $imm", IntCompare>;
def CMPWI : DForm_5_ext<11, (ops CRRC:$crD, GPRC:$rA, s16imm:$imm),
"cmpwi $crD, $rA, $imm", IntCompare>;
def CMPDI : DForm_5_ext<11, (ops CRRC:$crD, GPRC:$rA, s16imm:$imm),
"cmpdi $crD, $rA, $imm", IntCompare>, isPPC64;
def CMPLI : DForm_6<10, (ops CRRC:$dst, i1imm:$size, GPRC:$src1, u16imm:$src2),
"cmpli $dst, $size, $src1, $src2", IntCompare>;
def CMPLWI : DForm_6_ext<10, (ops CRRC:$dst, GPRC:$src1, u16imm:$src2),
"cmplwi $dst, $src1, $src2", IntCompare>;
def CMPLDI : DForm_6_ext<10, (ops CRRC:$dst, GPRC:$src1, u16imm:$src2),
"cmpldi $dst, $src1, $src2", IntCompare>, isPPC64;
let isLoad = 1 in {
def LFS : DForm_8<48, (ops F4RC:$rD, symbolLo:$disp, GPRC:$rA),
"lfs $rD, $disp($rA)", LdStLFDU,
[]>;
def LFD : DForm_8<50, (ops F8RC:$rD, symbolLo:$disp, GPRC:$rA),
"lfd $rD, $disp($rA)", LdStLFD,
[]>;
}
let isStore = 1 in {
def STFS : DForm_9<52, (ops F4RC:$rS, symbolLo:$disp, GPRC:$rA),
"stfs $rS, $disp($rA)", LdStUX,
[]>;
def STFD : DForm_9<54, (ops F8RC:$rS, symbolLo:$disp, GPRC:$rA),
"stfd $rS, $disp($rA)", LdStUX,
[]>;
}
// DS-Form instructions. Load/Store instructions available in PPC-64
//
let isLoad = 1 in {
def LWA : DSForm_1<58, 2, (ops GPRC:$rT, s16immX4:$DS, GPRC:$rA),
"lwa $rT, $DS($rA)", LdStLWA,
[]>, isPPC64;
def LD : DSForm_2<58, 0, (ops GPRC:$rT, s16immX4:$DS, GPRC:$rA),
"ld $rT, $DS($rA)", LdStLD,
[]>, isPPC64;
}
let isStore = 1 in {
def STD : DSForm_2<62, 0, (ops GPRC:$rT, s16immX4:$DS, GPRC:$rA),
"std $rT, $DS($rA)", LdStSTD,
[]>, isPPC64;
def STDU : DSForm_2<62, 1, (ops GPRC:$rT, s16immX4:$DS, GPRC:$rA),
"stdu $rT, $DS($rA)", LdStSTD,
[]>, isPPC64;
}
// X-Form instructions. Most instructions that perform an operation on a
// register and another register are of this type.
//
let isLoad = 1 in {
def LBZX : XForm_1<31, 87, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
"lbzx $dst, $base, $index", LdStGeneral,
[]>;
def LHAX : XForm_1<31, 343, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
"lhax $dst, $base, $index", LdStLHA,
[]>;
def LHZX : XForm_1<31, 279, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
"lhzx $dst, $base, $index", LdStGeneral,
[]>;
def LWAX : XForm_1<31, 341, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
"lwax $dst, $base, $index", LdStLHA,
[]>, isPPC64;
def LWZX : XForm_1<31, 23, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
"lwzx $dst, $base, $index", LdStGeneral,
[]>;
def LDX : XForm_1<31, 21, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
"ldx $dst, $base, $index", LdStLD,
[]>, isPPC64;
def LVEBX: XForm_1<31, 7, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
"lvebx $vD, $base, $rA", LdStGeneral,
[]>;
def LVEHX: XForm_1<31, 39, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
"lvehx $vD, $base, $rA", LdStGeneral,
[]>;
def LVEWX: XForm_1<31, 71, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
"lvewx $vD, $base, $rA", LdStGeneral,
[]>;
def LVX : XForm_1<31, 103, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
"lvx $vD, $base, $rA", LdStGeneral,
[]>;
}
def LVSL : XForm_1<31, 6, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
"lvsl $vD, $base, $rA", LdStGeneral,
[]>;
def LVSR : XForm_1<31, 38, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
"lvsl $vD, $base, $rA", LdStGeneral,
[]>;
def NAND : XForm_6<31, 476, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"nand $rA, $rS, $rB", IntGeneral,
[(set GPRC:$rA, (not (and GPRC:$rS, GPRC:$rB)))]>;
def AND : XForm_6<31, 28, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"and $rA, $rS, $rB", IntGeneral,
[(set GPRC:$rA, (and GPRC:$rS, GPRC:$rB))]>;
def ANDo : XForm_6<31, 28, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"and. $rA, $rS, $rB", IntGeneral,
[]>, isDOT;
def ANDC : XForm_6<31, 60, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"andc $rA, $rS, $rB", IntGeneral,
[(set GPRC:$rA, (and GPRC:$rS, (not GPRC:$rB)))]>;
def OR4 : XForm_6<31, 444, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"or $rA, $rS, $rB", IntGeneral,
[(set GPRC:$rA, (or GPRC:$rS, GPRC:$rB))]>;
def OR8 : XForm_6<31, 444, (ops G8RC:$rA, G8RC:$rS, G8RC:$rB),
"or $rA, $rS, $rB", IntGeneral,
[(set G8RC:$rA, (or G8RC:$rS, G8RC:$rB))]>;
def OR4To8 : XForm_6<31, 444, (ops G8RC:$rA, GPRC:$rS, GPRC:$rB),
"or $rA, $rS, $rB", IntGeneral,
[]>;
def OR8To4 : XForm_6<31, 444, (ops GPRC:$rA, G8RC:$rS, G8RC:$rB),
"or $rA, $rS, $rB", IntGeneral,
[]>;
def NOR : XForm_6<31, 124, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"nor $rA, $rS, $rB", IntGeneral,
[(set GPRC:$rA, (not (or GPRC:$rS, GPRC:$rB)))]>;
def ORo : XForm_6<31, 444, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"or. $rA, $rS, $rB", IntGeneral,
[]>, isDOT;
def ORC : XForm_6<31, 412, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"orc $rA, $rS, $rB", IntGeneral,
[(set GPRC:$rA, (or GPRC:$rS, (not GPRC:$rB)))]>;
def EQV : XForm_6<31, 284, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"eqv $rA, $rS, $rB", IntGeneral,
[(set GPRC:$rA, (not (xor GPRC:$rS, GPRC:$rB)))]>;
def XOR : XForm_6<31, 316, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"xor $rA, $rS, $rB", IntGeneral,
[(set GPRC:$rA, (xor GPRC:$rS, GPRC:$rB))]>;
def SLD : XForm_6<31, 27, (ops G8RC:$rA, G8RC:$rS, G8RC:$rB),
"sld $rA, $rS, $rB", IntRotateD,
[(set G8RC:$rA, (shl G8RC:$rS, G8RC:$rB))]>, isPPC64;
def SLW : XForm_6<31, 24, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"slw $rA, $rS, $rB", IntGeneral,
[(set GPRC:$rA, (PPCshl GPRC:$rS, GPRC:$rB))]>;
def SRD : XForm_6<31, 539, (ops G8RC:$rA, G8RC:$rS, G8RC:$rB),
"srd $rA, $rS, $rB", IntRotateD,
[(set G8RC:$rA, (srl G8RC:$rS, G8RC:$rB))]>, isPPC64;
def SRW : XForm_6<31, 536, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"srw $rA, $rS, $rB", IntGeneral,
[(set GPRC:$rA, (PPCsrl GPRC:$rS, GPRC:$rB))]>;
def SRAD : XForm_6<31, 794, (ops G8RC:$rA, G8RC:$rS, G8RC:$rB),
"srad $rA, $rS, $rB", IntRotateD,
[(set G8RC:$rA, (sra G8RC:$rS, G8RC:$rB))]>, isPPC64;
def SRAW : XForm_6<31, 792, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"sraw $rA, $rS, $rB", IntShift,
[(set GPRC:$rA, (PPCsra GPRC:$rS, GPRC:$rB))]>;
let isStore = 1 in {
def STBX : XForm_8<31, 215, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
"stbx $rS, $rA, $rB", LdStGeneral,
[]>;
def STHX : XForm_8<31, 407, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
"sthx $rS, $rA, $rB", LdStGeneral,
[]>;
def STWX : XForm_8<31, 151, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
"stwx $rS, $rA, $rB", LdStGeneral,
[]>;
def STWUX : XForm_8<31, 183, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
"stwux $rS, $rA, $rB", LdStGeneral,
[]>;
def STDX : XForm_8<31, 149, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
"stdx $rS, $rA, $rB", LdStSTD,
[]>, isPPC64;
def STDUX : XForm_8<31, 181, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
"stdux $rS, $rA, $rB", LdStSTD,
[]>, isPPC64;
def STVEBX: XForm_8<31, 135, (ops VRRC:$rS, GPRC:$rA, GPRC:$rB),
"stvebx $rS, $rA, $rB", LdStGeneral,
[]>;
def STVEHX: XForm_8<31, 167, (ops VRRC:$rS, GPRC:$rA, GPRC:$rB),
"stvehx $rS, $rA, $rB", LdStGeneral,
[]>;
def STVEWX: XForm_8<31, 199, (ops VRRC:$rS, GPRC:$rA, GPRC:$rB),
"stvewx $rS, $rA, $rB", LdStGeneral,
[]>;
def STVX : XForm_8<31, 231, (ops VRRC:$rS, GPRC:$rA, GPRC:$rB),
"stvx $rS, $rA, $rB", LdStGeneral,
[]>;
}
def SRAWI : XForm_10<31, 824, (ops GPRC:$rA, GPRC:$rS, u5imm:$SH),
"srawi $rA, $rS, $SH", IntShift,
[(set GPRC:$rA, (sra GPRC:$rS, (i32 imm:$SH)))]>;
def CNTLZW : XForm_11<31, 26, (ops GPRC:$rA, GPRC:$rS),
"cntlzw $rA, $rS", IntGeneral,
[(set GPRC:$rA, (ctlz GPRC:$rS))]>;
def EXTSB : XForm_11<31, 954, (ops GPRC:$rA, GPRC:$rS),
"extsb $rA, $rS", IntGeneral,
[(set GPRC:$rA, (sext_inreg GPRC:$rS, i8))]>;
def EXTSH : XForm_11<31, 922, (ops GPRC:$rA, GPRC:$rS),
"extsh $rA, $rS", IntGeneral,
[(set GPRC:$rA, (sext_inreg GPRC:$rS, i16))]>;
def EXTSW : XForm_11<31, 986, (ops G8RC:$rA, G8RC:$rS),
"extsw $rA, $rS", IntGeneral,
[(set G8RC:$rA, (sext_inreg G8RC:$rS, i32))]>, isPPC64;
def CMP : XForm_16<31, 0, (ops CRRC:$crD, i1imm:$long, GPRC:$rA, GPRC:$rB),
"cmp $crD, $long, $rA, $rB", IntCompare>;
def CMPL : XForm_16<31, 32, (ops CRRC:$crD, i1imm:$long, GPRC:$rA, GPRC:$rB),
"cmpl $crD, $long, $rA, $rB", IntCompare>;
def CMPW : XForm_16_ext<31, 0, (ops CRRC:$crD, GPRC:$rA, GPRC:$rB),
"cmpw $crD, $rA, $rB", IntCompare>;
def CMPD : XForm_16_ext<31, 0, (ops CRRC:$crD, GPRC:$rA, GPRC:$rB),
"cmpd $crD, $rA, $rB", IntCompare>, isPPC64;
def CMPLW : XForm_16_ext<31, 32, (ops CRRC:$crD, GPRC:$rA, GPRC:$rB),
"cmplw $crD, $rA, $rB", IntCompare>;
def CMPLD : XForm_16_ext<31, 32, (ops CRRC:$crD, GPRC:$rA, GPRC:$rB),
"cmpld $crD, $rA, $rB", IntCompare>, isPPC64;
//def FCMPO : XForm_17<63, 32, (ops CRRC:$crD, FPRC:$fA, FPRC:$fB),
// "fcmpo $crD, $fA, $fB", FPCompare>;
def FCMPUS : XForm_17<63, 0, (ops CRRC:$crD, F4RC:$fA, F4RC:$fB),
"fcmpu $crD, $fA, $fB", FPCompare>;
def FCMPUD : XForm_17<63, 0, (ops CRRC:$crD, F8RC:$fA, F8RC:$fB),
"fcmpu $crD, $fA, $fB", FPCompare>;
let isLoad = 1 in {
def LFSX : XForm_25<31, 535, (ops F4RC:$dst, GPRC:$base, GPRC:$index),
"lfsx $dst, $base, $index", LdStLFDU,
[]>;
def LFDX : XForm_25<31, 599, (ops F8RC:$dst, GPRC:$base, GPRC:$index),
"lfdx $dst, $base, $index", LdStLFDU,
[]>;
}
def FCFID : XForm_26<63, 846, (ops F8RC:$frD, F8RC:$frB),
"fcfid $frD, $frB", FPGeneral,
[(set F8RC:$frD, (PPCfcfid F8RC:$frB))]>, isPPC64;
def FCTIDZ : XForm_26<63, 815, (ops F8RC:$frD, F8RC:$frB),
"fctidz $frD, $frB", FPGeneral,
[(set F8RC:$frD, (PPCfctidz F8RC:$frB))]>, isPPC64;
def FCTIWZ : XForm_26<63, 15, (ops F8RC:$frD, F8RC:$frB),
"fctiwz $frD, $frB", FPGeneral,
[(set F8RC:$frD, (PPCfctiwz F8RC:$frB))]>;
def FRSP : XForm_26<63, 12, (ops F4RC:$frD, F8RC:$frB),
"frsp $frD, $frB", FPGeneral,
[(set F4RC:$frD, (fround F8RC:$frB))]>;
def FSQRT : XForm_26<63, 22, (ops F8RC:$frD, F8RC:$frB),
"fsqrt $frD, $frB", FPSqrt,
[(set F8RC:$frD, (fsqrt F8RC:$frB))]>;
def FSQRTS : XForm_26<59, 22, (ops F4RC:$frD, F4RC:$frB),
"fsqrts $frD, $frB", FPSqrt,
[(set F4RC:$frD, (fsqrt F4RC:$frB))]>;
/// FMR is split into 3 versions, one for 4/8 byte FP, and one for extending.
def FMRS : XForm_26<63, 72, (ops F4RC:$frD, F4RC:$frB),
"fmr $frD, $frB", FPGeneral,
[]>; // (set F4RC:$frD, F4RC:$frB)
def FMRD : XForm_26<63, 72, (ops F8RC:$frD, F8RC:$frB),
"fmr $frD, $frB", FPGeneral,
[]>; // (set F8RC:$frD, F8RC:$frB)
def FMRSD : XForm_26<63, 72, (ops F8RC:$frD, F4RC:$frB),
"fmr $frD, $frB", FPGeneral,
[(set F8RC:$frD, (fextend F4RC:$frB))]>;
// These are artificially split into two different forms, for 4/8 byte FP.
def FABSS : XForm_26<63, 264, (ops F4RC:$frD, F4RC:$frB),
"fabs $frD, $frB", FPGeneral,
[(set F4RC:$frD, (fabs F4RC:$frB))]>;
def FABSD : XForm_26<63, 264, (ops F8RC:$frD, F8RC:$frB),
"fabs $frD, $frB", FPGeneral,
[(set F8RC:$frD, (fabs F8RC:$frB))]>;
def FNABSS : XForm_26<63, 136, (ops F4RC:$frD, F4RC:$frB),
"fnabs $frD, $frB", FPGeneral,
[(set F4RC:$frD, (fneg (fabs F4RC:$frB)))]>;
def FNABSD : XForm_26<63, 136, (ops F8RC:$frD, F8RC:$frB),
"fnabs $frD, $frB", FPGeneral,
[(set F8RC:$frD, (fneg (fabs F8RC:$frB)))]>;
def FNEGS : XForm_26<63, 40, (ops F4RC:$frD, F4RC:$frB),
"fneg $frD, $frB", FPGeneral,
[(set F4RC:$frD, (fneg F4RC:$frB))]>;
def FNEGD : XForm_26<63, 40, (ops F8RC:$frD, F8RC:$frB),
"fneg $frD, $frB", FPGeneral,
[(set F8RC:$frD, (fneg F8RC:$frB))]>;
let isStore = 1 in {
def STFSX : XForm_28<31, 663, (ops F4RC:$frS, GPRC:$rA, GPRC:$rB),
"stfsx $frS, $rA, $rB", LdStUX,
[]>;
def STFDX : XForm_28<31, 727, (ops F8RC:$frS, GPRC:$rA, GPRC:$rB),
"stfdx $frS, $rA, $rB", LdStUX,
[]>;
}
// XL-Form instructions. condition register logical ops.
//
def MCRF : XLForm_3<19, 0, (ops CRRC:$BF, CRRC:$BFA),
"mcrf $BF, $BFA", BrMCR>;
// XFX-Form instructions. Instructions that deal with SPRs
//
// Note that although LR should be listed as `8' and CTR as `9' in the SPR
// field, the manual lists the groups of bits as [5-9] = 0, [0-4] = 8 or 9
// which means the SPR value needs to be multiplied by a factor of 32.
def MFCTR : XFXForm_1_ext<31, 339, 9, (ops GPRC:$rT), "mfctr $rT", SprMFSPR>;
def MFLR : XFXForm_1_ext<31, 339, 8, (ops GPRC:$rT), "mflr $rT", SprMFSPR>;
def MFCR : XFXForm_3<31, 19, (ops GPRC:$rT), "mfcr $rT", SprMFCR>;
def MTCRF : XFXForm_5<31, 144, (ops crbitm:$FXM, GPRC:$rS),
"mtcrf $FXM, $rS", BrMCRX>;
def MFOCRF: XFXForm_5a<31, 19, (ops GPRC:$rT, crbitm:$FXM),
"mfcr $rT, $FXM", SprMFCR>;
def MTCTR : XFXForm_7_ext<31, 467, 9, (ops GPRC:$rS), "mtctr $rS", SprMTSPR>;
def MTLR : XFXForm_7_ext<31, 467, 8, (ops GPRC:$rS), "mtlr $rS", SprMTSPR>;
def MTSPR : XFXForm_7<31, 467, (ops GPRC:$rS, u16imm:$UIMM), "mtspr $UIMM, $rS",
SprMTSPR>;
// XS-Form instructions. Just 'sradi'
//
def SRADI : XSForm_1<31, 413, (ops GPRC:$rA, GPRC:$rS, u6imm:$SH),
"sradi $rA, $rS, $SH", IntRotateD>, isPPC64;
// XO-Form instructions. Arithmetic instructions that can set overflow bit
//
def ADD4 : XOForm_1<31, 266, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"add $rT, $rA, $rB", IntGeneral,
[(set GPRC:$rT, (add GPRC:$rA, GPRC:$rB))]>;
def ADD8 : XOForm_1<31, 266, 0, (ops G8RC:$rT, G8RC:$rA, G8RC:$rB),
"add $rT, $rA, $rB", IntGeneral,
[(set G8RC:$rT, (add G8RC:$rA, G8RC:$rB))]>;
def ADDC : XOForm_1<31, 10, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"addc $rT, $rA, $rB", IntGeneral,
[]>;
def ADDE : XOForm_1<31, 138, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"adde $rT, $rA, $rB", IntGeneral,
[]>;
def DIVD : XOForm_1<31, 489, 0, (ops G8RC:$rT, G8RC:$rA, G8RC:$rB),
"divd $rT, $rA, $rB", IntDivD,
[(set G8RC:$rT, (sdiv G8RC:$rA, G8RC:$rB))]>, isPPC64;
def DIVDU : XOForm_1<31, 457, 0, (ops G8RC:$rT, G8RC:$rA, G8RC:$rB),
"divdu $rT, $rA, $rB", IntDivD,
[(set G8RC:$rT, (udiv G8RC:$rA, G8RC:$rB))]>, isPPC64;
def DIVW : XOForm_1<31, 491, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"divw $rT, $rA, $rB", IntDivW,
[(set GPRC:$rT, (sdiv GPRC:$rA, GPRC:$rB))]>;
def DIVWU : XOForm_1<31, 459, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"divwu $rT, $rA, $rB", IntDivW,
[(set GPRC:$rT, (udiv GPRC:$rA, GPRC:$rB))]>;
def MULHD : XOForm_1<31, 73, 0, (ops G8RC:$rT, G8RC:$rA, G8RC:$rB),
"mulhd $rT, $rA, $rB", IntMulHW,
[(set G8RC:$rT, (mulhs G8RC:$rA, G8RC:$rB))]>;
def MULHDU : XOForm_1<31, 9, 0, (ops G8RC:$rT, G8RC:$rA, G8RC:$rB),
"mulhdu $rT, $rA, $rB", IntMulHWU,
[(set G8RC:$rT, (mulhu G8RC:$rA, G8RC:$rB))]>;
def MULHW : XOForm_1<31, 75, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"mulhw $rT, $rA, $rB", IntMulHW,
[(set GPRC:$rT, (mulhs GPRC:$rA, GPRC:$rB))]>;
def MULHWU : XOForm_1<31, 11, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"mulhwu $rT, $rA, $rB", IntMulHWU,
[(set GPRC:$rT, (mulhu GPRC:$rA, GPRC:$rB))]>;
def MULLD : XOForm_1<31, 233, 0, (ops G8RC:$rT, G8RC:$rA, G8RC:$rB),
"mulld $rT, $rA, $rB", IntMulHD,
[(set G8RC:$rT, (mul G8RC:$rA, G8RC:$rB))]>, isPPC64;
def MULLW : XOForm_1<31, 235, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"mullw $rT, $rA, $rB", IntMulHW,
[(set GPRC:$rT, (mul GPRC:$rA, GPRC:$rB))]>;
def SUBF : XOForm_1<31, 40, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"subf $rT, $rA, $rB", IntGeneral,
[(set GPRC:$rT, (sub GPRC:$rB, GPRC:$rA))]>;
def SUBFC : XOForm_1<31, 8, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"subfc $rT, $rA, $rB", IntGeneral,
[]>;
def SUBFE : XOForm_1<31, 136, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"subfe $rT, $rA, $rB", IntGeneral,
[]>;
def ADDME : XOForm_3<31, 234, 0, (ops GPRC:$rT, GPRC:$rA),
"addme $rT, $rA", IntGeneral,
[]>;
def ADDZE : XOForm_3<31, 202, 0, (ops GPRC:$rT, GPRC:$rA),
"addze $rT, $rA", IntGeneral,
[]>;
def NEG : XOForm_3<31, 104, 0, (ops GPRC:$rT, GPRC:$rA),
"neg $rT, $rA", IntGeneral,
[(set GPRC:$rT, (ineg GPRC:$rA))]>;
def SUBFZE : XOForm_3<31, 200, 0, (ops GPRC:$rT, GPRC:$rA),
"subfze $rT, $rA", IntGeneral,
[]>;
// A-Form instructions. Most of the instructions executed in the FPU are of
// this type.
//
def FMADD : AForm_1<63, 29,
(ops F8RC:$FRT, F8RC:$FRA, F8RC:$FRC, F8RC:$FRB),
"fmadd $FRT, $FRA, $FRC, $FRB", FPFused,
[(set F8RC:$FRT, (fadd (fmul F8RC:$FRA, F8RC:$FRC),
F8RC:$FRB))]>,
Requires<[FPContractions]>;
def FMADDS : AForm_1<59, 29,
(ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRC, F4RC:$FRB),
"fmadds $FRT, $FRA, $FRC, $FRB", FPGeneral,
[(set F4RC:$FRT, (fadd (fmul F4RC:$FRA, F4RC:$FRC),
F4RC:$FRB))]>,
Requires<[FPContractions]>;
def FMSUB : AForm_1<63, 28,
(ops F8RC:$FRT, F8RC:$FRA, F8RC:$FRC, F8RC:$FRB),
"fmsub $FRT, $FRA, $FRC, $FRB", FPFused,
[(set F8RC:$FRT, (fsub (fmul F8RC:$FRA, F8RC:$FRC),
F8RC:$FRB))]>,
Requires<[FPContractions]>;
def FMSUBS : AForm_1<59, 28,
(ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRC, F4RC:$FRB),
"fmsubs $FRT, $FRA, $FRC, $FRB", FPGeneral,
[(set F4RC:$FRT, (fsub (fmul F4RC:$FRA, F4RC:$FRC),
F4RC:$FRB))]>,
Requires<[FPContractions]>;
def FNMADD : AForm_1<63, 31,
(ops F8RC:$FRT, F8RC:$FRA, F8RC:$FRC, F8RC:$FRB),
"fnmadd $FRT, $FRA, $FRC, $FRB", FPFused,
[(set F8RC:$FRT, (fneg (fadd (fmul F8RC:$FRA, F8RC:$FRC),
F8RC:$FRB)))]>,
Requires<[FPContractions]>;
def FNMADDS : AForm_1<59, 31,
(ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRC, F4RC:$FRB),
"fnmadds $FRT, $FRA, $FRC, $FRB", FPGeneral,
[(set F4RC:$FRT, (fneg (fadd (fmul F4RC:$FRA, F4RC:$FRC),
F4RC:$FRB)))]>,
Requires<[FPContractions]>;
def FNMSUB : AForm_1<63, 30,
(ops F8RC:$FRT, F8RC:$FRA, F8RC:$FRC, F8RC:$FRB),
"fnmsub $FRT, $FRA, $FRC, $FRB", FPFused,
[(set F8RC:$FRT, (fneg (fsub (fmul F8RC:$FRA, F8RC:$FRC),
F8RC:$FRB)))]>,
Requires<[FPContractions]>;
def FNMSUBS : AForm_1<59, 30,
(ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRC, F4RC:$FRB),
"fnmsubs $FRT, $FRA, $FRC, $FRB", FPGeneral,
[(set F4RC:$FRT, (fneg (fsub (fmul F4RC:$FRA, F4RC:$FRC),
F4RC:$FRB)))]>,
Requires<[FPContractions]>;
// FSEL is artificially split into 4 and 8-byte forms for the result. To avoid
// having 4 of these, force the comparison to always be an 8-byte double (code
// should use an FMRSD if the input comparison value really wants to be a float)
// and 4/8 byte forms for the result and operand type..
def FSELD : AForm_1<63, 23,
(ops F8RC:$FRT, F8RC:$FRA, F8RC:$FRC, F8RC:$FRB),
"fsel $FRT, $FRA, $FRC, $FRB", FPGeneral,
[(set F8RC:$FRT, (PPCfsel F8RC:$FRA,F8RC:$FRC,F8RC:$FRB))]>;
def FSELS : AForm_1<63, 23,
(ops F4RC:$FRT, F8RC:$FRA, F4RC:$FRC, F4RC:$FRB),
"fsel $FRT, $FRA, $FRC, $FRB", FPGeneral,
[(set F4RC:$FRT, (PPCfsel F8RC:$FRA,F4RC:$FRC,F4RC:$FRB))]>;
def FADD : AForm_2<63, 21,
(ops F8RC:$FRT, F8RC:$FRA, F8RC:$FRB),
"fadd $FRT, $FRA, $FRB", FPGeneral,
[(set F8RC:$FRT, (fadd F8RC:$FRA, F8RC:$FRB))]>;
def FADDS : AForm_2<59, 21,
(ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRB),
"fadds $FRT, $FRA, $FRB", FPGeneral,
[(set F4RC:$FRT, (fadd F4RC:$FRA, F4RC:$FRB))]>;
def FDIV : AForm_2<63, 18,
(ops F8RC:$FRT, F8RC:$FRA, F8RC:$FRB),
"fdiv $FRT, $FRA, $FRB", FPDivD,
[(set F8RC:$FRT, (fdiv F8RC:$FRA, F8RC:$FRB))]>;
def FDIVS : AForm_2<59, 18,
(ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRB),
"fdivs $FRT, $FRA, $FRB", FPDivS,
[(set F4RC:$FRT, (fdiv F4RC:$FRA, F4RC:$FRB))]>;
def FMUL : AForm_3<63, 25,
(ops F8RC:$FRT, F8RC:$FRA, F8RC:$FRB),
"fmul $FRT, $FRA, $FRB", FPFused,
[(set F8RC:$FRT, (fmul F8RC:$FRA, F8RC:$FRB))]>;
def FMULS : AForm_3<59, 25,
(ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRB),
"fmuls $FRT, $FRA, $FRB", FPGeneral,
[(set F4RC:$FRT, (fmul F4RC:$FRA, F4RC:$FRB))]>;
def FSUB : AForm_2<63, 20,
(ops F8RC:$FRT, F8RC:$FRA, F8RC:$FRB),
"fsub $FRT, $FRA, $FRB", FPGeneral,
[(set F8RC:$FRT, (fsub F8RC:$FRA, F8RC:$FRB))]>;
def FSUBS : AForm_2<59, 20,
(ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRB),
"fsubs $FRT, $FRA, $FRB", FPGeneral,
[(set F4RC:$FRT, (fsub F4RC:$FRA, F4RC:$FRB))]>;
// M-Form instructions. rotate and mask instructions.
//
let isTwoAddress = 1, isCommutable = 1 in {
// RLWIMI can be commuted if the rotate amount is zero.
def RLWIMI : MForm_2<20,
(ops GPRC:$rA, GPRC:$rSi, GPRC:$rS, u5imm:$SH, u5imm:$MB,
u5imm:$ME), "rlwimi $rA, $rS, $SH, $MB, $ME", IntRotate,
[]>;
def RLDIMI : MDForm_1<30, 3,
(ops G8RC:$rA, G8RC:$rSi, G8RC:$rS, u6imm:$SH, u6imm:$MB),
"rldimi $rA, $rS, $SH, $MB", IntRotateD,
[]>, isPPC64;
}
def RLWINM : MForm_2<21,
(ops GPRC:$rA, GPRC:$rS, u5imm:$SH, u5imm:$MB, u5imm:$ME),
"rlwinm $rA, $rS, $SH, $MB, $ME", IntGeneral,
[]>;
def RLWINMo : MForm_2<21,
(ops GPRC:$rA, GPRC:$rS, u5imm:$SH, u5imm:$MB, u5imm:$ME),
"rlwinm. $rA, $rS, $SH, $MB, $ME", IntGeneral,
[]>, isDOT;
def RLWNM : MForm_2<23,
(ops GPRC:$rA, GPRC:$rS, GPRC:$rB, u5imm:$MB, u5imm:$ME),
"rlwnm $rA, $rS, $rB, $MB, $ME", IntGeneral,
[]>;
// MD-Form instructions. 64 bit rotate instructions.
//
def RLDICL : MDForm_1<30, 0,
(ops G8RC:$rA, G8RC:$rS, u6imm:$SH, u6imm:$MB),
"rldicl $rA, $rS, $SH, $MB", IntRotateD,
[]>, isPPC64;
def RLDICR : MDForm_1<30, 1,
(ops G8RC:$rA, G8RC:$rS, u6imm:$SH, u6imm:$ME),
"rldicr $rA, $rS, $SH, $ME", IntRotateD,
[]>, isPPC64;
// VA-Form instructions. 3-input AltiVec ops.
def VMADDFP : VAForm_1<46, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB, VRRC:$vC),
"vmaddfp $vD, $vA, $vC, $vB", VecFP,
[(set VRRC:$vD, (fadd (fmul VRRC:$vA, VRRC:$vC),
VRRC:$vB))]>,
Requires<[FPContractions]>;
def VNMSUBFP: VAForm_1<47, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB, VRRC:$vC),
"vnmsubfp $vD, $vA, $vC, $vB", VecFP,
[(set VRRC:$vD, (fneg (fsub (fmul VRRC:$vA,
VRRC:$vC),
VRRC:$vB)))]>,
Requires<[FPContractions]>;
// VX-Form instructions. AltiVec arithmetic ops.
def VADDFP : VXForm_1<10, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
"vaddfp $vD, $vA, $vB", VecFP,
[(set VRRC:$vD, (fadd VRRC:$vA, VRRC:$vB))]>;
def VCFSX : VXForm_1<842, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
"vcfsx $vD, $vB, $UIMM", VecFP,
[]>;
def VCFUX : VXForm_1<778, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
"vcfux $vD, $vB, $UIMM", VecFP,
[]>;
def VCTSXS : VXForm_1<970, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
"vctsxs $vD, $vB, $UIMM", VecFP,
[]>;
def VCTUXS : VXForm_1<906, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
"vctuxs $vD, $vB, $UIMM", VecFP,
[]>;
def VEXPTEFP : VXForm_2<394, (ops VRRC:$vD, VRRC:$vB),
"vexptefp $vD, $vB", VecFP,
[]>;
def VLOGEFP : VXForm_2<458, (ops VRRC:$vD, VRRC:$vB),
"vlogefp $vD, $vB", VecFP,
[]>;
def VMAXFP : VXForm_1<1034, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
"vmaxfp $vD, $vA, $vB", VecFP,
[]>;
def VMINFP : VXForm_1<1098, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
"vminfp $vD, $vA, $vB", VecFP,
[]>;
def VREFP : VXForm_2<266, (ops VRRC:$vD, VRRC:$vB),
"vrefp $vD, $vB", VecFP,
[]>;
def VRFIM : VXForm_2<714, (ops VRRC:$vD, VRRC:$vB),
"vrfim $vD, $vB", VecFP,
[]>;
def VRFIN : VXForm_2<522, (ops VRRC:$vD, VRRC:$vB),
"vrfin $vD, $vB", VecFP,
[]>;
def VRFIP : VXForm_2<650, (ops VRRC:$vD, VRRC:$vB),
"vrfip $vD, $vB", VecFP,
[]>;
def VRFIZ : VXForm_2<586, (ops VRRC:$vD, VRRC:$vB),
"vrfiz $vD, $vB", VecFP,
[]>;
def VRSQRTEFP : VXForm_2<330, (ops VRRC:$vD, VRRC:$vB),
"vrsqrtefp $vD, $vB", VecFP,
[]>;
def VSUBFP : VXForm_1<74, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
"vsubfp $vD, $vA, $vB", VecFP,
[(set VRRC:$vD, (fsub VRRC:$vA, VRRC:$vB))]>;
def VXOR : VXForm_1<1220, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
"vxor $vD, $vA, $vB", VecFP,
[]>;
// VX-Form Pseudo Instructions
def V_SET0 : VXForm_setzero<1220, (ops VRRC:$vD),
"vxor $vD, $vD, $vD", VecFP,
[]>;
//===----------------------------------------------------------------------===//
// PowerPC Instruction Patterns
//
// Arbitrary immediate support. Implement in terms of LIS/ORI.
def : Pat<(i32 imm:$imm),
(ORI (LIS (HI16 imm:$imm)), (LO16 imm:$imm))>;
// Implement the 'not' operation with the NOR instruction.
def NOT : Pat<(not GPRC:$in),
(NOR GPRC:$in, GPRC:$in)>;
// ADD an arbitrary immediate.
def : Pat<(add GPRC:$in, imm:$imm),
(ADDIS (ADDI GPRC:$in, (LO16 imm:$imm)), (HA16 imm:$imm))>;
// OR an arbitrary immediate.
def : Pat<(or GPRC:$in, imm:$imm),
(ORIS (ORI GPRC:$in, (LO16 imm:$imm)), (HI16 imm:$imm))>;
// XOR an arbitrary immediate.
def : Pat<(xor GPRC:$in, imm:$imm),
(XORIS (XORI GPRC:$in, (LO16 imm:$imm)), (HI16 imm:$imm))>;
def : Pat<(or (shl GPRC:$rS, GPRC:$rB),
(srl GPRC:$rS, (sub 32, GPRC:$rB))),
(RLWNM GPRC:$rS, GPRC:$rB, 0, 31)>;
def : Pat<(zext GPRC:$in),
(RLDICL (OR4To8 GPRC:$in, GPRC:$in), 0, 32)>;
def : Pat<(anyext GPRC:$in),
(OR4To8 GPRC:$in, GPRC:$in)>;
def : Pat<(trunc G8RC:$in),
(OR8To4 G8RC:$in, G8RC:$in)>;
// SHL
def : Pat<(shl GPRC:$in, (i32 imm:$imm)),
(RLWINM GPRC:$in, imm:$imm, 0, (SHL32 imm:$imm))>;
def : Pat<(shl G8RC:$in, (i64 imm:$imm)),
(RLDICR G8RC:$in, imm:$imm, (SHL64 imm:$imm))>;
// SRL
def : Pat<(srl GPRC:$in, (i32 imm:$imm)),
(RLWINM GPRC:$in, (SRL32 imm:$imm), imm:$imm, 31)>;
def : Pat<(srl G8RC:$in, (i64 imm:$imm)),
(RLDICL G8RC:$in, (SRL64 imm:$imm), imm:$imm)>;
// Hi and Lo for Darwin Global Addresses.
def : Pat<(PPChi tglobaladdr:$in, 0), (LIS tglobaladdr:$in)>;
def : Pat<(PPClo tglobaladdr:$in, 0), (LI tglobaladdr:$in)>;
def : Pat<(PPChi tconstpool:$in, 0), (LIS tconstpool:$in)>;
def : Pat<(PPClo tconstpool:$in, 0), (LI tconstpool:$in)>;
def : Pat<(add GPRC:$in, (PPChi tglobaladdr:$g, 0)),
(ADDIS GPRC:$in, tglobaladdr:$g)>;
def : Pat<(add GPRC:$in, (PPChi tconstpool:$g, 0)),
(ADDIS GPRC:$in, tconstpool:$g)>;
def : Pat<(fmul VRRC:$vA, VRRC:$vB),
(VMADDFP VRRC:$vA, (V_SET0), VRRC:$vB)>;
// Fused negative multiply subtract, alternate pattern
def : Pat<(fsub F8RC:$B, (fmul F8RC:$A, F8RC:$C)),
(FNMSUB F8RC:$A, F8RC:$C, F8RC:$B)>,
Requires<[FPContractions]>;
def : Pat<(fsub F4RC:$B, (fmul F4RC:$A, F4RC:$C)),
(FNMSUBS F4RC:$A, F4RC:$C, F4RC:$B)>,
Requires<[FPContractions]>;
// Fused multiply add and multiply sub for packed float. These are represented
// separately from the real instructions above, for operations that must have
// the additional precision, such as Newton-Rhapson (used by divide, sqrt)
def : Pat<(PPCvmaddfp VRRC:$A, VRRC:$B, VRRC:$C),
(VMADDFP VRRC:$A, VRRC:$B, VRRC:$C)>;
def : Pat<(PPCvnmsubfp VRRC:$A, VRRC:$B, VRRC:$C),
(VNMSUBFP VRRC:$A, VRRC:$B, VRRC:$C)>;
// Standard shifts. These are represented separately from the real shifts above
// so that we can distinguish between shifts that allow 5-bit and 6-bit shift
// amounts.
def : Pat<(sra GPRC:$rS, GPRC:$rB),
(SRAW GPRC:$rS, GPRC:$rB)>;
def : Pat<(srl GPRC:$rS, GPRC:$rB),
(SRW GPRC:$rS, GPRC:$rB)>;
def : Pat<(shl GPRC:$rS, GPRC:$rB),
(SLW GPRC:$rS, GPRC:$rB)>;
// Same as above, but using a temporary. FIXME: implement temporaries :)
/*
def : Pattern<(xor GPRC:$in, imm:$imm),
[(set GPRC:$tmp, (XORI GPRC:$in, (LO16 imm:$imm))),
(XORIS GPRC:$tmp, (HI16 imm:$imm))]>;
*/
//===----------------------------------------------------------------------===//
// PowerPCInstrInfo Definition
//
def PowerPCInstrInfo : InstrInfo {
let PHIInst = PHI;
let TSFlagsFields = [ "VMX", "PPC64" ];
let TSFlagsShifts = [ 0, 1 ];
let isLittleEndianEncoding = 1;
}