[llvm-commits] [llvm] r44584 - in /llvm/trunk/lib/Target/CellSPU: SPUInstrInfo.cpp SPUInstrInfo.h SPUInstrInfo.td
Scott Michel
scottm at aero.org
Tue Dec 4 14:35:59 PST 2007
Author: pingbak
Date: Tue Dec 4 16:35:58 2007
New Revision: 44584
URL: http://llvm.org/viewvc/llvm-project?rev=44584&view=rev
Log:
More files in the CellSPU drop...
Added:
llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp
llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.h
llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td
Added: llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp?rev=44584&view=auto
==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp (added)
+++ llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp Tue Dec 4 16:35:58 2007
@@ -0,0 +1,184 @@
+//===- SPUInstrInfo.cpp - Cell SPU Instruction Information ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by a team from the Computer Systems Research
+// Department at The Aerospace Corporation.
+//
+// See README.txt for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the Cell SPU implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPURegisterNames.h"
+#include "SPUInstrInfo.h"
+#include "SPUTargetMachine.h"
+#include "SPUGenInstrInfo.inc"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include <iostream>
+
+using namespace llvm;
+
+SPUInstrInfo::SPUInstrInfo(SPUTargetMachine &tm)
+ : TargetInstrInfo(SPUInsts, sizeof(SPUInsts)/sizeof(SPUInsts[0])),
+ TM(tm),
+ RI(*TM.getSubtargetImpl(), *this)
+{
+ /* NOP */
+}
+
+/// getPointerRegClass - Return the register class to use to hold pointers.
+/// This is used for addressing modes.
+const TargetRegisterClass *
+SPUInstrInfo::getPointerRegClass() const
+{
+ return &SPU::R32CRegClass;
+}
+
+bool
+SPUInstrInfo::isMoveInstr(const MachineInstr& MI,
+ unsigned& sourceReg,
+ unsigned& destReg) const {
+ // Primarily, ORI and OR are generated by copyRegToReg. But, there are other
+ // cases where we can safely say that what's being done is really a move
+ // (see how PowerPC does this -- it's the model for this code too.)
+ switch (MI.getOpcode()) {
+ default:
+ break;
+ case SPU::ORIv4i32:
+ case SPU::ORIr32:
+ case SPU::ORIf64:
+ case SPU::ORIf32:
+ case SPU::ORIr64:
+ case SPU::ORHIv8i16:
+ case SPU::ORHIr16:
+ // case SPU::ORHI1To2:
+ case SPU::ORBIv16i8:
+ //case SPU::ORBIr8:
+ case SPU::ORI2To4:
+ // case SPU::ORI1To4:
+ case SPU::AHIvec:
+ case SPU::AHIr16:
+ case SPU::AIvec:
+ case SPU::AIr32:
+ assert(MI.getNumOperands() == 3 &&
+ MI.getOperand(0).isRegister() &&
+ MI.getOperand(1).isRegister() &&
+ MI.getOperand(2).isImmediate() &&
+ "invalid SPU ORI/ORHI/ORBI/AHI/AI/SFI/SFHI instruction!");
+ if (MI.getOperand(2).getImmedValue() == 0) {
+ sourceReg = MI.getOperand(1).getReg();
+ destReg = MI.getOperand(0).getReg();
+ return true;
+ }
+ break;
+#if 0
+ case SPU::ORIf64:
+ case SPU::ORIf32:
+ // Special case because there's no third immediate operand to the
+ // instruction (the constant is embedded in the instruction)
+ assert(MI.getOperand(0).isRegister() &&
+ MI.getOperand(1).isRegister() &&
+ "ORIf32/f64: operands not registers");
+ sourceReg = MI.getOperand(1).getReg();
+ destReg = MI.getOperand(0).getReg();
+ return true;
+#endif
+ // case SPU::ORv16i8_i8:
+ case SPU::ORv8i16_i16:
+ case SPU::ORv4i32_i32:
+ case SPU::ORv2i64_i64:
+ case SPU::ORv4f32_f32:
+ case SPU::ORv2f64_f64:
+ // case SPU::ORi8_v16i8:
+ case SPU::ORi16_v8i16:
+ case SPU::ORi32_v4i32:
+ case SPU::ORi64_v2i64:
+ case SPU::ORf32_v4f32:
+ case SPU::ORf64_v2f64:
+ case SPU::ORv16i8:
+ case SPU::ORv8i16:
+ case SPU::ORv4i32:
+ case SPU::ORr32:
+ case SPU::ORr64:
+ case SPU::ORgprc:
+ assert(MI.getNumOperands() == 3 &&
+ MI.getOperand(0).isRegister() &&
+ MI.getOperand(1).isRegister() &&
+ MI.getOperand(2).isRegister() &&
+ "invalid SPU OR(vec|r32|r64|gprc) instruction!");
+ if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
+ sourceReg = MI.getOperand(1).getReg();
+ destReg = MI.getOperand(0).getReg();
+ return true;
+ }
+ break;
+ }
+
+ return false;
+}
+
+unsigned
+SPUInstrInfo::isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const {
+ switch (MI->getOpcode()) {
+ default: break;
+ case SPU::LQDv16i8:
+ case SPU::LQDv8i16:
+ case SPU::LQDv4i32:
+ case SPU::LQDv4f32:
+ case SPU::LQDv2f64:
+ case SPU::LQDr128:
+ case SPU::LQDr64:
+ case SPU::LQDr32:
+ case SPU::LQDr16:
+ case SPU::LQXv4i32:
+ case SPU::LQXr128:
+ case SPU::LQXr64:
+ case SPU::LQXr32:
+ case SPU::LQXr16:
+ if (MI->getOperand(1).isImmediate() && !MI->getOperand(1).getImmedValue() &&
+ MI->getOperand(2).isFrameIndex()) {
+ FrameIndex = MI->getOperand(2).getFrameIndex();
+ return MI->getOperand(0).getReg();
+ }
+ break;
+ }
+ return 0;
+}
+
+unsigned
+SPUInstrInfo::isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const {
+ switch (MI->getOpcode()) {
+ default: break;
+ case SPU::STQDv16i8:
+ case SPU::STQDv8i16:
+ case SPU::STQDv4i32:
+ case SPU::STQDv4f32:
+ case SPU::STQDv2f64:
+ case SPU::STQDr128:
+ case SPU::STQDr64:
+ case SPU::STQDr32:
+ case SPU::STQDr16:
+ // case SPU::STQDr8:
+ case SPU::STQXv16i8:
+ case SPU::STQXv8i16:
+ case SPU::STQXv4i32:
+ case SPU::STQXv4f32:
+ case SPU::STQXv2f64:
+ case SPU::STQXr128:
+ case SPU::STQXr64:
+ case SPU::STQXr32:
+ case SPU::STQXr16:
+ // case SPU::STQXr8:
+ if (MI->getOperand(1).isImmediate() && !MI->getOperand(1).getImmedValue() &&
+ MI->getOperand(2).isFrameIndex()) {
+ FrameIndex = MI->getOperand(2).getFrameIndex();
+ return MI->getOperand(0).getReg();
+ }
+ break;
+ }
+ return 0;
+}
Added: llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.h?rev=44584&view=auto
==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.h (added)
+++ llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.h Tue Dec 4 16:35:58 2007
@@ -0,0 +1,54 @@
+//===- SPUInstrInfo.h - Cell SPU Instruction Information --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by a team from the Computer Systems Research
+// Department at The Aerospace Corporation.
+//
+// See README.txt for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the PowerPC implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SPU_INSTRUCTIONINFO_H
+#define SPU_INSTRUCTIONINFO_H
+
+#include "SPU.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "SPURegisterInfo.h"
+
+namespace llvm {
+ //! Cell SPU instruction information class
+ class SPUInstrInfo : public TargetInstrInfo
+ {
+ SPUTargetMachine &TM;
+ const SPURegisterInfo RI;
+ public:
+ SPUInstrInfo(SPUTargetMachine &tm);
+
+ /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
+ /// such, whenever a client has an instance of instruction info, it should
+ /// always be able to get register info as well (through this method).
+ ///
+ virtual const MRegisterInfo &getRegisterInfo() const { return RI; }
+
+ /// getPointerRegClass - Return the register class to use to hold pointers.
+ /// This is used for addressing modes.
+ virtual const TargetRegisterClass *getPointerRegClass() const;
+
+ // Return true if the instruction is a register to register move and
+ // leave the source and dest operands in the passed parameters.
+ //
+ virtual bool isMoveInstr(const MachineInstr& MI,
+ unsigned& sourceReg,
+ unsigned& destReg) const;
+
+ unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const;
+ unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const;
+ };
+}
+
+#endif
Added: llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td?rev=44584&view=auto
==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td (added)
+++ llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td Tue Dec 4 16:35:58 2007
@@ -0,0 +1,3145 @@
+//==- SPUInstrInfo.td - Describe the Cell SPU Instructions -*- tablegen -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by The Aerospace Corporation.
+//
+//===----------------------------------------------------------------------===//
+// Cell SPU Instructions:
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// TODO Items (not urgent today, but would be nice, low priority)
+//
+// ANDBI, ORBI: SPU constructs a 4-byte constant for these instructions by
+// concatenating the byte argument b as "bbbb". Could recognize this bit pattern
+// in 16-bit and 32-bit constants and reduce instruction count.
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Pseudo instructions:
+//===----------------------------------------------------------------------===//
+
+let hasCtrlDep = 1, Defs = [R1], Uses = [R1] in {
+ def ADJCALLSTACKDOWN : Pseudo<(outs), (ins u16imm:$amt),
+ "${:comment} ADJCALLSTACKDOWN",
+ [(callseq_start imm:$amt)]>;
+ def ADJCALLSTACKUP : Pseudo<(outs), (ins u16imm:$amt),
+ "${:comment} ADJCALLSTACKUP",
+ [(callseq_end imm:$amt)]>;
+}
+
+//===----------------------------------------------------------------------===//
+// 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))]>;
+
+//===----------------------------------------------------------------------===//
+// Loads:
+// NB: The ordering is actually important, since the instruction selection
+// will try each of the instructions in sequence, i.e., the D-form first with
+// the 10-bit displacement, then the A-form with the 16 bit displacement, and
+// finally the X-form with the register-register.
+//===----------------------------------------------------------------------===//
+
+let isLoad = 1 in {
+ def LQDv16i8:
+ RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
+ "lqd\t$rT, $src", LoadStore,
+ [(set (v16i8 VECREG:$rT), (load dform_addr:$src))]>;
+
+ def LQDv8i16:
+ RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
+ "lqd\t$rT, $src", LoadStore,
+ [(set (v8i16 VECREG:$rT), (load dform_addr:$src))]>;
+
+ def LQDv4i32:
+ RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
+ "lqd\t$rT, $src", LoadStore,
+ [(set (v4i32 VECREG:$rT), (load dform_addr:$src))]>;
+
+ def LQDv2i64:
+ RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
+ "lqd\t$rT, $src", LoadStore,
+ [(set (v2i64 VECREG:$rT), (load dform_addr:$src))]>;
+
+ def LQDv4f32:
+ RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
+ "lqd\t$rT, $src", LoadStore,
+ [(set (v4f32 VECREG:$rT), (load dform_addr:$src))]>;
+
+ def LQDv2f64:
+ RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
+ "lqd\t$rT, $src", LoadStore,
+ [(set (v2f64 VECREG:$rT), (load dform_addr:$src))]>;
+
+ def LQDr128:
+ RI10Form<0b00101100, (outs GPRC:$rT), (ins memri10:$src),
+ "lqd\t$rT, $src", LoadStore,
+ [(set GPRC:$rT, (load dform_addr:$src))]>;
+
+ def LQDr64:
+ RI10Form<0b00101100, (outs R64C:$rT), (ins memri10:$src),
+ "lqd\t$rT, $src", LoadStore,
+ [(set R64C:$rT, (load dform_addr:$src))]>;
+
+ def LQDr32:
+ RI10Form<0b00101100, (outs R32C:$rT), (ins memri10:$src),
+ "lqd\t$rT, $src", LoadStore,
+ [(set R32C:$rT, (load dform_addr:$src))]>;
+
+ // Floating Point
+ def LQDf32:
+ RI10Form<0b00101100, (outs R32FP:$rT), (ins memri10:$src),
+ "lqd\t$rT, $src", LoadStore,
+ [(set R32FP:$rT, (load dform_addr:$src))]>;
+
+ def LQDf64:
+ RI10Form<0b00101100, (outs R64FP:$rT), (ins memri10:$src),
+ "lqd\t$rT, $src", LoadStore,
+ [(set R64FP:$rT, (load dform_addr:$src))]>;
+ // END Floating Point
+
+ def LQDr16:
+ RI10Form<0b00101100, (outs R16C:$rT), (ins memri10:$src),
+ "lqd\t$rT, $src", LoadStore,
+ [(set R16C:$rT, (load dform_addr:$src))]>;
+
+ def LQAv16i8:
+ RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
+ "lqa\t$rT, $src", LoadStore,
+ [(set (v16i8 VECREG:$rT), (load aform_addr:$src))]>;
+
+ def LQAv8i16:
+ RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
+ "lqa\t$rT, $src", LoadStore,
+ [(set (v8i16 VECREG:$rT), (load aform_addr:$src))]>;
+
+ def LQAv4i32:
+ RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
+ "lqa\t$rT, $src", LoadStore,
+ [(set (v4i32 VECREG:$rT), (load aform_addr:$src))]>;
+
+ def LQAv2i64:
+ RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
+ "lqa\t$rT, $src", LoadStore,
+ [(set (v2i64 VECREG:$rT), (load aform_addr:$src))]>;
+
+ def LQAv4f32:
+ RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
+ "lqa\t$rT, $src", LoadStore,
+ [(set (v4f32 VECREG:$rT), (load aform_addr:$src))]>;
+
+ def LQAv2f64:
+ RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
+ "lqa\t$rT, $src", LoadStore,
+ [(set (v2f64 VECREG:$rT), (load aform_addr:$src))]>;
+
+ def LQAr128:
+ RI16Form<0b100001100, (outs GPRC:$rT), (ins addr256k:$src),
+ "lqa\t$rT, $src", LoadStore,
+ [(set GPRC:$rT, (load aform_addr:$src))]>;
+
+ def LQAr64:
+ RI16Form<0b100001100, (outs R64C:$rT), (ins addr256k:$src),
+ "lqa\t$rT, $src", LoadStore,
+ [(set R64C:$rT, (load aform_addr:$src))]>;
+
+ def LQAr32:
+ RI16Form<0b100001100, (outs R32C:$rT), (ins addr256k:$src),
+ "lqa\t$rT, $src", LoadStore,
+ [(set R32C:$rT, (load aform_addr:$src))]>;
+
+ def LQAf32:
+ RI16Form<0b100001100, (outs R32FP:$rT), (ins addr256k:$src),
+ "lqa\t$rT, $src", LoadStore,
+ [(set R32FP:$rT, (load aform_addr:$src))]>;
+
+ def LQAf64:
+ RI16Form<0b100001100, (outs R64FP:$rT), (ins addr256k:$src),
+ "lqa\t$rT, $src", LoadStore,
+ [(set R64FP:$rT, (load aform_addr:$src))]>;
+
+ def LQAr16:
+ RI16Form<0b100001100, (outs R16C:$rT), (ins addr256k:$src),
+ "lqa\t$rT, $src", LoadStore,
+ [(set R16C:$rT, (load aform_addr:$src))]>;
+
+ def LQXv16i8:
+ RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
+ "lqx\t$rT, $src", LoadStore,
+ [(set (v16i8 VECREG:$rT), (load xform_addr:$src))]>;
+
+ def LQXv8i16:
+ RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
+ "lqx\t$rT, $src", LoadStore,
+ [(set (v8i16 VECREG:$rT), (load xform_addr:$src))]>;
+
+ def LQXv4i32:
+ RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
+ "lqx\t$rT, $src", LoadStore,
+ [(set (v4i32 VECREG:$rT), (load xform_addr:$src))]>;
+
+ def LQXv2i64:
+ RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
+ "lqx\t$rT, $src", LoadStore,
+ [(set (v2i64 VECREG:$rT), (load xform_addr:$src))]>;
+
+ def LQXv4f32:
+ RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
+ "lqx\t$rT, $src", LoadStore,
+ [(set (v4f32 VECREG:$rT), (load xform_addr:$src))]>;
+
+ def LQXv2f64:
+ RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
+ "lqx\t$rT, $src", LoadStore,
+ [(set (v2f64 VECREG:$rT), (load xform_addr:$src))]>;
+
+ def LQXr128:
+ RRForm<0b00100011100, (outs GPRC:$rT), (ins memrr:$src),
+ "lqx\t$rT, $src", LoadStore,
+ [(set GPRC:$rT, (load xform_addr:$src))]>;
+
+ def LQXr64:
+ RRForm<0b00100011100, (outs R64C:$rT), (ins memrr:$src),
+ "lqx\t$rT, $src", LoadStore,
+ [(set R64C:$rT, (load xform_addr:$src))]>;
+
+ def LQXr32:
+ RRForm<0b00100011100, (outs R32C:$rT), (ins memrr:$src),
+ "lqx\t$rT, $src", LoadStore,
+ [(set R32C:$rT, (load xform_addr:$src))]>;
+
+ def LQXf32:
+ RRForm<0b00100011100, (outs R32FP:$rT), (ins memrr:$src),
+ "lqx\t$rT, $src", LoadStore,
+ [(set R32FP:$rT, (load xform_addr:$src))]>;
+
+ def LQXf64:
+ RRForm<0b00100011100, (outs R64FP:$rT), (ins memrr:$src),
+ "lqx\t$rT, $src", LoadStore,
+ [(set R64FP:$rT, (load xform_addr:$src))]>;
+
+ def LQXr16:
+ RRForm<0b00100011100, (outs R16C:$rT), (ins memrr:$src),
+ "lqx\t$rT, $src", LoadStore,
+ [(set R16C:$rT, (load xform_addr:$src))]>;
+
+/* Load quadword, PC relative: Not much use at this point in time.
+ Might be of use later for relocatable code.
+ def LQR : RI16Form<0b111001100, (outs VECREG:$rT), (ins s16imm:$disp),
+ "lqr\t$rT, $disp", LoadStore,
+ [(set VECREG:$rT, (load iaddr:$disp))]>;
+ */
+
+ // Catch-all for unaligned loads:
+}
+
+//===----------------------------------------------------------------------===//
+// Stores:
+//===----------------------------------------------------------------------===//
+
+let isStore = 1 in {
+ def STQDv16i8 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
+ "stqd\t$rT, $src", LoadStore,
+ [(store (v16i8 VECREG:$rT), dform_addr:$src)]>;
+
+ def STQDv8i16 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
+ "stqd\t$rT, $src", LoadStore,
+ [(store (v8i16 VECREG:$rT), dform_addr:$src)]>;
+
+ def STQDv4i32 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
+ "stqd\t$rT, $src", LoadStore,
+ [(store (v4i32 VECREG:$rT), dform_addr:$src)]>;
+
+ def STQDv2i64 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
+ "stqd\t$rT, $src", LoadStore,
+ [(store (v2i64 VECREG:$rT), dform_addr:$src)]>;
+
+ def STQDv4f32 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
+ "stqd\t$rT, $src", LoadStore,
+ [(store (v4f32 VECREG:$rT), dform_addr:$src)]>;
+
+ def STQDv2f64 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
+ "stqd\t$rT, $src", LoadStore,
+ [(store (v2f64 VECREG:$rT), dform_addr:$src)]>;
+
+ def STQDr128 : RI10Form<0b00100100, (outs), (ins GPRC:$rT, memri10:$src),
+ "stqd\t$rT, $src", LoadStore,
+ [(store GPRC:$rT, dform_addr:$src)]>;
+
+ def STQDr64 : RI10Form<0b00100100, (outs), (ins R64C:$rT, memri10:$src),
+ "stqd\t$rT, $src", LoadStore,
+ [(store R64C:$rT, dform_addr:$src)]>;
+
+ def STQDr32 : RI10Form<0b00100100, (outs), (ins R32C:$rT, memri10:$src),
+ "stqd\t$rT, $src", LoadStore,
+ [(store R32C:$rT, dform_addr:$src)]>;
+
+ // Floating Point
+ def STQDf32 : RI10Form<0b00100100, (outs), (ins R32FP:$rT, memri10:$src),
+ "stqd\t$rT, $src", LoadStore,
+ [(store R32FP:$rT, dform_addr:$src)]>;
+
+ def STQDf64 : RI10Form<0b00100100, (outs), (ins R64FP:$rT, memri10:$src),
+ "stqd\t$rT, $src", LoadStore,
+ [(store R64FP:$rT, dform_addr:$src)]>;
+
+ def STQDr16 : RI10Form<0b00100100, (outs), (ins R16C:$rT, memri10:$src),
+ "stqd\t$rT, $src", LoadStore,
+ [(store R16C:$rT, dform_addr:$src)]>;
+
+ def STQAv16i8 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, addr256k:$src),
+ "stqa\t$rT, $src", LoadStore,
+ [(store (v16i8 VECREG:$rT), aform_addr:$src)]>;
+
+ def STQAv8i16 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, addr256k:$src),
+ "stqa\t$rT, $src", LoadStore,
+ [(store (v8i16 VECREG:$rT), aform_addr:$src)]>;
+
+ def STQAv4i32 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, addr256k:$src),
+ "stqa\t$rT, $src", LoadStore,
+ [(store (v4i32 VECREG:$rT), aform_addr:$src)]>;
+
+ def STQAv2i64 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, addr256k:$src),
+ "stqa\t$rT, $src", LoadStore,
+ [(store (v2i64 VECREG:$rT), aform_addr:$src)]>;
+
+ def STQAv4f32 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, addr256k:$src),
+ "stqa\t$rT, $src", LoadStore,
+ [(store (v4f32 VECREG:$rT), aform_addr:$src)]>;
+
+ def STQAv2f64 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, addr256k:$src),
+ "stqa\t$rT, $src", LoadStore,
+ [(store (v2f64 VECREG:$rT), aform_addr:$src)]>;
+
+ def STQAr128 : RI10Form<0b00100100, (outs), (ins GPRC:$rT, addr256k:$src),
+ "stqa\t$rT, $src", LoadStore,
+ [(store GPRC:$rT, aform_addr:$src)]>;
+
+ def STQAr64 : RI10Form<0b00100100, (outs), (ins R64C:$rT, addr256k:$src),
+ "stqa\t$rT, $src", LoadStore,
+ [(store R64C:$rT, aform_addr:$src)]>;
+
+ def STQAr32 : RI10Form<0b00100100, (outs), (ins R32C:$rT, addr256k:$src),
+ "stqa\t$rT, $src", LoadStore,
+ [(store R32C:$rT, aform_addr:$src)]>;
+
+ // Floating Point
+ def STQAf32 : RI10Form<0b00100100, (outs), (ins R32FP:$rT, addr256k:$src),
+ "stqa\t$rT, $src", LoadStore,
+ [(store R32FP:$rT, aform_addr:$src)]>;
+
+ def STQAf64 : RI10Form<0b00100100, (outs), (ins R64FP:$rT, addr256k:$src),
+ "stqa\t$rT, $src", LoadStore,
+ [(store R64FP:$rT, aform_addr:$src)]>;
+
+ def STQXv16i8 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
+ "stqx\t$rT, $src", LoadStore,
+ [(store (v16i8 VECREG:$rT), xform_addr:$src)]>;
+
+ def STQXv8i16 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
+ "stqx\t$rT, $src", LoadStore,
+ [(store (v8i16 VECREG:$rT), xform_addr:$src)]>;
+
+ def STQXv4i32 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
+ "stqx\t$rT, $src", LoadStore,
+ [(store (v4i32 VECREG:$rT), xform_addr:$src)]>;
+
+ def STQXv2i64 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
+ "stqx\t$rT, $src", LoadStore,
+ [(store (v2i64 VECREG:$rT), xform_addr:$src)]>;
+
+ def STQXv4f32 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
+ "stqx\t$rT, $src", LoadStore,
+ [(store (v4f32 VECREG:$rT), xform_addr:$src)]>;
+
+ def STQXv2f64 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
+ "stqx\t$rT, $src", LoadStore,
+ [(store (v2f64 VECREG:$rT), xform_addr:$src)]>;
+
+ def STQXr128 : RI10Form<0b00100100, (outs), (ins GPRC:$rT, memrr:$src),
+ "stqx\t$rT, $src", LoadStore,
+ [(store GPRC:$rT, xform_addr:$src)]>;
+
+ def STQXr64 : RI10Form<0b00100100, (outs), (ins R64C:$rT, memrr:$src),
+ "stqx\t$rT, $src", LoadStore,
+ [(store R64C:$rT, xform_addr:$src)]>;
+
+ def STQXr32 : RI10Form<0b00100100, (outs), (ins R32C:$rT, memrr:$src),
+ "stqx\t$rT, $src", LoadStore,
+ [(store R32C:$rT, xform_addr:$src)]>;
+
+ // Floating Point
+ def STQXf32 : RI10Form<0b00100100, (outs), (ins R32FP:$rT, memrr:$src),
+ "stqx\t$rT, $src", LoadStore,
+ [(store R32FP:$rT, xform_addr:$src)]>;
+
+ def STQXf64 : RI10Form<0b00100100, (outs), (ins R64FP:$rT, memrr:$src),
+ "stqx\t$rT, $src", LoadStore,
+ [(store R64FP:$rT, xform_addr:$src)]>;
+
+ def STQXr16 : RI10Form<0b00100100, (outs), (ins R16C:$rT, memrr:$src),
+ "stqx\t$rT, $src", LoadStore,
+ [(store R16C:$rT, xform_addr:$src)]>;
+
+/* Store quadword, PC relative: Not much use at this point in time. Might
+ be useful for relocatable code.
+ def STQR : RI16Form<0b111000100, (outs), (ins VECREG:$rT, s16imm:$disp),
+ "stqr\t$rT, $disp", LoadStore,
+ [(store VECREG:$rT, iaddr:$disp)]>;
+ */
+}
+
+//===----------------------------------------------------------------------===//
+// Generate Controls for Insertion:
+//===----------------------------------------------------------------------===//
+
+def CBD :
+ RI7Form<0b10101111100, (outs VECREG:$rT), (ins memri7:$src),
+ "cbd\t$rT, $src", ShuffleOp,
+ [(set (v16i8 VECREG:$rT), (SPUvecinsmask dform2_addr:$src))]>;
+
+def CBX : RRForm<0b00101011100, (outs VECREG:$rT), (ins memrr:$src),
+ "cbx\t$rT, $src", ShuffleOp,
+ [(set (v16i8 VECREG:$rT), (SPUvecinsmask xform_addr:$src))]>;
+
+def CHD : RI7Form<0b10101111100, (outs VECREG:$rT), (ins memri7:$src),
+ "chd\t$rT, $src", ShuffleOp,
+ [(set (v8i16 VECREG:$rT), (SPUvecinsmask dform2_addr:$src))]>;
+
+def CHX : RRForm<0b10101011100, (outs VECREG:$rT), (ins memrr:$src),
+ "chx\t$rT, $src", ShuffleOp,
+ [(set (v8i16 VECREG:$rT), (SPUvecinsmask xform_addr:$src))]>;
+
+def CWD : RI7Form<0b01101111100, (outs VECREG:$rT), (ins memri7:$src),
+ "cwd\t$rT, $src", ShuffleOp,
+ [(set (v4i32 VECREG:$rT), (SPUvecinsmask dform2_addr:$src))]>;
+
+def CWX : RRForm<0b01101011100, (outs VECREG:$rT), (ins memrr:$src),
+ "cwx\t$rT, $src", ShuffleOp,
+ [(set (v4i32 VECREG:$rT), (SPUvecinsmask xform_addr:$src))]>;
+
+def CDD : RI7Form<0b11101111100, (outs VECREG:$rT), (ins memri7:$src),
+ "cdd\t$rT, $src", ShuffleOp,
+ [(set (v2i64 VECREG:$rT), (SPUvecinsmask dform2_addr:$src))]>;
+
+def CDX : RRForm<0b11101011100, (outs VECREG:$rT), (ins memrr:$src),
+ "cdx\t$rT, $src", ShuffleOp,
+ [(set (v2i64 VECREG:$rT), (SPUvecinsmask xform_addr:$src))]>;
+
+//===----------------------------------------------------------------------===//
+// Constant formation:
+//===----------------------------------------------------------------------===//
+
+def ILHv8i16:
+ RI16Form<0b110000010, (outs VECREG:$rT), (ins s16imm:$val),
+ "ilh\t$rT, $val", ImmLoad,
+ [(set (v8i16 VECREG:$rT), (v8i16 v8i16SExt16Imm:$val))]>;
+
+def ILHr16:
+ RI16Form<0b110000010, (outs R16C:$rT), (ins s16imm:$val),
+ "ilh\t$rT, $val", ImmLoad,
+ [(set R16C:$rT, immSExt16:$val)]>;
+
+// IL does sign extension!
+def ILr64:
+ RI16Form<0b100000010, (outs R64C:$rT), (ins s16imm_i64:$val),
+ "il\t$rT, $val", ImmLoad,
+ [(set R64C:$rT, immSExt16:$val)]>;
+
+def ILv2i64:
+ RI16Form<0b100000010, (outs VECREG:$rT), (ins s16imm_i64:$val),
+ "il\t$rT, $val", ImmLoad,
+ [(set VECREG:$rT, (v2i64 v2i64SExt16Imm:$val))]>;
+
+def ILv4i32:
+ RI16Form<0b100000010, (outs VECREG:$rT), (ins s16imm:$val),
+ "il\t$rT, $val", ImmLoad,
+ [(set VECREG:$rT, (v4i32 v4i32SExt16Imm:$val))]>;
+
+def ILr32:
+ RI16Form<0b100000010, (outs R32C:$rT), (ins s16imm_i32:$val),
+ "il\t$rT, $val", ImmLoad,
+ [(set R32C:$rT, immSExt16:$val)]>;
+
+def ILf32:
+ RI16Form<0b100000010, (outs R32FP:$rT), (ins s16imm_f32:$val),
+ "il\t$rT, $val", ImmLoad,
+ [(set R32FP:$rT, (SPUFPconstant fpimmSExt16:$val))]>;
+
+def ILf64:
+ RI16Form<0b100000010, (outs R64FP:$rT), (ins s16imm_f64:$val),
+ "il\t$rT, $val", ImmLoad,
+ [(set R64FP:$rT, (SPUFPconstant fpimmSExt16:$val))]>;
+
+def ILHUv4i32:
+ RI16Form<0b010000010, (outs VECREG:$rT), (ins u16imm:$val),
+ "ilhu\t$rT, $val", ImmLoad,
+ [(set VECREG:$rT, (v4i32 immILHUvec:$val))]>;
+
+def ILHUr32:
+ RI16Form<0b010000010, (outs R32C:$rT), (ins u16imm:$val),
+ "ilhu\t$rT, $val", ImmLoad,
+ [(set R32C:$rT, hi16:$val)]>;
+
+// ILHUf32: Used to custom lower float constant loads
+def ILHUf32:
+ RI16Form<0b010000010, (outs R32FP:$rT), (ins f16imm:$val),
+ "ilhu\t$rT, $val", ImmLoad,
+ [(set R32FP:$rT, (SPUFPconstant hi16_f32:$val))]>;
+
+// ILHUhi: Used for loading high portion of an address. Note the symbolHi
+// printer used for the operand.
+def ILHUhi : RI16Form<0b010000010, (outs R32C:$rT), (ins symbolHi:$val),
+ "ilhu\t$rT, $val", ImmLoad,
+ [(set R32C:$rT, hi16:$val)]>;
+
+// Immediate load address (can also be used to load 18-bit unsigned constants,
+// see the zext 16->32 pattern)
+def ILAr64:
+ RI18Form<0b1000010, (outs R64C:$rT), (ins u18imm_i64:$val),
+ "ila\t$rT, $val", LoadNOP,
+ [(set R64C:$rT, imm18:$val)]>;
+
+// TODO: ILAv2i64
+
+def ILAv2i64:
+ RI18Form<0b1000010, (outs VECREG:$rT), (ins u18imm:$val),
+ "ila\t$rT, $val", LoadNOP,
+ [(set (v2i64 VECREG:$rT), v2i64Uns18Imm:$val)]>;
+
+def ILAv4i32:
+ RI18Form<0b1000010, (outs VECREG:$rT), (ins u18imm:$val),
+ "ila\t$rT, $val", LoadNOP,
+ [(set (v4i32 VECREG:$rT), v4i32Uns18Imm:$val)]>;
+
+def ILAr32:
+ RI18Form<0b1000010, (outs R32C:$rT), (ins u18imm:$val),
+ "ila\t$rT, $val", LoadNOP,
+ [(set R32C:$rT, imm18:$val)]>;
+
+def ILAf32:
+ RI18Form<0b1000010, (outs R32FP:$rT), (ins f18imm:$val),
+ "ila\t$rT, $val", LoadNOP,
+ [(set R32FP:$rT, (SPUFPconstant fpimm18:$val))]>;
+
+def ILAf64:
+ RI18Form<0b1000010, (outs R64FP:$rT), (ins f18imm_f64:$val),
+ "ila\t$rT, $val", LoadNOP,
+ [(set R64FP:$rT, (SPUFPconstant fpimm18:$val))]>;
+
+def ILAlo:
+ RI18Form<0b1000010, (outs R32C:$rT), (ins symbolLo:$val),
+ "ila\t$rT, $val", ImmLoad,
+ [(set R32C:$rT, imm18:$val)]>;
+
+def ILAlsa:
+ RI18Form<0b1000010, (outs R32C:$rT), (ins symbolLSA:$val),
+ "ila\t$rT, $val", ImmLoad,
+ [/* no pattern */]>;
+
+// Immediate OR, Halfword Lower: The "other" part of loading large constants
+// into 32-bit registers. See the anonymous pattern Pat<(i32 imm:$imm), ...>
+// Note that these are really two operand instructions, but they're encoded
+// as three operands with the first two arguments tied-to each other.
+
+def IOHLvec:
+ RI16Form<0b100000110, (outs VECREG:$rT), (ins VECREG:$rS, u16imm:$val),
+ "iohl\t$rT, $val", ImmLoad,
+ [/* insert intrinsic here */]>,
+ RegConstraint<"$rS = $rT">,
+ NoEncode<"$rS">;
+
+def IOHLr32:
+ RI16Form<0b100000110, (outs R32C:$rT), (ins R32C:$rS, i32imm:$val),
+ "iohl\t$rT, $val", ImmLoad,
+ [/* insert intrinsic here */]>,
+ RegConstraint<"$rS = $rT">,
+ NoEncode<"$rS">;
+
+def IOHLf32:
+ RI16Form<0b100000110, (outs R32FP:$rT), (ins R32FP:$rS, f32imm:$val),
+ "iohl\t$rT, $val", ImmLoad,
+ [/* insert intrinsic here */]>,
+ RegConstraint<"$rS = $rT">,
+ NoEncode<"$rS">;
+
+// Form select mask for bytes using immediate, used in conjunction with the
+// SELB instruction:
+
+def FSMBIv16i8 : RI16Form<0b101001100, (outs VECREG:$rT), (ins u16imm:$val),
+ "fsmbi\t$rT, $val", SelectOp,
+ [(set (v16i8 VECREG:$rT), (SPUfsmbi_v16i8 immU16:$val))]>;
+
+def FSMBIv8i16 : RI16Form<0b101001100, (outs VECREG:$rT), (ins u16imm:$val),
+ "fsmbi\t$rT, $val", SelectOp,
+ [(set (v8i16 VECREG:$rT), (SPUfsmbi_v8i16 immU16:$val))]>;
+
+def FSMBIvecv4i32 : RI16Form<0b101001100, (outs VECREG:$rT), (ins u16imm:$val),
+ "fsmbi\t$rT, $val", SelectOp,
+ [(set (v4i32 VECREG:$rT), (SPUfsmbi_v4i32 immU16:$val))]>;
+
+//===----------------------------------------------------------------------===//
+// Integer and Logical Operations:
+//===----------------------------------------------------------------------===//
+
+def AHv8i16:
+ RRForm<0b00010011000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "ah\t$rT, $rA, $rB", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (int_spu_si_ah VECREG:$rA, VECREG:$rB))]>;
+
+def : Pat<(add (v8i16 VECREG:$rA), (v8i16 VECREG:$rB)),
+ (AHv8i16 VECREG:$rA, VECREG:$rB)>;
+
+// [(set (v8i16 VECREG:$rT), (add (v8i16 VECREG:$rA), (v8i16 VECREG:$rB)))]>;
+
+def AHr16:
+ RRForm<0b00010011000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
+ "ah\t$rT, $rA, $rB", IntegerOp,
+ [(set R16C:$rT, (add R16C:$rA, R16C:$rB))]>;
+
+def AHIvec:
+ RI10Form<0b10111000, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ "ahi\t$rT, $rA, $val", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (add (v8i16 VECREG:$rA),
+ v8i16SExt10Imm:$val))]>;
+
+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))]>;
+
+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)))]>;
+
+def : Pat<(add (v16i8 VECREG:$rA), (v16i8 VECREG:$rB)),
+ (Avec VECREG:$rA, VECREG:$rB)>;
+
+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))]>;
+
+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))]>;
+
+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 SFHvec : RRForm<0b00010010000, (outs VECREG:$rT),
+ (ins VECREG:$rA, VECREG:$rB),
+ "sfh\t$rT, $rA, $rB", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (sub (v8i16 VECREG:$rA), (v8i16 VECREG:$rB)))]>;
+
+def SFHr16 : RRForm<0b00010010000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
+ "sfh\t$rT, $rA, $rB", IntegerOp,
+ [(set R16C:$rT, (sub R16C:$rA, R16C:$rB))]>;
+
+def SFHIvec:
+ RI10Form<0b10110000, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ "sfhi\t$rT, $rA, $val", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (sub v8i16SExt10Imm:$val,
+ (v8i16 VECREG:$rA)))]>;
+
+def SFHIr16 : RI10Form<0b10110000, (outs R16C:$rT), (ins R16C:$rA, s10imm:$val),
+ "sfhi\t$rT, $rA, $val", IntegerOp,
+ [(set R16C:$rT, (sub i16ImmSExt10:$val, R16C:$rA))]>;
+
+def SFvec : RRForm<0b00000010000, (outs VECREG:$rT),
+ (ins VECREG:$rA, VECREG:$rB),
+ "sf\t$rT, $rA, $rB", IntegerOp,
+ [(set (v4i32 VECREG:$rT), (sub (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)))]>;
+
+def SFr32 : RRForm<0b00000010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "sf\t$rT, $rA, $rB", IntegerOp,
+ [(set R32C:$rT, (sub R32C:$rA, R32C:$rB))]>;
+
+def SFIvec:
+ RI10Form<0b00110000, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ "sfi\t$rT, $rA, $val", IntegerOp,
+ [(set (v4i32 VECREG:$rT), (sub v4i32SExt10Imm:$val,
+ (v4i32 VECREG:$rA)))]>;
+
+def SFIr32 : RI10Form<0b00110000, (outs R32C:$rT),
+ (ins R32C:$rA, s10imm_i32:$val),
+ "sfi\t$rT, $rA, $val", IntegerOp,
+ [(set R32C:$rT, (sub i32ImmSExt10:$val, R32C:$rA))]>;
+
+// ADDX: only available in vector form, doesn't match a pattern.
+def ADDXvec:
+ RRForm<0b00000010110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB,
+ VECREG:$rCarry),
+ "addx\t$rT, $rA, $rB", IntegerOp,
+ []>,
+ RegConstraint<"$rCarry = $rT">,
+ NoEncode<"$rCarry">;
+
+// CG: only available in vector form, doesn't match a pattern.
+def CGvec:
+ RRForm<0b01000011000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB,
+ VECREG:$rCarry),
+ "cg\t$rT, $rA, $rB", IntegerOp,
+ []>,
+ RegConstraint<"$rCarry = $rT">,
+ NoEncode<"$rCarry">;
+
+// SFX: only available in vector form, doesn't match a pattern
+def SFXvec:
+ RRForm<0b10000010110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB,
+ VECREG:$rCarry),
+ "sfx\t$rT, $rA, $rB", IntegerOp,
+ []>,
+ RegConstraint<"$rCarry = $rT">,
+ NoEncode<"$rCarry">;
+
+// BG: only available in vector form, doesn't match a pattern.
+def BGvec:
+ RRForm<0b01000010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB,
+ VECREG:$rCarry),
+ "bg\t$rT, $rA, $rB", IntegerOp,
+ []>,
+ RegConstraint<"$rCarry = $rT">,
+ NoEncode<"$rCarry">;
+
+// BGX: only available in vector form, doesn't match a pattern.
+def BGXvec:
+ RRForm<0b11000010110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB,
+ VECREG:$rCarry),
+ "bgx\t$rT, $rA, $rB", IntegerOp,
+ []>,
+ RegConstraint<"$rCarry = $rT">,
+ NoEncode<"$rCarry">;
+
+// Halfword multiply variants:
+// N.B: These can be used to build up larger quantities (16x16 -> 32)
+
+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)))]>;
+
+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))]>;
+
+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)))]>;
+
+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)))]>;
+
+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))]>;
+
+// 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\t$rT, $rA, $val", IntegerMulDiv,
+ [(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))]>;
+
+// mpyui: same issues as other multiplies, plus, this doesn't match a
+// pattern... but may be used during target DAG selection or lowering
+def MPYUIvec:
+ RI10Form<0b10101110, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ "mpyui\t$rT, $rA, $val", IntegerMulDiv,
+ []>;
+
+def MPYUIr16:
+ RI10Form<0b10101110, (outs R16C:$rT), (ins R16C:$rA, s10imm:$val),
+ "mpyui\t$rT, $rA, $val", IntegerMulDiv,
+ []>;
+
+// 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)))]>;
+
+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)>;
+
+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))]>;
+
+// mpyh: multiply high, used to synthesize 32-bit multiplies
+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)))]>;
+
+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))]>;
+
+// 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),
+ "mpys\t$rT, $rA, $rB", IntegerMulDiv,
+ []>;
+
+def MPYSr16:
+ RRForm<0b11100011110, (outs R32C:$rT), (ins R16C:$rA, R16C:$rB),
+ "mpys\t$rT, $rA, $rB", IntegerMulDiv,
+ []>;
+
+// mpyhh: multiply high-high (returns the 32-bit result from multiplying
+// the top 16 bits of the $rA, $rB)
+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)))]>;
+
+def MPYHHr32:
+ RRForm<0b01100011110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "mpyhh\t$rT, $rA, $rB", IntegerMulDiv,
+ []>;
+
+// mpyhha: Multiply high-high, add to $rT:
+def MPYHHAvec:
+ RRForm<0b01100010110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "mpyhha\t$rT, $rA, $rB", IntegerMulDiv,
+ []>;
+
+def MPYHHAr32:
+ RRForm<0b01100010110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "mpyhha\t$rT, $rA, $rB", IntegerMulDiv,
+ []>;
+
+// mpyhhu: Multiply high-high, unsigned
+def MPYHHUvec:
+ RRForm<0b01110011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "mpyhhu\t$rT, $rA, $rB", IntegerMulDiv,
+ []>;
+
+def MPYHHUr32:
+ RRForm<0b01110011110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "mpyhhu\t$rT, $rA, $rB", IntegerMulDiv,
+ []>;
+
+// mpyhhau: Multiply high-high, unsigned
+def MPYHHAUvec:
+ RRForm<0b01110010110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "mpyhhau\t$rT, $rA, $rB", IntegerMulDiv,
+ []>;
+
+def MPYHHAUr32:
+ RRForm<0b01110010110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "mpyhhau\t$rT, $rA, $rB", IntegerMulDiv,
+ []>;
+
+// clz: Count leading zeroes
+def CLZv4i32:
+ RRForm_1<0b10100101010, (outs VECREG:$rT), (ins VECREG:$rA),
+ "clz\t$rT, $rA", IntegerOp,
+ [/* intrinsic */]>;
+
+def CLZr32:
+ RRForm_1<0b10100101010, (outs R32C:$rT), (ins R32C:$rA),
+ "clz\t$rT, $rA", IntegerOp,
+ [(set R32C:$rT, (ctlz R32C:$rA))]>;
+
+// 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,
+ [(set (v16i8 VECREG:$rT), (SPUcntb_v16i8 (v16i8 VECREG:$rA)))]>;
+
+def CNTBv8i16 :
+ RRForm_1<0b00101101010, (outs VECREG:$rT), (ins VECREG:$rA),
+ "cntb\t$rT, $rA", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (SPUcntb_v8i16 (v8i16 VECREG:$rA)))]>;
+
+def CNTBv4i32 :
+ RRForm_1<0b00101101010, (outs VECREG:$rT), (ins VECREG:$rA),
+ "cntb\t$rT, $rA", IntegerOp,
+ [(set (v4i32 VECREG:$rT), (SPUcntb_v4i32 (v4i32 VECREG:$rA)))]>;
+
+// 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,
+ []>;
+
+// 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,
+ []>;
+
+// fsm: Form select mask for words. Like the other fsm* instructions,
+// only the lower 4 bits of $rA are significant.
+def FSM:
+ RRForm_1<0b00101101100, (outs VECREG:$rT), (ins R16C:$rA),
+ "fsm\t$rT, $rA", SelectOp,
+ []>;
+
+// 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,
+ []>;
+
+// 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,
+ []>;
+
+// 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,
+ []>;
+
+// avgb: average bytes
+def AVGB:
+ RRForm<0b11001011000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "avgb\t$rT, $rA, $rB", ByteOp,
+ []>;
+
+// absdb: absolute difference of bytes
+def ABSDB:
+ RRForm<0b11001010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "absdb\t$rT, $rA, $rB", ByteOp,
+ []>;
+
+// sumb: sum bytes into halfwords
+def SUMB:
+ RRForm<0b11001010010, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "sumb\t$rT, $rA, $rB", ByteOp,
+ []>;
+
+// Sign extension operations:
+def XSBHvec:
+ RRForm_1<0b01101101010, (outs VECREG:$rDst), (ins VECREG:$rSrc),
+ "xsbh\t$rDst, $rSrc", IntegerOp,
+ [(set (v8i16 VECREG:$rDst), (sext (v16i8 VECREG:$rSrc)))]>;
+
+// Ordinary form for XSBH
+def XSBHr16:
+ RRForm_1<0b01101101010, (outs R16C:$rDst), (ins R16C:$rSrc),
+ "xsbh\t$rDst, $rSrc", IntegerOp,
+ [(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 XSBHr32:
+ RRForm_1<0b01101101010, (outs R32C:$rDst), (ins R32C:$rSrc),
+ "xsbh\t$rDst, $rSrc", IntegerOp,
+ [(set R32C:$rDst, (sext_inreg R32C:$rSrc, i8))]>;
+
+// 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)>;
+
+// AND operations
+def ANDv16i8:
+ RRForm<0b10000011000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "and\t$rT, $rA, $rB", IntegerOp,
+ [(set (v16i8 VECREG:$rT), (and (v16i8 VECREG:$rA),
+ (v16i8 VECREG:$rB)))]>;
+
+def ANDv8i16:
+ RRForm<0b10000011000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "and\t$rT, $rA, $rB", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (and (v8i16 VECREG:$rA),
+ (v8i16 VECREG:$rB)))]>;
+
+def ANDv4i32:
+ RRForm<0b10000011000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "and\t$rT, $rA, $rB", IntegerOp,
+ [(set (v4i32 VECREG:$rT), (and (v4i32 VECREG:$rA),
+ (v4i32 VECREG:$rB)))]>;
+
+def ANDr32:
+ RRForm<0b10000011000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "and\t$rT, $rA, $rB", IntegerOp,
+ [(set R32C:$rT, (and R32C:$rA, R32C:$rB))]>;
+
+//===---------------------------------------------
+// Special instructions to perform the fabs instruction
+def ANDfabs32:
+ RRForm<0b10000011000, (outs R32FP:$rT), (ins R32FP:$rA, R32C:$rB),
+ "and\t$rT, $rA, $rB", IntegerOp,
+ [/* Intentionally does not match a pattern */]>;
+
+def ANDfabs64:
+ RRForm<0b10000011000, (outs R64FP:$rT), (ins R64FP:$rA, VECREG:$rB),
+ "and\t$rT, $rA, $rB", IntegerOp,
+ [/* Intentionally does not match a pattern */]>;
+
+// Could use ANDv4i32, but won't for clarity
+def ANDfabsvec:
+ RRForm<0b10000011000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "and\t$rT, $rA, $rB", IntegerOp,
+ [/* Intentionally does not match a pattern */]>;
+
+//===---------------------------------------------
+
+def ANDr16:
+ RRForm<0b10000011000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
+ "and\t$rT, $rA, $rB", IntegerOp,
+ [(set R16C:$rT, (and R16C:$rA, R16C:$rB))]>;
+
+// Hacked form of AND to zero-extend 16-bit quantities to 32-bit
+// quantities -- see 16->32 zext pattern.
+//
+// This pattern is somewhat artificial, since it might match some
+// compiler generated pattern but it is unlikely to do so.
+def AND2To4:
+ RRForm<0b10000011000, (outs R32C:$rT), (ins R16C:$rA, R32C:$rB),
+ "and\t$rT, $rA, $rB", IntegerOp,
+ [(set R32C:$rT, (and (zext R16C:$rA), R32C:$rB))]>;
+
+// N.B.: vnot_conv is one of those special target selection pattern fragments,
+// in which we expect there to be a bit_convert on the constant. Bear in mind
+// that llvm translates "not <reg>" to "xor <reg>, -1" (or in this case, a
+// constant -1 vector.)
+def ANDCv16i8:
+ RRForm<0b10000011010, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "andc\t$rT, $rA, $rB", IntegerOp,
+ [(set (v16i8 VECREG:$rT), (and (v16i8 VECREG:$rA),
+ (vnot (v16i8 VECREG:$rB))))]>;
+
+def ANDCv8i16:
+ RRForm<0b10000011010, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "andc\t$rT, $rA, $rB", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (and (v8i16 VECREG:$rA),
+ (vnot (v8i16 VECREG:$rB))))]>;
+
+def ANDCv4i32:
+ RRForm<0b10000011010, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "andc\t$rT, $rA, $rB", IntegerOp,
+ [(set (v4i32 VECREG:$rT), (and (v4i32 VECREG:$rA),
+ (vnot (v4i32 VECREG:$rB))))]>;
+
+def ANDCr32:
+ RRForm<0b10000011010, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "andc\t$rT, $rA, $rB", IntegerOp,
+ [(set R32C:$rT, (and R32C:$rA, (not R32C:$rB)))]>;
+
+def ANDCr16:
+ RRForm<0b10000011010, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
+ "andc\t$rT, $rA, $rB", IntegerOp,
+ [(set R16C:$rT, (and R16C:$rA, (not R16C:$rB)))]>;
+
+def ANDBIv16i8:
+ RI10Form<0b01101000, (outs VECREG:$rT), (ins VECREG:$rA, u10imm:$val),
+ "andbi\t$rT, $rA, $val", IntegerOp,
+ [(set (v16i8 VECREG:$rT),
+ (and (v16i8 VECREG:$rA), (v16i8 v16i8U8Imm:$val)))]>;
+
+def ANDHIv8i16:
+ RI10Form<0b10101000, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ "andhi\t$rT, $rA, $val", IntegerOp,
+ [(set (v8i16 VECREG:$rT),
+ (and (v8i16 VECREG:$rA), v8i16SExt10Imm:$val))]>;
+
+def ANDHIr16:
+ RI10Form<0b10101000, (outs R16C:$rT), (ins R16C:$rA, s10imm:$val),
+ "andhi\t$rT, $rA, $val", IntegerOp,
+ [(set R16C:$rT, (and R16C:$rA, i16ImmSExt10:$val))]>;
+
+def ANDIv4i32:
+ RI10Form<0b00101000, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ "andi\t$rT, $rA, $val", IntegerOp,
+ [(set (v4i32 VECREG:$rT),
+ (and (v4i32 VECREG:$rA), v4i32SExt10Imm:$val))]>;
+
+def ANDIr32:
+ RI10Form<0b10101000, (outs R32C:$rT), (ins R32C:$rA, s10imm_i32:$val),
+ "andi\t$rT, $rA, $val", IntegerOp,
+ [(set R32C:$rT, (and R32C:$rA, i32ImmSExt10:$val))]>;
+
+// Hacked form of ANDI to zero-extend i16 quantities to i32. See the
+// zext 16->32 pattern below.
+//
+// Note that this pattern is somewhat artificial, since it might match
+// something the compiler generates but is unlikely to occur in practice.
+def ANDI2To4:
+ RI10Form<0b10101000, (outs R32C:$rT), (ins R16C:$rA, s10imm_i32:$val),
+ "andi\t$rT, $rA, $val", IntegerOp,
+ [(set R32C:$rT, (and (zext R16C:$rA), i32ImmSExt10:$val))]>;
+
+// Bitwise OR group:
+// Bitwise "or" (N.B.: These are also register-register copy instructions...)
+def ORv16i8:
+ RRForm<0b10000010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [(set (v16i8 VECREG:$rT), (or (v16i8 VECREG:$rA), (v16i8 VECREG:$rB)))]>;
+
+def ORv8i16:
+ RRForm<0b10000010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (or (v8i16 VECREG:$rA), (v8i16 VECREG:$rB)))]>;
+
+def ORv4i32:
+ RRForm<0b10000010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [(set (v4i32 VECREG:$rT), (or (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)))]>;
+
+def ORv4f32:
+ RRForm<0b10000010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [(set (v4f32 VECREG:$rT),
+ (v4f32 (bitconvert (or (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)))))]>;
+
+def ORv2f64:
+ RRForm<0b10000010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [(set (v2f64 VECREG:$rT),
+ (v2f64 (bitconvert (or (v2i64 VECREG:$rA), (v2i64 VECREG:$rB)))))]>;
+
+def ORgprc:
+ RRForm<0b10000010000, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [(set GPRC:$rT, (or GPRC:$rA, GPRC:$rB))]>;
+
+def ORr64:
+ RRForm<0b10000010000, (outs R64C:$rT), (ins R64C:$rA, R64C:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [(set R64C:$rT, (or R64C:$rA, R64C:$rB))]>;
+
+def ORr32:
+ RRForm<0b10000010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [(set R32C:$rT, (or R32C:$rA, R32C:$rB))]>;
+
+def ORr16:
+ RRForm<0b10000010000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [(set R16C:$rT, (or R16C:$rA, R16C:$rB))]>;
+
+// ORv*_*: Used in scalar->vector promotions:
+def ORv8i16_i16:
+ RRForm<0b10000010000, (outs VECREG:$rT), (ins R16C:$rA, R16C:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [/* no pattern */]>;
+
+def : Pat<(v8i16 (SPUpromote_scalar R16C:$rA)),
+ (ORv8i16_i16 R16C:$rA, R16C:$rA)>;
+
+def ORv4i32_i32:
+ RRForm<0b10000010000, (outs VECREG:$rT), (ins R32C:$rA, R32C:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [/* no pattern */]>;
+
+def : Pat<(v4i32 (SPUpromote_scalar R32C:$rA)),
+ (ORv4i32_i32 R32C:$rA, R32C:$rA)>;
+
+def ORv2i64_i64:
+ RRForm<0b10000010000, (outs VECREG:$rT), (ins R64C:$rA, R64C:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [/* no pattern */]>;
+
+def : Pat<(v2i64 (SPUpromote_scalar R64C:$rA)),
+ (ORv2i64_i64 R64C:$rA, R64C:$rA)>;
+
+def ORv4f32_f32:
+ RRForm<0b10000010000, (outs VECREG:$rT), (ins R32FP:$rA, R32FP:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [/* no pattern */]>;
+
+def : Pat<(v4f32 (SPUpromote_scalar R32FP:$rA)),
+ (ORv4f32_f32 R32FP:$rA, R32FP:$rA)>;
+
+def ORv2f64_f64:
+ RRForm<0b10000010000, (outs VECREG:$rT), (ins R64FP:$rA, R64FP:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [/* no pattern */]>;
+
+def : Pat<(v2f64 (SPUpromote_scalar R64FP:$rA)),
+ (ORv2f64_f64 R64FP:$rA, R64FP:$rA)>;
+
+// ORi*_v*: Used to extract vector element 0 (the preferred slot)
+def ORi16_v8i16:
+ RRForm<0b10000010000, (outs R16C:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [/* no pattern */]>;
+
+def : Pat<(SPUextract_elt0 (v8i16 VECREG:$rA)),
+ (ORi16_v8i16 VECREG:$rA, VECREG:$rA)>;
+
+def : Pat<(SPUextract_elt0_chained (v8i16 VECREG:$rA)),
+ (ORi16_v8i16 VECREG:$rA, VECREG:$rA)>;
+
+def ORi32_v4i32:
+ RRForm<0b10000010000, (outs R32C:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [/* no pattern */]>;
+
+def : Pat<(SPUextract_elt0 (v4i32 VECREG:$rA)),
+ (ORi32_v4i32 VECREG:$rA, VECREG:$rA)>;
+
+def : Pat<(SPUextract_elt0_chained (v4i32 VECREG:$rA)),
+ (ORi32_v4i32 VECREG:$rA, VECREG:$rA)>;
+
+def ORi64_v2i64:
+ RRForm<0b10000010000, (outs R64C:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [/* no pattern */]>;
+
+def : Pat<(SPUextract_elt0 (v2i64 VECREG:$rA)),
+ (ORi64_v2i64 VECREG:$rA, VECREG:$rA)>;
+
+def : Pat<(SPUextract_elt0_chained (v2i64 VECREG:$rA)),
+ (ORi64_v2i64 VECREG:$rA, VECREG:$rA)>;
+
+def ORf32_v4f32:
+ RRForm<0b10000010000, (outs R32FP:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [/* no pattern */]>;
+
+def : Pat<(SPUextract_elt0 (v4f32 VECREG:$rA)),
+ (ORf32_v4f32 VECREG:$rA, VECREG:$rA)>;
+
+def : Pat<(SPUextract_elt0_chained (v4f32 VECREG:$rA)),
+ (ORf32_v4f32 VECREG:$rA, VECREG:$rA)>;
+
+def ORf64_v2f64:
+ RRForm<0b10000010000, (outs R64FP:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "or\t$rT, $rA, $rB", IntegerOp,
+ [/* no pattern */]>;
+
+def : Pat<(SPUextract_elt0 (v2f64 VECREG:$rA)),
+ (ORf64_v2f64 VECREG:$rA, VECREG:$rA)>;
+
+def : Pat<(SPUextract_elt0_chained (v2f64 VECREG:$rA)),
+ (ORf64_v2f64 VECREG:$rA, VECREG:$rA)>;
+
+// ORC: Bitwise "or" with complement (match before ORvec, ORr32)
+def ORCv16i8:
+ RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "orc\t$rT, $rA, $rB", IntegerOp,
+ [(set (v16i8 VECREG:$rT), (or (v16i8 VECREG:$rA),
+ (vnot (v16i8 VECREG:$rB))))]>;
+
+def ORCv8i16:
+ RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "orc\t$rT, $rA, $rB", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (or (v8i16 VECREG:$rA),
+ (vnot (v8i16 VECREG:$rB))))]>;
+
+def ORCv4i32:
+ RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "orc\t$rT, $rA, $rB", IntegerOp,
+ [(set (v4i32 VECREG:$rT), (or (v4i32 VECREG:$rA),
+ (vnot (v4i32 VECREG:$rB))))]>;
+
+def ORCr32:
+ RRForm<0b10010010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "orc\t$rT, $rA, $rB", IntegerOp,
+ [(set R32C:$rT, (or R32C:$rA, (not R32C:$rB)))]>;
+
+def ORCr16:
+ RRForm<0b10010010000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
+ "orc\t$rT, $rA, $rB", IntegerOp,
+ [(set R16C:$rT, (or R16C:$rA, (not R16C:$rB)))]>;
+
+// OR byte immediate
+def ORBIv16i8:
+ RI10Form<0b01100000, (outs VECREG:$rT), (ins VECREG:$rA, u10imm:$val),
+ "orbi\t$rT, $rA, $val", IntegerOp,
+ [(set (v16i8 VECREG:$rT),
+ (or (v16i8 VECREG:$rA), (v16i8 v16i8U8Imm:$val)))]>;
+
+// OR halfword immediate
+def ORHIv8i16:
+ RI10Form<0b10100000, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ "orhi\t$rT, $rA, $val", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (or (v8i16 VECREG:$rA),
+ v8i16SExt10Imm:$val))]>;
+
+def ORHIr16:
+ RI10Form<0b10100000, (outs R16C:$rT), (ins R16C:$rA, s10imm:$val),
+ "orhi\t$rT, $rA, $val", IntegerOp,
+ [(set R16C:$rT, (or R16C:$rA, i16ImmSExt10:$val))]>;
+
+// Bitwise "or" with immediate
+def ORIv4i32:
+ RI10Form<0b00100000, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ "ori\t$rT, $rA, $val", IntegerOp,
+ [(set (v4i32 VECREG:$rT), (or (v4i32 VECREG:$rA),
+ v4i32SExt10Imm:$val))]>;
+
+def ORIr32:
+ RI10Form<0b00100000, (outs R32C:$rT), (ins R32C:$rA, s10imm_i32:$val),
+ "ori\t$rT, $rA, $val", IntegerOp,
+ [(set R32C:$rT, (or R32C:$rA, i32ImmSExt10:$val))]>;
+
+// Hacked forms of or immediate to copy one 32- and 64-bit FP register
+// to another. Do not match patterns.
+def ORIf32:
+ RI10Form_1<0b00100000, (outs R32FP:$rT), (ins R32FP:$rA, s10imm_i32:$val),
+ "ori\t$rT, $rA, $val", IntegerOp,
+ [/* no pattern */]>;
+
+def ORIf64:
+ RI10Form_1<0b00100000, (outs R64FP:$rT), (ins R64FP:$rA, s10imm_i32:$val),
+ "ori\t$rT, $rA, $val", IntegerOp,
+ [/* no pattern */]>;
+
+def ORIr64:
+ RI10Form_1<0b00100000, (outs R64C:$rT), (ins R64C:$rA, s10imm_i32:$val),
+ "ori\t$rT, $rA, $val", IntegerOp,
+ [/* no pattern */]>;
+
+// ORI2To4: hacked version of the ori instruction to extend 16-bit quantities
+// to 32-bit quantities. used exclusively to match "anyext" conversions (vide
+// infra "anyext 16->32" pattern.)
+def ORI2To4:
+ RI10Form<0b00100000, (outs R32C:$rT), (ins R16C:$rA, s10imm_i32:$val),
+ "ori\t$rT, $rA, $val", IntegerOp,
+ [(set R32C:$rT, (or (anyext R16C:$rA), i32ImmSExt10:$val))]>;
+
+// ORX: "or" across the vector: or's $rA's word slots leaving the result in
+// $rT[0], slots 1-3 are zeroed.
+//
+// Needs to match an intrinsic pattern.
+def ORXv4i32:
+ RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "orx\t$rT, $rA, $rB", IntegerOp,
+ []>;
+
+def XORv16i8:
+ RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "xor\t$rT, $rA, $rB", IntegerOp,
+ [(set (v16i8 VECREG:$rT), (xor (v16i8 VECREG:$rA), (v16i8 VECREG:$rB)))]>;
+
+def XORv8i16:
+ RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "xor\t$rT, $rA, $rB", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (xor (v8i16 VECREG:$rA), (v8i16 VECREG:$rB)))]>;
+
+def XORv4i32:
+ RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "xor\t$rT, $rA, $rB", IntegerOp,
+ [(set (v4i32 VECREG:$rT), (xor (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)))]>;
+
+def XORr32:
+ RRForm<0b10010010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "xor\t$rT, $rA, $rB", IntegerOp,
+ [(set R32C:$rT, (xor R32C:$rA, R32C:$rB))]>;
+
+//==----------------------------------------------------------
+// Special forms for floating point instructions.
+// Bitwise ORs and ANDs don't make sense for normal floating
+// point numbers. These operations (fneg and fabs), however,
+// require bitwise logical ops to manipulate the sign bit.
+def XORfneg32:
+ RRForm<0b10010010000, (outs R32FP:$rT), (ins R32FP:$rA, R32C:$rB),
+ "xor\t$rT, $rA, $rB", IntegerOp,
+ [/* Intentionally does not match a pattern, see fneg32 */]>;
+
+// KLUDGY! Better way to do this without a VECREG? bitconvert?
+// VECREG is assumed to contain two identical 64-bit masks, so
+// it doesn't matter which word we select for the xor
+def XORfneg64:
+ RRForm<0b10010010000, (outs R64FP:$rT), (ins R64FP:$rA, VECREG:$rB),
+ "xor\t$rT, $rA, $rB", IntegerOp,
+ [/* Intentionally does not match a pattern, see fneg64 */]>;
+
+// Could use XORv4i32, but will use this for clarity
+def XORfnegvec:
+ RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "xor\t$rT, $rA, $rB", IntegerOp,
+ [/* Intentionally does not match a pattern, see fneg{32,64} */]>;
+
+//==----------------------------------------------------------
+
+def XORr16:
+ RRForm<0b10010010000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
+ "xor\t$rT, $rA, $rB", IntegerOp,
+ [(set R16C:$rT, (xor R16C:$rA, R16C:$rB))]>;
+
+def XORBIv16i8:
+ RI10Form<0b01100000, (outs VECREG:$rT), (ins VECREG:$rA, u10imm:$val),
+ "xorbi\t$rT, $rA, $val", IntegerOp,
+ [(set (v16i8 VECREG:$rT), (xor (v16i8 VECREG:$rA), v16i8U8Imm:$val))]>;
+
+def XORHIv8i16:
+ RI10Form<0b10100000, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ "xorhi\t$rT, $rA, $val", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (xor (v8i16 VECREG:$rA),
+ v8i16SExt10Imm:$val))]>;
+
+def XORHIr16:
+ RI10Form<0b10100000, (outs R16C:$rT), (ins R16C:$rA, s10imm:$val),
+ "xorhi\t$rT, $rA, $val", IntegerOp,
+ [(set R16C:$rT, (xor R16C:$rA, i16ImmSExt10:$val))]>;
+
+def XORIv4i32:
+ RI10Form<0b00100000, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ "xori\t$rT, $rA, $val", IntegerOp,
+ [(set (v4i32 VECREG:$rT), (xor (v4i32 VECREG:$rA),
+ v4i32SExt10Imm:$val))]>;
+
+def XORIr32:
+ RI10Form<0b00100000, (outs R32C:$rT), (ins R32C:$rA, s10imm_i32:$val),
+ "xori\t$rT, $rA, $val", IntegerOp,
+ [(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))))]>;
+
+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)))]>;
+
+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)))]>;
+
+// 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))))]>;
+
+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)))]>;
+
+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)))]>;
+
+// EQV: Equivalence (1 for each same bit, otherwise 0)
+def EQVv16i8:
+ RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "eqv\t$rT, $rA, $rB", IntegerOp,
+ [(set (v16i8 VECREG:$rT), (or (and (v16i8 VECREG:$rA),
+ (v16i8 VECREG:$rB)),
+ (and (vnot (v16i8 VECREG:$rA)),
+ (vnot (v16i8 VECREG:$rB)))))]>;
+
+def : Pat<(xor (v16i8 VECREG:$rA), (vnot (v16i8 VECREG:$rB))),
+ (EQVv16i8 VECREG:$rA, VECREG:$rB)>;
+
+def : Pat<(xor (vnot (v16i8 VECREG:$rA)), (v16i8 VECREG:$rB)),
+ (EQVv16i8 VECREG:$rA, VECREG:$rB)>;
+
+def EQVv8i16:
+ RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "eqv\t$rT, $rA, $rB", IntegerOp,
+ [(set (v8i16 VECREG:$rT), (or (and (v8i16 VECREG:$rA),
+ (v8i16 VECREG:$rB)),
+ (and (vnot (v8i16 VECREG:$rA)),
+ (vnot (v8i16 VECREG:$rB)))))]>;
+
+def : Pat<(xor (v8i16 VECREG:$rA), (vnot (v8i16 VECREG:$rB))),
+ (EQVv8i16 VECREG:$rA, VECREG:$rB)>;
+
+def : Pat<(xor (vnot (v8i16 VECREG:$rA)), (v8i16 VECREG:$rB)),
+ (EQVv8i16 VECREG:$rA, VECREG:$rB)>;
+
+def EQVv4i32:
+ RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "eqv\t$rT, $rA, $rB", IntegerOp,
+ [(set (v4i32 VECREG:$rT), (or (and (v4i32 VECREG:$rA),
+ (v4i32 VECREG:$rB)),
+ (and (vnot (v4i32 VECREG:$rA)),
+ (vnot (v4i32 VECREG:$rB)))))]>;
+
+def : Pat<(xor (v4i32 VECREG:$rA), (vnot (v4i32 VECREG:$rB))),
+ (EQVv4i32 VECREG:$rA, VECREG:$rB)>;
+
+def : Pat<(xor (vnot (v4i32 VECREG:$rA)), (v4i32 VECREG:$rB)),
+ (EQVv4i32 VECREG:$rA, VECREG:$rB)>;
+
+def EQVr32:
+ RRForm<0b10010010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "eqv\t$rT, $rA, $rB", IntegerOp,
+ [(set R32C:$rT, (or (and R32C:$rA, R32C:$rB),
+ (and (not R32C:$rA), (not R32C:$rB))))]>;
+
+def : Pat<(xor R32C:$rA, (not R32C:$rB)),
+ (EQVr32 R32C:$rA, R32C:$rB)>;
+
+def : Pat<(xor (not R32C:$rA), R32C:$rB),
+ (EQVr32 R32C:$rA, R32C:$rB)>;
+
+def EQVr16:
+ RRForm<0b10010010000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
+ "eqv\t$rT, $rA, $rB", IntegerOp,
+ [(set R16C:$rT, (or (and R16C:$rA, R16C:$rB),
+ (and (not R16C:$rA), (not R16C:$rB))))]>;
+
+def : Pat<(xor R16C:$rA, (not R16C:$rB)),
+ (EQVr16 R16C:$rA, R16C:$rB)>;
+
+def : Pat<(xor (not R16C:$rA), R16C:$rB),
+ (EQVr16 R16C:$rA, R16C:$rB)>;
+
+// gcc optimizes (p & q) | (~p & ~q) -> ~(p | q) | (p & q), so match that
+// pattern also:
+def : Pat<(or (vnot (or (v16i8 VECREG:$rA), (v16i8 VECREG:$rB))),
+ (and (v16i8 VECREG:$rA), (v16i8 VECREG:$rB))),
+ (EQVv16i8 VECREG:$rA, VECREG:$rB)>;
+
+def : Pat<(or (vnot (or (v8i16 VECREG:$rA), (v8i16 VECREG:$rB))),
+ (and (v8i16 VECREG:$rA), (v8i16 VECREG:$rB))),
+ (EQVv8i16 VECREG:$rA, VECREG:$rB)>;
+
+def : Pat<(or (vnot (or (v4i32 VECREG:$rA), (v4i32 VECREG:$rB))),
+ (and (v4i32 VECREG:$rA), (v4i32 VECREG:$rB))),
+ (EQVv4i32 VECREG:$rA, VECREG:$rB)>;
+
+def : Pat<(or (not (or R32C:$rA, R32C:$rB)), (and R32C:$rA, R32C:$rB)),
+ (EQVr32 R32C:$rA, R32C:$rB)>;
+
+def : Pat<(or (not (or R16C:$rA, R16C:$rB)), (and R16C:$rA, R16C:$rB)),
+ (EQVr16 R16C:$rA, R16C:$rB)>;
+
+// Select bits:
+def SELBv16i8:
+ RRRForm<0b1000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ "selb\t$rT, $rA, $rB, $rC", IntegerOp,
+ [(set (v16i8 VECREG:$rT),
+ (SPUselb_v16i8 (v16i8 VECREG:$rA), (v16i8 VECREG:$rB),
+ (v16i8 VECREG:$rC)))]>;
+
+def : Pat<(or (and (v16i8 VECREG:$rA), (v16i8 VECREG:$rC)),
+ (and (v16i8 VECREG:$rB), (vnot (v16i8 VECREG:$rC)))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v16i8 VECREG:$rC), (v16i8 VECREG:$rA)),
+ (and (v16i8 VECREG:$rB), (vnot (v16i8 VECREG:$rC)))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v16i8 VECREG:$rA), (v16i8 VECREG:$rC)),
+ (and (vnot (v16i8 VECREG:$rC)), (v16i8 VECREG:$rB))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v16i8 VECREG:$rC), (v16i8 VECREG:$rA)),
+ (and (vnot (v16i8 VECREG:$rC)), (v16i8 VECREG:$rB))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v16i8 VECREG:$rA), (vnot (v16i8 VECREG:$rC))),
+ (and (v16i8 VECREG:$rB), (v16i8 VECREG:$rC))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v16i8 VECREG:$rA), (vnot (v16i8 VECREG:$rC))),
+ (and (v16i8 VECREG:$rC), (v16i8 VECREG:$rB))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (vnot (v16i8 VECREG:$rC)), (v16i8 VECREG:$rA)),
+ (and (v16i8 VECREG:$rB), (v16i8 VECREG:$rC))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (vnot (v16i8 VECREG:$rC)), (v16i8 VECREG:$rA)),
+ (and (v16i8 VECREG:$rC), (v16i8 VECREG:$rB))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v16i8 VECREG:$rA), (v16i8 VECREG:$rC)),
+ (and (v16i8 VECREG:$rB), (vnot (v16i8 VECREG:$rC)))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v16i8 VECREG:$rC), (v16i8 VECREG:$rA)),
+ (and (v16i8 VECREG:$rB), (vnot (v16i8 VECREG:$rC)))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v16i8 VECREG:$rA), (v16i8 VECREG:$rC)),
+ (and (vnot (v16i8 VECREG:$rC)), (v16i8 VECREG:$rB))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v16i8 VECREG:$rC), (v16i8 VECREG:$rA)),
+ (and (vnot (v16i8 VECREG:$rC)), (v16i8 VECREG:$rB))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v16i8 VECREG:$rA), (vnot (v16i8 VECREG:$rC))),
+ (and (v16i8 VECREG:$rB), (v16i8 VECREG:$rC))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v16i8 VECREG:$rA), (vnot (v16i8 VECREG:$rC))),
+ (and (v16i8 VECREG:$rC), (v16i8 VECREG:$rB))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (vnot (v16i8 VECREG:$rC)), (v16i8 VECREG:$rA)),
+ (and (v16i8 VECREG:$rB), (v16i8 VECREG:$rC))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (vnot (v16i8 VECREG:$rC)), (v16i8 VECREG:$rA)),
+ (and (v16i8 VECREG:$rC), (v16i8 VECREG:$rB))),
+ (SELBv16i8 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def SELBv8i16:
+ RRRForm<0b1000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ "selb\t$rT, $rA, $rB, $rC", IntegerOp,
+ [(set (v8i16 VECREG:$rT),
+ (SPUselb_v8i16 (v8i16 VECREG:$rA), (v8i16 VECREG:$rB),
+ (v8i16 VECREG:$rC)))]>;
+
+def : Pat<(or (and (v8i16 VECREG:$rA), (v8i16 VECREG:$rC)),
+ (and (v8i16 VECREG:$rB), (vnot (v8i16 VECREG:$rC)))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v8i16 VECREG:$rC), (v8i16 VECREG:$rA)),
+ (and (v8i16 VECREG:$rB), (vnot (v8i16 VECREG:$rC)))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v8i16 VECREG:$rA), (v8i16 VECREG:$rC)),
+ (and (vnot (v8i16 VECREG:$rC)), (v8i16 VECREG:$rB))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v8i16 VECREG:$rC), (v8i16 VECREG:$rA)),
+ (and (vnot (v8i16 VECREG:$rC)), (v8i16 VECREG:$rB))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v8i16 VECREG:$rA), (vnot (v8i16 VECREG:$rC))),
+ (and (v8i16 VECREG:$rB), (v8i16 VECREG:$rC))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v8i16 VECREG:$rA), (vnot (v8i16 VECREG:$rC))),
+ (and (v8i16 VECREG:$rC), (v8i16 VECREG:$rB))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (vnot (v8i16 VECREG:$rC)), (v8i16 VECREG:$rA)),
+ (and (v8i16 VECREG:$rB), (v8i16 VECREG:$rC))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (vnot (v8i16 VECREG:$rC)), (v8i16 VECREG:$rA)),
+ (and (v8i16 VECREG:$rC), (v8i16 VECREG:$rB))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v8i16 VECREG:$rA), (v8i16 VECREG:$rC)),
+ (and (v8i16 VECREG:$rB), (vnot (v8i16 VECREG:$rC)))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v8i16 VECREG:$rC), (v8i16 VECREG:$rA)),
+ (and (v8i16 VECREG:$rB), (vnot (v8i16 VECREG:$rC)))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v8i16 VECREG:$rA), (v8i16 VECREG:$rC)),
+ (and (vnot (v8i16 VECREG:$rC)), (v8i16 VECREG:$rB))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v8i16 VECREG:$rC), (v8i16 VECREG:$rA)),
+ (and (vnot (v8i16 VECREG:$rC)), (v8i16 VECREG:$rB))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v8i16 VECREG:$rA), (vnot (v8i16 VECREG:$rC))),
+ (and (v8i16 VECREG:$rB), (v8i16 VECREG:$rC))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v8i16 VECREG:$rA), (vnot (v8i16 VECREG:$rC))),
+ (and (v8i16 VECREG:$rC), (v8i16 VECREG:$rB))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (vnot (v8i16 VECREG:$rC)), (v8i16 VECREG:$rA)),
+ (and (v8i16 VECREG:$rB), (v8i16 VECREG:$rC))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (vnot (v8i16 VECREG:$rC)), (v8i16 VECREG:$rA)),
+ (and (v8i16 VECREG:$rC), (v8i16 VECREG:$rB))),
+ (SELBv8i16 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def SELBv4i32:
+ RRRForm<0b1000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ "selb\t$rT, $rA, $rB, $rC", IntegerOp,
+ [(set (v4i32 VECREG:$rT),
+ (SPUselb_v4i32 (v4i32 VECREG:$rA), (v4i32 VECREG:$rB),
+ (v4i32 VECREG:$rC)))]>;
+
+def : Pat<(or (and (v4i32 VECREG:$rA), (v4i32 VECREG:$rC)),
+ (and (v4i32 VECREG:$rB), (vnot (v4i32 VECREG:$rC)))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v4i32 VECREG:$rC), (v4i32 VECREG:$rA)),
+ (and (v4i32 VECREG:$rB), (vnot (v4i32 VECREG:$rC)))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v4i32 VECREG:$rA), (v4i32 VECREG:$rC)),
+ (and (vnot (v4i32 VECREG:$rC)), (v4i32 VECREG:$rB))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v4i32 VECREG:$rC), (v4i32 VECREG:$rA)),
+ (and (vnot (v4i32 VECREG:$rC)), (v4i32 VECREG:$rB))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v4i32 VECREG:$rA), (vnot (v4i32 VECREG:$rC))),
+ (and (v4i32 VECREG:$rB), (v4i32 VECREG:$rC))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v4i32 VECREG:$rA), (vnot (v4i32 VECREG:$rC))),
+ (and (v4i32 VECREG:$rC), (v4i32 VECREG:$rB))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (vnot (v4i32 VECREG:$rC)), (v4i32 VECREG:$rA)),
+ (and (v4i32 VECREG:$rB), (v4i32 VECREG:$rC))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (vnot (v4i32 VECREG:$rC)), (v4i32 VECREG:$rA)),
+ (and (v4i32 VECREG:$rC), (v4i32 VECREG:$rB))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v4i32 VECREG:$rA), (v4i32 VECREG:$rC)),
+ (and (v4i32 VECREG:$rB), (vnot (v4i32 VECREG:$rC)))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v4i32 VECREG:$rC), (v4i32 VECREG:$rA)),
+ (and (v4i32 VECREG:$rB), (vnot (v4i32 VECREG:$rC)))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v4i32 VECREG:$rA), (v4i32 VECREG:$rC)),
+ (and (vnot (v4i32 VECREG:$rC)), (v4i32 VECREG:$rB))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v4i32 VECREG:$rC), (v4i32 VECREG:$rA)),
+ (and (vnot (v4i32 VECREG:$rC)), (v4i32 VECREG:$rB))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v4i32 VECREG:$rA), (vnot (v4i32 VECREG:$rC))),
+ (and (v4i32 VECREG:$rB), (v4i32 VECREG:$rC))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (v4i32 VECREG:$rA), (vnot (v4i32 VECREG:$rC))),
+ (and (v4i32 VECREG:$rC), (v4i32 VECREG:$rB))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (vnot (v4i32 VECREG:$rC)), (v4i32 VECREG:$rA)),
+ (and (v4i32 VECREG:$rB), (v4i32 VECREG:$rC))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(or (and (vnot (v4i32 VECREG:$rC)), (v4i32 VECREG:$rA)),
+ (and (v4i32 VECREG:$rC), (v4i32 VECREG:$rB))),
+ (SELBv4i32 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def SELBr32:
+ RRRForm<0b1000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB, R32C:$rC),
+ "selb\t$rT, $rA, $rB, $rC", IntegerOp,
+ []>;
+
+// And the various patterns that can be matched... (all 8 of them :-)
+def : Pat<(or (and R32C:$rA, R32C:$rC),
+ (and R32C:$rB, (not R32C:$rC))),
+ (SELBr32 R32C:$rA, R32C:$rB, R32C:$rC)>;
+
+def : Pat<(or (and R32C:$rC, R32C:$rA),
+ (and R32C:$rB, (not R32C:$rC))),
+ (SELBr32 R32C:$rA, R32C:$rB, R32C:$rC)>;
+
+def : Pat<(or (and R32C:$rA, R32C:$rC),
+ (and (not R32C:$rC), R32C:$rB)),
+ (SELBr32 R32C:$rA, R32C:$rB, R32C:$rC)>;
+
+def : Pat<(or (and R32C:$rC, R32C:$rA),
+ (and (not R32C:$rC), R32C:$rB)),
+ (SELBr32 R32C:$rA, R32C:$rB, R32C:$rC)>;
+
+def : Pat<(or (and R32C:$rA, (not R32C:$rC)),
+ (and R32C:$rB, R32C:$rC)),
+ (SELBr32 R32C:$rA, R32C:$rB, R32C:$rC)>;
+
+def : Pat<(or (and R32C:$rA, (not R32C:$rC)),
+ (and R32C:$rC, R32C:$rB)),
+ (SELBr32 R32C:$rA, R32C:$rB, R32C:$rC)>;
+
+def : Pat<(or (and (not R32C:$rC), R32C:$rA),
+ (and R32C:$rB, R32C:$rC)),
+ (SELBr32 R32C:$rA, R32C:$rB, R32C:$rC)>;
+
+def : Pat<(or (and (not R32C:$rC), R32C:$rA),
+ (and R32C:$rC, R32C:$rB)),
+ (SELBr32 R32C:$rA, R32C:$rB, R32C:$rC)>;
+
+def SELBr16:
+ RRRForm<0b1000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB, R16C:$rC),
+ "selb\t$rT, $rA, $rB, $rC", IntegerOp,
+ []>;
+
+def : Pat<(or (and R16C:$rA, R16C:$rC),
+ (and R16C:$rB, (not R16C:$rC))),
+ (SELBr16 R16C:$rA, R16C:$rB, R16C:$rC)>;
+
+def : Pat<(or (and R16C:$rC, R16C:$rA),
+ (and R16C:$rB, (not R16C:$rC))),
+ (SELBr16 R16C:$rA, R16C:$rB, R16C:$rC)>;
+
+def : Pat<(or (and R16C:$rA, R16C:$rC),
+ (and (not R16C:$rC), R16C:$rB)),
+ (SELBr16 R16C:$rA, R16C:$rB, R16C:$rC)>;
+
+def : Pat<(or (and R16C:$rC, R16C:$rA),
+ (and (not R16C:$rC), R16C:$rB)),
+ (SELBr16 R16C:$rA, R16C:$rB, R16C:$rC)>;
+
+def : Pat<(or (and R16C:$rA, (not R16C:$rC)),
+ (and R16C:$rB, R16C:$rC)),
+ (SELBr16 R16C:$rA, R16C:$rB, R16C:$rC)>;
+
+def : Pat<(or (and R16C:$rA, (not R16C:$rC)),
+ (and R16C:$rC, R16C:$rB)),
+ (SELBr16 R16C:$rA, R16C:$rB, R16C:$rC)>;
+
+def : Pat<(or (and (not R16C:$rC), R16C:$rA),
+ (and R16C:$rB, R16C:$rC)),
+ (SELBr16 R16C:$rA, R16C:$rB, R16C:$rC)>;
+
+def : Pat<(or (and (not R16C:$rC), R16C:$rA),
+ (and R16C:$rC, R16C:$rB)),
+ (SELBr16 R16C:$rA, R16C:$rB, R16C:$rC)>;
+
+//===----------------------------------------------------------------------===//
+// Vector shuffle...
+//===----------------------------------------------------------------------===//
+
+def SHUFB:
+ RRRForm<0b1000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ "shufb\t$rT, $rA, $rB, $rC", IntegerOp,
+ [/* insert intrinsic here */]>;
+
+// SPUshuffle is generated in LowerVECTOR_SHUFFLE and gets replaced with SHUFB.
+// See the SPUshuffle SDNode operand above, which sets up the DAG pattern
+// matcher to emit something when the LowerVECTOR_SHUFFLE generates a node with
+// the SPUISD::SHUFB opcode.
+def : Pat<(SPUshuffle (v16i8 VECREG:$rA), (v16i8 VECREG:$rB), VECREG:$rC),
+ (SHUFB VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(SPUshuffle (v8i16 VECREG:$rA), (v8i16 VECREG:$rB), VECREG:$rC),
+ (SHUFB VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(SPUshuffle (v4i32 VECREG:$rA), (v4i32 VECREG:$rB), VECREG:$rC),
+ (SHUFB VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+def : Pat<(SPUshuffle (v2i64 VECREG:$rA), (v2i64 VECREG:$rB), VECREG:$rC),
+ (SHUFB VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+//===----------------------------------------------------------------------===//
+// Shift and rotate group:
+//===----------------------------------------------------------------------===//
+
+def SHLHv8i16:
+ RRForm<0b11111010000, (outs VECREG:$rT), (ins VECREG:$rA, R16C:$rB),
+ "shlh\t$rT, $rA, $rB", RotateShift,
+ [(set (v8i16 VECREG:$rT),
+ (SPUvec_shl_v8i16 (v8i16 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
+// }
+//
+// However, we will generate this code when lowering 8-bit shifts and rotates.
+
+def SHLHr16:
+ RRForm<0b11111010000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
+ "shlh\t$rT, $rA, $rB", RotateShift,
+ [(set R16C:$rT, (shl R16C:$rA, R16C:$rB))]>;
+
+def SHLHr16_r32:
+ RRForm<0b11111010000, (outs R16C:$rT), (ins R16C:$rA, R32C:$rB),
+ "shlh\t$rT, $rA, $rB", RotateShift,
+ [(set R16C:$rT, (shl R16C:$rA, R32C:$rB))]>;
+
+def SHLHIv8i16:
+ RI7Form<0b11111010000, (outs VECREG:$rT), (ins VECREG:$rA, u7imm:$val),
+ "shlhi\t$rT, $rA, $val", RotateShift,
+ [(set (v8i16 VECREG:$rT),
+ (SPUvec_shl_v8i16 (v8i16 VECREG:$rA), (i16 uimm7:$val)))]>;
+
+def : Pat<(SPUvec_shl_v8i16 (v8i16 VECREG:$rA), (i32 uimm7:$val)),
+ (SHLHIv8i16 VECREG:$rA, imm:$val)>;
+
+def SHLHIr16:
+ RI7Form<0b11111010000, (outs R16C:$rT), (ins R16C:$rA, u7imm_i32:$val),
+ "shlhi\t$rT, $rA, $val", RotateShift,
+ [(set R16C:$rT, (shl R16C:$rA, (i32 uimm7:$val)))]>;
+
+def : Pat<(shl R16C:$rA, (i16 uimm7:$val)),
+ (SHLHIr16 R16C:$rA, uimm7:$val)>;
+
+def SHLv4i32:
+ RRForm<0b11111010000, (outs VECREG:$rT), (ins VECREG:$rA, R16C:$rB),
+ "shl\t$rT, $rA, $rB", RotateShift,
+ [(set (v4i32 VECREG:$rT),
+ (SPUvec_shl_v4i32 (v4i32 VECREG:$rA), R16C:$rB))]>;
+
+def SHLr32:
+ RRForm<0b11111010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "shl\t$rT, $rA, $rB", RotateShift,
+ [(set R32C:$rT, (shl R32C:$rA, R32C:$rB))]>;
+
+def SHLIv4i32:
+ RI7Form<0b11111010000, (outs VECREG:$rT), (ins VECREG:$rA, u7imm:$val),
+ "shli\t$rT, $rA, $val", RotateShift,
+ [(set (v4i32 VECREG:$rT),
+ (SPUvec_shl_v4i32 (v4i32 VECREG:$rA), (i16 uimm7:$val)))]>;
+
+def: Pat<(SPUvec_shl_v4i32 (v4i32 VECREG:$rA), (i32 uimm7:$val)),
+ (SHLIv4i32 VECREG:$rA, uimm7:$val)>;
+
+def SHLIr32:
+ RI7Form<0b11111010000, (outs R32C:$rT), (ins R32C:$rA, u7imm_i32:$val),
+ "shli\t$rT, $rA, $val", RotateShift,
+ [(set R32C:$rT, (shl R32C:$rA, (i32 uimm7:$val)))]>;
+
+def : Pat<(shl R32C:$rA, (i16 uimm7:$val)),
+ (SHLIr32 R32C:$rA, uimm7:$val)>;
+
+// SHLQBI vec form: Note that this will shift the entire vector (the 128-bit
+// register) to the left. Vector form is here to ensure type correctness.
+def SHLQBIvec:
+ RRForm<0b11011011100, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "shlqbi\t$rT, $rA, $rB", RotateShift,
+ [/* intrinsic */]>;
+
+// See note above on SHLQBI.
+def SHLQBIIvec:
+ RI7Form<0b11011111100, (outs VECREG:$rT), (ins VECREG:$rA, u7imm:$val),
+ "shlqbii\t$rT, $rA, $val", RotateShift,
+ [/* intrinsic */]>;
+
+// SHLQBY, SHLQBYI vector forms: Shift the entire vector to the left by bytes,
+// not by bits.
+def SHLQBYvec:
+ RI7Form<0b11111011100, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "shlqbyi\t$rT, $rA, $rB", RotateShift,
+ [/* intrinsic */]>;
+
+def SHLQBYIvec:
+ RI7Form<0b11111111100, (outs VECREG:$rT), (ins VECREG:$rA, u7imm:$val),
+ "shlqbyi\t$rT, $rA, $val", RotateShift,
+ [/* intrinsic */]>;
+
+// ROTH v8i16 form:
+def ROTHv8i16:
+ RRForm<0b00111010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "roth\t$rT, $rA, $rB", RotateShift,
+ [(set (v8i16 VECREG:$rT),
+ (SPUvec_rotl_v8i16 VECREG:$rA, VECREG:$rB))]>;
+
+def ROTHr16:
+ RRForm<0b00111010000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
+ "roth\t$rT, $rA, $rB", RotateShift,
+ [(set R16C:$rT, (rotl R16C:$rA, R16C:$rB))]>;
+
+def ROTHr16_r32:
+ RRForm<0b00111010000, (outs R16C:$rT), (ins R16C:$rA, R32C:$rB),
+ "roth\t$rT, $rA, $rB", RotateShift,
+ [(set R16C:$rT, (rotl R16C:$rA, R32C:$rB))]>;
+
+def ROTHIv8i16:
+ RI7Form<0b00111110000, (outs VECREG:$rT), (ins VECREG:$rA, u7imm:$val),
+ "rothi\t$rT, $rA, $val", RotateShift,
+ [(set (v8i16 VECREG:$rT),
+ (SPUvec_rotl_v8i16 VECREG:$rA, (i16 uimm7:$val)))]>;
+
+def : Pat<(SPUvec_rotl_v8i16 VECREG:$rA, (i16 uimm7:$val)),
+ (ROTHIv8i16 VECREG:$rA, imm:$val)>;
+
+def : Pat<(SPUvec_rotl_v8i16 VECREG:$rA, (i32 uimm7:$val)),
+ (ROTHIv8i16 VECREG:$rA, imm:$val)>;
+
+def ROTHIr16:
+ RI7Form<0b00111110000, (outs R16C:$rT), (ins R16C:$rA, u7imm:$val),
+ "rothi\t$rT, $rA, $val", RotateShift,
+ [(set R16C:$rT, (rotl R16C:$rA, (i16 uimm7:$val)))]>;
+
+def ROTHIr16_i32:
+ RI7Form<0b00111110000, (outs R16C:$rT), (ins R16C:$rA, u7imm_i32:$val),
+ "rothi\t$rT, $rA, $val", RotateShift,
+ [(set R16C:$rT, (rotl R16C:$rA, (i32 uimm7:$val)))]>;
+
+def ROTv4i32:
+ RRForm<0b00011010000, (outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB),
+ "rot\t$rT, $rA, $rB", RotateShift,
+ [(set (v4i32 VECREG:$rT),
+ (SPUvec_rotl_v4i32 (v4i32 VECREG:$rA), R32C:$rB))]>;
+
+def ROTr32:
+ RRForm<0b00011010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "rot\t$rT, $rA, $rB", RotateShift,
+ [(set R32C:$rT, (rotl R32C:$rA, R32C:$rB))]>;
+
+def ROTIv4i32:
+ RI7Form<0b00011110000, (outs VECREG:$rT), (ins VECREG:$rA, u7imm_i32:$val),
+ "roti\t$rT, $rA, $val", RotateShift,
+ [(set (v4i32 VECREG:$rT),
+ (SPUvec_rotl_v4i32 (v4i32 VECREG:$rA), (i32 uimm7:$val)))]>;
+
+def : Pat<(SPUvec_rotl_v4i32 (v4i32 VECREG:$rA), (i16 uimm7:$val)),
+ (ROTIv4i32 VECREG:$rA, imm:$val)>;
+
+def ROTIr32:
+ RI7Form<0b00011110000, (outs R32C:$rT), (ins R32C:$rA, u7imm_i32:$val),
+ "roti\t$rT, $rA, $val", RotateShift,
+ [(set R32C:$rT, (rotl R32C:$rA, (i32 uimm7:$val)))]>;
+
+def ROTIr32_i16:
+ RI7Form<0b00111110000, (outs R32C:$rT), (ins R32C:$rA, u7imm:$val),
+ "roti\t$rT, $rA, $val", RotateShift,
+ [(set R32C:$rT, (rotl R32C:$rA, (i16 uimm7:$val)))]>;
+
+// ROTQBY* vector forms: This rotates the entire vector, but vector registers
+// are used here for type checking (instances where ROTQBI is used actually
+// use vector registers)
+def ROTQBYvec:
+ RRForm<0b00111011100, (outs VECREG:$rT), (ins VECREG:$rA, R16C:$rB),
+ "rotqby\t$rT, $rA, $rB", RotateShift,
+ [(set (v16i8 VECREG:$rT), (SPUrotbytes_left (v16i8 VECREG:$rA), R16C:$rB))]>;
+
+def : Pat<(SPUrotbytes_left_chained (v16i8 VECREG:$rA), R16C:$rB),
+ (ROTQBYvec VECREG:$rA, R16C:$rB)>;
+
+// See ROTQBY note above.
+def ROTQBYIvec:
+ RI7Form<0b00111111100, (outs VECREG:$rT), (ins VECREG:$rA, u7imm:$val),
+ "rotqbyi\t$rT, $rA, $val", RotateShift,
+ [(set (v16i8 VECREG:$rT),
+ (SPUrotbytes_left (v16i8 VECREG:$rA), (i16 uimm7:$val)))]>;
+
+def : Pat<(SPUrotbytes_left_chained (v16i8 VECREG:$rA), (i16 uimm7:$val)),
+ (ROTQBYIvec VECREG:$rA, uimm7:$val)>;
+
+// See ROTQBY note above.
+def ROTQBYBIvec:
+ RI7Form<0b00110011100, (outs VECREG:$rT), (ins VECREG:$rA, u7imm:$val),
+ "rotqbybi\t$rT, $rA, $val", RotateShift,
+ [/* intrinsic */]>;
+
+// See ROTQBY note above.
+//
+// Assume that the user of this instruction knows to shift the rotate count
+// into bit 29
+def ROTQBIvec:
+ RRForm<0b00011011100, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "rotqbi\t$rT, $rA, $rB", RotateShift,
+ [/* insert intrinsic here */]>;
+
+// See ROTQBY note above.
+def ROTQBIIvec:
+ RI7Form<0b00011111100, (outs VECREG:$rT), (ins VECREG:$rA, u7imm_i32:$val),
+ "rotqbii\t$rT, $rA, $val", RotateShift,
+ [/* insert intrinsic here */]>;
+
+// ROTHM v8i16 form:
+// NOTE(1): No vector rotate is generated by the C/C++ frontend (today),
+// so this only matches a synthetically generated/lowered code
+// fragment.
+// NOTE(2): $rB must be negated before the right rotate!
+def ROTHMv8i16:
+ RRForm<0b10111010000, (outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB),
+ "rothm\t$rT, $rA, $rB", RotateShift,
+ [/* see patterns below - $rB must be negated */]>;
+
+def : Pat<(SPUvec_srl_v8i16 (v8i16 VECREG:$rA), R32C:$rB),
+ (ROTHMv8i16 VECREG:$rA, (SFIr32 R32C:$rB, 0))>;
+
+def : Pat<(SPUvec_srl_v8i16 (v8i16 VECREG:$rA), R16C:$rB),
+ (ROTHMv8i16 VECREG:$rA,
+ (SFIr32 (XSHWr16 R16C:$rB), 0))>;
+
+def : Pat<(SPUvec_srl_v8i16 (v8i16 VECREG:$rA), /* R8C */ R16C:$rB),
+ (ROTHMv8i16 VECREG:$rA,
+ (SFIr32 (XSHWr16 /* (XSBHr8 R8C */ R16C:$rB) /*)*/, 0))>;
+
+// ROTHM r16 form: Rotate 16-bit quantity to right, zero fill at the left
+// Note: This instruction doesn't match a pattern because rB must be negated
+// for the instruction to work. Thus, the pattern below the instruction!
+def ROTHMr16:
+ RRForm<0b10111010000, (outs R16C:$rT), (ins R16C:$rA, R32C:$rB),
+ "rothm\t$rT, $rA, $rB", RotateShift,
+ [/* see patterns below - $rB must be negated! */]>;
+
+def : Pat<(srl R16C:$rA, R32C:$rB),
+ (ROTHMr16 R16C:$rA, (SFIr32 R32C:$rB, 0))>;
+
+def : Pat<(srl R16C:$rA, R16C:$rB),
+ (ROTHMr16 R16C:$rA,
+ (SFIr32 (XSHWr16 R16C:$rB), 0))>;
+
+def : Pat<(srl R16C:$rA, /* R8C */ R16C:$rB),
+ (ROTHMr16 R16C:$rA,
+ (SFIr32 (XSHWr16 /* (XSBHr8 R8C */ R16C:$rB) /* ) */, 0))>;
+
+// ROTHMI v8i16 form: See the comment for ROTHM v8i16. The difference here is
+// that the immediate can be complemented, so that the user doesn't have to
+// worry about it.
+def ROTHMIv8i16:
+ RI7Form<0b10111110000, (outs VECREG:$rT), (ins VECREG:$rA, rothNeg7imm:$val),
+ "rothmi\t$rT, $rA, $val", RotateShift,
+ [(set (v8i16 VECREG:$rT),
+ (SPUvec_srl_v8i16 (v8i16 VECREG:$rA), (i32 imm:$val)))]>;
+
+def: Pat<(SPUvec_srl_v8i16 (v8i16 VECREG:$rA), (i16 imm:$val)),
+ (ROTHMIv8i16 VECREG:$rA, imm:$val)>;
+
+def ROTHMIr16:
+ RI7Form<0b10111110000, (outs R16C:$rT), (ins R16C:$rA, rothNeg7imm:$val),
+ "rothmi\t$rT, $rA, $val", RotateShift,
+ [(set R16C:$rT, (srl R16C:$rA, (i32 uimm7:$val)))]>;
+
+def: Pat<(srl R16C:$rA, (i16 uimm7:$val)),
+ (ROTHMIr16 R16C:$rA, uimm7:$val)>;
+
+// ROTM v4i32 form: See the ROTHM v8i16 comments.
+def ROTMv4i32:
+ RRForm<0b10011010000, (outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB),
+ "rotm\t$rT, $rA, $rB", RotateShift,
+ [/* see patterns below - $rB must be negated */]>;
+
+def : Pat<(SPUvec_srl_v4i32 VECREG:$rA, R32C:$rB),
+ (ROTMv4i32 VECREG:$rA, (SFIr32 R32C:$rB, 0))>;
+
+def : Pat<(SPUvec_srl_v4i32 VECREG:$rA, R16C:$rB),
+ (ROTMv4i32 VECREG:$rA,
+ (SFIr32 (XSHWr16 R16C:$rB), 0))>;
+
+def : Pat<(SPUvec_srl_v4i32 VECREG:$rA, /* R8C */ R16C:$rB),
+ (ROTMv4i32 VECREG:$rA,
+ (SFIr32 (XSHWr16 /* (XSBHr8 R8C */ R16C:$rB) /*)*/, 0))>;
+
+def ROTMr32:
+ RRForm<0b10011010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "rotm\t$rT, $rA, $rB", RotateShift,
+ [/* see patterns below - $rB must be negated */]>;
+
+def : Pat<(srl R32C:$rA, R32C:$rB),
+ (ROTMr32 R32C:$rA, (SFIr32 R32C:$rB, 0))>;
+
+def : Pat<(srl R32C:$rA, R16C:$rB),
+ (ROTMr32 R32C:$rA,
+ (SFIr32 (XSHWr16 R16C:$rB), 0))>;
+
+// ROTMI v4i32 form: See the comment for ROTHM v8i16.
+def ROTMIv4i32:
+ RI7Form<0b10011110000, (outs VECREG:$rT), (ins VECREG:$rA, rotNeg7imm:$val),
+ "rotmi\t$rT, $rA, $val", RotateShift,
+ [(set (v4i32 VECREG:$rT),
+ (SPUvec_srl_v4i32 VECREG:$rA, (i32 uimm7:$val)))]>;
+
+def : Pat<(SPUvec_srl_v4i32 VECREG:$rA, (i16 uimm7:$val)),
+ (ROTMIv4i32 VECREG:$rA, uimm7:$val)>;
+
+// ROTMI r32 form: know how to complement the immediate value.
+def ROTMIr32:
+ RI7Form<0b10011110000, (outs R32C:$rT), (ins R32C:$rA, rotNeg7imm:$val),
+ "rotmi\t$rT, $rA, $val", RotateShift,
+ [(set R32C:$rT, (srl R32C:$rA, (i32 uimm7:$val)))]>;
+
+def : Pat<(srl R32C:$rA, (i16 imm:$val)),
+ (ROTMIr32 R32C:$rA, uimm7:$val)>;
+
+// ROTQMBYvec: 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 complement $rB.
+def ROTQMBYvec:
+ RRForm<0b10111011100, (outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB),
+ "rotqmby\t$rT, $rA, $rB", RotateShift,
+ [(set (v16i8 VECREG:$rT),
+ (SPUrotbytes_right_zfill (v16i8 VECREG:$rA), R32C:$rB))]>;
+
+def ROTQMBYIvec:
+ RI7Form<0b10111111100, (outs VECREG:$rT), (ins VECREG:$rA, rotNeg7imm:$val),
+ "rotqmbyi\t$rT, $rA, $val", RotateShift,
+ [(set (v16i8 VECREG:$rT),
+ (SPUrotbytes_right_zfill (v16i8 VECREG:$rA), (i32 uimm7:$val)))]>;
+
+def : Pat<(SPUrotbytes_right_zfill VECREG:$rA, (i16 uimm7:$val)),
+ (ROTQMBYIvec VECREG:$rA, uimm7:$val)>;
+
+def ROTQMBYBIvec:
+ RRForm<0b10110011100, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "rotqmbybi\t$rT, $rA, $rB", RotateShift,
+ [/* intrinsic */]>;
+
+def ROTQMBIvec:
+ RRForm<0b10011011100, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "rotqmbi\t$rT, $rA, $rB", RotateShift,
+ [/* intrinsic */]>;
+
+def ROTQMBIIvec:
+ RI7Form<0b10011111100, (outs VECREG:$rT), (ins VECREG:$rA, rotNeg7imm:$val),
+ "rotqmbii\t$rT, $rA, $val", RotateShift,
+ [/* intrinsic */]>;
+
+def ROTMAHv8i16:
+ RRForm<0b01111010000, (outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB),
+ "rotmah\t$rT, $rA, $rB", RotateShift,
+ [/* see patterns below - $rB must be negated */]>;
+
+def : Pat<(SPUvec_sra_v8i16 VECREG:$rA, R32C:$rB),
+ (ROTMAHv8i16 VECREG:$rA, (SFIr32 R32C:$rB, 0))>;
+
+def : Pat<(SPUvec_sra_v8i16 VECREG:$rA, R16C:$rB),
+ (ROTMAHv8i16 VECREG:$rA,
+ (SFIr32 (XSHWr16 R16C:$rB), 0))>;
+
+def ROTMAHr16:
+ RRForm<0b01111010000, (outs R16C:$rT), (ins R16C:$rA, R32C:$rB),
+ "rotmah\t$rT, $rA, $rB", RotateShift,
+ [/* see patterns below - $rB must be negated */]>;
+
+def : Pat<(sra R16C:$rA, R32C:$rB),
+ (ROTMAHr16 R16C:$rA, (SFIr32 R32C:$rB, 0))>;
+
+def : Pat<(sra R16C:$rA, R16C:$rB),
+ (ROTMAHr16 R16C:$rA,
+ (SFIr32 (XSHWr16 R16C:$rB), 0))>;
+
+def ROTMAHIv8i16:
+ RRForm<0b01111110000, (outs VECREG:$rT), (ins VECREG:$rA, rothNeg7imm:$val),
+ "rotmahi\t$rT, $rA, $val", RotateShift,
+ [(set (v8i16 VECREG:$rT),
+ (SPUvec_sra_v8i16 (v8i16 VECREG:$rA), (i32 uimm7:$val)))]>;
+
+def : Pat<(SPUvec_sra_v8i16 (v8i16 VECREG:$rA), (i16 uimm7:$val)),
+ (ROTMAHIv8i16 (v8i16 VECREG:$rA), (i32 uimm7:$val))>;
+
+def ROTMAHIr16:
+ RRForm<0b01111110000, (outs R16C:$rT), (ins R16C:$rA, rothNeg7imm_i16:$val),
+ "rotmahi\t$rT, $rA, $val", RotateShift,
+ [(set R16C:$rT, (sra R16C:$rA, (i16 uimm7:$val)))]>;
+
+def : Pat<(sra R16C:$rA, (i32 imm:$val)),
+ (ROTMAHIr16 R16C:$rA, uimm7:$val)>;
+
+def ROTMAv4i32:
+ RRForm<0b01011010000, (outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB),
+ "rotma\t$rT, $rA, $rB", RotateShift,
+ [/* see patterns below - $rB must be negated */]>;
+
+def : Pat<(SPUvec_sra_v4i32 VECREG:$rA, R32C:$rB),
+ (ROTMAv4i32 (v4i32 VECREG:$rA), (SFIr32 R32C:$rB, 0))>;
+
+def : Pat<(SPUvec_sra_v4i32 VECREG:$rA, R16C:$rB),
+ (ROTMAv4i32 (v4i32 VECREG:$rA),
+ (SFIr32 (XSHWr16 R16C:$rB), 0))>;
+
+def ROTMAr32:
+ RRForm<0b01011010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "rotma\t$rT, $rA, $rB", RotateShift,
+ [/* see patterns below - $rB must be negated */]>;
+
+def : Pat<(sra R32C:$rA, R32C:$rB),
+ (ROTMAr32 R32C:$rA, (SFIr32 R32C:$rB, 0))>;
+
+def : Pat<(sra R32C:$rA, R16C:$rB),
+ (ROTMAr32 R32C:$rA,
+ (SFIr32 (XSHWr16 R16C:$rB), 0))>;
+
+def ROTMAIv4i32:
+ RRForm<0b01011110000, (outs VECREG:$rT), (ins VECREG:$rA, rotNeg7imm:$val),
+ "rotmai\t$rT, $rA, $val", RotateShift,
+ [(set (v4i32 VECREG:$rT),
+ (SPUvec_sra_v4i32 VECREG:$rA, (i32 uimm7:$val)))]>;
+
+def : Pat<(SPUvec_sra_v4i32 VECREG:$rA, (i16 uimm7:$val)),
+ (ROTMAIv4i32 VECREG:$rA, uimm7:$val)>;
+
+def ROTMAIr32:
+ RRForm<0b01011110000, (outs R32C:$rT), (ins R32C:$rA, rotNeg7imm:$val),
+ "rotmai\t$rT, $rA, $val", RotateShift,
+ [(set R32C:$rT, (sra R32C:$rA, (i32 uimm7:$val)))]>;
+
+def : Pat<(sra R32C:$rA, (i16 uimm7:$val)),
+ (ROTMAIr32 R32C:$rA, uimm7:$val)>;
+
+//===----------------------------------------------------------------------===//
+// Branch and conditionals:
+//===----------------------------------------------------------------------===//
+
+let isTerminator = 1, isBarrier = 1 in {
+ // Halt If Equal (r32 preferred slot only, no vector form)
+ def HEQr32:
+ RRForm_3<0b00011011110, (outs), (ins R32C:$rA, R32C:$rB),
+ "heq\t$rA, $rB", BranchResolv,
+ [/* no pattern to match */]>;
+
+ def HEQIr32 :
+ RI10Form_2<0b11111110, (outs), (ins R32C:$rA, s10imm:$val),
+ "heqi\t$rA, $val", BranchResolv,
+ [/* no pattern to match */]>;
+
+ // HGT/HGTI: These instructions use signed arithmetic for the comparison,
+ // contrasting with HLGT/HLGTI, which use unsigned comparison:
+ def HGTr32:
+ RRForm_3<0b00011010010, (outs), (ins R32C:$rA, R32C:$rB),
+ "hgt\t$rA, $rB", BranchResolv,
+ [/* no pattern to match */]>;
+
+ def HGTIr32:
+ RI10Form_2<0b11110010, (outs), (ins R32C:$rA, s10imm:$val),
+ "hgti\t$rA, $val", BranchResolv,
+ [/* no pattern to match */]>;
+
+ def HLGTr32:
+ RRForm_3<0b00011011010, (outs), (ins R32C:$rA, R32C:$rB),
+ "hlgt\t$rA, $rB", BranchResolv,
+ [/* no pattern to match */]>;
+
+ def HLGTIr32:
+ RI10Form_2<0b11111010, (outs), (ins R32C:$rA, s10imm:$val),
+ "hlgti\t$rA, $val", BranchResolv,
+ [/* no pattern to match */]>;
+}
+
+// Comparison operators:
+
+def CEQBv16i8:
+ RRForm<0b00001011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "ceqb\t$rT, $rA, $rB", ByteOp,
+ [/* no pattern to match: intrinsic */]>;
+
+def CEQBIv16i8:
+ RI10Form<0b01111110, (outs VECREG:$rT), (ins VECREG:$rA, s7imm:$val),
+ "ceqbi\t$rT, $rA, $val", ByteOp,
+ [/* no pattern to match: intrinsic */]>;
+
+def CEQHr16:
+ RRForm<0b00010011110, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
+ "ceqh\t$rT, $rA, $rB", ByteOp,
+ [/* no pattern to match */]>;
+
+def CEQHv8i16:
+ RRForm<0b00010011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "ceqh\t$rT, $rA, $rB", ByteOp,
+ [/* no pattern to match: intrinsic */]>;
+
+def CEQHIr16:
+ RI10Form<0b10111110, (outs R16C:$rT), (ins R16C:$rA, s10imm:$val),
+ "ceqhi\t$rT, $rA, $val", ByteOp,
+ [/* no pattern to match: intrinsic */]>;
+
+def CEQHIv8i16:
+ RI10Form<0b10111110, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ "ceqhi\t$rT, $rA, $val", ByteOp,
+ [/* no pattern to match: intrinsic */]>;
+
+def CEQr32:
+ RRForm<0b00000011110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
+ "ceq\t$rT, $rA, $rB", ByteOp,
+ [/* no pattern to match: intrinsic */]>;
+
+def CEQv4i32:
+ RRForm<0b00000011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "ceq\t$rT, $rA, $rB", ByteOp,
+ [/* no pattern to match: intrinsic */]>;
+
+def CEQIr32:
+ RI10Form<0b00111110, (outs R32C:$rT), (ins R32C:$rA, s10imm:$val),
+ "ceqi\t$rT, $rA, $val", ByteOp,
+ [/* no pattern to match: intrinsic */]>;
+
+def CEQIv4i32:
+ RI10Form<0b00111110, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
+ "ceqi\t$rT, $rA, $val", ByteOp,
+ [/* no pattern to match: intrinsic */]>;
+
+let isCall = 1,
+ // All calls clobber the non-callee-saved registers:
+ Defs = [R0, R1, R2, R3, R4, R5, R6, R7, R8, R9,
+ R10,R11,R12,R13,R14,R15,R16,R17,R18,R19,
+ R20,R21,R22,R23,R24,R25,R26,R27,R28,R29,
+ R30,R31,R32,R33,R34,R35,R36,R37,R38,R39,
+ R40,R41,R42,R43,R44,R45,R46,R47,R48,R49,
+ R50,R51,R52,R53,R54,R55,R56,R57,R58,R59,
+ R60,R61,R62,R63,R64,R65,R66,R67,R68,R69,
+ R70,R71,R72,R73,R74,R75,R76,R77,R78,R79],
+ // All of these instructions use $lr (aka $0)
+ Uses = [R0] in {
+ // Branch relative and set link: Used if we actually know that the target
+ // is within [-32768, 32767] bytes of the target
+ def BRSL:
+ BranchSetLink<0b011001100, (outs), (ins relcalltarget:$func, variable_ops),
+ "brsl\t$$lr, $func",
+ [(SPUcall (SPUpcrel tglobaladdr:$func, 0))]>;
+
+ // Branch absolute and set link: Used if we actually know that the target
+ // is an absolute address
+ def BRASL:
+ BranchSetLink<0b011001100, (outs), (ins calltarget:$func, variable_ops),
+ "brasl\t$$lr, $func",
+ [(SPUcall tglobaladdr:$func)]>;
+
+ // Branch indirect and set link if external data. These instructions are not
+ // actually generated, matched by an intrinsic:
+ def BISLED_00: BISLEDForm<0b11, "bisled\t$$lr, $func", [/* empty pattern */]>;
+ def BISLED_E0: BISLEDForm<0b10, "bisled\t$$lr, $func", [/* empty pattern */]>;
+ def BISLED_0D: BISLEDForm<0b01, "bisled\t$$lr, $func", [/* empty pattern */]>;
+ def BISLED_ED: BISLEDForm<0b00, "bisled\t$$lr, $func", [/* empty pattern */]>;
+
+ // Branch indirect and set link. This is the "X-form" address version of a
+ // function call
+ def BISL:
+ BIForm<0b10010101100, "bisl\t$$lr, $func", [(SPUcall R32C:$func)]>;
+}
+
+// Unconditional branches:
+let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in {
+ def BR :
+ UncondBranch<0b001001100, (outs), (ins brtarget:$dest),
+ "br\t$dest",
+ [(br bb:$dest)]>;
+
+ // Unconditional, absolute address branch
+ def BRA:
+ UncondBranch<0b001100000, (outs), (ins brtarget:$dest),
+ "bra\t$dest",
+ [/* no pattern */]>;
+
+ // Indirect branch
+ 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 */]>;
+
+ def BRHNZ:
+ RI16Form<0b011000100, (outs), (ins R16C:$rCond, brtarget:$dest),
+ "brhnz\t$rCond,$dest",
+ BranchResolv,
+ [(brcond R16C:$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)]>;
+
+ def BIZ:
+ BICondForm<0b00010100100, "biz\t$rA, $func",
+ [(SPUbiz R32C:$rA, R32C:$func)]>;
+*/
+}
+
+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 (i32 (seteq R32C:$rA, 0)), bb:$dest),
+ (BRZ R32C:$rA, bb:$dest)>;
+def : Pat<(brcond (i32 (setne R32C:$rA, 0)), bb:$dest),
+ (BRZ R32C:$rA, bb:$dest)>;
+
+let isTerminator = 1, isBarrier = 1 in {
+ let isReturn = 1 in {
+ def RET:
+ RETForm<"bi\t$$lr", [(retflag)]>;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Various brcond predicates:
+//===----------------------------------------------------------------------===//
+/*
+def : Pat<(brcond (i32 (seteq R32C:$rA, 0)), bb:$dest),
+ (BRZ R32C:$rA, bb:$dest)>;
+
+def : Pat<(brcond (i32 (seteq R32C:$rA, R32C:$rB)), bb:$dest),
+ (BRNZ (CEQr32 R32C:$rA, R32C:$rB), bb:$dest)>;
+
+def : Pat<(brcond (i16 (seteq R16C:$rA, i16ImmSExt10:$val)), bb:$dest),
+ (BRHNZ (CEQHIr16 R16C:$rA, i16ImmSExt10:$val), bb:$dest)>;
+
+def : Pat<(brcond (i16 (seteq R16C:$rA, R16C:$rB)), bb:$dest),
+ (BRHNZ (CEQHr16 R16C:$rA, R16C:$rB), bb:$dest)>;
+*/
+
+//===----------------------------------------------------------------------===//
+// 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)))]>;
+
+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))]>;
+
+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)))]>;
+
+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))]>;
+
+// 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))]>;
+
+// 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)))]>;
+
+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))]>;
+
+// Floating Compare Equal
+def FCEQf32 :
+ RRForm<0b01000011110, (outs R32C:$rT), (ins R32FP:$rA, R32FP:$rB),
+ "fceq\t$rT, $rA, $rB", SPrecFP,
+ [(set R32C:$rT, (setoeq R32FP:$rA, R32FP:$rB))]>;
+
+def FCMEQf32 :
+ RRForm<0b01010011110, (outs R32C:$rT), (ins R32FP:$rA, R32FP:$rB),
+ "fcmeq\t$rT, $rA, $rB", SPrecFP,
+ [(set R32C:$rT, (setoeq (fabs R32FP:$rA), (fabs R32FP:$rB)))]>;
+
+def FCGTf32 :
+ RRForm<0b01000011010, (outs R32C:$rT), (ins R32FP:$rA, R32FP:$rB),
+ "fcgt\t$rT, $rA, $rB", SPrecFP,
+ [(set R32C:$rT, (setogt R32FP:$rA, R32FP:$rB))]>;
+
+def FCMGTf32 :
+ RRForm<0b01010011010, (outs R32C:$rT), (ins R32FP:$rA, R32FP:$rB),
+ "fcmgt\t$rT, $rA, $rB", SPrecFP,
+ [(set R32C:$rT, (setogt (fabs R32FP:$rA), (fabs R32FP:$rB)))]>;
+
+// FP Status and Control Register Write
+// Why isn't rT a don't care in the ISA?
+// Should we create a special RRForm_3 for this guy and zero out the rT?
+def FSCRWf32 :
+ RRForm_1<0b01011101110, (outs R32FP:$rT), (ins R32FP:$rA),
+ "fscrwr\t$rA", SPrecFP,
+ [/* This instruction requires an intrinsic. Note: rT is unused. */]>;
+
+// FP Status and Control Register Read
+def FSCRRf32 :
+ RRForm_2<0b01011101110, (outs R32FP:$rT), (ins),
+ "fscrrd\t$rT", SPrecFP,
+ [/* This instruction requires an intrinsic */]>;
+
+// llvm instruction space
+// How do these map onto cell instructions?
+// fdiv rA rB
+// frest rC rB # c = 1/b (both lines)
+// fi rC rB rC
+// fm rD rA rC # d = a * 1/b
+// fnms rB rD rB rA # b = - (d * b - a) --should == 0 in a perfect world
+// fma rB rB rC rD # b = b * c + d
+// = -(d *b -a) * c + d
+// = a * c - c ( a *b *c - a)
+
+// fcopysign (???)
+
+// Library calls:
+// These llvm instructions will actually map to library calls.
+// All that's needed, then, is to check that the appropriate library is
+// imported and do a brsl to the proper function name.
+// frem # fmod(x, y): x - (x/y) * y
+// (Note: fmod(double, double), fmodf(float,float)
+// fsqrt?
+// fsin?
+// fcos?
+// Unimplemented SPU instruction space
+// floating reciprocal absolute square root estimate (frsqest)
+
+// The following are probably just intrinsics
+// status and control register write
+// status and control register read
+
+//--------------------------------------
+// Floating point multiply instructions
+//--------------------------------------
+
+def FMv4f32:
+ RRForm<0b00100011010, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "fm\t$rT, $rA, $rB", SPrecFP,
+ [(set (v4f32 VECREG:$rT), (fmul (v4f32 VECREG:$rA),
+ (v4f32 VECREG:$rB)))]>;
+
+def FMf32 :
+ RRForm<0b01100011010, (outs R32FP:$rT), (ins R32FP:$rA, R32FP:$rB),
+ "fm\t$rT, $rA, $rB", SPrecFP,
+ [(set R32FP:$rT, (fmul R32FP:$rA, R32FP:$rB))]>;
+
+// Floating point multiply and add
+// e.g. d = c + (a * b)
+def FMAv4f32:
+ RRRForm<0b0111, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ "fma\t$rT, $rA, $rB, $rC", SPrecFP,
+ [(set (v4f32 VECREG:$rT),
+ (fadd (v4f32 VECREG:$rC),
+ (fmul (v4f32 VECREG:$rA), (v4f32 VECREG:$rB))))]>;
+
+def FMAf32:
+ RRRForm<0b0111, (outs R32FP:$rT), (ins R32FP:$rA, R32FP:$rB, R32FP:$rC),
+ "fma\t$rT, $rA, $rB, $rC", SPrecFP,
+ [(set R32FP:$rT, (fadd R32FP:$rC, (fmul R32FP:$rA, R32FP:$rB)))]>;
+
+// FP multiply and subtract
+// Subtracts value in rC from product
+// res = a * b - c
+def FMSv4f32 :
+ RRRForm<0b0111, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ "fms\t$rT, $rA, $rB, $rC", SPrecFP,
+ [(set (v4f32 VECREG:$rT),
+ (fsub (fmul (v4f32 VECREG:$rA), (v4f32 VECREG:$rB)),
+ (v4f32 VECREG:$rC)))]>;
+
+def FMSf32 :
+ RRRForm<0b0111, (outs R32FP:$rT), (ins R32FP:$rA, R32FP:$rB, R32FP:$rC),
+ "fms\t$rT, $rA, $rB, $rC", SPrecFP,
+ [(set R32FP:$rT,
+ (fsub (fmul R32FP:$rA, R32FP:$rB), R32FP:$rC))]>;
+
+// Floating Negative Mulitply and Subtract
+// Subtracts product from value in rC
+// res = fneg(fms a b c)
+// = - (a * b - c)
+// = c - a * b
+// NOTE: subtraction order
+// fsub a b = a - b
+// 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,
+ [(set R32FP:$rT, (fsub R32FP:$rC, (fmul R32FP:$rA, R32FP:$rB)))]>;
+
+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),
+ (v4f32 VECREG:$rB))))]>;
+
+//--------------------------------------
+// Floating Point Conversions
+// Signed conversions:
+def CSiFv4f32:
+ CVTIntFPForm<0b0101101110, (outs VECREG:$rT), (ins VECREG:$rA),
+ "csflt\t$rT, $rA, 0", SPrecFP,
+ [(set (v4f32 VECREG:$rT), (sint_to_fp (v4i32 VECREG:$rA)))]>;
+
+// Convert signed integer to floating point
+def CSiFf32 :
+ CVTIntFPForm<0b0101101110, (outs R32FP:$rT), (ins R32C:$rA),
+ "csflt\t$rT, $rA, 0", SPrecFP,
+ [(set R32FP:$rT, (sint_to_fp R32C:$rA))]>;
+
+// Convert unsigned into to float
+def CUiFv4f32 :
+ CVTIntFPForm<0b1101101110, (outs VECREG:$rT), (ins VECREG:$rA),
+ "cuflt\t$rT, $rA, 0", SPrecFP,
+ [(set (v4f32 VECREG:$rT), (uint_to_fp (v4i32 VECREG:$rA)))]>;
+
+def CUiFf32 :
+ CVTIntFPForm<0b1101101110, (outs R32FP:$rT), (ins R32C:$rA),
+ "cuflt\t$rT, $rA, 0", SPrecFP,
+ [(set R32FP:$rT, (uint_to_fp R32C:$rA))]>;
+
+// Convert float to unsigned int
+// Assume that scale = 0
+
+def CFUiv4f32 :
+ CVTIntFPForm<0b1101101110, (outs VECREG:$rT), (ins VECREG:$rA),
+ "cfltu\t$rT, $rA, 0", SPrecFP,
+ [(set (v4i32 VECREG:$rT), (fp_to_uint (v4f32 VECREG:$rA)))]>;
+
+def CFUif32 :
+ CVTIntFPForm<0b1101101110, (outs R32C:$rT), (ins R32FP:$rA),
+ "cfltu\t$rT, $rA, 0", SPrecFP,
+ [(set R32C:$rT, (fp_to_uint R32FP:$rA))]>;
+
+// Convert float to signed int
+// Assume that scale = 0
+
+def CFSiv4f32 :
+ CVTIntFPForm<0b1101101110, (outs VECREG:$rT), (ins VECREG:$rA),
+ "cflts\t$rT, $rA, 0", SPrecFP,
+ [(set (v4i32 VECREG:$rT), (fp_to_sint (v4f32 VECREG:$rA)))]>;
+
+def CFSif32 :
+ CVTIntFPForm<0b1101101110, (outs R32C:$rT), (ins R32FP:$rA),
+ "cflts\t$rT, $rA, 0", SPrecFP,
+ [(set R32C:$rT, (fp_to_sint R32FP:$rA))]>;
+
+//===----------------------------------------------------------------------==//
+// Single<->Double precision conversions
+//===----------------------------------------------------------------------==//
+
+// NOTE: We use "vec" name suffix here to avoid confusion (e.g. input is a
+// v4f32, output is v2f64--which goes in the name?)
+
+// Floating point extend single to double
+// NOTE: Not sure if passing in v4f32 to FESDvec is correct since it
+// operates on two double-word slots (i.e. 1st and 3rd fp numbers
+// are ignored).
+def FESDvec :
+ RRForm_1<0b00011101110, (outs VECREG:$rT), (ins VECREG:$rA),
+ "fesd\t$rT, $rA", SPrecFP,
+ [(set (v2f64 VECREG:$rT), (fextend (v4f32 VECREG:$rA)))]>;
+
+def FESDf32 :
+ RRForm_1<0b00011101110, (outs R64FP:$rT), (ins R32FP:$rA),
+ "fesd\t$rT, $rA", SPrecFP,
+ [(set R64FP:$rT, (fextend R32FP:$rA))]>;
+
+// Floating point round double to single
+//def FRDSvec :
+// RRForm_1<0b10011101110, (outs VECREG:$rT), (ins VECREG:$rA),
+// "frds\t$rT, $rA,", SPrecFP,
+// [(set (v4f32 R32FP:$rT), (fround (v2f64 R64FP:$rA)))]>;
+
+def FRDSf64 :
+ RRForm_1<0b10011101110, (outs R32FP:$rT), (ins R64FP:$rA),
+ "frds\t$rT, $rA", SPrecFP,
+ [(set R32FP:$rT, (fround R64FP:$rA))]>;
+
+//ToDo include anyextend?
+
+//===----------------------------------------------------------------------==//
+// Double precision floating point instructions
+//===----------------------------------------------------------------------==//
+def FAf64 :
+ RRForm<0b00110011010, (outs R64FP:$rT), (ins R64FP:$rA, R64FP:$rB),
+ "dfa\t$rT, $rA, $rB", DPrecFP,
+ [(set R64FP:$rT, (fadd R64FP:$rA, R64FP:$rB))]>;
+
+def FAv2f64 :
+ RRForm<0b00110011010, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "dfa\t$rT, $rA, $rB", DPrecFP,
+ [(set (v2f64 VECREG:$rT), (fadd (v2f64 VECREG:$rA), (v2f64 VECREG:$rB)))]>;
+
+def FSf64 :
+ RRForm<0b10100011010, (outs R64FP:$rT), (ins R64FP:$rA, R64FP:$rB),
+ "dfs\t$rT, $rA, $rB", DPrecFP,
+ [(set R64FP:$rT, (fsub R64FP:$rA, R64FP:$rB))]>;
+
+def FSv2f64 :
+ RRForm<0b10100011010, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "dfs\t$rT, $rA, $rB", DPrecFP,
+ [(set (v2f64 VECREG:$rT),
+ (fsub (v2f64 VECREG:$rA), (v2f64 VECREG:$rB)))]>;
+
+def FMf64 :
+ RRForm<0b01100011010, (outs R64FP:$rT), (ins R64FP:$rA, R64FP:$rB),
+ "dfm\t$rT, $rA, $rB", DPrecFP,
+ [(set R64FP:$rT, (fmul R64FP:$rA, R64FP:$rB))]>;
+
+def FMv2f64:
+ RRForm<0b00100011010, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ "dfm\t$rT, $rA, $rB", DPrecFP,
+ [(set (v2f64 VECREG:$rT),
+ (fmul (v2f64 VECREG:$rA), (v2f64 VECREG:$rB)))]>;
+
+def FMAf64:
+ RRForm<0b00111010110, (outs R64FP:$rT),
+ (ins R64FP:$rA, R64FP:$rB, R64FP:$rC),
+ "dfma\t$rT, $rA, $rB", DPrecFP,
+ [(set R64FP:$rT, (fadd R64FP:$rC, (fmul R64FP:$rA, R64FP:$rB)))]>,
+ RegConstraint<"$rC = $rT">,
+ NoEncode<"$rC">;
+
+def FMAv2f64:
+ RRForm<0b00111010110, (outs VECREG:$rT),
+ (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ "dfma\t$rT, $rA, $rB", DPrecFP,
+ [(set (v2f64 VECREG:$rT),
+ (fadd (v2f64 VECREG:$rC),
+ (fmul (v2f64 VECREG:$rA), (v2f64 VECREG:$rB))))]>,
+ RegConstraint<"$rC = $rT">,
+ NoEncode<"$rC">;
+
+def FMSf64 :
+ RRForm<0b10111010110, (outs R64FP:$rT),
+ (ins R64FP:$rA, R64FP:$rB, R64FP:$rC),
+ "dfms\t$rT, $rA, $rB", DPrecFP,
+ [(set R64FP:$rT, (fsub (fmul R64FP:$rA, R64FP:$rB), R64FP:$rC))]>,
+ RegConstraint<"$rC = $rT">,
+ NoEncode<"$rC">;
+
+def FMSv2f64 :
+ RRForm<0b10111010110, (outs VECREG:$rT),
+ (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ "dfms\t$rT, $rA, $rB", DPrecFP,
+ [(set (v2f64 VECREG:$rT),
+ (fsub (fmul (v2f64 VECREG:$rA), (v2f64 VECREG:$rB)),
+ (v2f64 VECREG:$rC)))]>;
+
+// FNMS: - (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)))]>,
+ RegConstraint<"$rC = $rT">,
+ NoEncode<"$rC">;
+
+def : Pat<(fneg (fsub (fmul R64FP:$rA, R64FP:$rB), R64FP:$rC)),
+ (FNMSf64 R64FP:$rA, R64FP:$rB, R64FP:$rC)>;
+
+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">;
+
+def : Pat<(fneg (fsub (fmul (v2f64 VECREG:$rA), (v2f64 VECREG:$rB)),
+ (v2f64 VECREG:$rC))),
+ (FNMSv2f64 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+
+// - (a * b + c)
+// - (a * b) - c
+def FNMAf64 :
+ RRForm<0b11111010110, (outs R64FP:$rT),
+ (ins R64FP:$rA, R64FP:$rB, R64FP:$rC),
+ "dfnma\t$rT, $rA, $rB", DPrecFP,
+ [(set R64FP:$rT, (fneg (fadd R64FP:$rC, (fmul R64FP:$rA, R64FP:$rB))))]>,
+ RegConstraint<"$rC = $rT">,
+ NoEncode<"$rC">;
+
+def FNMAv2f64 :
+ 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),
+ (v2f64 VECREG:$rB)))))]>,
+ RegConstraint<"$rC = $rT">,
+ NoEncode<"$rC">;
+
+//===----------------------------------------------------------------------==//
+// Floating point negation and absolute value
+//===----------------------------------------------------------------------==//
+
+def : Pat<(fneg (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
+
+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)))>;
+
+def : Pat<(fabs R64FP:$rA),
+ (ANDfabs64 R64FP:$rA, (ANDBIv16i8 (FSMBIv16i8 0xffff), 0x7f))>;
+
+def : Pat<(fabs (v2f64 VECREG:$rA)),
+ (ANDfabsvec (v2f64 VECREG:$rA),
+ (v2f64 (ANDBIv16i8 (FSMBIv16i8 0xffff), 0x7f)))>;
+
+//===----------------------------------------------------------------------===//
+// Execution, Load NOP (execute NOPs belong in even pipeline, load NOPs belong
+// in the odd pipeline)
+//===----------------------------------------------------------------------===//
+
+def ENOP : I<(outs), (ins), "enop", ExecNOP> {
+ let Pattern = [];
+
+ let Inst{0-10} = 0b10000000010;
+ let Inst{11-17} = 0;
+ let Inst{18-24} = 0;
+ let Inst{25-31} = 0;
+}
+
+def LNOP : I<(outs), (ins), "lnop", LoadNOP> {
+ let Pattern = [];
+
+ let Inst{0-10} = 0b10000000000;
+ let Inst{11-17} = 0;
+ let Inst{18-24} = 0;
+ let Inst{25-31} = 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Bit conversions (type conversions between vector/packed types)
+// NOTE: Promotions are handled using the XS* instructions. Truncation
+// is not handled.
+//===----------------------------------------------------------------------===//
+def : Pat<(v16i8 (bitconvert (v8i16 VECREG:$src))), (v16i8 VECREG:$src)>;
+def : Pat<(v16i8 (bitconvert (v4i32 VECREG:$src))), (v16i8 VECREG:$src)>;
+def : Pat<(v16i8 (bitconvert (v2i64 VECREG:$src))), (v16i8 VECREG:$src)>;
+def : Pat<(v16i8 (bitconvert (v4f32 VECREG:$src))), (v16i8 VECREG:$src)>;
+def : Pat<(v16i8 (bitconvert (v2f64 VECREG:$src))), (v16i8 VECREG:$src)>;
+
+def : Pat<(v8i16 (bitconvert (v16i8 VECREG:$src))), (v8i16 VECREG:$src)>;
+def : Pat<(v8i16 (bitconvert (v4i32 VECREG:$src))), (v8i16 VECREG:$src)>;
+def : Pat<(v8i16 (bitconvert (v2i64 VECREG:$src))), (v8i16 VECREG:$src)>;
+def : Pat<(v8i16 (bitconvert (v4f32 VECREG:$src))), (v8i16 VECREG:$src)>;
+def : Pat<(v8i16 (bitconvert (v2f64 VECREG:$src))), (v8i16 VECREG:$src)>;
+
+def : Pat<(v4i32 (bitconvert (v16i8 VECREG:$src))), (v4i32 VECREG:$src)>;
+def : Pat<(v4i32 (bitconvert (v8i16 VECREG:$src))), (v4i32 VECREG:$src)>;
+def : Pat<(v4i32 (bitconvert (v2i64 VECREG:$src))), (v4i32 VECREG:$src)>;
+def : Pat<(v4i32 (bitconvert (v4f32 VECREG:$src))), (v4i32 VECREG:$src)>;
+def : Pat<(v4i32 (bitconvert (v2f64 VECREG:$src))), (v4i32 VECREG:$src)>;
+
+def : Pat<(v2i64 (bitconvert (v16i8 VECREG:$src))), (v2i64 VECREG:$src)>;
+def : Pat<(v2i64 (bitconvert (v8i16 VECREG:$src))), (v2i64 VECREG:$src)>;
+def : Pat<(v2i64 (bitconvert (v4i32 VECREG:$src))), (v2i64 VECREG:$src)>;
+def : Pat<(v2i64 (bitconvert (v4f32 VECREG:$src))), (v2i64 VECREG:$src)>;
+def : Pat<(v2i64 (bitconvert (v2f64 VECREG:$src))), (v2i64 VECREG:$src)>;
+
+def : Pat<(v4f32 (bitconvert (v16i8 VECREG:$src))), (v4f32 VECREG:$src)>;
+def : Pat<(v4f32 (bitconvert (v8i16 VECREG:$src))), (v4f32 VECREG:$src)>;
+def : Pat<(v4f32 (bitconvert (v2i64 VECREG:$src))), (v4f32 VECREG:$src)>;
+def : Pat<(v4f32 (bitconvert (v4i32 VECREG:$src))), (v4f32 VECREG:$src)>;
+def : Pat<(v4f32 (bitconvert (v2f64 VECREG:$src))), (v4f32 VECREG:$src)>;
+
+def : Pat<(v2f64 (bitconvert (v16i8 VECREG:$src))), (v2f64 VECREG:$src)>;
+def : Pat<(v2f64 (bitconvert (v8i16 VECREG:$src))), (v2f64 VECREG:$src)>;
+def : Pat<(v2f64 (bitconvert (v4i32 VECREG:$src))), (v2f64 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)>;
+
+//===----------------------------------------------------------------------===//
+// Instruction patterns:
+//===----------------------------------------------------------------------===//
+
+// General 32-bit constants:
+def : Pat<(i32 imm:$imm),
+ (IOHLr32 (ILHUr32 (HI16 imm:$imm)), (LO16 imm:$imm))>;
+
+// Single precision float constants:
+def : Pat<(SPUFPconstant (f32 fpimm:$imm)),
+ (IOHLf32 (ILHUf32 (HI16_f32 fpimm:$imm)), (LO16_f32 fpimm:$imm))>;
+
+// General constant 32-bit vectors
+def : Pat<(v4i32 v4i32Imm:$imm),
+ (IOHLvec (v4i32 (ILHUv4i32 (HI16_vec v4i32Imm:$imm))),
+ (LO16_vec v4i32Imm:$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<(SPUextract_i8_sext VECREG:$rSrc),
+ (XSHWr32 (XSBHr32 (ORi32_v4i32 (v4i32 VECREG:$rSrc),
+ (v4i32 VECREG:$rSrc))))>;
+
+def : Pat<(SPUextract_i8_zext VECREG:$rSrc),
+ (ANDIr32 (ORi32_v4i32 (v4i32 VECREG:$rSrc), (v4i32 VECREG:$rSrc)),
+ 0xff)>;
+
+// zext 16->32: Zero extend halfwords to words (note that we have to juggle the
+// 0xffff constant since it will not fit into an immediate.)
+def : Pat<(i32 (zext R16C:$rSrc)),
+ (AND2To4 R16C:$rSrc, (ILAr32 0xffff))>;
+
+def : Pat<(i32 (zext (and R16C:$rSrc, 0xf))),
+ (ANDI2To4 R16C:$rSrc, 0xf)>;
+
+def : Pat<(i32 (zext (and R16C:$rSrc, 0xff))),
+ (ANDI2To4 R16C:$rSrc, 0xff)>;
+
+def : Pat<(i32 (zext (and R16C:$rSrc, 0xfff))),
+ (ANDI2To4 R16C:$rSrc, 0xfff)>;
+
+// anyext 16->32: Extend 16->32 bits, irrespective of sign
+def : Pat<(i32 (anyext R16C:$rSrc)),
+ (ORI2To4 R16C:$rSrc, 0)>;
+
+//===----------------------------------------------------------------------===//
+// Address translation: SPU, like PPC, has to split addresses into high and
+// low parts in order to load them into a register.
+//===----------------------------------------------------------------------===//
+
+def : Pat<(SPUhi tglobaladdr:$in, 0), (ILHUhi tglobaladdr:$in)>;
+def : Pat<(SPUlo tglobaladdr:$in, 0), (ILAlo tglobaladdr:$in)>;
+def : Pat<(SPUdform tglobaladdr:$in, imm:$imm), (ILAlsa tglobaladdr:$in)>;
+def : Pat<(SPUhi tconstpool:$in , 0), (ILHUhi tconstpool:$in)>;
+def : Pat<(SPUlo tconstpool:$in , 0), (ILAlo tconstpool:$in)>;
+def : Pat<(SPUdform tconstpool:$in, imm:$imm), (ILAlsa tconstpool:$in)>;
+def : Pat<(SPUhi tjumptable:$in, 0), (ILHUhi tjumptable:$in)>;
+def : Pat<(SPUlo tjumptable:$in, 0), (ILAlo tjumptable:$in)>;
+def : Pat<(SPUdform tjumptable:$in, imm:$imm), (ILAlsa tjumptable:$in)>;
+
+// Force load of global address to a register. These forms show up in
+// SPUISD::DFormAddr pseudo instructions:
+/*
+def : Pat<(add tglobaladdr:$in, 0), (ILAlsa tglobaladdr:$in)>;
+def : Pat<(add tconstpool:$in, 0), (ILAlsa tglobaladdr:$in)>;
+def : Pat<(add tjumptable:$in, 0), (ILAlsa tglobaladdr:$in)>;
+ */
+// Instrinsics:
+include "CellSDKIntrinsics.td"
More information about the llvm-commits
mailing list