summaryrefslogtreecommitdiff
path: root/lib/Target/R600/MCTargetDesc
diff options
context:
space:
mode:
authorChristian Konig <christian.koenig@amd.com>2013-02-16 11:28:22 +0000
committerChristian Konig <christian.koenig@amd.com>2013-02-16 11:28:22 +0000
commite25e490793241e471036c3e2f969ce6a068e5ce1 (patch)
tree3a45cc748382fb881432d9993e1e03e5ce28514d /lib/Target/R600/MCTargetDesc
parent8e4eebcecf291386a321d0f8582b8a57841ea8c9 (diff)
downloadllvm-e25e490793241e471036c3e2f969ce6a068e5ce1.tar.gz
llvm-e25e490793241e471036c3e2f969ce6a068e5ce1.tar.bz2
llvm-e25e490793241e471036c3e2f969ce6a068e5ce1.tar.xz
R600/SI: cleanup literal handling v3
Seems to be allot simpler, and also paves the way for further improvements. v2: rebased on master, use 0 in BUFFER_LOAD_FORMAT_XYZW, use VGPR0 in dummy EXP, avoid compiler warning, break after encoding the first literal. v3: correctly use V_ADD_F32_e64 This is a candidate for the stable branch. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Tom Stellard <thomas.stellard@amd.com> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175354 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/R600/MCTargetDesc')
-rw-r--r--lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp146
1 files changed, 125 insertions, 21 deletions
diff --git a/lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp b/lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp
index fbdf77e8dc..0d9f3d8140 100644
--- a/lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp
+++ b/lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp
@@ -27,6 +27,13 @@
using namespace llvm;
namespace {
+
+/// \brief Helper type used in encoding
+typedef union {
+ int32_t I;
+ float F;
+} IntFloatUnion;
+
class SIMCCodeEmitter : public AMDGPUMCCodeEmitter {
SIMCCodeEmitter(const SIMCCodeEmitter &); // DO NOT IMPLEMENT
void operator=(const SIMCCodeEmitter &); // DO NOT IMPLEMENT
@@ -35,6 +42,15 @@ class SIMCCodeEmitter : public AMDGPUMCCodeEmitter {
const MCSubtargetInfo &STI;
MCContext &Ctx;
+ /// \brief Encode a sequence of registers with the correct alignment.
+ unsigned GPRAlign(const MCInst &MI, unsigned OpNo, unsigned shift) const;
+
+ /// \brief Can this operand also contain immediate values?
+ bool isSrcOperand(const MCInstrDesc &Desc, unsigned OpNo) const;
+
+ /// \brief Encode an fp or int literal
+ uint32_t getLitEncoding(const MCOperand &MO) const;
+
public:
SIMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri,
const MCSubtargetInfo &sti, MCContext &ctx)
@@ -50,11 +66,6 @@ public:
virtual uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups) const;
-public:
-
- /// \brief Encode a sequence of registers with the correct alignment.
- unsigned GPRAlign(const MCInst &MI, unsigned OpNo, unsigned shift) const;
-
/// \brief Encoding for when 2 consecutive registers are used
virtual unsigned GPR2AlignEncode(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixup) const;
@@ -73,39 +84,131 @@ MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII,
return new SIMCCodeEmitter(MCII, MRI, STI, Ctx);
}
+bool SIMCCodeEmitter::isSrcOperand(const MCInstrDesc &Desc,
+ unsigned OpNo) const {
+
+ unsigned RegClass = Desc.OpInfo[OpNo].RegClass;
+ return (AMDGPU::SSrc_32RegClassID == RegClass) ||
+ (AMDGPU::SSrc_64RegClassID == RegClass) ||
+ (AMDGPU::VSrc_32RegClassID == RegClass) ||
+ (AMDGPU::VSrc_64RegClassID == RegClass);
+}
+
+uint32_t SIMCCodeEmitter::getLitEncoding(const MCOperand &MO) const {
+
+ IntFloatUnion Imm;
+ if (MO.isImm())
+ Imm.I = MO.getImm();
+ else if (MO.isFPImm())
+ Imm.F = MO.getFPImm();
+ else
+ return ~0;
+
+ if (Imm.I >= 0 && Imm.I <= 64)
+ return 128 + Imm.I;
+
+ if (Imm.I >= -16 && Imm.I <= -1)
+ return 192 + abs(Imm.I);
+
+ if (Imm.F == 0.5f)
+ return 240;
+
+ if (Imm.F == -0.5f)
+ return 241;
+
+ if (Imm.F == 1.0f)
+ return 242;
+
+ if (Imm.F == -1.0f)
+ return 243;
+
+ if (Imm.F == 2.0f)
+ return 244;
+
+ if (Imm.F == -2.0f)
+ return 245;
+
+ if (Imm.F == 4.0f)
+ return 246;
+
+ if (Imm.F == 4.0f)
+ return 247;
+
+ return 255;
+}
+
void SIMCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups) const {
+
uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups);
- unsigned bytes = MCII.get(MI.getOpcode()).getSize();
+ const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
+ unsigned bytes = Desc.getSize();
+
for (unsigned i = 0; i < bytes; i++) {
OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff));
}
+
+ if (bytes > 4)
+ return;
+
+ // Check for additional literals in SRC0/1/2 (Op 1/2/3)
+ for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) {
+
+ // Check if this operand should be encoded as [SV]Src
+ if (!isSrcOperand(Desc, i))
+ continue;
+
+ // Is this operand a literal immediate?
+ const MCOperand &Op = MI.getOperand(i);
+ if (getLitEncoding(Op) != 255)
+ continue;
+
+ // Yes! Encode it
+ IntFloatUnion Imm;
+ if (Op.isImm())
+ Imm.I = Op.getImm();
+ else
+ Imm.F = Op.getFPImm();
+
+ for (unsigned j = 0; j < 4; j++) {
+ OS.write((uint8_t) ((Imm.I >> (8 * j)) & 0xff));
+ }
+
+ // Only one literal value allowed
+ break;
+ }
}
uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI,
const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups) const {
- if (MO.isReg()) {
+ if (MO.isReg())
return MRI.getEncodingValue(MO.getReg());
- } else if (MO.isImm()) {
- return MO.getImm();
- } else if (MO.isFPImm()) {
- // XXX: Not all instructions can use inline literals
- // XXX: We should make sure this is a 32-bit constant
- union {
- float F;
- uint32_t I;
- } Imm;
- Imm.F = MO.getFPImm();
- return Imm.I;
- } else if (MO.isExpr()) {
+
+ if (MO.isExpr()) {
const MCExpr *Expr = MO.getExpr();
MCFixupKind Kind = MCFixupKind(FK_PCRel_4);
Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
return 0;
- } else{
- llvm_unreachable("Encoding of this operand type is not supported yet.");
}
+
+ // Figure out the operand number, needed for isSrcOperand check
+ unsigned OpNo = 0;
+ for (unsigned e = MI.getNumOperands(); OpNo < e; ++OpNo) {
+ if (&MO == &MI.getOperand(OpNo))
+ break;
+ }
+
+ const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
+ if (isSrcOperand(Desc, OpNo)) {
+ uint32_t Enc = getLitEncoding(MO);
+ if (Enc != ~0U && (Enc != 255 || Desc.getSize() == 4))
+ return Enc;
+
+ } else if (MO.isImm())
+ return MO.getImm();
+
+ llvm_unreachable("Encoding of this operand type is not supported yet.");
return 0;
}
@@ -118,6 +221,7 @@ unsigned SIMCCodeEmitter::GPRAlign(const MCInst &MI, unsigned OpNo,
unsigned regCode = MRI.getEncodingValue(MI.getOperand(OpNo).getReg());
return (regCode & 0xff) >> shift;
}
+
unsigned SIMCCodeEmitter::GPR2AlignEncode(const MCInst &MI,
unsigned OpNo ,
SmallVectorImpl<MCFixup> &Fixup) const {