LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
R600MCCodeEmitter.cpp
Go to the documentation of this file.
1 //===- R600MCCodeEmitter.cpp - Code Emitter for R600->Cayman GPU families -===//
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 ///
12 /// \brief The R600 code emitter produces machine code that can be executed
13 /// directly on the GPU device.
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #include "R600Defines.h"
20 #include "llvm/MC/MCCodeEmitter.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCInstrInfo.h"
24 #include "llvm/MC/MCRegisterInfo.h"
27 
28 using namespace llvm;
29 
30 namespace {
31 
32 class R600MCCodeEmitter : public AMDGPUMCCodeEmitter {
33  R600MCCodeEmitter(const R600MCCodeEmitter &) LLVM_DELETED_FUNCTION;
34  void operator=(const R600MCCodeEmitter &) LLVM_DELETED_FUNCTION;
35  const MCInstrInfo &MCII;
36  const MCRegisterInfo &MRI;
37  const MCSubtargetInfo &STI;
38 
39 public:
40 
41  R600MCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri,
42  const MCSubtargetInfo &sti)
43  : MCII(mcii), MRI(mri), STI(sti) { }
44 
45  /// \brief Encode the instruction and write it to the OS.
46  virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
48 
49  /// \returns the encoding for an MCOperand.
50  virtual uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
52 private:
53 
54  void EmitByte(unsigned int byte, raw_ostream &OS) const;
55 
56  void Emit(uint32_t value, raw_ostream &OS) const;
57  void Emit(uint64_t value, raw_ostream &OS) const;
58 
59  unsigned getHWRegChan(unsigned reg) const;
60  unsigned getHWReg(unsigned regNo) const;
61 
62 };
63 
64 } // End anonymous namespace
65 
66 enum RegElement {
67  ELEMENT_X = 0,
71 };
72 
73 enum FCInstr {
81 };
82 
84  const MCRegisterInfo &MRI,
85  const MCSubtargetInfo &STI) {
86  return new R600MCCodeEmitter(MCII, MRI, STI);
87 }
88 
89 void R600MCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS,
91  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
92  if (MI.getOpcode() == AMDGPU::RETURN ||
93  MI.getOpcode() == AMDGPU::FETCH_CLAUSE ||
94  MI.getOpcode() == AMDGPU::ALU_CLAUSE ||
95  MI.getOpcode() == AMDGPU::BUNDLE ||
96  MI.getOpcode() == AMDGPU::KILL) {
97  return;
98  } else if (IS_VTX(Desc)) {
99  uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups);
100  uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset
101  if (!(STI.getFeatureBits() & AMDGPU::FeatureCaymanISA)) {
102  InstWord2 |= 1 << 19; // Mega-Fetch bit
103  }
104 
105  Emit(InstWord01, OS);
106  Emit(InstWord2, OS);
107  Emit((uint32_t) 0, OS);
108  } else if (IS_TEX(Desc)) {
109  int64_t Sampler = MI.getOperand(14).getImm();
110 
111  int64_t SrcSelect[4] = {
112  MI.getOperand(2).getImm(),
113  MI.getOperand(3).getImm(),
114  MI.getOperand(4).getImm(),
115  MI.getOperand(5).getImm()
116  };
117  int64_t Offsets[3] = {
118  MI.getOperand(6).getImm() & 0x1F,
119  MI.getOperand(7).getImm() & 0x1F,
120  MI.getOperand(8).getImm() & 0x1F
121  };
122 
123  uint64_t Word01 = getBinaryCodeForInstr(MI, Fixups);
124  uint32_t Word2 = Sampler << 15 | SrcSelect[ELEMENT_X] << 20 |
125  SrcSelect[ELEMENT_Y] << 23 | SrcSelect[ELEMENT_Z] << 26 |
126  SrcSelect[ELEMENT_W] << 29 | Offsets[0] << 0 | Offsets[1] << 5 |
127  Offsets[2] << 10;
128 
129  Emit(Word01, OS);
130  Emit(Word2, OS);
131  Emit((uint32_t) 0, OS);
132  } else {
133  uint64_t Inst = getBinaryCodeForInstr(MI, Fixups);
134  if ((STI.getFeatureBits() & AMDGPU::FeatureR600ALUInst) &&
135  ((Desc.TSFlags & R600_InstFlag::OP1) ||
136  Desc.TSFlags & R600_InstFlag::OP2)) {
137  uint64_t ISAOpCode = Inst & (0x3FFULL << 39);
138  Inst &= ~(0x3FFULL << 39);
139  Inst |= ISAOpCode << 1;
140  }
141  Emit(Inst, OS);
142  }
143 }
144 
145 void R600MCCodeEmitter::EmitByte(unsigned int Byte, raw_ostream &OS) const {
146  OS.write((uint8_t) Byte & 0xff);
147 }
148 
149 void R600MCCodeEmitter::Emit(uint32_t Value, raw_ostream &OS) const {
150  for (unsigned i = 0; i < 4; i++) {
151  OS.write((uint8_t) ((Value >> (8 * i)) & 0xff));
152  }
153 }
154 
155 void R600MCCodeEmitter::Emit(uint64_t Value, raw_ostream &OS) const {
156  for (unsigned i = 0; i < 8; i++) {
157  EmitByte((Value >> (8 * i)) & 0xff, OS);
158  }
159 }
160 
161 unsigned R600MCCodeEmitter::getHWRegChan(unsigned reg) const {
162  return MRI.getEncodingValue(reg) >> HW_CHAN_SHIFT;
163 }
164 
165 unsigned R600MCCodeEmitter::getHWReg(unsigned RegNo) const {
166  return MRI.getEncodingValue(RegNo) & HW_REG_MASK;
167 }
168 
169 uint64_t R600MCCodeEmitter::getMachineOpValue(const MCInst &MI,
170  const MCOperand &MO,
171  SmallVectorImpl<MCFixup> &Fixup) const {
172  if (MO.isReg()) {
173  if (HAS_NATIVE_OPERANDS(MCII.get(MI.getOpcode()).TSFlags)) {
174  return MRI.getEncodingValue(MO.getReg());
175  } else {
176  return getHWReg(MO.getReg());
177  }
178  } else if (MO.isImm()) {
179  return MO.getImm();
180  } else {
181  assert(0);
182  return 0;
183  }
184 }
185 
186 #include "AMDGPUGenMCCodeEmitter.inc"
bool isReg() const
Definition: MCInst.h:56
MCCodeEmitter * createR600MCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI)
#define HW_CHAN_SHIFT
Definition: R600Defines.h:57
#define HAS_NATIVE_OPERANDS(Flags)
Definition: R600Defines.h:53
unsigned getReg() const
getReg - Returns the register number.
Definition: MCInst.h:63
#define HW_REG_MASK
Defines for extracting register infomation from register encoding.
Definition: R600Defines.h:56
bool isImm() const
Definition: MCInst.h:57
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:22
raw_ostream & write(unsigned char C)
#define IS_TEX(desc)
Definition: R600Defines.h:63
#define LLVM_DELETED_FUNCTION
Definition: Compiler.h:137
unsigned getOpcode() const
Definition: MCInst.h:158
int64_t getImm() const
Definition: MCInst.h:74
Provides AMDGPU specific target descriptions.
CodeEmitter interface for R600 and SI codegen.
uint16_t getEncodingValue(unsigned RegNo) const
Returns the encoding for RegNo.
LLVM Value Representation.
Definition: Value.h:66
#define IS_VTX(desc)
Definition: R600Defines.h:62
const MCRegisterInfo & MRI
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:163