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