//==- SPUInstrInfo.td - Describe the Cell SPU Instructions -*- tablegen -*-==//
-//
+//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
-//
+//
//===----------------------------------------------------------------------===//
// Cell SPU Instructions:
//===----------------------------------------------------------------------===//
// DWARF debugging Pseudo Instructions
//===----------------------------------------------------------------------===//
-def DWARF_LOC : Pseudo<(outs), (ins i32imm:$line, i32imm:$col, i32imm:$file),
- "${:comment} .loc $file, $line, $col",
- [(dwarf_loc (i32 imm:$line), (i32 imm:$col),
- (i32 imm:$file))]>;
+def DWARF_LOC : Pseudo<(outs), (ins i32imm:$line, i32imm:$col, i32imm:$file),
+ ".loc $file, $line, $col",
+ [(dwarf_loc (i32 imm:$line), (i32 imm:$col), (i32 imm:$file))]>;
//===----------------------------------------------------------------------===//
// Loads:
// finally the X-form with the register-register.
//===----------------------------------------------------------------------===//
-let isSimpleLoad = 1 in {
+let canFoldAsLoad = 1 in {
class LoadDFormVec<ValueType vectype>
- : RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
+ : RI10Form<0b00101100, (outs VECREG:$rT), (ins dformaddr:$src),
"lqd\t$rT, $src",
LoadStore,
[(set (vectype VECREG:$rT), (load dform_addr:$src))]>
{ }
class LoadDForm<RegisterClass rclass>
- : RI10Form<0b00101100, (outs rclass:$rT), (ins memri10:$src),
+ : RI10Form<0b00101100, (outs rclass:$rT), (ins dformaddr:$src),
"lqd\t$rT, $src",
LoadStore,
[(set rclass:$rT, (load dform_addr:$src))]>
def v4f32: LoadDFormVec<v4f32>;
def v2f64: LoadDFormVec<v2f64>;
+ def v2i32: LoadDFormVec<v2i32>;
+
def r128: LoadDForm<GPRC>;
def r64: LoadDForm<R64C>;
def r32: LoadDForm<R32C>;
def v4f32: LoadAFormVec<v4f32>;
def v2f64: LoadAFormVec<v2f64>;
+ def v2i32: LoadAFormVec<v2i32>;
+
def r128: LoadAForm<GPRC>;
def r64: LoadAForm<R64C>;
def r32: LoadAForm<R32C>;
def v4f32: LoadXFormVec<v4f32>;
def v2f64: LoadXFormVec<v2f64>;
+ def v2i32: LoadXFormVec<v2i32>;
+
def r128: LoadXForm<GPRC>;
def r64: LoadXForm<R64C>;
def r32: LoadXForm<R32C>;
// Stores:
//===----------------------------------------------------------------------===//
class StoreDFormVec<ValueType vectype>
- : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
+ : RI10Form<0b00100100, (outs), (ins VECREG:$rT, dformaddr:$src),
"stqd\t$rT, $src",
LoadStore,
[(store (vectype VECREG:$rT), dform_addr:$src)]>
{ }
class StoreDForm<RegisterClass rclass>
- : RI10Form<0b00100100, (outs), (ins rclass:$rT, memri10:$src),
+ : RI10Form<0b00100100, (outs), (ins rclass:$rT, dformaddr:$src),
"stqd\t$rT, $src",
LoadStore,
[(store rclass:$rT, dform_addr:$src)]>
def v4f32: StoreDFormVec<v4f32>;
def v2f64: StoreDFormVec<v2f64>;
+ def v2i32: StoreDFormVec<v2i32>;
+
def r128: StoreDForm<GPRC>;
def r64: StoreDForm<R64C>;
def r32: StoreDForm<R32C>;
def v4f32: StoreAFormVec<v4f32>;
def v2f64: StoreAFormVec<v2f64>;
+ def v2i32: StoreAFormVec<v2i32>;
+
def r128: StoreAForm<GPRC>;
def r64: StoreAForm<R64C>;
def r32: StoreAForm<R32C>;
def v4f32: StoreXFormVec<v4f32>;
def v2f64: StoreXFormVec<v2f64>;
+ def v2i32: StoreXFormVec<v2i32>;
+
def r128: StoreXForm<GPRC>;
def r64: StoreXForm<R64C>;
def r32: StoreXForm<R32C>;
// Generate Controls for Insertion:
//===----------------------------------------------------------------------===//
-def CBD :
- RI7Form<0b10101111100, (outs VECREG:$rT), (ins memri7:$src),
- "cbd\t$rT, $src", ShuffleOp,
- [(set (v16i8 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
+def CBD: RI7Form<0b10101111100, (outs VECREG:$rT), (ins shufaddr:$src),
+ "cbd\t$rT, $src", ShuffleOp,
+ [(set (v16i8 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
-def CBX : RRForm<0b00101011100, (outs VECREG:$rT), (ins memrr:$src),
+def CBX: RRForm<0b00101011100, (outs VECREG:$rT), (ins memrr:$src),
"cbx\t$rT, $src", ShuffleOp,
[(set (v16i8 VECREG:$rT), (SPUshufmask xform_addr:$src))]>;
-def CHD : RI7Form<0b10101111100, (outs VECREG:$rT), (ins memri7:$src),
+def CHD: RI7Form<0b10101111100, (outs VECREG:$rT), (ins shufaddr:$src),
"chd\t$rT, $src", ShuffleOp,
[(set (v8i16 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
-def CHX : RRForm<0b10101011100, (outs VECREG:$rT), (ins memrr:$src),
+def CHX: RRForm<0b10101011100, (outs VECREG:$rT), (ins memrr:$src),
"chx\t$rT, $src", ShuffleOp,
[(set (v8i16 VECREG:$rT), (SPUshufmask xform_addr:$src))]>;
-def CWD : RI7Form<0b01101111100, (outs VECREG:$rT), (ins memri7:$src),
+def CWD: RI7Form<0b01101111100, (outs VECREG:$rT), (ins shufaddr:$src),
"cwd\t$rT, $src", ShuffleOp,
[(set (v4i32 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
-def CWDf32 : RI7Form<0b01101111100, (outs VECREG:$rT), (ins memri7:$src),
- "cwd\t$rT, $src", ShuffleOp,
- [(set (v4f32 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
-
-def CWX : RRForm<0b01101011100, (outs VECREG:$rT), (ins memrr:$src),
+def CWX: RRForm<0b01101011100, (outs VECREG:$rT), (ins memrr:$src),
"cwx\t$rT, $src", ShuffleOp,
[(set (v4i32 VECREG:$rT), (SPUshufmask xform_addr:$src))]>;
-def CWXf32 : RRForm<0b01101011100, (outs VECREG:$rT), (ins memrr:$src),
+def CWDf32: RI7Form<0b01101111100, (outs VECREG:$rT), (ins shufaddr:$src),
+ "cwd\t$rT, $src", ShuffleOp,
+ [(set (v4f32 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
+
+def CWXf32: RRForm<0b01101011100, (outs VECREG:$rT), (ins memrr:$src),
"cwx\t$rT, $src", ShuffleOp,
[(set (v4f32 VECREG:$rT), (SPUshufmask xform_addr:$src))]>;
-def CDD : RI7Form<0b11101111100, (outs VECREG:$rT), (ins memri7:$src),
+def CDD: RI7Form<0b11101111100, (outs VECREG:$rT), (ins shufaddr:$src),
"cdd\t$rT, $src", ShuffleOp,
[(set (v2i64 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
-def CDDf64 : RI7Form<0b11101111100, (outs VECREG:$rT), (ins memri7:$src),
- "cdd\t$rT, $src", ShuffleOp,
- [(set (v2f64 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
-
-def CDX : RRForm<0b11101011100, (outs VECREG:$rT), (ins memrr:$src),
+def CDX: RRForm<0b11101011100, (outs VECREG:$rT), (ins memrr:$src),
"cdx\t$rT, $src", ShuffleOp,
[(set (v2i64 VECREG:$rT), (SPUshufmask xform_addr:$src))]>;
-def CDXf64 : RRForm<0b11101011100, (outs VECREG:$rT), (ins memrr:$src),
+def CDDf64: RI7Form<0b11101111100, (outs VECREG:$rT), (ins shufaddr:$src),
+ "cdd\t$rT, $src", ShuffleOp,
+ [(set (v2f64 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
+
+def CDXf64: RRForm<0b11101011100, (outs VECREG:$rT), (ins memrr:$src),
"cdx\t$rT, $src", ShuffleOp,
[(set (v2f64 VECREG:$rT), (SPUshufmask xform_addr:$src))]>;
def f32: ILARegInst<R32FP, f18imm, fpimm18>;
def f64: ILARegInst<R64FP, f18imm_f64, fpimm18>;
+ def hi: ILARegInst<R32C, symbolHi, imm18>;
def lo: ILARegInst<R32C, symbolLo, imm18>;
def lsa: ILAInst<(outs R32C:$rT), (ins symbolLSA:$val),
defm FSMBI : FormSelectMaskBytesImm;
// fsmb: Form select mask for bytes. N.B. Input operand, $rA, is 16-bits
-def FSMB:
- RRForm_1<0b01101101100, (outs VECREG:$rT), (ins R16C:$rA),
- "fsmb\t$rT, $rA", SelectOp,
- [(set (v16i8 VECREG:$rT), (SPUselmask R16C:$rA))]>;
+class FSMBInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm_1<0b01101101100, OOL, IOL, "fsmb\t$rT, $rA", SelectOp,
+ pattern>;
+
+class FSMBRegInst<RegisterClass rclass, ValueType vectype>:
+ FSMBInst<(outs VECREG:$rT), (ins rclass:$rA),
+ [(set (vectype VECREG:$rT), (SPUselmask rclass:$rA))]>;
+
+class FSMBVecInst<ValueType vectype>:
+ FSMBInst<(outs VECREG:$rT), (ins VECREG:$rA),
+ [(set (vectype VECREG:$rT),
+ (SPUselmask (vectype VECREG:$rA)))]>;
+
+multiclass FormSelectMaskBits {
+ def v16i8_r16: FSMBRegInst<R16C, v16i8>;
+ def v16i8: FSMBVecInst<v16i8>;
+}
+
+defm FSMB: FormSelectMaskBits;
// fsmh: Form select mask for halfwords. N.B., Input operand, $rA, is
// only 8-bits wide (even though it's input as 16-bits here)
-def FSMH:
- RRForm_1<0b10101101100, (outs VECREG:$rT), (ins R16C:$rA),
- "fsmh\t$rT, $rA", SelectOp,
- [(set (v8i16 VECREG:$rT), (SPUselmask R16C:$rA))]>;
+
+class FSMHInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm_1<0b10101101100, OOL, IOL, "fsmh\t$rT, $rA", SelectOp,
+ pattern>;
+
+class FSMHRegInst<RegisterClass rclass, ValueType vectype>:
+ FSMHInst<(outs VECREG:$rT), (ins rclass:$rA),
+ [(set (vectype VECREG:$rT), (SPUselmask rclass:$rA))]>;
+
+class FSMHVecInst<ValueType vectype>:
+ FSMHInst<(outs VECREG:$rT), (ins VECREG:$rA),
+ [(set (vectype VECREG:$rT),
+ (SPUselmask (vectype VECREG:$rA)))]>;
+
+multiclass FormSelectMaskHalfword {
+ def v8i16_r16: FSMHRegInst<R16C, v8i16>;
+ def v8i16: FSMHVecInst<v8i16>;
+}
+
+defm FSMH: FormSelectMaskHalfword;
// fsm: Form select mask for words. Like the other fsm* instructions,
// only the lower 4 bits of $rA are significant.
-class FSMInst<ValueType vectype, RegisterClass rclass>:
- RRForm_1<0b00101101100, (outs VECREG:$rT), (ins rclass:$rA),
- "fsm\t$rT, $rA",
- SelectOp,
- [(set (vectype VECREG:$rT), (SPUselmask rclass:$rA))]>;
+
+class FSMInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm_1<0b00101101100, OOL, IOL, "fsm\t$rT, $rA", SelectOp,
+ pattern>;
+
+class FSMRegInst<ValueType vectype, RegisterClass rclass>:
+ FSMInst<(outs VECREG:$rT), (ins rclass:$rA),
+ [(set (vectype VECREG:$rT), (SPUselmask rclass:$rA))]>;
+
+class FSMVecInst<ValueType vectype>:
+ FSMInst<(outs VECREG:$rT), (ins VECREG:$rA),
+ [(set (vectype VECREG:$rT), (SPUselmask (vectype VECREG:$rA)))]>;
multiclass FormSelectMaskWord {
- def r32 : FSMInst<v4i32, R32C>;
- def r16 : FSMInst<v4i32, R16C>;
+ def v4i32: FSMVecInst<v4i32>;
+
+ def r32 : FSMRegInst<v4i32, R32C>;
+ def r16 : FSMRegInst<v4i32, R16C>;
}
defm FSM : FormSelectMaskWord;
// Special case when used for i64 math operations
multiclass FormSelectMaskWord64 {
- def r32 : FSMInst<v2i64, R32C>;
- def r16 : FSMInst<v2i64, R16C>;
+ def r32 : FSMRegInst<v2i64, R32C>;
+ def r16 : FSMRegInst<v2i64, R16C>;
}
defm FSM64 : FormSelectMaskWord64;
def AHIr16:
RI10Form<0b10111000, (outs R16C:$rT), (ins R16C:$rA, s10imm:$val),
"ahi\t$rT, $rA, $val", IntegerOp,
- [(set R16C:$rT, (add R16C:$rA, v8i16SExt10Imm:$val))]>;
+ [(set R16C:$rT, (add R16C:$rA, i16ImmSExt10:$val))]>;
+
+// v4i32, i32 add instruction:
+
+class AInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm<0b00000011000, OOL, IOL,
+ "a\t$rT, $rA, $rB", IntegerOp,
+ pattern>;
+
+class AVecInst<ValueType vectype>:
+ AInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ [(set (vectype VECREG:$rT), (add (vectype VECREG:$rA),
+ (vectype VECREG:$rB)))]>;
+
+class ARegInst<RegisterClass rclass>:
+ AInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB),
+ [(set rclass:$rT, (add rclass:$rA, rclass:$rB))]>;
+
+multiclass AddInstruction {
+ def v4i32: AVecInst<v4i32>;
+ def v16i8: AVecInst<v16i8>;
+
+ def r32: ARegInst<R32C>;
+}
-def Avec:
- RRForm<0b00000011000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "a\t$rT, $rA, $rB", IntegerOp,
- [(set (v4i32 VECREG:$rT), (add (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)))]>;
+defm A : AddInstruction;
-def : Pat<(add (v16i8 VECREG:$rA), (v16i8 VECREG:$rB)),
- (Avec VECREG:$rA, VECREG:$rB)>;
+class AIInst<dag OOL, dag IOL, list<dag> pattern>:
+ RI10Form<0b00111000, OOL, IOL,
+ "ai\t$rT, $rA, $val", IntegerOp,
+ pattern>;
-def Ar32:
- RRForm<0b00000011000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
- "a\t$rT, $rA, $rB", IntegerOp,
- [(set R32C:$rT, (add R32C:$rA, R32C:$rB))]>;
+class AIVecInst<ValueType vectype, PatLeaf immpred>:
+ AIInst<(outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ [(set (vectype VECREG:$rT), (add (vectype VECREG:$rA), immpred:$val))]>;
-def Ar8:
- RRForm<0b00000011000, (outs R8C:$rT), (ins R8C:$rA, R8C:$rB),
- "a\t$rT, $rA, $rB", IntegerOp,
- [/* no pattern */]>;
+class AIFPVecInst<ValueType vectype, PatLeaf immpred>:
+ AIInst<(outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ [/* no pattern */]>;
+
+class AIRegInst<RegisterClass rclass, PatLeaf immpred>:
+ AIInst<(outs rclass:$rT), (ins rclass:$rA, s10imm_i32:$val),
+ [(set rclass:$rT, (add rclass:$rA, immpred:$val))]>;
+
+// This is used to add epsilons to floating point numbers in the f32 fdiv code:
+class AIFPInst<RegisterClass rclass, PatLeaf immpred>:
+ AIInst<(outs rclass:$rT), (ins rclass:$rA, s10imm_i32:$val),
+ [/* no pattern */]>;
-def AIvec:
- RI10Form<0b00111000, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
- "ai\t$rT, $rA, $val", IntegerOp,
- [(set (v4i32 VECREG:$rT), (add (v4i32 VECREG:$rA),
- v4i32SExt10Imm:$val))]>;
+multiclass AddImmediate {
+ def v4i32: AIVecInst<v4i32, v4i32SExt10Imm>;
-def AIr32:
- RI10Form<0b00111000, (outs R32C:$rT), (ins R32C:$rA, s10imm_i32:$val),
- "ai\t$rT, $rA, $val", IntegerOp,
- [(set R32C:$rT, (add R32C:$rA, i32ImmSExt10:$val))]>;
+ def r32: AIRegInst<R32C, i32ImmSExt10>;
+
+ def v4f32: AIFPVecInst<v4f32, v4i32SExt10Imm>;
+ def f32: AIFPInst<R32FP, i32ImmSExt10>;
+}
+
+defm AI : AddImmediate;
def SFHvec:
RRForm<0b00010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
class ADDXVecInst<ValueType vectype>:
ADDXInst<(outs VECREG:$rT),
(ins VECREG:$rA, VECREG:$rB, VECREG:$rCarry),
- [(set (vectype VECREG:$rT),
- (SPUaddx (vectype VECREG:$rA), (vectype VECREG:$rB),
- (vectype VECREG:$rCarry)))]>,
+ [/* no pattern */]>,
RegConstraint<"$rCarry = $rT">,
NoEncode<"$rCarry">;
class ADDXRegInst<RegisterClass rclass>:
ADDXInst<(outs rclass:$rT),
(ins rclass:$rA, rclass:$rB, rclass:$rCarry),
- [(set rclass:$rT,
- (SPUaddx rclass:$rA, rclass:$rB, rclass:$rCarry))]>,
+ [/* no pattern */]>,
RegConstraint<"$rCarry = $rT">,
NoEncode<"$rCarry">;
class CGVecInst<ValueType vectype>:
CGInst<(outs VECREG:$rT),
(ins VECREG:$rA, VECREG:$rB),
- [(set (vectype VECREG:$rT),
- (SPUcarry_gen (vectype VECREG:$rA), (vectype VECREG:$rB)))]>;
+ [/* no pattern */]>;
class CGRegInst<RegisterClass rclass>:
CGInst<(outs rclass:$rT),
(ins rclass:$rA, rclass:$rB),
- [(set rclass:$rT,
- (SPUcarry_gen rclass:$rA, rclass:$rB))]>;
+ [/* no pattern */]>;
multiclass CarryGenerate {
def v2i64 : CGVecInst<v2i64>;
class SFXVecInst<ValueType vectype>:
SFXInst<(outs VECREG:$rT),
(ins VECREG:$rA, VECREG:$rB, VECREG:$rCarry),
- [(set (vectype VECREG:$rT),
- (SPUsubx (vectype VECREG:$rA), (vectype VECREG:$rB),
- (vectype VECREG:$rCarry)))]>,
+ [/* no pattern */]>,
RegConstraint<"$rCarry = $rT">,
NoEncode<"$rCarry">;
class SFXRegInst<RegisterClass rclass>:
SFXInst<(outs rclass:$rT),
(ins rclass:$rA, rclass:$rB, rclass:$rCarry),
- [(set rclass:$rT,
- (SPUsubx rclass:$rA, rclass:$rB, rclass:$rCarry))]>,
+ [/* no pattern */]>,
RegConstraint<"$rCarry = $rT">,
NoEncode<"$rCarry">;
class BGVecInst<ValueType vectype>:
BGInst<(outs VECREG:$rT),
(ins VECREG:$rA, VECREG:$rB),
- [(set (vectype VECREG:$rT),
- (SPUborrow_gen (vectype VECREG:$rA), (vectype VECREG:$rB)))]>;
+ [/* no pattern */]>;
class BGRegInst<RegisterClass rclass>:
BGInst<(outs rclass:$rT),
(ins rclass:$rA, rclass:$rB),
- [(set rclass:$rT,
- (SPUborrow_gen rclass:$rA, rclass:$rB))]>;
+ [/* no pattern */]>;
multiclass BorrowGenerate {
def v4i32 : BGVecInst<v4i32>;
// BGX: Borrow generate, extended.
def BGXvec:
RRForm<0b11000010110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB,
- VECREG:$rCarry),
+ VECREG:$rCarry),
"bgx\t$rT, $rA, $rB", IntegerOp,
[]>,
RegConstraint<"$rCarry = $rT">,
def MPYv8i16:
RRForm<0b00100011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
"mpy\t$rT, $rA, $rB", IntegerMulDiv,
- [(set (v8i16 VECREG:$rT), (SPUmpy_v8i16 (v8i16 VECREG:$rA),
- (v8i16 VECREG:$rB)))]>;
+ [/* no pattern */]>;
def MPYr16:
RRForm<0b00100011110, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
"mpy\t$rT, $rA, $rB", IntegerMulDiv,
[(set R16C:$rT, (mul R16C:$rA, R16C:$rB))]>;
+// Unsigned 16-bit multiply:
+
+class MPYUInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm<0b00110011110, OOL, IOL,
+ "mpyu\t$rT, $rA, $rB", IntegerMulDiv,
+ pattern>;
+
def MPYUv4i32:
- RRForm<0b00110011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "mpyu\t$rT, $rA, $rB", IntegerMulDiv,
- [(set (v4i32 VECREG:$rT),
- (SPUmpyu_v4i32 (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)))]>;
+ MPYUInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ [/* no pattern */]>;
def MPYUr16:
- RRForm<0b00110011110, (outs R32C:$rT), (ins R16C:$rA, R16C:$rB),
- "mpyu\t$rT, $rA, $rB", IntegerMulDiv,
- [(set R32C:$rT, (mul (zext R16C:$rA),
- (zext R16C:$rB)))]>;
+ MPYUInst<(outs R32C:$rT), (ins R16C:$rA, R16C:$rB),
+ [(set R32C:$rT, (mul (zext R16C:$rA), (zext R16C:$rB)))]>;
def MPYUr32:
- RRForm<0b00110011110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
- "mpyu\t$rT, $rA, $rB", IntegerMulDiv,
- [(set R32C:$rT, (SPUmpyu_i32 R32C:$rA, R32C:$rB))]>;
+ MPYUInst<(outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ [/* no pattern */]>;
-// mpyi: multiply 16 x s10imm -> 32 result (custom lowering for 32 bit result,
-// this only produces the lower 16 bits)
-def MPYIvec:
- RI10Form<0b00101110, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+// mpyi: multiply 16 x s10imm -> 32 result.
+
+class MPYIInst<dag OOL, dag IOL, list<dag> pattern>:
+ RI10Form<0b00101110, OOL, IOL,
"mpyi\t$rT, $rA, $val", IntegerMulDiv,
- [(set (v8i16 VECREG:$rT), (mul (v8i16 VECREG:$rA), v8i16SExt10Imm:$val))]>;
+ pattern>;
+
+def MPYIvec:
+ MPYIInst<(outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ [(set (v8i16 VECREG:$rT),
+ (mul (v8i16 VECREG:$rA), v8i16SExt10Imm:$val))]>;
def MPYIr16:
- RI10Form<0b00101110, (outs R16C:$rT), (ins R16C:$rA, s10imm:$val),
- "mpyi\t$rT, $rA, $val", IntegerMulDiv,
- [(set R16C:$rT, (mul R16C:$rA, i16ImmSExt10:$val))]>;
+ MPYIInst<(outs R16C:$rT), (ins R16C:$rA, s10imm:$val),
+ [(set R16C:$rT, (mul R16C:$rA, i16ImmSExt10:$val))]>;
// mpyui: same issues as other multiplies, plus, this doesn't match a
// pattern... but may be used during target DAG selection or lowering
+
+class MPYUIInst<dag OOL, dag IOL, list<dag> pattern>:
+ RI10Form<0b10101110, OOL, IOL,
+ "mpyui\t$rT, $rA, $val", IntegerMulDiv,
+ pattern>;
+
def MPYUIvec:
- RI10Form<0b10101110, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
- "mpyui\t$rT, $rA, $val", IntegerMulDiv,
- []>;
+ MPYUIInst<(outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ []>;
def MPYUIr16:
- RI10Form<0b10101110, (outs R16C:$rT), (ins R16C:$rA, s10imm:$val),
- "mpyui\t$rT, $rA, $val", IntegerMulDiv,
- []>;
+ MPYUIInst<(outs R16C:$rT), (ins R16C:$rA, s10imm:$val),
+ []>;
// mpya: 16 x 16 + 16 -> 32 bit result
-def MPYAvec:
- RRRForm<0b0011, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
- "mpya\t$rT, $rA, $rB, $rC", IntegerMulDiv,
- [(set (v4i32 VECREG:$rT), (add (v4i32 (bitconvert (mul (v8i16 VECREG:$rA),
- (v8i16 VECREG:$rB)))),
- (v4i32 VECREG:$rC)))]>;
+class MPYAInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRRForm<0b0011, OOL, IOL,
+ "mpya\t$rT, $rA, $rB, $rC", IntegerMulDiv,
+ pattern>;
+
+def MPYAv4i32:
+ MPYAInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ [(set (v4i32 VECREG:$rT),
+ (add (v4i32 (bitconvert (mul (v8i16 VECREG:$rA),
+ (v8i16 VECREG:$rB)))),
+ (v4i32 VECREG:$rC)))]>;
def MPYAr32:
- RRRForm<0b0011, (outs R32C:$rT), (ins R16C:$rA, R16C:$rB, R32C:$rC),
- "mpya\t$rT, $rA, $rB, $rC", IntegerMulDiv,
- [(set R32C:$rT, (add (sext (mul R16C:$rA, R16C:$rB)),
- R32C:$rC))]>;
-
-def : Pat<(add (mul (sext R16C:$rA), (sext R16C:$rB)), R32C:$rC),
- (MPYAr32 R16C:$rA, R16C:$rB, R32C:$rC)>;
+ MPYAInst<(outs R32C:$rT), (ins R16C:$rA, R16C:$rB, R32C:$rC),
+ [(set R32C:$rT, (add (sext (mul R16C:$rA, R16C:$rB)),
+ R32C:$rC))]>;
+
+def MPYAr32_sext:
+ MPYAInst<(outs R32C:$rT), (ins R16C:$rA, R16C:$rB, R32C:$rC),
+ [(set R32C:$rT, (add (mul (sext R16C:$rA), (sext R16C:$rB)),
+ R32C:$rC))]>;
def MPYAr32_sextinreg:
- RRRForm<0b0011, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB, R32C:$rC),
- "mpya\t$rT, $rA, $rB, $rC", IntegerMulDiv,
- [(set R32C:$rT, (add (mul (sext_inreg R32C:$rA, i16),
- (sext_inreg R32C:$rB, i16)),
- R32C:$rC))]>;
-
-//def MPYAr32:
-// RRRForm<0b0011, (outs R32C:$rT), (ins R16C:$rA, R16C:$rB, R32C:$rC),
-// "mpya\t$rT, $rA, $rB, $rC", IntegerMulDiv,
-// [(set R32C:$rT, (add (sext (mul R16C:$rA, R16C:$rB)),
-// R32C:$rC))]>;
+ MPYAInst<(outs R32C:$rT), (ins R32C:$rA, R32C:$rB, R32C:$rC),
+ [(set R32C:$rT, (add (mul (sext_inreg R32C:$rA, i16),
+ (sext_inreg R32C:$rB, i16)),
+ R32C:$rC))]>;
// mpyh: multiply high, used to synthesize 32-bit multiplies
+class MPYHInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm<0b10100011110, OOL, IOL,
+ "mpyh\t$rT, $rA, $rB", IntegerMulDiv,
+ pattern>;
+
def MPYHv4i32:
- RRForm<0b10100011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "mpyh\t$rT, $rA, $rB", IntegerMulDiv,
- [(set (v4i32 VECREG:$rT),
- (SPUmpyh_v4i32 (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)))]>;
+ MPYHInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ [/* no pattern */]>;
def MPYHr32:
- RRForm<0b10100011110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
- "mpyh\t$rT, $rA, $rB", IntegerMulDiv,
- [(set R32C:$rT, (SPUmpyh_i32 R32C:$rA, R32C:$rB))]>;
+ MPYHInst<(outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ [/* no pattern */]>;
// mpys: multiply high and shift right (returns the top half of
// a 16-bit multiply, sign extended to 32 bits.)
-def MPYSvec:
- RRForm<0b11100011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+
+class MPYSInst<dag OOL, dag IOL>:
+ RRForm<0b11100011110, OOL, IOL,
"mpys\t$rT, $rA, $rB", IntegerMulDiv,
- []>;
+ [/* no pattern */]>;
+def MPYSv4i32:
+ MPYSInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB)>;
+
def MPYSr16:
- RRForm<0b11100011110, (outs R32C:$rT), (ins R16C:$rA, R16C:$rB),
- "mpys\t$rT, $rA, $rB", IntegerMulDiv,
- []>;
+ MPYSInst<(outs R32C:$rT), (ins R16C:$rA, R16C:$rB)>;
// mpyhh: multiply high-high (returns the 32-bit result from multiplying
// the top 16 bits of the $rA, $rB)
+
+class MPYHHInst<dag OOL, dag IOL>:
+ RRForm<0b01100011110, OOL, IOL,
+ "mpyhh\t$rT, $rA, $rB", IntegerMulDiv,
+ [/* no pattern */]>;
+
def MPYHHv8i16:
- RRForm<0b01100011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "mpyhh\t$rT, $rA, $rB", IntegerMulDiv,
- [(set (v8i16 VECREG:$rT),
- (SPUmpyhh_v8i16 (v8i16 VECREG:$rA), (v8i16 VECREG:$rB)))]>;
+ MPYHHInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB)>;
def MPYHHr32:
- RRForm<0b01100011110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
- "mpyhh\t$rT, $rA, $rB", IntegerMulDiv,
- []>;
+ MPYHHInst<(outs R32C:$rT), (ins R32C:$rA, R32C:$rB)>;
// mpyhha: Multiply high-high, add to $rT:
-def MPYHHAvec:
- RRForm<0b01100010110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+
+class MPYHHAInst<dag OOL, dag IOL>:
+ RRForm<0b01100010110, OOL, IOL,
"mpyhha\t$rT, $rA, $rB", IntegerMulDiv,
- []>;
+ [/* no pattern */]>;
+def MPYHHAvec:
+ MPYHHAInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB)>;
+
def MPYHHAr32:
- RRForm<0b01100010110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
- "mpyhha\t$rT, $rA, $rB", IntegerMulDiv,
- []>;
+ MPYHHAInst<(outs R32C:$rT), (ins R32C:$rA, R32C:$rB)>;
-// mpyhhu: Multiply high-high, unsigned
-def MPYHHUvec:
- RRForm<0b01110011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+// mpyhhu: Multiply high-high, unsigned, e.g.:
+//
+// +-------+-------+ +-------+-------+ +---------+
+// | a0 . a1 | x | b0 . b1 | = | a0 x b0 |
+// +-------+-------+ +-------+-------+ +---------+
+//
+// where a0, b0 are the upper 16 bits of the 32-bit word
+
+class MPYHHUInst<dag OOL, dag IOL>:
+ RRForm<0b01110011110, OOL, IOL,
"mpyhhu\t$rT, $rA, $rB", IntegerMulDiv,
- []>;
+ [/* no pattern */]>;
+def MPYHHUv4i32:
+ MPYHHUInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB)>;
+
def MPYHHUr32:
- RRForm<0b01110011110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
- "mpyhhu\t$rT, $rA, $rB", IntegerMulDiv,
- []>;
+ MPYHHUInst<(outs R32C:$rT), (ins R32C:$rA, R32C:$rB)>;
// mpyhhau: Multiply high-high, unsigned
-def MPYHHAUvec:
- RRForm<0b01110010110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+
+class MPYHHAUInst<dag OOL, dag IOL>:
+ RRForm<0b01110010110, OOL, IOL,
"mpyhhau\t$rT, $rA, $rB", IntegerMulDiv,
- []>;
+ [/* no pattern */]>;
+def MPYHHAUvec:
+ MPYHHAUInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB)>;
+
def MPYHHAUr32:
- RRForm<0b01110010110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
- "mpyhhau\t$rT, $rA, $rB", IntegerMulDiv,
- []>;
+ MPYHHAUInst<(outs R32C:$rT), (ins R32C:$rA, R32C:$rB)>;
+//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
// clz: Count leading zeroes
-def CLZv4i32:
- RRForm_1<0b10100101010, (outs VECREG:$rT), (ins VECREG:$rA),
- "clz\t$rT, $rA", IntegerOp,
- [/* intrinsic */]>;
+//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
+class CLZInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm_1<0b10100101010, OOL, IOL, "clz\t$rT, $rA",
+ IntegerOp, pattern>;
+
+class CLZRegInst<RegisterClass rclass>:
+ CLZInst<(outs rclass:$rT), (ins rclass:$rA),
+ [(set rclass:$rT, (ctlz rclass:$rA))]>;
+
+class CLZVecInst<ValueType vectype>:
+ CLZInst<(outs VECREG:$rT), (ins VECREG:$rA),
+ [(set (vectype VECREG:$rT), (ctlz (vectype VECREG:$rA)))]>;
+
+multiclass CountLeadingZeroes {
+ def v4i32 : CLZVecInst<v4i32>;
+ def r32 : CLZRegInst<R32C>;
+}
-def CLZr32:
- RRForm_1<0b10100101010, (outs R32C:$rT), (ins R32C:$rA),
- "clz\t$rT, $rA", IntegerOp,
- [(set R32C:$rT, (ctlz R32C:$rA))]>;
+defm CLZ : CountLeadingZeroes;
// cntb: Count ones in bytes (aka "population count")
+//
// NOTE: This instruction is really a vector instruction, but the custom
// lowering code uses it in unorthodox ways to support CTPOP for other
// data types!
+
def CNTBv16i8:
RRForm_1<0b00101101010, (outs VECREG:$rT), (ins VECREG:$rA),
"cntb\t$rT, $rA", IntegerOp,
"cntb\t$rT, $rA", IntegerOp,
[(set (v4i32 VECREG:$rT), (SPUcntb (v4i32 VECREG:$rA)))]>;
-// gbb: Gather all low order bits from each byte in $rA into a single 16-bit
-// quantity stored into $rT
-def GBB:
- RRForm_1<0b01001101100, (outs R16C:$rT), (ins VECREG:$rA),
- "gbb\t$rT, $rA", GatherOp,
- []>;
+// gbb: Gather the low order bits from each byte in $rA into a single 16-bit
+// quantity stored into $rT's slot 0, upper 16 bits are zeroed, as are
+// slots 1-3.
+//
+// Note: This instruction "pairs" with the fsmb instruction for all of the
+// various types defined here.
+//
+// Note 2: The "VecInst" and "RegInst" forms refer to the result being either
+// a vector or register.
+
+class GBBInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm_1<0b01001101100, OOL, IOL, "gbb\t$rT, $rA", GatherOp, pattern>;
+
+class GBBRegInst<RegisterClass rclass, ValueType vectype>:
+ GBBInst<(outs rclass:$rT), (ins VECREG:$rA),
+ [/* no pattern */]>;
+
+class GBBVecInst<ValueType vectype>:
+ GBBInst<(outs VECREG:$rT), (ins VECREG:$rA),
+ [/* no pattern */]>;
+
+multiclass GatherBitsFromBytes {
+ def v16i8_r32: GBBRegInst<R32C, v16i8>;
+ def v16i8_r16: GBBRegInst<R16C, v16i8>;
+ def v16i8: GBBVecInst<v16i8>;
+}
+
+defm GBB: GatherBitsFromBytes;
// gbh: Gather all low order bits from each halfword in $rA into a single
-// 8-bit quantity stored in $rT
-def GBH:
- RRForm_1<0b10001101100, (outs R16C:$rT), (ins VECREG:$rA),
- "gbh\t$rT, $rA", GatherOp,
- []>;
+// 8-bit quantity stored in $rT's slot 0, with the upper bits of $rT set to 0
+// and slots 1-3 also set to 0.
+//
+// See notes for GBBInst, above.
+
+class GBHInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm_1<0b10001101100, OOL, IOL, "gbh\t$rT, $rA", GatherOp,
+ pattern>;
+
+class GBHRegInst<RegisterClass rclass, ValueType vectype>:
+ GBHInst<(outs rclass:$rT), (ins VECREG:$rA),
+ [/* no pattern */]>;
+
+class GBHVecInst<ValueType vectype>:
+ GBHInst<(outs VECREG:$rT), (ins VECREG:$rA),
+ [/* no pattern */]>;
+
+multiclass GatherBitsHalfword {
+ def v8i16_r32: GBHRegInst<R32C, v8i16>;
+ def v8i16_r16: GBHRegInst<R16C, v8i16>;
+ def v8i16: GBHVecInst<v8i16>;
+}
+
+defm GBH: GatherBitsHalfword;
// gb: Gather all low order bits from each word in $rA into a single
-// 4-bit quantity stored in $rT
-def GB:
- RRForm_1<0b00001101100, (outs R16C:$rT), (ins VECREG:$rA),
- "gb\t$rT, $rA", GatherOp,
- []>;
+// 4-bit quantity stored in $rT's slot 0, upper bits in $rT set to 0,
+// as well as slots 1-3.
+//
+// See notes for gbb, above.
+
+class GBInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm_1<0b00001101100, OOL, IOL, "gb\t$rT, $rA", GatherOp,
+ pattern>;
+
+class GBRegInst<RegisterClass rclass, ValueType vectype>:
+ GBInst<(outs rclass:$rT), (ins VECREG:$rA),
+ [/* no pattern */]>;
+
+class GBVecInst<ValueType vectype>:
+ GBInst<(outs VECREG:$rT), (ins VECREG:$rA),
+ [/* no pattern */]>;
+
+multiclass GatherBitsWord {
+ def v4i32_r32: GBRegInst<R32C, v4i32>;
+ def v4i32_r16: GBRegInst<R16C, v4i32>;
+ def v4i32: GBVecInst<v4i32>;
+}
+
+defm GB: GatherBitsWord;
// avgb: average bytes
def AVGB:
XSBHInst<(outs VECREG:$rDst), (ins VECREG:$rSrc),
[(set (v8i16 VECREG:$rDst), (sext (vectype VECREG:$rSrc)))]>;
-class XSBHRegInst<RegisterClass rclass>:
+class XSBHInRegInst<RegisterClass rclass, list<dag> pattern>:
XSBHInst<(outs rclass:$rDst), (ins rclass:$rSrc),
- [(set rclass:$rDst, (sext_inreg rclass:$rSrc, i8))]>;
+ pattern>;
multiclass ExtendByteHalfword {
- def v16i8: XSBHVecInst<v8i16>;
- def r16: XSBHRegInst<R16C>;
+ def v16i8: XSBHVecInst<v8i16>;
+ def r8: XSBHInst<(outs R16C:$rDst), (ins R8C:$rSrc),
+ [(set R16C:$rDst, (sext R8C:$rSrc))]>;
+ def r16: XSBHInRegInst<R16C,
+ [(set R16C:$rDst, (sext_inreg R16C:$rSrc, i8))]>;
// 32-bit form for XSBH: used to sign extend 8-bit quantities to 16-bit
// quantities to 32-bit quantities via a 32-bit register (see the sext 8->32
// pattern below). Intentionally doesn't match a pattern because we want the
// sext 8->32 pattern to do the work for us, namely because we need the extra
// XSHWr32.
- def r32: XSBHRegInst<R32C>;
+ def r32: XSBHInRegInst<R32C, [/* no pattern */]>;
+
+ // Same as the 32-bit version, but for i64
+ def r64: XSBHInRegInst<R64C, [/* no pattern */]>;
}
defm XSBH : ExtendByteHalfword;
-// Sign-extend, but take an 8-bit register to a 16-bit register (not done as
-// sext_inreg)
-def XSBHr8:
- XSBHInst<(outs R16C:$rDst), (ins R8C:$rSrc),
- [(set R16C:$rDst, (sext R8C:$rSrc))]>;
-
// Sign extend halfwords to words:
-def XSHWvec:
- RRForm_1<0b01101101010, (outs VECREG:$rDest), (ins VECREG:$rSrc),
- "xshw\t$rDest, $rSrc", IntegerOp,
- [(set (v4i32 VECREG:$rDest), (sext (v8i16 VECREG:$rSrc)))]>;
-
-def XSHWr32:
- RRForm_1<0b01101101010, (outs R32C:$rDst), (ins R32C:$rSrc),
- "xshw\t$rDst, $rSrc", IntegerOp,
- [(set R32C:$rDst, (sext_inreg R32C:$rSrc, i16))]>;
-
-def XSHWr16:
- RRForm_1<0b01101101010, (outs R32C:$rDst), (ins R16C:$rSrc),
- "xshw\t$rDst, $rSrc", IntegerOp,
- [(set R32C:$rDst, (sext R16C:$rSrc))]>;
-
-def XSWDvec:
- RRForm_1<0b01100101010, (outs VECREG:$rDst), (ins VECREG:$rSrc),
- "xswd\t$rDst, $rSrc", IntegerOp,
- [(set (v2i64 VECREG:$rDst), (sext (v4i32 VECREG:$rSrc)))]>;
-
-def XSWDr64:
- RRForm_1<0b01100101010, (outs R64C:$rDst), (ins R64C:$rSrc),
- "xswd\t$rDst, $rSrc", IntegerOp,
- [(set R64C:$rDst, (sext_inreg R64C:$rSrc, i32))]>;
-
-def XSWDr32:
- RRForm_1<0b01100101010, (outs R64C:$rDst), (ins R32C:$rSrc),
- "xswd\t$rDst, $rSrc", IntegerOp,
- [(set R64C:$rDst, (SPUsext32_to_64 R32C:$rSrc))]>;
-
-def : Pat<(sext R32C:$inp),
- (XSWDr32 R32C:$inp)>;
+
+class XSHWInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm_1<0b01101101010, OOL, IOL, "xshw\t$rDest, $rSrc",
+ IntegerOp, pattern>;
+
+class XSHWVecInst<ValueType in_vectype, ValueType out_vectype>:
+ XSHWInst<(outs VECREG:$rDest), (ins VECREG:$rSrc),
+ [(set (out_vectype VECREG:$rDest),
+ (sext (in_vectype VECREG:$rSrc)))]>;
+
+class XSHWInRegInst<RegisterClass rclass, list<dag> pattern>:
+ XSHWInst<(outs rclass:$rDest), (ins rclass:$rSrc),
+ pattern>;
+
+class XSHWRegInst<RegisterClass rclass>:
+ XSHWInst<(outs rclass:$rDest), (ins R16C:$rSrc),
+ [(set rclass:$rDest, (sext R16C:$rSrc))]>;
+
+multiclass ExtendHalfwordWord {
+ def v4i32: XSHWVecInst<v4i32, v8i16>;
+
+ def r16: XSHWRegInst<R32C>;
+
+ def r32: XSHWInRegInst<R32C,
+ [(set R32C:$rDest, (sext_inreg R32C:$rSrc, i16))]>;
+ def r64: XSHWInRegInst<R64C, [/* no pattern */]>;
+}
+
+defm XSHW : ExtendHalfwordWord;
+
+// Sign-extend words to doublewords (32->64 bits)
+
+class XSWDInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm_1<0b01100101010, OOL, IOL, "xswd\t$rDst, $rSrc",
+ IntegerOp, pattern>;
+
+class XSWDVecInst<ValueType in_vectype, ValueType out_vectype>:
+ XSWDInst<(outs VECREG:$rDst), (ins VECREG:$rSrc),
+ [(set (out_vectype VECREG:$rDst),
+ (sext (out_vectype VECREG:$rSrc)))]>;
+
+class XSWDRegInst<RegisterClass in_rclass, RegisterClass out_rclass>:
+ XSWDInst<(outs out_rclass:$rDst), (ins in_rclass:$rSrc),
+ [(set out_rclass:$rDst, (sext in_rclass:$rSrc))]>;
+
+multiclass ExtendWordToDoubleWord {
+ def v2i64: XSWDVecInst<v4i32, v2i64>;
+ def r64: XSWDRegInst<R32C, R64C>;
+
+ def r64_inreg: XSWDInst<(outs R64C:$rDst), (ins R64C:$rSrc),
+ [(set R64C:$rDst, (sext_inreg R64C:$rSrc, i32))]>;
+}
+
+defm XSWD : ExtendWordToDoubleWord;
// AND operations
def fabs32: ANDInst<(outs R32FP:$rT), (ins R32FP:$rA, R32C:$rB),
[/* Intentionally does not match a pattern */]>;
- def fabs64: ANDInst<(outs R64FP:$rT), (ins R64FP:$rA, VECREG:$rB),
+ def fabs64: ANDInst<(outs R64FP:$rT), (ins R64FP:$rA, R64C:$rB),
[/* Intentionally does not match a pattern */]>;
- // Could use v4i32, but won't for clarity
def fabsvec: ANDInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
[/* Intentionally does not match a pattern */]>;
RRForm<0b10000011010, OOL, IOL, "andc\t$rT, $rA, $rB",
IntegerOp, pattern>;
-class ANDCVecInst<ValueType vectype>:
+class ANDCVecInst<ValueType vectype, PatFrag vnot_frag = vnot>:
ANDCInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- [(set (vectype VECREG:$rT), (and (vectype VECREG:$rA),
- (vnot (vectype VECREG:$rB))))]>;
+ [(set (vectype VECREG:$rT),
+ (and (vectype VECREG:$rA),
+ (vnot_frag (vectype VECREG:$rB))))]>;
class ANDCRegInst<RegisterClass rclass>:
ANDCInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB),
def r32: ANDCRegInst<R32C>;
def r16: ANDCRegInst<R16C>;
def r8: ANDCRegInst<R8C>;
+
+ // Sometimes, the xor pattern has a bitcast constant:
+ def v16i8_conv: ANDCVecInst<v16i8, vnot_conv>;
}
defm ANDC : AndComplement;
class ANDBIInst<dag OOL, dag IOL, list<dag> pattern>:
RI10Form<0b01101000, OOL, IOL, "andbi\t$rT, $rA, $val",
- IntegerOp, pattern>;
+ ByteOp, pattern>;
multiclass AndByteImm
{
class ANDHIInst<dag OOL, dag IOL, list<dag> pattern> :
RI10Form<0b10101000, OOL, IOL, "andhi\t$rT, $rA, $val",
- IntegerOp, pattern>;
+ ByteOp, pattern>;
multiclass AndHalfwordImm
{
ORInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB),
[(set rclass:$rT, (or rclass:$rA, rclass:$rB))]>;
+// ORCvtForm: OR conversion form
+//
+// This is used to "convert" the preferred slot to its vector equivalent, as
+// well as convert a vector back to its preferred slot.
+//
+// These are effectively no-ops, but need to exist for proper type conversion
+// and type coercion.
+
+class ORCvtForm<dag OOL, dag IOL, list<dag> pattern = [/* no pattern */]>
+ : SPUInstr<OOL, IOL, "or\t$rT, $rA, $rA", IntegerOp> {
+ bits<7> RA;
+ bits<7> RT;
+
+ let Pattern = pattern;
+
+ let Inst{0-10} = 0b10000010000;
+ let Inst{11-17} = RA;
+ let Inst{18-24} = RA;
+ let Inst{25-31} = RT;
+}
+
class ORPromoteScalar<RegisterClass rclass>:
- ORInst<(outs VECREG:$rT), (ins rclass:$rA, rclass:$rB),
- [/* no pattern */]>;
+ ORCvtForm<(outs VECREG:$rT), (ins rclass:$rA)>;
class ORExtractElt<RegisterClass rclass>:
- ORInst<(outs rclass:$rT), (ins VECREG:$rA, VECREG:$rB),
- [/* no pattern */]>;
+ ORCvtForm<(outs rclass:$rT), (ins VECREG:$rA)>;
+
+/* class ORCvtRegGPRC<RegisterClass rclass>:
+ ORCvtForm<(outs GPRC:$rT), (ins rclass:$rA)>; */
+
+/* class ORCvtGPRCReg<RegisterClass rclass>:
+ ORCvtForm<(outs rclass:$rT), (ins GPRC:$rA)>; */
+
+class ORCvtFormR32Reg<RegisterClass rclass, list<dag> pattern = [ ]>:
+ ORCvtForm<(outs rclass:$rT), (ins R32C:$rA), pattern>;
+
+class ORCvtFormRegR32<RegisterClass rclass, list<dag> pattern = [ ]>:
+ ORCvtForm<(outs R32C:$rT), (ins rclass:$rA), pattern>;
+
+class ORCvtFormR64Reg<RegisterClass rclass, list<dag> pattern = [ ]>:
+ ORCvtForm<(outs rclass:$rT), (ins R64C:$rA), pattern>;
+
+class ORCvtFormRegR64<RegisterClass rclass, list<dag> pattern = [ ]>:
+ ORCvtForm<(outs R64C:$rT), (ins rclass:$rA), pattern>;
+
+class ORCvtGPRCVec:
+ ORCvtForm<(outs VECREG:$rT), (ins GPRC:$rA)>;
+
+class ORCvtVecGPRC:
+ ORCvtForm<(outs GPRC:$rT), (ins VECREG:$rA)>;
multiclass BitwiseOr
{
(v4i32 VECREG:$rB)))))]>;
def v2f64: ORInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- [(set (v2f64 VECREG:$rT),
+ [(set (v2f64 VECREG:$rT),
(v2f64 (bitconvert (or (v2i64 VECREG:$rA),
(v2i64 VECREG:$rB)))))]>;
- def r64: ORRegInst<R64C>;
- def r32: ORRegInst<R32C>;
- def r16: ORRegInst<R16C>;
- def r8: ORRegInst<R8C>;
+ def r128: ORRegInst<GPRC>;
+ def r64: ORRegInst<R64C>;
+ def r32: ORRegInst<R32C>;
+ def r16: ORRegInst<R16C>;
+ def r8: ORRegInst<R8C>;
// OR instructions used to copy f32 and f64 registers.
def f32: ORInst<(outs R32FP:$rT), (ins R32FP:$rA, R32FP:$rB),
def f64: ORInst<(outs R64FP:$rT), (ins R64FP:$rA, R64FP:$rB),
[/* no pattern */]>;
- // scalar->vector promotion:
+ // scalar->vector promotion, prefslot2vec:
def v16i8_i8: ORPromoteScalar<R8C>;
def v8i16_i16: ORPromoteScalar<R16C>;
def v4i32_i32: ORPromoteScalar<R32C>;
def v4f32_f32: ORPromoteScalar<R32FP>;
def v2f64_f64: ORPromoteScalar<R64FP>;
- // extract element 0:
+ // vector->scalar demotion, vec2prefslot:
def i8_v16i8: ORExtractElt<R8C>;
def i16_v8i16: ORExtractElt<R16C>;
def i32_v4i32: ORExtractElt<R32C>;
def i64_v2i64: ORExtractElt<R64C>;
def f32_v4f32: ORExtractElt<R32FP>;
def f64_v2f64: ORExtractElt<R64FP>;
+
+ // Conversion from vector to GPRC
+ def i128_vec: ORCvtVecGPRC;
+
+ // Conversion from GPRC to vector
+ def vec_i128: ORCvtGPRCVec;
+
+/*
+ // Conversion from register to GPRC
+ def i128_r64: ORCvtRegGPRC<R64C>;
+ def i128_f64: ORCvtRegGPRC<R64FP>;
+ def i128_r32: ORCvtRegGPRC<R32C>;
+ def i128_f32: ORCvtRegGPRC<R32FP>;
+ def i128_r16: ORCvtRegGPRC<R16C>;
+ def i128_r8: ORCvtRegGPRC<R8C>;
+
+ // Conversion from GPRC to register
+ def r64_i128: ORCvtGPRCReg<R64C>;
+ def f64_i128: ORCvtGPRCReg<R64FP>;
+ def r32_i128: ORCvtGPRCReg<R32C>;
+ def f32_i128: ORCvtGPRCReg<R32FP>;
+ def r16_i128: ORCvtGPRCReg<R16C>;
+ def r8_i128: ORCvtGPRCReg<R8C>;
+*/
+/*
+ // Conversion from register to R32C:
+ def r32_r16: ORCvtFormRegR32<R16C>;
+ def r32_r8: ORCvtFormRegR32<R8C>;
+
+ // Conversion from R32C to register
+ def r32_r16: ORCvtFormR32Reg<R16C>;
+ def r32_r8: ORCvtFormR32Reg<R8C>;
+*/
+
+ // Conversion from R64C to register:
+ def r32_r64: ORCvtFormR64Reg<R32C>;
+ // def r16_r64: ORCvtFormR64Reg<R16C>;
+ // def r8_r64: ORCvtFormR64Reg<R8C>;
+
+ // Conversion to R64C from register:
+ def r64_r32: ORCvtFormRegR64<R32C>;
+ // def r64_r16: ORCvtFormRegR64<R16C>;
+ // def r64_r8: ORCvtFormRegR64<R8C>;
+
+ // bitconvert patterns:
+ def r32_f32: ORCvtFormR32Reg<R32FP,
+ [(set R32FP:$rT, (bitconvert R32C:$rA))]>;
+ def f32_r32: ORCvtFormRegR32<R32FP,
+ [(set R32C:$rT, (bitconvert R32FP:$rA))]>;
+
+ def r64_f64: ORCvtFormR64Reg<R64FP,
+ [(set R64FP:$rT, (bitconvert R64C:$rA))]>;
+ def f64_r64: ORCvtFormRegR64<R64FP,
+ [(set R64C:$rT, (bitconvert R64FP:$rA))]>;
}
defm OR : BitwiseOr;
-// scalar->vector promotion patterns:
-def : Pat<(v16i8 (SPUpromote_scalar R8C:$rA)),
- (ORv16i8_i8 R8C:$rA, R8C:$rA)>;
+// scalar->vector promotion patterns (preferred slot to vector):
+def : Pat<(v16i8 (SPUprefslot2vec R8C:$rA)),
+ (ORv16i8_i8 R8C:$rA)>;
-def : Pat<(v8i16 (SPUpromote_scalar R16C:$rA)),
- (ORv8i16_i16 R16C:$rA, R16C:$rA)>;
+def : Pat<(v8i16 (SPUprefslot2vec R16C:$rA)),
+ (ORv8i16_i16 R16C:$rA)>;
-def : Pat<(v4i32 (SPUpromote_scalar R32C:$rA)),
- (ORv4i32_i32 R32C:$rA, R32C:$rA)>;
+def : Pat<(v4i32 (SPUprefslot2vec R32C:$rA)),
+ (ORv4i32_i32 R32C:$rA)>;
-def : Pat<(v2i64 (SPUpromote_scalar R64C:$rA)),
- (ORv2i64_i64 R64C:$rA, R64C:$rA)>;
+def : Pat<(v2i64 (SPUprefslot2vec R64C:$rA)),
+ (ORv2i64_i64 R64C:$rA)>;
-def : Pat<(v4f32 (SPUpromote_scalar R32FP:$rA)),
- (ORv4f32_f32 R32FP:$rA, R32FP:$rA)>;
+def : Pat<(v4f32 (SPUprefslot2vec R32FP:$rA)),
+ (ORv4f32_f32 R32FP:$rA)>;
-def : Pat<(v2f64 (SPUpromote_scalar R64FP:$rA)),
- (ORv2f64_f64 R64FP:$rA, R64FP:$rA)>;
+def : Pat<(v2f64 (SPUprefslot2vec R64FP:$rA)),
+ (ORv2f64_f64 R64FP:$rA)>;
-// ORi*_v*: Used to extract vector element 0 (the preferred slot)
+// ORi*_v*: Used to extract vector element 0 (the preferred slot), otherwise
+// known as converting the vector back to its preferred slot
def : Pat<(SPUvec2prefslot (v16i8 VECREG:$rA)),
- (ORi8_v16i8 VECREG:$rA, VECREG:$rA)>;
-
-def : Pat<(SPUvec2prefslot_chained (v16i8 VECREG:$rA)),
- (ORi8_v16i8 VECREG:$rA, VECREG:$rA)>;
+ (ORi8_v16i8 VECREG:$rA)>;
def : Pat<(SPUvec2prefslot (v8i16 VECREG:$rA)),
- (ORi16_v8i16 VECREG:$rA, VECREG:$rA)>;
-
-def : Pat<(SPUvec2prefslot_chained (v8i16 VECREG:$rA)),
- (ORi16_v8i16 VECREG:$rA, VECREG:$rA)>;
+ (ORi16_v8i16 VECREG:$rA)>;
def : Pat<(SPUvec2prefslot (v4i32 VECREG:$rA)),
- (ORi32_v4i32 VECREG:$rA, VECREG:$rA)>;
-
-def : Pat<(SPUvec2prefslot_chained (v4i32 VECREG:$rA)),
- (ORi32_v4i32 VECREG:$rA, VECREG:$rA)>;
+ (ORi32_v4i32 VECREG:$rA)>;
def : Pat<(SPUvec2prefslot (v2i64 VECREG:$rA)),
- (ORi64_v2i64 VECREG:$rA, VECREG:$rA)>;
-
-def : Pat<(SPUvec2prefslot_chained (v2i64 VECREG:$rA)),
- (ORi64_v2i64 VECREG:$rA, VECREG:$rA)>;
+ (ORi64_v2i64 VECREG:$rA)>;
def : Pat<(SPUvec2prefslot (v4f32 VECREG:$rA)),
- (ORf32_v4f32 VECREG:$rA, VECREG:$rA)>;
-
-def : Pat<(SPUvec2prefslot_chained (v4f32 VECREG:$rA)),
- (ORf32_v4f32 VECREG:$rA, VECREG:$rA)>;
+ (ORf32_v4f32 VECREG:$rA)>;
def : Pat<(SPUvec2prefslot (v2f64 VECREG:$rA)),
- (ORf64_v2f64 VECREG:$rA, VECREG:$rA)>;
-
-def : Pat<(SPUvec2prefslot_chained (v2f64 VECREG:$rA)),
- (ORf64_v2f64 VECREG:$rA, VECREG:$rA)>;
+ (ORf64_v2f64 VECREG:$rA)>;
+
+// Load Register: This is an assembler alias for a bitwise OR of a register
+// against itself. It's here because it brings some clarity to assembly
+// language output.
+
+let hasCtrlDep = 1 in {
+ class LRInst<dag OOL, dag IOL>
+ : SPUInstr<OOL, IOL, "lr\t$rT, $rA", IntegerOp> {
+ bits<7> RA;
+ bits<7> RT;
+
+ let Pattern = [/*no pattern*/];
+
+ let Inst{0-10} = 0b10000010000; /* It's an OR operation */
+ let Inst{11-17} = RA;
+ let Inst{18-24} = RA;
+ let Inst{25-31} = RT;
+ }
+
+ class LRVecInst<ValueType vectype>:
+ LRInst<(outs VECREG:$rT), (ins VECREG:$rA)>;
+
+ class LRRegInst<RegisterClass rclass>:
+ LRInst<(outs rclass:$rT), (ins rclass:$rA)>;
+
+ multiclass LoadRegister {
+ def v2i64: LRVecInst<v2i64>;
+ def v2f64: LRVecInst<v2f64>;
+ def v4i32: LRVecInst<v4i32>;
+ def v4f32: LRVecInst<v4f32>;
+ def v8i16: LRVecInst<v8i16>;
+ def v16i8: LRVecInst<v16i8>;
+
+ def r128: LRRegInst<GPRC>;
+ def r64: LRRegInst<R64C>;
+ def f64: LRRegInst<R64FP>;
+ def r32: LRRegInst<R32C>;
+ def f32: LRRegInst<R32FP>;
+ def r16: LRRegInst<R16C>;
+ def r8: LRRegInst<R8C>;
+ }
+
+ defm LR: LoadRegister;
+}
// ORC: Bitwise "or" with complement (c = a | ~b)
def v4i32: ORCVecInst<v4i32>;
def v2i64: ORCVecInst<v2i64>;
+ def r128: ORCRegInst<GPRC>;
def r64: ORCRegInst<R64C>;
def r32: ORCRegInst<R32C>;
def r16: ORCRegInst<R16C>;
defm ORBI : BitwiseOrByteImm;
-// Truncate i16 -> i8
-def ORBItrunc : ORBIInst<(outs R8C:$rT), (ins R16C:$rA, u10imm:$val),
- [/* empty */]>;
-
-def : Pat<(trunc R16C:$rSrc),
- (ORBItrunc R16C:$rSrc, 0)>;
-
// OR halfword immediate
class ORHIInst<dag OOL, dag IOL, list<dag> pattern>:
RI10Form<0b10100000, OOL, IOL, "orhi\t$rT, $rA, $val",
defm ORHI : BitwiseOrHalfwordImm;
-// Truncate i32 -> i16
-def ORHItrunc : ORHIInst<(outs R16C:$rT), (ins R32C:$rA, u10imm:$val),
- [/* empty */]>;
-
-def : Pat<(trunc R32C:$rSrc),
- (ORHItrunc R32C:$rSrc, 0)>;
-
class ORIInst<dag OOL, dag IOL, list<dag> pattern>:
RI10Form<0b00100000, OOL, IOL, "ori\t$rT, $rA, $val",
IntegerOp, pattern>;
defm ORI : BitwiseOrImm;
-// Truncate i64 -> i32
-def ORItrunc : ORIInst<(outs R32C:$rT), (ins R64C:$rA, u10imm_i32:$val),
- [/* empty */]>;
-
-def : Pat<(trunc R64C:$rSrc),
- (ORItrunc R64C:$rSrc, 0)>;
-
// ORX: "or" across the vector: or's $rA's word slots leaving the result in
// $rT[0], slots 1-3 are zeroed.
//
def r16: XORRegInst<R16C>;
def r8: XORRegInst<R8C>;
- // Special forms for floating point instructions.
- // fneg and fabs require bitwise logical ops to manipulate the sign bit.
+ // XOR instructions used to negate f32 and f64 quantities.
def fneg32: XORInst<(outs R32FP:$rT), (ins R32FP:$rA, R32C:$rB),
- [/* no pattern */]>;
+ [/* no pattern */]>;
- def fneg64: XORInst<(outs R64FP:$rT), (ins R64FP:$rA, VECREG:$rB),
- [/* no pattern */]>;
+ def fneg64: XORInst<(outs R64FP:$rT), (ins R64FP:$rA, R64C:$rB),
+ [/* no pattern */]>;
def fnegvec: XORInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- [/* no pattern, see fneg{32,64} */]>;
+ [/* no pattern, see fneg{32,64} */]>;
}
defm XOR : BitwiseExclusiveOr;
[(set R32C:$rT, (xor R32C:$rA, i32ImmSExt10:$val))]>;
// NAND:
-def NANDv16i8:
- RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "nand\t$rT, $rA, $rB", IntegerOp,
- [(set (v16i8 VECREG:$rT), (vnot (and (v16i8 VECREG:$rA),
- (v16i8 VECREG:$rB))))]>;
-
-def NANDv8i16:
- RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "nand\t$rT, $rA, $rB", IntegerOp,
- [(set (v8i16 VECREG:$rT), (vnot (and (v8i16 VECREG:$rA),
- (v8i16 VECREG:$rB))))]>;
-def NANDv4i32:
- RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "nand\t$rT, $rA, $rB", IntegerOp,
- [(set (v4i32 VECREG:$rT), (vnot (and (v4i32 VECREG:$rA),
- (v4i32 VECREG:$rB))))]>;
+class NANDInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm<0b10010011000, OOL, IOL, "nand\t$rT, $rA, $rB",
+ IntegerOp, pattern>;
-def NANDr32:
- RRForm<0b10010010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
- "nand\t$rT, $rA, $rB", IntegerOp,
- [(set R32C:$rT, (not (and R32C:$rA, R32C:$rB)))]>;
+class NANDVecInst<ValueType vectype>:
+ NANDInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ [(set (vectype VECREG:$rT), (vnot (and (vectype VECREG:$rA),
+ (vectype VECREG:$rB))))]>;
+class NANDRegInst<RegisterClass rclass>:
+ NANDInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB),
+ [(set rclass:$rT, (not (and rclass:$rA, rclass:$rB)))]>;
-def NANDr16:
- RRForm<0b10010010000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
- "nand\t$rT, $rA, $rB", IntegerOp,
- [(set R16C:$rT, (not (and R16C:$rA, R16C:$rB)))]>;
+multiclass BitwiseNand
+{
+ def v16i8: NANDVecInst<v16i8>;
+ def v8i16: NANDVecInst<v8i16>;
+ def v4i32: NANDVecInst<v4i32>;
+ def v2i64: NANDVecInst<v2i64>;
+
+ def r128: NANDRegInst<GPRC>;
+ def r64: NANDRegInst<R64C>;
+ def r32: NANDRegInst<R32C>;
+ def r16: NANDRegInst<R16C>;
+ def r8: NANDRegInst<R8C>;
+}
-def NANDr8:
- RRForm<0b10010010000, (outs R8C:$rT), (ins R8C:$rA, R8C:$rB),
- "nand\t$rT, $rA, $rB", IntegerOp,
- [(set R8C:$rT, (not (and R8C:$rA, R8C:$rB)))]>;
+defm NAND : BitwiseNand;
// NOR:
-def NORv16i8:
- RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "nor\t$rT, $rA, $rB", IntegerOp,
- [(set (v16i8 VECREG:$rT), (vnot (or (v16i8 VECREG:$rA),
- (v16i8 VECREG:$rB))))]>;
-def NORv8i16:
- RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "nor\t$rT, $rA, $rB", IntegerOp,
- [(set (v8i16 VECREG:$rT), (vnot (or (v8i16 VECREG:$rA),
- (v8i16 VECREG:$rB))))]>;
-
-def NORv4i32:
- RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "nor\t$rT, $rA, $rB", IntegerOp,
- [(set (v4i32 VECREG:$rT), (vnot (or (v4i32 VECREG:$rA),
- (v4i32 VECREG:$rB))))]>;
+class NORInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm<0b10010010000, OOL, IOL, "nor\t$rT, $rA, $rB",
+ IntegerOp, pattern>;
-def NORr32:
- RRForm<0b10010010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
- "nor\t$rT, $rA, $rB", IntegerOp,
- [(set R32C:$rT, (not (or R32C:$rA, R32C:$rB)))]>;
+class NORVecInst<ValueType vectype>:
+ NORInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ [(set (vectype VECREG:$rT), (vnot (or (vectype VECREG:$rA),
+ (vectype VECREG:$rB))))]>;
+class NORRegInst<RegisterClass rclass>:
+ NORInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB),
+ [(set rclass:$rT, (not (or rclass:$rA, rclass:$rB)))]>;
-def NORr16:
- RRForm<0b10010010000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
- "nor\t$rT, $rA, $rB", IntegerOp,
- [(set R16C:$rT, (not (or R16C:$rA, R16C:$rB)))]>;
+multiclass BitwiseNor
+{
+ def v16i8: NORVecInst<v16i8>;
+ def v8i16: NORVecInst<v8i16>;
+ def v4i32: NORVecInst<v4i32>;
+ def v2i64: NORVecInst<v2i64>;
+
+ def r128: NORRegInst<GPRC>;
+ def r64: NORRegInst<R64C>;
+ def r32: NORRegInst<R32C>;
+ def r16: NORRegInst<R16C>;
+ def r8: NORRegInst<R8C>;
+}
-def NORr8:
- RRForm<0b10010010000, (outs R8C:$rT), (ins R8C:$rA, R8C:$rB),
- "nor\t$rT, $rA, $rB", IntegerOp,
- [(set R8C:$rT, (not (or R8C:$rA, R8C:$rB)))]>;
+defm NOR : BitwiseNor;
// Select bits:
class SELBInst<dag OOL, dag IOL, list<dag> pattern>:
RRRForm<0b1000, OOL, IOL, "selb\t$rT, $rA, $rB, $rC",
IntegerOp, pattern>;
-class SELBVecInst<ValueType vectype>:
+class SELBVecInst<ValueType vectype, PatFrag vnot_frag = vnot>:
SELBInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
[(set (vectype VECREG:$rT),
(or (and (vectype VECREG:$rC), (vectype VECREG:$rB)),
- (and (vnot (vectype VECREG:$rC)),
+ (and (vnot_frag (vectype VECREG:$rC)),
(vectype VECREG:$rA))))]>;
+class SELBVecVCondInst<ValueType vectype>:
+ SELBInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ [(set (vectype VECREG:$rT),
+ (select (vectype VECREG:$rC),
+ (vectype VECREG:$rB),
+ (vectype VECREG:$rA)))]>;
+
+class SELBVecCondInst<ValueType vectype>:
+ SELBInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, R32C:$rC),
+ [(set (vectype VECREG:$rT),
+ (select R32C:$rC,
+ (vectype VECREG:$rB),
+ (vectype VECREG:$rA)))]>;
+
class SELBRegInst<RegisterClass rclass>:
SELBInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB, rclass:$rC),
[(set rclass:$rT,
- (or (and rclass:$rA, rclass:$rC),
- (and rclass:$rB, (not rclass:$rC))))]>;
+ (or (and rclass:$rB, rclass:$rC),
+ (and rclass:$rA, (not rclass:$rC))))]>;
+
+class SELBRegCondInst<RegisterClass rcond, RegisterClass rclass>:
+ SELBInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB, rcond:$rC),
+ [(set rclass:$rT,
+ (select rcond:$rC, rclass:$rB, rclass:$rA))]>;
multiclass SelectBits
{
def v16i8: SELBVecInst<v16i8>;
def v8i16: SELBVecInst<v8i16>;
def v4i32: SELBVecInst<v4i32>;
- def v2i64: SELBVecInst<v2i64>;
+ def v2i64: SELBVecInst<v2i64, vnot_conv>;
def r128: SELBRegInst<GPRC>;
def r64: SELBRegInst<R64C>;
def r32: SELBRegInst<R32C>;
def r16: SELBRegInst<R16C>;
def r8: SELBRegInst<R8C>;
+
+ def v16i8_cond: SELBVecCondInst<v16i8>;
+ def v8i16_cond: SELBVecCondInst<v8i16>;
+ def v4i32_cond: SELBVecCondInst<v4i32>;
+ def v2i64_cond: SELBVecCondInst<v2i64>;
+
+ def v16i8_vcond: SELBVecCondInst<v16i8>;
+ def v8i16_vcond: SELBVecCondInst<v8i16>;
+ def v4i32_vcond: SELBVecCondInst<v4i32>;
+ def v2i64_vcond: SELBVecCondInst<v2i64>;
+
+ def v4f32_cond:
+ SELBInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ [(set (v4f32 VECREG:$rT),
+ (select (v4i32 VECREG:$rC),
+ (v4f32 VECREG:$rB),
+ (v4f32 VECREG:$rA)))]>;
+
+ // SELBr64_cond is defined in SPU64InstrInfo.td
+ def r32_cond: SELBRegCondInst<R32C, R32C>;
+ def f32_cond: SELBRegCondInst<R32C, R32FP>;
+ def r16_cond: SELBRegCondInst<R16C, R16C>;
+ def r8_cond: SELBRegCondInst<R8C, R8C>;
}
defm SELB : SelectBits;
def : SPUselbPatReg<R32C, SELBr32>;
def : SPUselbPatReg<R64C, SELBr64>;
-class SelectConditional<RegisterClass rclass, SPUInstr inst>:
- Pat<(select rclass:$rCond, rclass:$rTrue, rclass:$rFalse),
- (inst rclass:$rFalse, rclass:$rTrue, rclass:$rCond)>;
-
-def : SelectConditional<R32C, SELBr32>;
-def : SelectConditional<R16C, SELBr16>;
-def : SelectConditional<R8C, SELBr8>;
-
// EQV: Equivalence (1 for each same bit, otherwise 0)
//
// Note: There are a lot of ways to match this bit operator and these patterns
RRRForm<0b1000, OOL, IOL, "shufb\t$rT, $rA, $rB, $rC",
IntegerOp, pattern>;
-class SHUFBVecInst<ValueType vectype>:
+class SHUFBVecInst<ValueType resultvec, ValueType maskvec>:
SHUFBInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
- [(set (vectype VECREG:$rT), (SPUshuffle (vectype VECREG:$rA),
- (vectype VECREG:$rB),
- (vectype VECREG:$rC)))]>;
+ [(set (resultvec VECREG:$rT),
+ (SPUshuffle (resultvec VECREG:$rA),
+ (resultvec VECREG:$rB),
+ (maskvec VECREG:$rC)))]>;
-// It's this pattern that's probably the most useful, since SPUISelLowering
-// methods create a v16i8 vector for $rC:
-class SHUFBVecPat1<ValueType vectype, ValueType masktype, SPUInstr inst>:
- Pat<(SPUshuffle (vectype VECREG:$rA), (vectype VECREG:$rB),
- (masktype VECREG:$rC)),
- (inst VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+class SHUFBGPRCInst:
+ SHUFBInst<(outs VECREG:$rT), (ins GPRC:$rA, GPRC:$rB, VECREG:$rC),
+ [/* no pattern */]>;
multiclass ShuffleBytes
{
- def v16i8 : SHUFBVecInst<v16i8>;
- def v8i16 : SHUFBVecInst<v8i16>;
- def v4i32 : SHUFBVecInst<v4i32>;
- def v2i64 : SHUFBVecInst<v2i64>;
-
- def v4f32 : SHUFBVecInst<v4f32>;
- def v2f64 : SHUFBVecInst<v2f64>;
+ def v16i8 : SHUFBVecInst<v16i8, v16i8>;
+ def v16i8_m32 : SHUFBVecInst<v16i8, v4i32>;
+ def v8i16 : SHUFBVecInst<v8i16, v16i8>;
+ def v8i16_m32 : SHUFBVecInst<v8i16, v4i32>;
+ def v4i32 : SHUFBVecInst<v4i32, v16i8>;
+ def v4i32_m32 : SHUFBVecInst<v4i32, v4i32>;
+ def v2i64 : SHUFBVecInst<v2i64, v16i8>;
+ def v2i64_m32 : SHUFBVecInst<v2i64, v4i32>;
+
+ def v4f32 : SHUFBVecInst<v4f32, v16i8>;
+ def v4f32_m32 : SHUFBVecInst<v4f32, v4i32>;
+
+ def v2f64 : SHUFBVecInst<v2f64, v16i8>;
+ def v2f64_m32 : SHUFBVecInst<v2f64, v4i32>;
+
+ def gprc : SHUFBGPRCInst;
}
defm SHUFB : ShuffleBytes;
-// Shuffle mask is a v16i8 vector
-def : SHUFBVecPat1<v8i16, v16i8, SHUFBv16i8>;
-def : SHUFBVecPat1<v4i32, v16i8, SHUFBv16i8>;
-def : SHUFBVecPat1<v2i64, v16i8, SHUFBv16i8>;
-def : SHUFBVecPat1<v4f32, v16i8, SHUFBv16i8>;
-def : SHUFBVecPat1<v2f64, v16i8, SHUFBv16i8>;
-
-// Shuffle mask is a v4i32 vector:
-def : SHUFBVecPat1<v16i8, v4i32, SHUFBv4i32>;
-def : SHUFBVecPat1<v8i16, v4i32, SHUFBv4i32>;
-def : SHUFBVecPat1<v2i64, v4i32, SHUFBv4i32>;
-def : SHUFBVecPat1<v4f32, v4i32, SHUFBv4i32>;
-def : SHUFBVecPat1<v2f64, v4i32, SHUFBv4i32>;
-
//===----------------------------------------------------------------------===//
// Shift and rotate group:
//===----------------------------------------------------------------------===//
[(set (vectype VECREG:$rT),
(SPUvec_shl (vectype VECREG:$rA), R16C:$rB))]>;
-// $rB gets promoted to 32-bit register type when confronted with
-// this llvm assembly code:
-//
-// define i16 @shlh_i16_1(i16 %arg1, i16 %arg2) {
-// %A = shl i16 %arg1, %arg2
-// ret i16 %A
-// }
-
multiclass ShiftLeftHalfword
{
def v8i16: SHLHVecInst<v8i16>;
[(set (vectype VECREG:$rT),
(SPUshlquad_l_bits (vectype VECREG:$rA), R32C:$rB))]>;
+class SHLQBIRegInst<RegisterClass rclass>:
+ SHLQBIInst<(outs rclass:$rT), (ins rclass:$rA, R32C:$rB),
+ [/* no pattern */]>;
+
multiclass ShiftLeftQuadByBits
{
def v16i8: SHLQBIVecInst<v16i8>;
def v4f32: SHLQBIVecInst<v4f32>;
def v2i64: SHLQBIVecInst<v2i64>;
def v2f64: SHLQBIVecInst<v2f64>;
+
+ def r128: SHLQBIRegInst<GPRC>;
}
defm SHLQBI : ShiftLeftQuadByBits;
defm SHLQBYI : ShiftLeftQuadBytesImm;
-// Special form for truncating i64 to i32:
-def SHLQBYItrunc64: SHLQBYIInst<(outs R32C:$rT), (ins R64C:$rA, u7imm_i32:$val),
- [/* no pattern, see below */]>;
+class SHLQBYBIInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm<0b00111001111, OOL, IOL, "shlqbybi\t$rT, $rA, $rB",
+ RotateShift, pattern>;
+
+class SHLQBYBIVecInst<ValueType vectype>:
+ SHLQBYBIInst<(outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB),
+ [/* no pattern */]>;
-def : Pat<(trunc R64C:$rSrc),
- (SHLQBYItrunc64 R64C:$rSrc, 4)>;
+class SHLQBYBIRegInst<RegisterClass rclass>:
+ SHLQBYBIInst<(outs rclass:$rT), (ins rclass:$rA, R32C:$rB),
+ [/* no pattern */]>;
+
+multiclass ShiftLeftQuadBytesBitCount
+{
+ def v16i8: SHLQBYBIVecInst<v16i8>;
+ def v8i16: SHLQBYBIVecInst<v8i16>;
+ def v4i32: SHLQBYBIVecInst<v4i32>;
+ def v4f32: SHLQBYBIVecInst<v4f32>;
+ def v2i64: SHLQBYBIVecInst<v2i64>;
+ def v2f64: SHLQBYBIVecInst<v2f64>;
+
+ def r128: SHLQBYBIRegInst<GPRC>;
+}
+
+defm SHLQBYBI : ShiftLeftQuadBytesBitCount;
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
// Rotate halfword:
def : Pat<(SPUvec_rotl VECREG:$rA, (i32 uimm7:$val)),
(ROTHIv8i16 VECREG:$rA, imm:$val)>;
-
+
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
// Rotate word:
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
def v16i8: ROTQBYVecInst<v16i8>;
def v8i16: ROTQBYVecInst<v8i16>;
def v4i32: ROTQBYVecInst<v4i32>;
+ def v4f32: ROTQBYVecInst<v4f32>;
def v2i64: ROTQBYVecInst<v2i64>;
+ def v2f64: ROTQBYVecInst<v2f64>;
}
defm ROTQBY: RotateQuadLeftByBytes;
-def : Pat<(SPUrotbytes_left_chained (v16i8 VECREG:$rA), R32C:$rB),
- (ROTQBYv16i8 VECREG:$rA, R32C:$rB)>;
-def : Pat<(SPUrotbytes_left_chained (v8i16 VECREG:$rA), R32C:$rB),
- (ROTQBYv8i16 VECREG:$rA, R32C:$rB)>;
-def : Pat<(SPUrotbytes_left_chained (v4i32 VECREG:$rA), R32C:$rB),
- (ROTQBYv4i32 VECREG:$rA, R32C:$rB)>;
-def : Pat<(SPUrotbytes_left_chained (v2i64 VECREG:$rA), R32C:$rB),
- (ROTQBYv2i64 VECREG:$rA, R32C:$rB)>;
-
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
// Rotate quad by byte (count), immediate
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
def v16i8: ROTQBYIVecInst<v16i8>;
def v8i16: ROTQBYIVecInst<v8i16>;
def v4i32: ROTQBYIVecInst<v4i32>;
+ def v4f32: ROTQBYIVecInst<v4f32>;
def v2i64: ROTQBYIVecInst<v2i64>;
+ def vfi64: ROTQBYIVecInst<v2f64>;
}
defm ROTQBYI: RotateQuadByBytesImm;
-def : Pat<(SPUrotbytes_left_chained (v16i8 VECREG:$rA), (i16 uimm7:$val)),
- (ROTQBYIv16i8 VECREG:$rA, uimm7:$val)>;
-def : Pat<(SPUrotbytes_left_chained (v8i16 VECREG:$rA), (i16 uimm7:$val)),
- (ROTQBYIv8i16 VECREG:$rA, uimm7:$val)>;
-def : Pat<(SPUrotbytes_left_chained (v4i32 VECREG:$rA), (i16 uimm7:$val)),
- (ROTQBYIv4i32 VECREG:$rA, uimm7:$val)>;
-def : Pat<(SPUrotbytes_left_chained (v2i64 VECREG:$rA), (i16 uimm7:$val)),
- (ROTQBYIv2i64 VECREG:$rA, uimm7:$val)>;
-
// See ROTQBY note above.
class ROTQBYBIInst<dag OOL, dag IOL, list<dag> pattern>:
RI7Form<0b00110011100, OOL, IOL,
RotateShift, pattern>;
class ROTQBIVecInst<ValueType vectype>:
- ROTQBIInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ ROTQBIInst<(outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB),
[/* no pattern yet */]>;
class ROTQBIRegInst<RegisterClass rclass>:
- ROTQBIInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB),
+ ROTQBIInst<(outs rclass:$rT), (ins rclass:$rA, R32C:$rB),
[/* no pattern yet */]>;
multiclass RotateQuadByBitCount
}
defm ROTQBI: RotateQuadByBitCount;
-
+
class ROTQBIIInst<dag OOL, dag IOL, list<dag> pattern>:
RI7Form<0b00011111100, OOL, IOL, "rotqbii\t$rT, $rA, $val",
RotateShift, pattern>;
def: Pat<(SPUvec_srl (v8i16 VECREG:$rA), (i16 imm:$val)),
(ROTHMIv8i16 VECREG:$rA, imm:$val)>;
-
+
def: Pat<(SPUvec_srl (v8i16 VECREG:$rA), (i8 imm:$val)),
(ROTHMIv8i16 VECREG:$rA, imm:$val)>;
def : Pat<(SPUvec_srl VECREG:$rA, (i16 uimm7:$val)),
(ROTMIv4i32 VECREG:$rA, uimm7:$val)>;
-
+
def : Pat<(SPUvec_srl VECREG:$rA, (i8 uimm7:$val)),
(ROTMIv4i32 VECREG:$rA, uimm7:$val)>;
(ROTMIr32 R32C:$rA, uimm7:$val)>;
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
-// ROTQMBYvec: This is a vector form merely so that when used in an
+// ROTQMBY: This is a vector form merely so that when used in an
// instruction pattern, type checking will succeed. This instruction assumes
// that the user knew to negate $rB.
-//
-// Using the SPUrotquad_rz_bytes target-specific DAG node, the patterns
-// ensure that $rB is negated.
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
class ROTQMBYInst<dag OOL, dag IOL, list<dag> pattern>:
class ROTQMBYRegInst<RegisterClass rclass>:
ROTQMBYInst<(outs rclass:$rT), (ins rclass:$rA, R32C:$rB),
- [(set rclass:$rT,
- (SPUrotquad_rz_bytes rclass:$rA, R32C:$rB))]>;
+ [/* no pattern */]>;
multiclass RotateQuadBytes
{
defm ROTQMBY : RotateQuadBytes;
-def : Pat<(SPUrotquad_rz_bytes (v16i8 VECREG:$rA), R32C:$rB),
- (ROTQMBYv16i8 VECREG:$rA, (SFIr32 R32C:$rB, 0))>;
-def : Pat<(SPUrotquad_rz_bytes (v8i16 VECREG:$rA), R32C:$rB),
- (ROTQMBYv8i16 VECREG:$rA, (SFIr32 R32C:$rB, 0))>;
-def : Pat<(SPUrotquad_rz_bytes (v4i32 VECREG:$rA), R32C:$rB),
- (ROTQMBYv4i32 VECREG:$rA, (SFIr32 R32C:$rB, 0))>;
-def : Pat<(SPUrotquad_rz_bytes (v2i64 VECREG:$rA), R32C:$rB),
- (ROTQMBYv2i64 VECREG:$rA, (SFIr32 R32C:$rB, 0))>;
-def : Pat<(SPUrotquad_rz_bytes GPRC:$rA, R32C:$rB),
- (ROTQMBYr128 GPRC:$rA, (SFIr32 R32C:$rB, 0))>;
-def : Pat<(SPUrotquad_rz_bytes R64C:$rA, R32C:$rB),
- (ROTQMBYr64 R64C:$rA, (SFIr32 R32C:$rB, 0))>;
-
class ROTQMBYIInst<dag OOL, dag IOL, list<dag> pattern>:
RI7Form<0b10111111100, OOL, IOL, "rotqmbyi\t$rT, $rA, $val",
RotateShift, pattern>;
class ROTQMBYIVecInst<ValueType vectype>:
ROTQMBYIInst<(outs VECREG:$rT), (ins VECREG:$rA, rotNeg7imm:$val),
- [(set (vectype VECREG:$rT),
- (SPUrotquad_rz_bytes (vectype VECREG:$rA), (i32 uimm7:$val)))]>;
+ [/* no pattern */]>;
-class ROTQMBYIRegInst<RegisterClass rclass, Operand optype, ValueType inttype, PatLeaf pred>:
+class ROTQMBYIRegInst<RegisterClass rclass, Operand optype, ValueType inttype,
+ PatLeaf pred>:
ROTQMBYIInst<(outs rclass:$rT), (ins rclass:$rA, optype:$val),
- [(set rclass:$rT,
- (SPUrotquad_rz_bytes rclass:$rA, (inttype pred:$val)))]>;
+ [/* no pattern */]>;
+
+// 128-bit zero extension form:
+class ROTQMBYIZExtInst<RegisterClass rclass, Operand optype, PatLeaf pred>:
+ ROTQMBYIInst<(outs GPRC:$rT), (ins rclass:$rA, optype:$val),
+ [/* no pattern */]>;
multiclass RotateQuadBytesImm
{
def r128: ROTQMBYIRegInst<GPRC, rotNeg7imm, i32, uimm7>;
def r64: ROTQMBYIRegInst<R64C, rotNeg7imm, i32, uimm7>;
+
+ def r128_zext_r8: ROTQMBYIZExtInst<R8C, rotNeg7imm, uimm7>;
+ def r128_zext_r16: ROTQMBYIZExtInst<R16C, rotNeg7imm, uimm7>;
+ def r128_zext_r32: ROTQMBYIZExtInst<R32C, rotNeg7imm, uimm7>;
+ def r128_zext_r64: ROTQMBYIZExtInst<R64C, rotNeg7imm, uimm7>;
}
defm ROTQMBYI : RotateQuadBytesImm;
RotateShift, pattern>;
class ROTQMBYBIVecInst<ValueType vectype>:
- ROTQMBYBIInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- [/* no pattern, intrinsic? */]>;
+ ROTQMBYBIInst<(outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB),
+ [/* no pattern, */]>;
multiclass RotateMaskQuadByBitCount
{
defm ROTQMBI: RotateMaskQuadByBits;
-def : Pat<(SPUrotquad_rz_bits (v16i8 VECREG:$rA), R32C:$rB),
- (ROTQMBIv16i8 VECREG:$rA, (SFIr32 R32C:$rB, 0))>;
-def : Pat<(SPUrotquad_rz_bits (v8i16 VECREG:$rA), R32C:$rB),
- (ROTQMBIv8i16 VECREG:$rA, (SFIr32 R32C:$rB, 0))>;
-def : Pat<(SPUrotquad_rz_bits (v4i32 VECREG:$rA), R32C:$rB),
- (ROTQMBIv4i32 VECREG:$rA, (SFIr32 R32C:$rB, 0))>;
-def : Pat<(SPUrotquad_rz_bits (v2i64 VECREG:$rA), R32C:$rB),
- (ROTQMBIv2i64 VECREG:$rA, (SFIr32 R32C:$rB, 0))>;
-def : Pat<(SPUrotquad_rz_bits GPRC:$rA, R32C:$rB),
- (ROTQMBIr128 GPRC:$rA, (SFIr32 R32C:$rB, 0))>;
-def : Pat<(SPUrotquad_rz_bits R64C:$rA, R32C:$rB),
- (ROTQMBIr64 R64C:$rA, (SFIr32 R32C:$rB, 0))>;
-
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
// Rotate quad and mask by bits, immediate
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
class ROTQMBIIVecInst<ValueType vectype>:
ROTQMBIIInst<(outs VECREG:$rT), (ins VECREG:$rA, rotNeg7imm:$val),
- [(set (vectype VECREG:$rT),
- (SPUrotquad_rz_bits (vectype VECREG:$rA), (i32 uimm7:$val)))]>;
+ [/* no pattern */]>;
class ROTQMBIIRegInst<RegisterClass rclass>:
ROTQMBIIInst<(outs rclass:$rT), (ins rclass:$rA, rotNeg7imm:$val),
- [(set rclass:$rT,
- (SPUrotquad_rz_bits rclass:$rA, (i32 uimm7:$val)))]>;
+ [/* no pattern */]>;
multiclass RotateMaskQuadByBitsImm
{
"hgt\t$rA, $rB", BranchResolv,
[/* no pattern to match */]>;
- def HGTIr32:
+ def HGTIr32:
RI10Form_2<0b11110010, (outs), (ins R32C:$rA, s10imm:$val),
"hgti\t$rA, $val", BranchResolv,
[/* no pattern to match */]>;
[/* no pattern to match */]>;
}
-//------------------------------------------------------------------------
-// Comparison operators:
-//------------------------------------------------------------------------
+//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
+// Comparison operators for i8, i16 and i32:
+//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
class CEQBInst<dag OOL, dag IOL, list<dag> pattern> :
RRForm<0b00001011110, OOL, IOL, "ceqb\t$rT, $rA, $rB",
def r32: CGTIInst<(outs R32C:$rT), (ins R32C:$rA, s10imm_i32:$val),
[(set R32C:$rT, (setgt R32C:$rA, i32ImmSExt10:$val))]>;
+
+ // CGTIv4f32, CGTIf32: These are used in the f32 fdiv instruction sequence:
+ def v4f32: CGTIInst<(outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ [(set (v4i32 VECREG:$rT),
+ (setgt (v4i32 (bitconvert (v4f32 VECREG:$rA))),
+ (v4i32 v4i32SExt16Imm:$val)))]>;
+
+ def f32: CGTIInst<(outs R32C:$rT), (ins R32FP:$rA, s10imm_i32:$val),
+ [/* no pattern */]>;
}
class CLGTBInst<dag OOL, dag IOL, list<dag> pattern> :
// define a pattern to generate the right code, as a binary operator
// (in a manner of speaking.)
//
-// N.B.: This only matches the setcc set of conditionals. Special pattern
-// matching is used for select conditionals.
+// Notes:
+// 1. This only matches the setcc set of conditionals. Special pattern
+// matching is used for select conditionals.
+//
+// 2. The "DAG" versions of these classes is almost exclusively used for
+// i64 comparisons. See the tblgen fundamentals documentation for what
+// ".ResultInstrs[0]" means; see TargetSelectionDAG.td and the Pattern
+// class for where ResultInstrs originates.
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
class SETCCNegCondReg<PatFrag cond, RegisterClass rclass, ValueType inttype,
Pat<(cond rclass:$rA, (inttype immpred:$imm)),
(xorinst (cmpare rclass:$rA, (inttype immpred:$imm)), (inttype -1))>;
-def : SETCCNegCondReg<setne, R8C, i8, XORBIr8, CEQBr8>;
+def : SETCCNegCondReg<setne, R8C, i8, XORBIr8, CEQBr8>;
def : SETCCNegCondImm<setne, R8C, i8, immSExt8, XORBIr8, CEQBIr8>;
-def : SETCCNegCondReg<setne, R16C, i16, XORHIr16, CEQHr16>;
+def : SETCCNegCondReg<setne, R16C, i16, XORHIr16, CEQHr16>;
def : SETCCNegCondImm<setne, R16C, i16, i16ImmSExt10, XORHIr16, CEQHIr16>;
def : SETCCNegCondReg<setne, R32C, i32, XORIr32, CEQr32>;
SPUInstr selinstr, SPUInstr binop, SPUInstr cmpOp1,
SPUInstr cmpOp2>:
Pat<(select (inttype (cond rclass:$rA, rclass:$rB)),
- rclass:$rFalse, rclass:$rTrue),
- (selinstr rclass:$rTrue, rclass:$rFalse,
+ rclass:$rTrue, rclass:$rFalse),
+ (selinstr rclass:$rFalse, rclass:$rTrue,
(binop (cmpOp1 rclass:$rA, rclass:$rB),
(cmpOp2 rclass:$rA, rclass:$rB)))>;
BIForm<0b10010101100, "bisl\t$$lr, $func", [(SPUcall R32C:$func)]>;
}
+// Support calls to external symbols:
+def : Pat<(SPUcall (SPUpcrel texternalsym:$func, 0)),
+ (BRSL texternalsym:$func)>;
+
+def : Pat<(SPUcall (SPUaform texternalsym:$func, 0)),
+ (BRASL texternalsym:$func)>;
+
// Unconditional branches:
let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in {
def BR :
def BI:
BIForm<0b00010101100, "bi\t$func", [(brind R32C:$func)]>;
- // Various branches:
- def BRNZ:
- RI16Form<0b010000100, (outs), (ins R32C:$rCond, brtarget:$dest),
- "brnz\t$rCond,$dest",
- BranchResolv,
- [(brcond R32C:$rCond, bb:$dest)]>;
-
- def BRZ:
- RI16Form<0b000000100, (outs), (ins R32C:$rT, brtarget:$dest),
- "brz\t$rT,$dest",
- BranchResolv,
- [/* no pattern */]>;
+ // Conditional branches:
+ class BRNZInst<dag IOL, list<dag> pattern>:
+ RI16Form<0b010000100, (outs), IOL, "brnz\t$rCond,$dest",
+ BranchResolv, pattern>;
- def BRHNZ:
- RI16Form<0b011000100, (outs), (ins R16C:$rCond, brtarget:$dest),
- "brhnz\t$rCond,$dest",
- BranchResolv,
- [(brcond R16C:$rCond, bb:$dest)]>;
+ class BRNZRegInst<RegisterClass rclass>:
+ BRNZInst<(ins rclass:$rCond, brtarget:$dest),
+ [(brcond rclass:$rCond, bb:$dest)]>;
- def BRHZ:
- RI16Form<0b001000100, (outs), (ins R16C:$rT, brtarget:$dest),
- "brhz\t$rT,$dest",
- BranchResolv,
- [/* no pattern */]>;
-
-/*
- def BINZ:
- BICondForm<0b10010100100, "binz\t$rA, $func",
- [(SPUbinz R32C:$rA, R32C:$func)]>;
+ class BRNZVecInst<ValueType vectype>:
+ BRNZInst<(ins VECREG:$rCond, brtarget:$dest),
+ [(brcond (vectype VECREG:$rCond), bb:$dest)]>;
- def BIZ:
- BICondForm<0b00010100100, "biz\t$rA, $func",
- [(SPUbiz R32C:$rA, R32C:$func)]>;
-*/
+ multiclass BranchNotZero {
+ def v4i32 : BRNZVecInst<v4i32>;
+ def r32 : BRNZRegInst<R32C>;
+ }
+
+ defm BRNZ : BranchNotZero;
+
+ class BRZInst<dag IOL, list<dag> pattern>:
+ RI16Form<0b000000100, (outs), IOL, "brz\t$rT,$dest",
+ BranchResolv, pattern>;
+
+ class BRZRegInst<RegisterClass rclass>:
+ BRZInst<(ins rclass:$rT, brtarget:$dest), [/* no pattern */]>;
+
+ class BRZVecInst<ValueType vectype>:
+ BRZInst<(ins VECREG:$rT, brtarget:$dest), [/* no pattern */]>;
+
+ multiclass BranchZero {
+ def v4i32: BRZVecInst<v4i32>;
+ def r32: BRZRegInst<R32C>;
+ }
+
+ defm BRZ: BranchZero;
+
+ // Note: LLVM doesn't do branch conditional, indirect. Otherwise these would
+ // be useful:
+ /*
+ class BINZInst<dag IOL, list<dag> pattern>:
+ BICondForm<0b10010100100, (outs), IOL, "binz\t$rA, $dest", pattern>;
+
+ class BINZRegInst<RegisterClass rclass>:
+ BINZInst<(ins rclass:$rA, brtarget:$dest),
+ [(brcond rclass:$rA, R32C:$dest)]>;
+
+ class BINZVecInst<ValueType vectype>:
+ BINZInst<(ins VECREG:$rA, R32C:$dest),
+ [(brcond (vectype VECREG:$rA), R32C:$dest)]>;
+
+ multiclass BranchNotZeroIndirect {
+ def v4i32: BINZVecInst<v4i32>;
+ def r32: BINZRegInst<R32C>;
+ }
+
+ defm BINZ: BranchNotZeroIndirect;
+
+ class BIZInst<dag IOL, list<dag> pattern>:
+ BICondForm<0b00010100100, (outs), IOL, "biz\t$rA, $func", pattern>;
+
+ class BIZRegInst<RegisterClass rclass>:
+ BIZInst<(ins rclass:$rA, R32C:$func), [/* no pattern */]>;
+
+ class BIZVecInst<ValueType vectype>:
+ BIZInst<(ins VECREG:$rA, R32C:$func), [/* no pattern */]>;
+
+ multiclass BranchZeroIndirect {
+ def v4i32: BIZVecInst<v4i32>;
+ def r32: BIZRegInst<R32C>;
+ }
+
+ defm BIZ: BranchZeroIndirect;
+ */
+
+ class BRHNZInst<dag IOL, list<dag> pattern>:
+ RI16Form<0b011000100, (outs), IOL, "brhnz\t$rCond,$dest", BranchResolv,
+ pattern>;
+
+ class BRHNZRegInst<RegisterClass rclass>:
+ BRHNZInst<(ins rclass:$rCond, brtarget:$dest),
+ [(brcond rclass:$rCond, bb:$dest)]>;
+
+ class BRHNZVecInst<ValueType vectype>:
+ BRHNZInst<(ins VECREG:$rCond, brtarget:$dest), [/* no pattern */]>;
+
+ multiclass BranchNotZeroHalfword {
+ def v8i16: BRHNZVecInst<v8i16>;
+ def r16: BRHNZRegInst<R16C>;
+ }
+
+ defm BRHNZ: BranchNotZeroHalfword;
+
+ class BRHZInst<dag IOL, list<dag> pattern>:
+ RI16Form<0b001000100, (outs), IOL, "brhz\t$rT,$dest", BranchResolv,
+ pattern>;
+
+ class BRHZRegInst<RegisterClass rclass>:
+ BRHZInst<(ins rclass:$rT, brtarget:$dest), [/* no pattern */]>;
+
+ class BRHZVecInst<ValueType vectype>:
+ BRHZInst<(ins VECREG:$rT, brtarget:$dest), [/* no pattern */]>;
+
+ multiclass BranchZeroHalfword {
+ def v8i16: BRHZVecInst<v8i16>;
+ def r16: BRHZRegInst<R16C>;
+ }
+
+ defm BRHZ: BranchZeroHalfword;
}
//===----------------------------------------------------------------------===//
// setcc and brcond patterns:
//===----------------------------------------------------------------------===//
-def : Pat<(brcond (i16 (seteq R16C:$rA, 0)), bb:$dest),
- (BRHZ R16C:$rA, bb:$dest)>;
-def : Pat<(brcond (i16 (setne R16C:$rA, 0)), bb:$dest),
- (BRHNZ R16C:$rA, bb:$dest)>;
+def : Pat<(brcond (i16 (seteq R16C:$rA, 0)), bb:$dest),
+ (BRHZr16 R16C:$rA, bb:$dest)>;
+def : Pat<(brcond (i16 (setne R16C:$rA, 0)), bb:$dest),
+ (BRHNZr16 R16C:$rA, bb:$dest)>;
-def : Pat<(brcond (i32 (seteq R32C:$rA, 0)), bb:$dest),
- (BRZ R32C:$rA, bb:$dest)>;
-def : Pat<(brcond (i32 (setne R32C:$rA, 0)), bb:$dest),
- (BRNZ R32C:$rA, bb:$dest)>;
+def : Pat<(brcond (i32 (seteq R32C:$rA, 0)), bb:$dest),
+ (BRZr32 R32C:$rA, bb:$dest)>;
+def : Pat<(brcond (i32 (setne R32C:$rA, 0)), bb:$dest),
+ (BRNZr32 R32C:$rA, bb:$dest)>;
multiclass BranchCondEQ<PatFrag cond, SPUInstr brinst16, SPUInstr brinst32>
{
(brinst32 (CEQr32 R32C:$rA, R32C:$rB), bb:$dest)>;
}
-defm BRCONDeq : BranchCondEQ<seteq, BRHZ, BRZ>;
-defm BRCONDne : BranchCondEQ<setne, BRHNZ, BRNZ>;
+defm BRCONDeq : BranchCondEQ<seteq, BRHNZr16, BRNZr32>;
+defm BRCONDne : BranchCondEQ<setne, BRHZr16, BRZr32>;
multiclass BranchCondLGT<PatFrag cond, SPUInstr brinst16, SPUInstr brinst32>
{
(brinst32 (CLGTr32 R32C:$rA, R32C:$rB), bb:$dest)>;
}
-defm BRCONDugt : BranchCondLGT<setugt, BRHNZ, BRNZ>;
-defm BRCONDule : BranchCondLGT<setule, BRHZ, BRZ>;
+defm BRCONDugt : BranchCondLGT<setugt, BRHNZr16, BRNZr32>;
+defm BRCONDule : BranchCondLGT<setule, BRHZr16, BRZr32>;
multiclass BranchCondLGTEQ<PatFrag cond, SPUInstr orinst16, SPUInstr brinst16,
SPUInstr orinst32, SPUInstr brinst32>
bb:$dest)>;
}
-defm BRCONDuge : BranchCondLGTEQ<setuge, ORr16, BRHNZ, ORr32, BRNZ>;
-defm BRCONDult : BranchCondLGTEQ<setult, ORr16, BRHZ, ORr32, BRZ>;
+defm BRCONDuge : BranchCondLGTEQ<setuge, ORr16, BRHNZr16, ORr32, BRNZr32>;
+defm BRCONDult : BranchCondLGTEQ<setult, ORr16, BRHZr16, ORr32, BRZr32>;
multiclass BranchCondGT<PatFrag cond, SPUInstr brinst16, SPUInstr brinst32>
{
(brinst32 (CGTr32 R32C:$rA, R32C:$rB), bb:$dest)>;
}
-defm BRCONDgt : BranchCondGT<setgt, BRHNZ, BRNZ>;
-defm BRCONDle : BranchCondGT<setle, BRHZ, BRZ>;
+defm BRCONDgt : BranchCondGT<setgt, BRHNZr16, BRNZr32>;
+defm BRCONDle : BranchCondGT<setle, BRHZr16, BRZr32>;
multiclass BranchCondGTEQ<PatFrag cond, SPUInstr orinst16, SPUInstr brinst16,
SPUInstr orinst32, SPUInstr brinst32>
bb:$dest)>;
}
-defm BRCONDge : BranchCondGTEQ<setge, ORr16, BRHNZ, ORr32, BRNZ>;
-defm BRCONDlt : BranchCondGTEQ<setlt, ORr16, BRHZ, ORr32, BRZ>;
+defm BRCONDge : BranchCondGTEQ<setge, ORr16, BRHNZr16, ORr32, BRNZr32>;
+defm BRCONDlt : BranchCondGTEQ<setlt, ORr16, BRHZr16, ORr32, BRZr32>;
let isTerminator = 1, isBarrier = 1 in {
let isReturn = 1 in {
// Single precision floating point instructions
//===----------------------------------------------------------------------===//
-def FAv4f32:
- RRForm<0b00100011010, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "fa\t$rT, $rA, $rB", SPrecFP,
- [(set (v4f32 VECREG:$rT), (fadd (v4f32 VECREG:$rA), (v4f32 VECREG:$rB)))]>;
+class FAInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm<0b01011000100, OOL, IOL, "fa\t$rT, $rA, $rB",
+ SPrecFP, pattern>;
-def FAf32 :
- RRForm<0b00100011010, (outs R32FP:$rT), (ins R32FP:$rA, R32FP:$rB),
- "fa\t$rT, $rA, $rB", SPrecFP,
- [(set R32FP:$rT, (fadd R32FP:$rA, R32FP:$rB))]>;
+class FAVecInst<ValueType vectype>:
+ FAInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ [(set (vectype VECREG:$rT),
+ (fadd (vectype VECREG:$rA), (vectype VECREG:$rB)))]>;
-def FSv4f32:
- RRForm<0b00100011010, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "fs\t$rT, $rA, $rB", SPrecFP,
- [(set (v4f32 VECREG:$rT), (fsub (v4f32 VECREG:$rA), (v4f32 VECREG:$rB)))]>;
+multiclass SFPAdd
+{
+ def v4f32: FAVecInst<v4f32>;
+ def f32: FAInst<(outs R32FP:$rT), (ins R32FP:$rA, R32FP:$rB),
+ [(set R32FP:$rT, (fadd R32FP:$rA, R32FP:$rB))]>;
+}
+
+defm FA : SFPAdd;
-def FSf32 :
- RRForm<0b10100011010, (outs R32FP:$rT), (ins R32FP:$rA, R32FP:$rB),
- "fs\t$rT, $rA, $rB", SPrecFP,
- [(set R32FP:$rT, (fsub R32FP:$rA, R32FP:$rB))]>;
+class FSInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm<0b01011000100, OOL, IOL, "fs\t$rT, $rA, $rB",
+ SPrecFP, pattern>;
+
+class FSVecInst<ValueType vectype>:
+ FSInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ [(set (vectype VECREG:$rT),
+ (fsub (vectype VECREG:$rA), (vectype VECREG:$rB)))]>;
+
+multiclass SFPSub
+{
+ def v4f32: FSVecInst<v4f32>;
+ def f32: FSInst<(outs R32FP:$rT), (ins R32FP:$rA, R32FP:$rB),
+ [(set R32FP:$rT, (fsub R32FP:$rA, R32FP:$rB))]>;
+}
+
+defm FS : SFPSub;
// Floating point reciprocal estimate
-def FREv4f32 :
- RRForm_1<0b00011101100, (outs VECREG:$rT), (ins VECREG:$rA),
- "frest\t$rT, $rA", SPrecFP,
- [(set (v4f32 VECREG:$rT), (SPUreciprocalEst (v4f32 VECREG:$rA)))]>;
-def FREf32 :
- RRForm_1<0b00011101100, (outs R32FP:$rT), (ins R32FP:$rA),
- "frest\t$rT, $rA", SPrecFP,
- [(set R32FP:$rT, (SPUreciprocalEst R32FP:$rA))]>;
+class FRESTInst<dag OOL, dag IOL>:
+ RRForm_1<0b00110111000, OOL, IOL,
+ "frest\t$rT, $rA", SPrecFP,
+ [/* no pattern */]>;
+
+def FRESTv4f32 :
+ FRESTInst<(outs VECREG:$rT), (ins VECREG:$rA)>;
+
+def FRESTf32 :
+ FRESTInst<(outs R32FP:$rT), (ins R32FP:$rA)>;
// Floating point interpolate (used in conjunction with reciprocal estimate)
def FIv4f32 :
RRForm<0b00101011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
"fi\t$rT, $rA, $rB", SPrecFP,
- [(set (v4f32 VECREG:$rT), (SPUinterpolate (v4f32 VECREG:$rA),
- (v4f32 VECREG:$rB)))]>;
+ [/* no pattern */]>;
def FIf32 :
RRForm<0b00101011110, (outs R32FP:$rT), (ins R32FP:$rA, R32FP:$rB),
"fi\t$rT, $rA, $rB", SPrecFP,
- [(set R32FP:$rT, (SPUinterpolate R32FP:$rA, R32FP:$rB))]>;
+ [/* no pattern */]>;
//--------------------------------------------------------------------------
// Basic single precision floating point comparisons:
// floating reciprocal absolute square root estimate (frsqest)
// The following are probably just intrinsics
-// status and control register write
+// status and control register write
// status and control register read
//--------------------------------------
// = c - a * b
// NOTE: subtraction order
// fsub a b = a - b
-// fs a b = b - a?
+// fs a b = b - a?
def FNMSf32 :
RRRForm<0b1101, (outs R32FP:$rT), (ins R32FP:$rA, R32FP:$rB, R32FP:$rC),
"fnms\t$rT, $rA, $rB, $rC", SPrecFP,
def FNMSv4f32 :
RRRForm<0b1101, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
"fnms\t$rT, $rA, $rB, $rC", SPrecFP,
- [(set (v4f32 VECREG:$rT),
- (fsub (v4f32 VECREG:$rC),
- (fmul (v4f32 VECREG:$rA),
+ [(set (v4f32 VECREG:$rT),
+ (fsub (v4f32 VECREG:$rC),
+ (fmul (v4f32 VECREG:$rA),
(v4f32 VECREG:$rB))))]>;
//--------------------------------------
"csflt\t$rT, $rA, 0", SPrecFP,
[(set (v4f32 VECREG:$rT), (sint_to_fp (v4i32 VECREG:$rA)))]>;
-// Convert signed integer to floating point
+// Convert signed integer to floating point
def CSiFf32 :
CVTIntFPForm<0b0101101110, (outs R32FP:$rT), (ins R32C:$rA),
"csflt\t$rT, $rA, 0", SPrecFP,
"cuflt\t$rT, $rA, 0", SPrecFP,
[(set R32FP:$rT, (uint_to_fp R32C:$rA))]>;
-// Convert float to unsigned int
+// Convert float to unsigned int
// Assume that scale = 0
def CFUiv4f32 :
"cfltu\t$rT, $rA, 0", SPrecFP,
[(set R32C:$rT, (fp_to_uint R32FP:$rA))]>;
-// Convert float to signed int
+// Convert float to signed int
// Assume that scale = 0
def CFSiv4f32 :
(fsub (fmul (v2f64 VECREG:$rA), (v2f64 VECREG:$rB)),
(v2f64 VECREG:$rC)))]>;
-// FNMS: - (a * b - c)
+// DFNMS: - (a * b - c)
// - (a * b) + c => c - (a * b)
-def FNMSf64 :
- RRForm<0b01111010110, (outs R64FP:$rT),
- (ins R64FP:$rA, R64FP:$rB, R64FP:$rC),
- "dfnms\t$rT, $rA, $rB", DPrecFP,
- [(set R64FP:$rT, (fsub R64FP:$rC, (fmul R64FP:$rA, R64FP:$rB)))]>,
+
+class DFNMSInst<dag OOL, dag IOL, list<dag> pattern>:
+ RRForm<0b01111010110, OOL, IOL, "dfnms\t$rT, $rA, $rB",
+ DPrecFP, pattern>,
RegConstraint<"$rC = $rT">,
NoEncode<"$rC">;
-def : Pat<(fneg (fsub (fmul R64FP:$rA, R64FP:$rB), R64FP:$rC)),
- (FNMSf64 R64FP:$rA, R64FP:$rB, R64FP:$rC)>;
+class DFNMSVecInst<list<dag> pattern>:
+ DFNMSInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ pattern>;
-def FNMSv2f64 :
- RRForm<0b01111010110, (outs VECREG:$rT),
- (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
- "dfnms\t$rT, $rA, $rB", DPrecFP,
- [(set (v2f64 VECREG:$rT),
- (fsub (v2f64 VECREG:$rC),
- (fmul (v2f64 VECREG:$rA),
- (v2f64 VECREG:$rB))))]>,
- RegConstraint<"$rC = $rT">,
- NoEncode<"$rC">;
+class DFNMSRegInst<list<dag> pattern>:
+ DFNMSInst<(outs R64FP:$rT), (ins R64FP:$rA, R64FP:$rB, R64FP:$rC),
+ pattern>;
+
+multiclass DFMultiplySubtract
+{
+ def v2f64 : DFNMSVecInst<[(set (v2f64 VECREG:$rT),
+ (fsub (v2f64 VECREG:$rC),
+ (fmul (v2f64 VECREG:$rA),
+ (v2f64 VECREG:$rB))))]>;
+
+ def f64 : DFNMSRegInst<[(set R64FP:$rT,
+ (fsub R64FP:$rC,
+ (fmul R64FP:$rA, R64FP:$rB)))]>;
+}
-def : Pat<(fneg (fsub (fmul (v2f64 VECREG:$rA), (v2f64 VECREG:$rB)),
- (v2f64 VECREG:$rC))),
- (FNMSv2f64 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+defm DFNMS : DFMultiplySubtract;
// - (a * b + c)
// - (a * b) - c
RRForm<0b11111010110, (outs VECREG:$rT),
(ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
"dfnma\t$rT, $rA, $rB", DPrecFP,
- [(set (v2f64 VECREG:$rT),
- (fneg (fadd (v2f64 VECREG:$rC),
- (fmul (v2f64 VECREG:$rA),
+ [(set (v2f64 VECREG:$rT),
+ (fneg (fadd (v2f64 VECREG:$rC),
+ (fmul (v2f64 VECREG:$rA),
(v2f64 VECREG:$rB)))))]>,
RegConstraint<"$rC = $rT">,
NoEncode<"$rC">;
//===----------------------------------------------------------------------==//
def : Pat<(fneg (v4f32 VECREG:$rA)),
- (XORfnegvec (v4f32 VECREG:$rA),
+ (XORfnegvec (v4f32 VECREG:$rA),
(v4f32 (ILHUv4i32 0x8000)))>;
def : Pat<(fneg R32FP:$rA),
(XORfneg32 R32FP:$rA, (ILHUr32 0x8000))>;
-def : Pat<(fneg (v2f64 VECREG:$rA)),
- (XORfnegvec (v2f64 VECREG:$rA),
- (v2f64 (ANDBIv16i8 (FSMBIv16i8 0x8080), 0x80)))>;
-
-def : Pat<(fneg R64FP:$rA),
- (XORfneg64 R64FP:$rA,
- (ANDBIv16i8 (FSMBIv16i8 0x8080), 0x80))>;
-
// Floating point absolute value
+// Note: f64 fabs is custom-selected.
def : Pat<(fabs R32FP:$rA),
(ANDfabs32 R32FP:$rA, (IOHLr32 (ILHUr32 0x7fff), 0xffff))>;
def : Pat<(fabs (v4f32 VECREG:$rA)),
(ANDfabsvec (v4f32 VECREG:$rA),
- (v4f32 (ANDBIv16i8 (FSMBIv16i8 0xffff), 0x7f)))>;
+ (IOHLv4i32 (ILHUv4i32 0x7fff), 0xffff))>;
-def : Pat<(fabs R64FP:$rA),
- (ANDfabs64 R64FP:$rA, (ANDBIv16i8 (FSMBIv16i8 0xffff), 0x7f))>;
+//===----------------------------------------------------------------------===//
+// Hint for branch instructions:
+//===----------------------------------------------------------------------===//
-def : Pat<(fabs (v2f64 VECREG:$rA)),
- (ANDfabsvec (v2f64 VECREG:$rA),
- (v2f64 (ANDBIv16i8 (FSMBIv16i8 0xffff), 0x7f)))>;
+/* def HBR : SPUInstr<(outs), (ins), "hbr\t" */
//===----------------------------------------------------------------------===//
// Execution, Load NOP (execute NOPs belong in even pipeline, load NOPs belong
//===----------------------------------------------------------------------===//
// Bit conversions (type conversions between vector/packed types)
-// NOTE: Promotions are handled using the XS* instructions. Truncation
-// is not handled.
+// NOTE: Promotions are handled using the XS* instructions.
//===----------------------------------------------------------------------===//
def : Pat<(v16i8 (bitconvert (v8i16 VECREG:$src))), (v16i8 VECREG:$src)>;
def : Pat<(v16i8 (bitconvert (v4i32 VECREG:$src))), (v16i8 VECREG:$src)>;
def : Pat<(v2f64 (bitconvert (v2i64 VECREG:$src))), (v2f64 VECREG:$src)>;
def : Pat<(v2f64 (bitconvert (v2f64 VECREG:$src))), (v2f64 VECREG:$src)>;
-def : Pat<(f32 (bitconvert (i32 R32C:$src))), (f32 R32FP:$src)>;
-def : Pat<(f64 (bitconvert (i64 R64C:$src))), (f64 R64FP:$src)>;
+def : Pat<(i128 (bitconvert (v16i8 VECREG:$src))),
+ (ORi128_vec VECREG:$src)>;
+def : Pat<(i128 (bitconvert (v8i16 VECREG:$src))),
+ (ORi128_vec VECREG:$src)>;
+def : Pat<(i128 (bitconvert (v4i32 VECREG:$src))),
+ (ORi128_vec VECREG:$src)>;
+def : Pat<(i128 (bitconvert (v2i64 VECREG:$src))),
+ (ORi128_vec VECREG:$src)>;
+def : Pat<(i128 (bitconvert (v4f32 VECREG:$src))),
+ (ORi128_vec VECREG:$src)>;
+def : Pat<(i128 (bitconvert (v2f64 VECREG:$src))),
+ (ORi128_vec VECREG:$src)>;
+
+def : Pat<(v16i8 (bitconvert (i128 GPRC:$src))),
+ (v16i8 (ORvec_i128 GPRC:$src))>;
+def : Pat<(v8i16 (bitconvert (i128 GPRC:$src))),
+ (v8i16 (ORvec_i128 GPRC:$src))>;
+def : Pat<(v4i32 (bitconvert (i128 GPRC:$src))),
+ (v4i32 (ORvec_i128 GPRC:$src))>;
+def : Pat<(v2i64 (bitconvert (i128 GPRC:$src))),
+ (v2i64 (ORvec_i128 GPRC:$src))>;
+def : Pat<(v4f32 (bitconvert (i128 GPRC:$src))),
+ (v4f32 (ORvec_i128 GPRC:$src))>;
+def : Pat<(v2f64 (bitconvert (i128 GPRC:$src))),
+ (v2f64 (ORvec_i128 GPRC:$src))>;
//===----------------------------------------------------------------------===//
// Instruction patterns:
def : Pat<(v4i32 v4i32Imm:$imm),
(IOHLv4i32 (v4i32 (ILHUv4i32 (HI16_vec v4i32Imm:$imm))),
(LO16_vec v4i32Imm:$imm))>;
-
+
// 8-bit constants
def : Pat<(i8 imm:$imm),
(ILHr8 imm:$imm)>;
-//===----------------------------------------------------------------------===//
-// Call instruction patterns:
-//===----------------------------------------------------------------------===//
-// Return void
-def : Pat<(ret),
- (RET)>;
-
//===----------------------------------------------------------------------===//
// Zero/Any/Sign extensions
//===----------------------------------------------------------------------===//
-// zext 1->32: Zero extend i1 to i32
-def : Pat<(SPUextract_i1_zext R32C:$rSrc),
- (ANDIr32 R32C:$rSrc, 0x1)>;
-
// sext 8->32: Sign extend bytes to words
def : Pat<(sext_inreg R32C:$rSrc, i8),
(XSHWr32 (XSBHr32 R32C:$rSrc))>;
def : Pat<(i32 (sext R8C:$rSrc)),
(XSHWr16 (XSBHr8 R8C:$rSrc))>;
-def : Pat<(SPUextract_i8_sext VECREG:$rSrc),
- (XSHWr32 (XSBHr32 (ORi32_v4i32 (v4i32 VECREG:$rSrc),
- (v4i32 VECREG:$rSrc))))>;
+// sext 8->64: Sign extend bytes to double word
+def : Pat<(sext_inreg R64C:$rSrc, i8),
+ (XSWDr64_inreg (XSHWr64 (XSBHr64 R64C:$rSrc)))>;
+
+def : Pat<(i64 (sext R8C:$rSrc)),
+ (XSWDr64 (XSHWr16 (XSBHr8 R8C:$rSrc)))>;
// zext 8->16: Zero extend bytes to halfwords
def : Pat<(i16 (zext R8C:$rSrc)),
(ANDHIi8i16 R8C:$rSrc, 0xff)>;
-// zext 8->32 from preferred slot in load/store
-def : Pat<(SPUextract_i8_zext VECREG:$rSrc),
- (ANDIr32 (ORi32_v4i32 (v4i32 VECREG:$rSrc), (v4i32 VECREG:$rSrc)),
- 0xff)>;
-
// zext 8->32: Zero extend bytes to words
def : Pat<(i32 (zext R8C:$rSrc)),
(ANDIi8i32 R8C:$rSrc, 0xff)>;
-// anyext 8->16: Extend 8->16 bits, irrespective of sign
+// zext 8->64: Zero extend bytes to double words
+def : Pat<(i64 (zext R8C:$rSrc)),
+ (ORi64_v2i64 (SELBv4i32 (ROTQMBYv4i32
+ (ORv4i32_i32 (ANDIi8i32 R8C:$rSrc, 0xff)),
+ 0x4),
+ (ILv4i32 0x0),
+ (FSMBIv4i32 0x0f0f)))>;
+
+// anyext 8->16: Extend 8->16 bits, irrespective of sign, preserves high bits
def : Pat<(i16 (anyext R8C:$rSrc)),
(ORHIi8i16 R8C:$rSrc, 0)>;
-// anyext 8->32: Extend 8->32 bits, irrespective of sign
+// anyext 8->32: Extend 8->32 bits, irrespective of sign, preserves high bits
def : Pat<(i32 (anyext R8C:$rSrc)),
(ORIi8i32 R8C:$rSrc, 0)>;
+// sext 16->64: Sign extend halfword to double word
+def : Pat<(sext_inreg R64C:$rSrc, i16),
+ (XSWDr64_inreg (XSHWr64 R64C:$rSrc))>;
+
+def : Pat<(sext R16C:$rSrc),
+ (XSWDr64 (XSHWr16 R16C:$rSrc))>;
+
// zext 16->32: Zero extend halfwords to words
def : Pat<(i32 (zext R16C:$rSrc)),
(ANDi16i32 R16C:$rSrc, (ILAr32 0xffff))>;
def : Pat<(i32 (anyext R16C:$rSrc)),
(ORIi16i32 R16C:$rSrc, 0)>;
+//===----------------------------------------------------------------------===//
+// Truncates:
+// These truncates are for the SPU's supported types (i8, i16, i32). i64 and
+// above are custom lowered.
+//===----------------------------------------------------------------------===//
+
+def : Pat<(i8 (trunc GPRC:$src)),
+ (ORi8_v16i8
+ (SHUFBgprc GPRC:$src, GPRC:$src,
+ (IOHLv4i32 (ILHUv4i32 0x0f0f), 0x0f0f)))>;
+
+def : Pat<(i8 (trunc R64C:$src)),
+ (ORi8_v16i8
+ (SHUFBv2i64_m32
+ (ORv2i64_i64 R64C:$src),
+ (ORv2i64_i64 R64C:$src),
+ (IOHLv4i32 (ILHUv4i32 0x0707), 0x0707)))>;
+
+def : Pat<(i8 (trunc R32C:$src)),
+ (ORi8_v16i8
+ (SHUFBv4i32_m32
+ (ORv4i32_i32 R32C:$src),
+ (ORv4i32_i32 R32C:$src),
+ (IOHLv4i32 (ILHUv4i32 0x0303), 0x0303)))>;
+
+def : Pat<(i8 (trunc R16C:$src)),
+ (ORi8_v16i8
+ (SHUFBv4i32_m32
+ (ORv8i16_i16 R16C:$src),
+ (ORv8i16_i16 R16C:$src),
+ (IOHLv4i32 (ILHUv4i32 0x0303), 0x0303)))>;
+
+def : Pat<(i16 (trunc GPRC:$src)),
+ (ORi16_v8i16
+ (SHUFBgprc GPRC:$src, GPRC:$src,
+ (IOHLv4i32 (ILHUv4i32 0x0e0f), 0x0e0f)))>;
+
+def : Pat<(i16 (trunc R64C:$src)),
+ (ORi16_v8i16
+ (SHUFBv2i64_m32
+ (ORv2i64_i64 R64C:$src),
+ (ORv2i64_i64 R64C:$src),
+ (IOHLv4i32 (ILHUv4i32 0x0607), 0x0607)))>;
+
+def : Pat<(i16 (trunc R32C:$src)),
+ (ORi16_v8i16
+ (SHUFBv4i32_m32
+ (ORv4i32_i32 R32C:$src),
+ (ORv4i32_i32 R32C:$src),
+ (IOHLv4i32 (ILHUv4i32 0x0203), 0x0203)))>;
+
+def : Pat<(i32 (trunc GPRC:$src)),
+ (ORi32_v4i32
+ (SHUFBgprc GPRC:$src, GPRC:$src,
+ (IOHLv4i32 (ILHUv4i32 0x0c0d), 0x0e0f)))>;
+
+def : Pat<(i32 (trunc R64C:$src)),
+ (ORi32_v4i32
+ (SHUFBv2i64_m32
+ (ORv2i64_i64 R64C:$src),
+ (ORv2i64_i64 R64C:$src),
+ (IOHLv4i32 (ILHUv4i32 0x0405), 0x0607)))>;
+
//===----------------------------------------------------------------------===//
// Address generation: SPU, like PPC, has to split addresses into high and
// low parts in order to load them into a register.
(SPUlo tconstpool:$in, 0)),
(IOHLlo (ILHUhi tconstpool:$in), tconstpool:$in)>;
-def : Pat<(SPUindirect R32C:$sp, i32ImmSExt10:$imm),
- (AIr32 R32C:$sp, i32ImmSExt10:$imm)>;
-
-def : Pat<(SPUindirect R32C:$sp, imm:$imm),
- (Ar32 R32C:$sp,
- (IOHLr32 (ILHUr32 (HI16 imm:$imm)), (LO16 imm:$imm)))>;
-
def : Pat<(add (SPUhi tglobaladdr:$in, 0), (SPUlo tglobaladdr:$in, 0)),
(IOHLlo (ILHUhi tglobaladdr:$in), tglobaladdr:$in)>;
def : Pat<(add (SPUhi tconstpool:$in, 0), (SPUlo tconstpool:$in, 0)),
(IOHLlo (ILHUhi tconstpool:$in), tconstpool:$in)>;
-// Instrinsics:
+// Intrinsics:
include "CellSDKIntrinsics.td"
+// Various math operator instruction sequences
+include "SPUMathInstr.td"
+// 64-bit "instructions"/support
+include "SPU64InstrInfo.td"
+// 128-bit "instructions"/support
+include "SPU128InstrInfo.td"