SIMCCodeEmitter.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===-- SIMCCodeEmitter.cpp - SI Code Emitter -------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10/// \file
11/// \brief The SI code emitter produces machine code that can be executed
12/// directly on the GPU device.
13//
14//===----------------------------------------------------------------------===//
15
16#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
17#include "MCTargetDesc/AMDGPUMCCodeEmitter.h"
18#include "llvm/MC/MCCodeEmitter.h"
19#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCFixup.h"
21#include "llvm/MC/MCInst.h"
22#include "llvm/MC/MCInstrInfo.h"
23#include "llvm/MC/MCRegisterInfo.h"
24#include "llvm/MC/MCSubtargetInfo.h"
25#include "llvm/Support/raw_ostream.h"
26
27using namespace llvm;
28
29namespace {
30
31/// \brief Helper type used in encoding
32typedef union {
33  int32_t I;
34  float F;
35} IntFloatUnion;
36
37class SIMCCodeEmitter : public  AMDGPUMCCodeEmitter {
38  SIMCCodeEmitter(const SIMCCodeEmitter &) LLVM_DELETED_FUNCTION;
39  void operator=(const SIMCCodeEmitter &) LLVM_DELETED_FUNCTION;
40  const MCInstrInfo &MCII;
41  const MCRegisterInfo &MRI;
42
43  /// \brief Can this operand also contain immediate values?
44  bool isSrcOperand(const MCInstrDesc &Desc, unsigned OpNo) const;
45
46  /// \brief Encode an fp or int literal
47  uint32_t getLitEncoding(const MCOperand &MO) const;
48
49public:
50  SIMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri,
51                  MCContext &ctx)
52    : MCII(mcii), MRI(mri) { }
53
54  ~SIMCCodeEmitter() { }
55
56  /// \brief Encode the instruction and write it to the OS.
57  virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
58                         SmallVectorImpl<MCFixup> &Fixups,
59                         const MCSubtargetInfo &STI) const;
60
61  /// \returns the encoding for an MCOperand.
62  virtual uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
63                                     SmallVectorImpl<MCFixup> &Fixups,
64                                     const MCSubtargetInfo &STI) const;
65};
66
67} // End anonymous namespace
68
69MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII,
70                                           const MCRegisterInfo &MRI,
71                                           const MCSubtargetInfo &STI,
72                                           MCContext &Ctx) {
73  return new SIMCCodeEmitter(MCII, MRI, Ctx);
74}
75
76bool SIMCCodeEmitter::isSrcOperand(const MCInstrDesc &Desc,
77                                   unsigned OpNo) const {
78
79  unsigned RegClass = Desc.OpInfo[OpNo].RegClass;
80  return (AMDGPU::SSrc_32RegClassID == RegClass) ||
81         (AMDGPU::SSrc_64RegClassID == RegClass) ||
82         (AMDGPU::VSrc_32RegClassID == RegClass) ||
83         (AMDGPU::VSrc_64RegClassID == RegClass);
84}
85
86uint32_t SIMCCodeEmitter::getLitEncoding(const MCOperand &MO) const {
87
88  IntFloatUnion Imm;
89  if (MO.isImm())
90    Imm.I = MO.getImm();
91  else if (MO.isFPImm())
92    Imm.F = MO.getFPImm();
93  else
94    return ~0;
95
96  if (Imm.I >= 0 && Imm.I <= 64)
97    return 128 + Imm.I;
98
99  if (Imm.I >= -16 && Imm.I <= -1)
100    return 192 + abs(Imm.I);
101
102  if (Imm.F == 0.5f)
103    return 240;
104
105  if (Imm.F == -0.5f)
106    return 241;
107
108  if (Imm.F == 1.0f)
109    return 242;
110
111  if (Imm.F == -1.0f)
112    return 243;
113
114  if (Imm.F == 2.0f)
115    return 244;
116
117  if (Imm.F == -2.0f)
118    return 245;
119
120  if (Imm.F == 4.0f)
121    return 246;
122
123  if (Imm.F == -4.0f)
124    return 247;
125
126  return 255;
127}
128
129void SIMCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS,
130                                       SmallVectorImpl<MCFixup> &Fixups,
131                                       const MCSubtargetInfo &STI) const {
132
133  uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups, STI);
134  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
135  unsigned bytes = Desc.getSize();
136
137  for (unsigned i = 0; i < bytes; i++) {
138    OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff));
139  }
140
141  if (bytes > 4)
142    return;
143
144  // Check for additional literals in SRC0/1/2 (Op 1/2/3)
145  for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) {
146
147    // Check if this operand should be encoded as [SV]Src
148    if (!isSrcOperand(Desc, i))
149      continue;
150
151    // Is this operand a literal immediate?
152    const MCOperand &Op = MI.getOperand(i);
153    if (getLitEncoding(Op) != 255)
154      continue;
155
156    // Yes! Encode it
157    IntFloatUnion Imm;
158    if (Op.isImm())
159      Imm.I = Op.getImm();
160    else
161      Imm.F = Op.getFPImm();
162
163    for (unsigned j = 0; j < 4; j++) {
164      OS.write((uint8_t) ((Imm.I >> (8 * j)) & 0xff));
165    }
166
167    // Only one literal value allowed
168    break;
169  }
170}
171
172uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI,
173                                            const MCOperand &MO,
174                                       SmallVectorImpl<MCFixup> &Fixups,
175                                       const MCSubtargetInfo &STI) const {
176  if (MO.isReg())
177    return MRI.getEncodingValue(MO.getReg());
178
179  if (MO.isExpr()) {
180    const MCExpr *Expr = MO.getExpr();
181    MCFixupKind Kind = MCFixupKind(FK_PCRel_4);
182    Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
183    return 0;
184  }
185
186  // Figure out the operand number, needed for isSrcOperand check
187  unsigned OpNo = 0;
188  for (unsigned e = MI.getNumOperands(); OpNo < e; ++OpNo) {
189    if (&MO == &MI.getOperand(OpNo))
190      break;
191  }
192
193  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
194  if (isSrcOperand(Desc, OpNo)) {
195    uint32_t Enc = getLitEncoding(MO);
196    if (Enc != ~0U && (Enc != 255 || Desc.getSize() == 4))
197      return Enc;
198
199  } else if (MO.isImm())
200    return MO.getImm();
201
202  llvm_unreachable("Encoding of this operand type is not supported yet.");
203  return 0;
204}
205
206