blob: bc5c9d8e97f725b92384135a96a3da61e5237220 [file] [log] [blame]
Tom Stellard75aadc22012-12-11 21:25:42 +00001//===- 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/// This code emitter outputs bytecode that is understood by the r600g driver
13/// in the Mesa [1] project. The bytecode is very similar to the hardware's ISA,
14/// but it still needs to be run through a finalizer in order to be executed
15/// by the GPU.
16///
17/// [1] http://www.mesa3d.org/
18//
19//===----------------------------------------------------------------------===//
20
21#include "R600Defines.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000022#include "MCTargetDesc/AMDGPUMCCodeEmitter.h"
Chandler Carruthbe810232013-01-02 10:22:59 +000023#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000024#include "llvm/MC/MCCodeEmitter.h"
25#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCInst.h"
27#include "llvm/MC/MCInstrInfo.h"
28#include "llvm/MC/MCRegisterInfo.h"
29#include "llvm/MC/MCSubtargetInfo.h"
30#include "llvm/Support/raw_ostream.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000031#include <stdio.h>
32
33#define SRC_BYTE_COUNT 11
34#define DST_BYTE_COUNT 5
35
36using namespace llvm;
37
38namespace {
39
40class R600MCCodeEmitter : public AMDGPUMCCodeEmitter {
David Blaikie772d4f72013-02-18 23:11:17 +000041 R600MCCodeEmitter(const R600MCCodeEmitter &) LLVM_DELETED_FUNCTION;
42 void operator=(const R600MCCodeEmitter &) LLVM_DELETED_FUNCTION;
Tom Stellard75aadc22012-12-11 21:25:42 +000043 const MCInstrInfo &MCII;
44 const MCRegisterInfo &MRI;
45 const MCSubtargetInfo &STI;
46 MCContext &Ctx;
47
48public:
49
50 R600MCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri,
51 const MCSubtargetInfo &sti, MCContext &ctx)
52 : MCII(mcii), MRI(mri), STI(sti), Ctx(ctx) { }
53
54 /// \brief Encode the instruction and write it to the OS.
55 virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
56 SmallVectorImpl<MCFixup> &Fixups) const;
57
58 /// \returns the encoding for an MCOperand.
59 virtual uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
60 SmallVectorImpl<MCFixup> &Fixups) const;
61private:
62
63 void EmitALUInstr(const MCInst &MI, SmallVectorImpl<MCFixup> &Fixups,
64 raw_ostream &OS) const;
65 void EmitSrc(const MCInst &MI, unsigned OpIdx, raw_ostream &OS) const;
Tom Stellard365366f2013-01-23 02:09:06 +000066 void EmitSrcISA(const MCInst &MI, unsigned RegOpIdx, unsigned SelOpIdx,
67 raw_ostream &OS) const;
Tom Stellard75aadc22012-12-11 21:25:42 +000068 void EmitDst(const MCInst &MI, raw_ostream &OS) const;
Tom Stellard75aadc22012-12-11 21:25:42 +000069 void EmitFCInstr(const MCInst &MI, raw_ostream &OS) const;
70
71 void EmitNullBytes(unsigned int byteCount, raw_ostream &OS) const;
72
73 void EmitByte(unsigned int byte, raw_ostream &OS) const;
74
75 void EmitTwoBytes(uint32_t bytes, raw_ostream &OS) const;
76
77 void Emit(uint32_t value, raw_ostream &OS) const;
78 void Emit(uint64_t value, raw_ostream &OS) const;
79
80 unsigned getHWRegChan(unsigned reg) const;
81 unsigned getHWReg(unsigned regNo) const;
82
83 bool isFCOp(unsigned opcode) const;
84 bool isTexOp(unsigned opcode) const;
85 bool isFlagSet(const MCInst &MI, unsigned Operand, unsigned Flag) const;
86
87};
88
89} // End anonymous namespace
90
91enum RegElement {
92 ELEMENT_X = 0,
93 ELEMENT_Y,
94 ELEMENT_Z,
95 ELEMENT_W
96};
97
98enum InstrTypes {
99 INSTR_ALU = 0,
100 INSTR_TEX,
101 INSTR_FC,
102 INSTR_NATIVE,
103 INSTR_VTX,
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000104 INSTR_EXPORT,
105 INSTR_CFALU
Tom Stellard75aadc22012-12-11 21:25:42 +0000106};
107
108enum FCInstr {
109 FC_IF_PREDICATE = 0,
110 FC_ELSE,
111 FC_ENDIF,
112 FC_BGNLOOP,
113 FC_ENDLOOP,
114 FC_BREAK_PREDICATE,
115 FC_CONTINUE
116};
117
118enum TextureTypes {
119 TEXTURE_1D = 1,
120 TEXTURE_2D,
121 TEXTURE_3D,
122 TEXTURE_CUBE,
123 TEXTURE_RECT,
124 TEXTURE_SHADOW1D,
125 TEXTURE_SHADOW2D,
126 TEXTURE_SHADOWRECT,
127 TEXTURE_1D_ARRAY,
128 TEXTURE_2D_ARRAY,
129 TEXTURE_SHADOW1D_ARRAY,
130 TEXTURE_SHADOW2D_ARRAY
131};
132
133MCCodeEmitter *llvm::createR600MCCodeEmitter(const MCInstrInfo &MCII,
134 const MCRegisterInfo &MRI,
135 const MCSubtargetInfo &STI,
136 MCContext &Ctx) {
137 return new R600MCCodeEmitter(MCII, MRI, STI, Ctx);
138}
139
140void R600MCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS,
141 SmallVectorImpl<MCFixup> &Fixups) const {
Vincent Lejeune53f35252013-03-31 19:33:04 +0000142 if (isFCOp(MI.getOpcode())){
Tom Stellard75aadc22012-12-11 21:25:42 +0000143 EmitFCInstr(MI, OS);
144 } else if (MI.getOpcode() == AMDGPU::RETURN ||
Vincent Lejeune3f1d1362013-04-30 00:13:53 +0000145 MI.getOpcode() == AMDGPU::FETCH_CLAUSE ||
Tom Stellard75aadc22012-12-11 21:25:42 +0000146 MI.getOpcode() == AMDGPU::BUNDLE ||
147 MI.getOpcode() == AMDGPU::KILL) {
148 return;
149 } else {
150 switch(MI.getOpcode()) {
151 case AMDGPU::RAT_WRITE_CACHELESS_32_eg:
152 case AMDGPU::RAT_WRITE_CACHELESS_128_eg: {
153 uint64_t inst = getBinaryCodeForInstr(MI, Fixups);
154 EmitByte(INSTR_NATIVE, OS);
155 Emit(inst, OS);
156 break;
157 }
158 case AMDGPU::CONSTANT_LOAD_eg:
159 case AMDGPU::VTX_READ_PARAM_8_eg:
160 case AMDGPU::VTX_READ_PARAM_16_eg:
161 case AMDGPU::VTX_READ_PARAM_32_eg:
Tom Stellard91da4e92013-02-13 22:05:20 +0000162 case AMDGPU::VTX_READ_PARAM_128_eg:
Tom Stellard75aadc22012-12-11 21:25:42 +0000163 case AMDGPU::VTX_READ_GLOBAL_8_eg:
164 case AMDGPU::VTX_READ_GLOBAL_32_eg:
Tom Stellard365366f2013-01-23 02:09:06 +0000165 case AMDGPU::VTX_READ_GLOBAL_128_eg:
Vincent Lejeune68501802013-02-18 14:11:19 +0000166 case AMDGPU::TEX_VTX_CONSTBUF:
167 case AMDGPU::TEX_VTX_TEXBUF : {
Tom Stellard75aadc22012-12-11 21:25:42 +0000168 uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups);
169 uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset
Vincent Lejeune3f1d1362013-04-30 00:13:53 +0000170 InstWord2 |= 1 << 19;
Tom Stellard75aadc22012-12-11 21:25:42 +0000171
Vincent Lejeune3f1d1362013-04-30 00:13:53 +0000172 EmitByte(INSTR_NATIVE, OS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000173 Emit(InstWord01, OS);
Vincent Lejeune3f1d1362013-04-30 00:13:53 +0000174 EmitByte(INSTR_NATIVE, OS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000175 Emit(InstWord2, OS);
Vincent Lejeune3f1d1362013-04-30 00:13:53 +0000176 Emit((u_int32_t) 0, OS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000177 break;
178 }
Vincent Lejeune53f35252013-03-31 19:33:04 +0000179 case AMDGPU::TEX_LD:
180 case AMDGPU::TEX_GET_TEXTURE_RESINFO:
181 case AMDGPU::TEX_SAMPLE:
182 case AMDGPU::TEX_SAMPLE_C:
183 case AMDGPU::TEX_SAMPLE_L:
184 case AMDGPU::TEX_SAMPLE_C_L:
185 case AMDGPU::TEX_SAMPLE_LB:
186 case AMDGPU::TEX_SAMPLE_C_LB:
187 case AMDGPU::TEX_SAMPLE_G:
188 case AMDGPU::TEX_SAMPLE_C_G:
189 case AMDGPU::TEX_GET_GRADIENTS_H:
190 case AMDGPU::TEX_GET_GRADIENTS_V:
191 case AMDGPU::TEX_SET_GRADIENTS_H:
192 case AMDGPU::TEX_SET_GRADIENTS_V: {
193 unsigned Opcode = MI.getOpcode();
194 bool HasOffsets = (Opcode == AMDGPU::TEX_LD);
195 unsigned OpOffset = HasOffsets ? 3 : 0;
196 int64_t Sampler = MI.getOperand(OpOffset + 3).getImm();
197 int64_t TextureType = MI.getOperand(OpOffset + 4).getImm();
198
199 uint32_t SrcSelect[4] = {0, 1, 2, 3};
200 uint32_t Offsets[3] = {0, 0, 0};
201 uint64_t CoordType[4] = {1, 1, 1, 1};
202
203 if (HasOffsets)
Vincent Lejeunebcbb13d2013-04-04 14:00:09 +0000204 for (unsigned i = 0; i < 3; i++) {
205 int SignedOffset = MI.getOperand(i + 2).getImm();
206 Offsets[i] = (SignedOffset & 0x1F);
207 }
208
Vincent Lejeune53f35252013-03-31 19:33:04 +0000209
210 if (TextureType == TEXTURE_RECT ||
211 TextureType == TEXTURE_SHADOWRECT) {
212 CoordType[ELEMENT_X] = 0;
213 CoordType[ELEMENT_Y] = 0;
214 }
215
216 if (TextureType == TEXTURE_1D_ARRAY ||
217 TextureType == TEXTURE_SHADOW1D_ARRAY) {
218 if (Opcode == AMDGPU::TEX_SAMPLE_C_L ||
219 Opcode == AMDGPU::TEX_SAMPLE_C_LB) {
220 CoordType[ELEMENT_Y] = 0;
221 } else {
222 CoordType[ELEMENT_Z] = 0;
223 SrcSelect[ELEMENT_Z] = ELEMENT_Y;
224 }
225 } else if (TextureType == TEXTURE_2D_ARRAY ||
226 TextureType == TEXTURE_SHADOW2D_ARRAY) {
227 CoordType[ELEMENT_Z] = 0;
228 }
229
230
231 if ((TextureType == TEXTURE_SHADOW1D ||
232 TextureType == TEXTURE_SHADOW2D ||
233 TextureType == TEXTURE_SHADOWRECT ||
234 TextureType == TEXTURE_SHADOW1D_ARRAY) &&
235 Opcode != AMDGPU::TEX_SAMPLE_C_L &&
236 Opcode != AMDGPU::TEX_SAMPLE_C_LB) {
237 SrcSelect[ELEMENT_W] = ELEMENT_Z;
238 }
239
240 uint64_t Word01 = getBinaryCodeForInstr(MI, Fixups) |
241 CoordType[ELEMENT_X] << 60 | CoordType[ELEMENT_Y] << 61 |
242 CoordType[ELEMENT_Z] << 62 | CoordType[ELEMENT_W] << 63;
243 uint32_t Word2 = Sampler << 15 | SrcSelect[ELEMENT_X] << 20 |
244 SrcSelect[ELEMENT_Y] << 23 | SrcSelect[ELEMENT_Z] << 26 |
245 SrcSelect[ELEMENT_W] << 29 | Offsets[0] << 0 | Offsets[1] << 5 |
246 Offsets[2] << 10;
247
Vincent Lejeune3f1d1362013-04-30 00:13:53 +0000248 EmitByte(INSTR_NATIVE, OS);
Vincent Lejeune53f35252013-03-31 19:33:04 +0000249 Emit(Word01, OS);
Vincent Lejeune3f1d1362013-04-30 00:13:53 +0000250 EmitByte(INSTR_NATIVE, OS);
Vincent Lejeune53f35252013-03-31 19:33:04 +0000251 Emit(Word2, OS);
Vincent Lejeune3f1d1362013-04-30 00:13:53 +0000252 Emit((u_int32_t) 0, OS);
Vincent Lejeune53f35252013-03-31 19:33:04 +0000253 break;
254 }
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000255 case AMDGPU::CF_ALU:
256 case AMDGPU::CF_ALU_PUSH_BEFORE: {
257 uint64_t Inst = getBinaryCodeForInstr(MI, Fixups);
258 EmitByte(INSTR_CFALU, OS);
259 Emit(Inst, OS);
260 break;
261 }
Vincent Lejeune5f11dd32013-04-08 13:05:49 +0000262 case AMDGPU::CF_CALL_FS_EG:
Vincent Lejeune5f11dd32013-04-08 13:05:49 +0000263 case AMDGPU::CF_CALL_FS_R600:
Vincent Lejeunebfaa63a62013-04-01 21:48:05 +0000264 return;
Vincent Lejeune3f1d1362013-04-30 00:13:53 +0000265 case AMDGPU::CF_TC_EG:
266 case AMDGPU::CF_VC_EG:
267 case AMDGPU::CF_TC_R600:
268 case AMDGPU::CF_VC_R600:
Vincent Lejeune5f11dd32013-04-08 13:05:49 +0000269 case AMDGPU::WHILE_LOOP_EG:
270 case AMDGPU::END_LOOP_EG:
271 case AMDGPU::LOOP_BREAK_EG:
272 case AMDGPU::CF_CONTINUE_EG:
273 case AMDGPU::CF_JUMP_EG:
274 case AMDGPU::CF_ELSE_EG:
275 case AMDGPU::POP_EG:
276 case AMDGPU::WHILE_LOOP_R600:
277 case AMDGPU::END_LOOP_R600:
278 case AMDGPU::LOOP_BREAK_R600:
279 case AMDGPU::CF_CONTINUE_R600:
280 case AMDGPU::CF_JUMP_R600:
281 case AMDGPU::CF_ELSE_R600:
Vincent Lejeune218093e2013-04-17 15:17:32 +0000282 case AMDGPU::POP_R600:
283 case AMDGPU::EG_ExportSwz:
284 case AMDGPU::R600_ExportSwz:
285 case AMDGPU::EG_ExportBuf:
Vincent Lejeuneb6bfe852013-04-23 17:34:00 +0000286 case AMDGPU::R600_ExportBuf:
287 case AMDGPU::PAD:
288 case AMDGPU::CF_END_R600:
289 case AMDGPU::CF_END_EG:
290 case AMDGPU::CF_END_CM: {
Vincent Lejeunebfaa63a62013-04-01 21:48:05 +0000291 uint64_t Inst = getBinaryCodeForInstr(MI, Fixups);
292 EmitByte(INSTR_NATIVE, OS);
293 Emit(Inst, OS);
294 break;
295 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000296 default:
297 EmitALUInstr(MI, Fixups, OS);
298 break;
299 }
300 }
301}
302
303void R600MCCodeEmitter::EmitALUInstr(const MCInst &MI,
304 SmallVectorImpl<MCFixup> &Fixups,
305 raw_ostream &OS) const {
306 const MCInstrDesc &MCDesc = MCII.get(MI.getOpcode());
Tom Stellard75aadc22012-12-11 21:25:42 +0000307
308 // Emit instruction type
309 EmitByte(INSTR_ALU, OS);
310
311 uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups);
312
313 //older alu have different encoding for instructions with one or two src
314 //parameters.
315 if ((STI.getFeatureBits() & AMDGPU::FeatureR600ALUInst) &&
316 !(MCDesc.TSFlags & R600_InstFlag::OP3)) {
317 uint64_t ISAOpCode = InstWord01 & (0x3FFULL << 39);
318 InstWord01 &= ~(0x3FFULL << 39);
319 InstWord01 |= ISAOpCode << 1;
320 }
321
Tom Stellard365366f2013-01-23 02:09:06 +0000322 unsigned SrcNum = MCDesc.TSFlags & R600_InstFlag::OP3 ? 3 :
323 MCDesc.TSFlags & R600_InstFlag::OP2 ? 2 : 1;
Tom Stellard75aadc22012-12-11 21:25:42 +0000324
Tom Stellard365366f2013-01-23 02:09:06 +0000325 EmitByte(SrcNum, OS);
326
327 const unsigned SrcOps[3][2] = {
328 {R600Operands::SRC0, R600Operands::SRC0_SEL},
329 {R600Operands::SRC1, R600Operands::SRC1_SEL},
330 {R600Operands::SRC2, R600Operands::SRC2_SEL}
331 };
332
333 for (unsigned SrcIdx = 0; SrcIdx < SrcNum; ++SrcIdx) {
334 unsigned RegOpIdx = R600Operands::ALUOpTable[SrcNum-1][SrcOps[SrcIdx][0]];
335 unsigned SelOpIdx = R600Operands::ALUOpTable[SrcNum-1][SrcOps[SrcIdx][1]];
336 EmitSrcISA(MI, RegOpIdx, SelOpIdx, OS);
Tom Stellard75aadc22012-12-11 21:25:42 +0000337 }
338
339 Emit(InstWord01, OS);
340 return;
341}
342
343void R600MCCodeEmitter::EmitSrc(const MCInst &MI, unsigned OpIdx,
344 raw_ostream &OS) const {
345 const MCOperand &MO = MI.getOperand(OpIdx);
346 union {
347 float f;
348 uint32_t i;
349 } Value;
350 Value.i = 0;
351 // Emit the source select (2 bytes). For GPRs, this is the register index.
352 // For other potential instruction operands, (e.g. constant registers) the
353 // value of the source select is defined in the r600isa docs.
354 if (MO.isReg()) {
355 unsigned reg = MO.getReg();
356 EmitTwoBytes(getHWReg(reg), OS);
357 if (reg == AMDGPU::ALU_LITERAL_X) {
358 unsigned ImmOpIndex = MI.getNumOperands() - 1;
359 MCOperand ImmOp = MI.getOperand(ImmOpIndex);
360 if (ImmOp.isFPImm()) {
361 Value.f = ImmOp.getFPImm();
362 } else {
363 assert(ImmOp.isImm());
364 Value.i = ImmOp.getImm();
365 }
366 }
367 } else {
368 // XXX: Handle other operand types.
369 EmitTwoBytes(0, OS);
370 }
371
372 // Emit the source channel (1 byte)
373 if (MO.isReg()) {
374 EmitByte(getHWRegChan(MO.getReg()), OS);
375 } else {
376 EmitByte(0, OS);
377 }
378
379 // XXX: Emit isNegated (1 byte)
380 if ((!(isFlagSet(MI, OpIdx, MO_FLAG_ABS)))
381 && (isFlagSet(MI, OpIdx, MO_FLAG_NEG) ||
382 (MO.isReg() &&
383 (MO.getReg() == AMDGPU::NEG_ONE || MO.getReg() == AMDGPU::NEG_HALF)))){
384 EmitByte(1, OS);
385 } else {
386 EmitByte(0, OS);
387 }
388
389 // Emit isAbsolute (1 byte)
390 if (isFlagSet(MI, OpIdx, MO_FLAG_ABS)) {
391 EmitByte(1, OS);
392 } else {
393 EmitByte(0, OS);
394 }
395
396 // XXX: Emit relative addressing mode (1 byte)
397 EmitByte(0, OS);
398
399 // Emit kc_bank, This will be adjusted later by r600_asm
400 EmitByte(0, OS);
401
402 // Emit the literal value, if applicable (4 bytes).
403 Emit(Value.i, OS);
404
405}
406
Tom Stellard365366f2013-01-23 02:09:06 +0000407void R600MCCodeEmitter::EmitSrcISA(const MCInst &MI, unsigned RegOpIdx,
408 unsigned SelOpIdx, raw_ostream &OS) const {
409 const MCOperand &RegMO = MI.getOperand(RegOpIdx);
410 const MCOperand &SelMO = MI.getOperand(SelOpIdx);
411
Tom Stellard75aadc22012-12-11 21:25:42 +0000412 union {
413 float f;
414 uint32_t i;
415 } InlineConstant;
416 InlineConstant.i = 0;
Tom Stellard365366f2013-01-23 02:09:06 +0000417 // Emit source type (1 byte) and source select (4 bytes). For GPRs type is 0
418 // and select is 0 (GPR index is encoded in the instr encoding. For constants
419 // type is 1 and select is the original const select passed from the driver.
420 unsigned Reg = RegMO.getReg();
421 if (Reg == AMDGPU::ALU_CONST) {
422 EmitByte(1, OS);
423 uint32_t Sel = SelMO.getImm();
424 Emit(Sel, OS);
425 } else {
426 EmitByte(0, OS);
427 Emit((uint32_t)0, OS);
428 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000429
Tom Stellard365366f2013-01-23 02:09:06 +0000430 if (Reg == AMDGPU::ALU_LITERAL_X) {
Vincent Lejeune22c42482013-04-30 00:14:08 +0000431 unsigned ImmOpIndex = MI.getNumOperands() - 2;
Tom Stellard365366f2013-01-23 02:09:06 +0000432 MCOperand ImmOp = MI.getOperand(ImmOpIndex);
433 if (ImmOp.isFPImm()) {
434 InlineConstant.f = ImmOp.getFPImm();
435 } else {
436 assert(ImmOp.isImm());
437 InlineConstant.i = ImmOp.getImm();
Tom Stellard75aadc22012-12-11 21:25:42 +0000438 }
439 }
440
441 // Emit the literal value, if applicable (4 bytes).
442 Emit(InlineConstant.i, OS);
443}
444
Tom Stellard75aadc22012-12-11 21:25:42 +0000445void R600MCCodeEmitter::EmitFCInstr(const MCInst &MI, raw_ostream &OS) const {
446
447 // Emit instruction type
448 EmitByte(INSTR_FC, OS);
449
450 // Emit SRC
451 unsigned NumOperands = MI.getNumOperands();
452 if (NumOperands > 0) {
453 assert(NumOperands == 1);
454 EmitSrc(MI, 0, OS);
455 } else {
456 EmitNullBytes(SRC_BYTE_COUNT, OS);
457 }
458
459 // Emit FC Instruction
460 enum FCInstr instr;
461 switch (MI.getOpcode()) {
462 case AMDGPU::PREDICATED_BREAK:
463 instr = FC_BREAK_PREDICATE;
464 break;
465 case AMDGPU::CONTINUE:
466 instr = FC_CONTINUE;
467 break;
468 case AMDGPU::IF_PREDICATE_SET:
469 instr = FC_IF_PREDICATE;
470 break;
471 case AMDGPU::ELSE:
472 instr = FC_ELSE;
473 break;
474 case AMDGPU::ENDIF:
475 instr = FC_ENDIF;
476 break;
477 case AMDGPU::ENDLOOP:
478 instr = FC_ENDLOOP;
479 break;
480 case AMDGPU::WHILELOOP:
481 instr = FC_BGNLOOP;
482 break;
483 default:
484 abort();
485 break;
486 }
487 EmitByte(instr, OS);
488}
489
490void R600MCCodeEmitter::EmitNullBytes(unsigned int ByteCount,
491 raw_ostream &OS) const {
492
493 for (unsigned int i = 0; i < ByteCount; i++) {
494 EmitByte(0, OS);
495 }
496}
497
498void R600MCCodeEmitter::EmitByte(unsigned int Byte, raw_ostream &OS) const {
499 OS.write((uint8_t) Byte & 0xff);
500}
501
502void R600MCCodeEmitter::EmitTwoBytes(unsigned int Bytes,
503 raw_ostream &OS) const {
504 OS.write((uint8_t) (Bytes & 0xff));
505 OS.write((uint8_t) ((Bytes >> 8) & 0xff));
506}
507
508void R600MCCodeEmitter::Emit(uint32_t Value, raw_ostream &OS) const {
509 for (unsigned i = 0; i < 4; i++) {
510 OS.write((uint8_t) ((Value >> (8 * i)) & 0xff));
511 }
512}
513
514void R600MCCodeEmitter::Emit(uint64_t Value, raw_ostream &OS) const {
515 for (unsigned i = 0; i < 8; i++) {
516 EmitByte((Value >> (8 * i)) & 0xff, OS);
517 }
518}
519
520unsigned R600MCCodeEmitter::getHWRegChan(unsigned reg) const {
521 return MRI.getEncodingValue(reg) >> HW_CHAN_SHIFT;
522}
523
524unsigned R600MCCodeEmitter::getHWReg(unsigned RegNo) const {
525 return MRI.getEncodingValue(RegNo) & HW_REG_MASK;
526}
527
528uint64_t R600MCCodeEmitter::getMachineOpValue(const MCInst &MI,
529 const MCOperand &MO,
530 SmallVectorImpl<MCFixup> &Fixup) const {
531 if (MO.isReg()) {
532 if (HAS_NATIVE_OPERANDS(MCII.get(MI.getOpcode()).TSFlags)) {
533 return MRI.getEncodingValue(MO.getReg());
534 } else {
535 return getHWReg(MO.getReg());
536 }
537 } else if (MO.isImm()) {
538 return MO.getImm();
539 } else {
540 assert(0);
541 return 0;
542 }
543}
544
545//===----------------------------------------------------------------------===//
546// Encoding helper functions
547//===----------------------------------------------------------------------===//
548
549bool R600MCCodeEmitter::isFCOp(unsigned opcode) const {
550 switch(opcode) {
551 default: return false;
552 case AMDGPU::PREDICATED_BREAK:
553 case AMDGPU::CONTINUE:
554 case AMDGPU::IF_PREDICATE_SET:
555 case AMDGPU::ELSE:
556 case AMDGPU::ENDIF:
557 case AMDGPU::ENDLOOP:
558 case AMDGPU::WHILELOOP:
559 return true;
560 }
561}
562
563bool R600MCCodeEmitter::isTexOp(unsigned opcode) const {
564 switch(opcode) {
565 default: return false;
566 case AMDGPU::TEX_LD:
567 case AMDGPU::TEX_GET_TEXTURE_RESINFO:
568 case AMDGPU::TEX_SAMPLE:
569 case AMDGPU::TEX_SAMPLE_C:
570 case AMDGPU::TEX_SAMPLE_L:
571 case AMDGPU::TEX_SAMPLE_C_L:
572 case AMDGPU::TEX_SAMPLE_LB:
573 case AMDGPU::TEX_SAMPLE_C_LB:
574 case AMDGPU::TEX_SAMPLE_G:
575 case AMDGPU::TEX_SAMPLE_C_G:
576 case AMDGPU::TEX_GET_GRADIENTS_H:
577 case AMDGPU::TEX_GET_GRADIENTS_V:
578 case AMDGPU::TEX_SET_GRADIENTS_H:
579 case AMDGPU::TEX_SET_GRADIENTS_V:
580 return true;
581 }
582}
583
584bool R600MCCodeEmitter::isFlagSet(const MCInst &MI, unsigned Operand,
585 unsigned Flag) const {
586 const MCInstrDesc &MCDesc = MCII.get(MI.getOpcode());
587 unsigned FlagIndex = GET_FLAG_OPERAND_IDX(MCDesc.TSFlags);
588 if (FlagIndex == 0) {
589 return false;
590 }
591 assert(MI.getOperand(FlagIndex).isImm());
592 return !!((MI.getOperand(FlagIndex).getImm() >>
593 (NUM_MO_FLAGS * Operand)) & Flag);
594}
595
596#include "AMDGPUGenMCCodeEmitter.inc"