diff options
author | Scott Michel <scottm@aero.org> | 2007-12-04 22:35:58 +0000 |
---|---|---|
committer | Scott Michel <scottm@aero.org> | 2007-12-04 22:35:58 +0000 |
commit | 663775299889de76a7d67e52482c2ee352cd5123 (patch) | |
tree | 69e035d96d2a1ed1be815d40891f8c307f1d4c31 | |
parent | 266bc8f7774b153401e54ed537db299159840981 (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.cpp | 184 | ||||
-rw-r--r-- | lib/Target/CellSPU/SPUInstrInfo.h | 54 | ||||
-rw-r--r-- | lib/Target/CellSPU/SPUInstrInfo.td | 3145 |
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 + |