aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Michel <scottm@aero.org>2007-12-04 22:35:58 +0000
committerScott Michel <scottm@aero.org>2007-12-04 22:35:58 +0000
commit663775299889de76a7d67e52482c2ee352cd5123 (patch)
tree69e035d96d2a1ed1be815d40891f8c307f1d4c31
parent266bc8f7774b153401e54ed537db299159840981 (diff)
More files in the CellSPU drop...
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44584 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/CellSPU/SPUInstrInfo.cpp184
-rw-r--r--lib/Target/CellSPU/SPUInstrInfo.h54
-rw-r--r--lib/Target/CellSPU/SPUInstrInfo.td3145
3 files changed, 3383 insertions, 0 deletions
diff --git a/lib/Target/CellSPU/SPUInstrInfo.cpp b/lib/Target/CellSPU/SPUInstrInfo.cpp
new file mode 100644
index 0000000000..d65a528943
--- /dev/null
+++ b/lib/Target/CellSPU/SPUInstrInfo.cpp
@@ -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;
+}
diff --git a/lib/Target/CellSPU/SPUInstrInfo.h b/lib/Target/CellSPU/SPUInstrInfo.h
new file mode 100644
index 0000000000..0728c41ade
--- /dev/null
+++ b/lib/Target/CellSPU/SPUInstrInfo.h
@@ -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
diff --git a/lib/Target/CellSPU/SPUInstrInfo.td b/lib/Target/CellSPU/SPUInstrInfo.td
new file mode 100644
index 0000000000..71ff34b02b
--- /dev/null
+++ b/lib/Target/CellSPU/SPUInstrInfo.td
@@ -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
+