1*9880d681SAndroid Build Coastguard Worker //===- R600MCCodeEmitter.cpp - Code Emitter for R600->Cayman GPU families -===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker /// \file
11*9880d681SAndroid Build Coastguard Worker ///
12*9880d681SAndroid Build Coastguard Worker /// \brief The R600 code emitter produces machine code that can be executed
13*9880d681SAndroid Build Coastguard Worker /// directly on the GPU device.
14*9880d681SAndroid Build Coastguard Worker //
15*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
16*9880d681SAndroid Build Coastguard Worker
17*9880d681SAndroid Build Coastguard Worker #include "R600Defines.h"
18*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AMDGPUFixupKinds.h"
19*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AMDGPUMCCodeEmitter.h"
20*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCCodeEmitter.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCRegisterInfo.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/EndianStream.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker using namespace llvm;
31*9880d681SAndroid Build Coastguard Worker
32*9880d681SAndroid Build Coastguard Worker namespace {
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker class R600MCCodeEmitter : public AMDGPUMCCodeEmitter {
35*9880d681SAndroid Build Coastguard Worker R600MCCodeEmitter(const R600MCCodeEmitter &) = delete;
36*9880d681SAndroid Build Coastguard Worker void operator=(const R600MCCodeEmitter &) = delete;
37*9880d681SAndroid Build Coastguard Worker const MCInstrInfo &MCII;
38*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo &MRI;
39*9880d681SAndroid Build Coastguard Worker
40*9880d681SAndroid Build Coastguard Worker public:
R600MCCodeEmitter(const MCInstrInfo & mcii,const MCRegisterInfo & mri)41*9880d681SAndroid Build Coastguard Worker R600MCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri)
42*9880d681SAndroid Build Coastguard Worker : MCII(mcii), MRI(mri) { }
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker /// \brief Encode the instruction and write it to the OS.
45*9880d681SAndroid Build Coastguard Worker void encodeInstruction(const MCInst &MI, raw_ostream &OS,
46*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
47*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const override;
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker /// \returns the encoding for an MCOperand.
50*9880d681SAndroid Build Coastguard Worker uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
51*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
52*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const override;
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker private:
55*9880d681SAndroid Build Coastguard Worker void Emit(uint32_t value, raw_ostream &OS) const;
56*9880d681SAndroid Build Coastguard Worker void Emit(uint64_t value, raw_ostream &OS) const;
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Worker unsigned getHWReg(unsigned regNo) const;
59*9880d681SAndroid Build Coastguard Worker };
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker } // End anonymous namespace
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker enum RegElement {
64*9880d681SAndroid Build Coastguard Worker ELEMENT_X = 0,
65*9880d681SAndroid Build Coastguard Worker ELEMENT_Y,
66*9880d681SAndroid Build Coastguard Worker ELEMENT_Z,
67*9880d681SAndroid Build Coastguard Worker ELEMENT_W
68*9880d681SAndroid Build Coastguard Worker };
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker enum FCInstr {
71*9880d681SAndroid Build Coastguard Worker FC_IF_PREDICATE = 0,
72*9880d681SAndroid Build Coastguard Worker FC_ELSE,
73*9880d681SAndroid Build Coastguard Worker FC_ENDIF,
74*9880d681SAndroid Build Coastguard Worker FC_BGNLOOP,
75*9880d681SAndroid Build Coastguard Worker FC_ENDLOOP,
76*9880d681SAndroid Build Coastguard Worker FC_BREAK_PREDICATE,
77*9880d681SAndroid Build Coastguard Worker FC_CONTINUE
78*9880d681SAndroid Build Coastguard Worker };
79*9880d681SAndroid Build Coastguard Worker
createR600MCCodeEmitter(const MCInstrInfo & MCII,const MCRegisterInfo & MRI,MCContext & Ctx)80*9880d681SAndroid Build Coastguard Worker MCCodeEmitter *llvm::createR600MCCodeEmitter(const MCInstrInfo &MCII,
81*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo &MRI,
82*9880d681SAndroid Build Coastguard Worker MCContext &Ctx) {
83*9880d681SAndroid Build Coastguard Worker return new R600MCCodeEmitter(MCII, MRI);
84*9880d681SAndroid Build Coastguard Worker }
85*9880d681SAndroid Build Coastguard Worker
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const86*9880d681SAndroid Build Coastguard Worker void R600MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
87*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
88*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const {
89*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
90*9880d681SAndroid Build Coastguard Worker if (MI.getOpcode() == AMDGPU::RETURN ||
91*9880d681SAndroid Build Coastguard Worker MI.getOpcode() == AMDGPU::FETCH_CLAUSE ||
92*9880d681SAndroid Build Coastguard Worker MI.getOpcode() == AMDGPU::ALU_CLAUSE ||
93*9880d681SAndroid Build Coastguard Worker MI.getOpcode() == AMDGPU::BUNDLE ||
94*9880d681SAndroid Build Coastguard Worker MI.getOpcode() == AMDGPU::KILL) {
95*9880d681SAndroid Build Coastguard Worker return;
96*9880d681SAndroid Build Coastguard Worker } else if (IS_VTX(Desc)) {
97*9880d681SAndroid Build Coastguard Worker uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups, STI);
98*9880d681SAndroid Build Coastguard Worker uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset
99*9880d681SAndroid Build Coastguard Worker if (!(STI.getFeatureBits()[AMDGPU::FeatureCaymanISA])) {
100*9880d681SAndroid Build Coastguard Worker InstWord2 |= 1 << 19; // Mega-Fetch bit
101*9880d681SAndroid Build Coastguard Worker }
102*9880d681SAndroid Build Coastguard Worker
103*9880d681SAndroid Build Coastguard Worker Emit(InstWord01, OS);
104*9880d681SAndroid Build Coastguard Worker Emit(InstWord2, OS);
105*9880d681SAndroid Build Coastguard Worker Emit((uint32_t) 0, OS);
106*9880d681SAndroid Build Coastguard Worker } else if (IS_TEX(Desc)) {
107*9880d681SAndroid Build Coastguard Worker int64_t Sampler = MI.getOperand(14).getImm();
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker int64_t SrcSelect[4] = {
110*9880d681SAndroid Build Coastguard Worker MI.getOperand(2).getImm(),
111*9880d681SAndroid Build Coastguard Worker MI.getOperand(3).getImm(),
112*9880d681SAndroid Build Coastguard Worker MI.getOperand(4).getImm(),
113*9880d681SAndroid Build Coastguard Worker MI.getOperand(5).getImm()
114*9880d681SAndroid Build Coastguard Worker };
115*9880d681SAndroid Build Coastguard Worker int64_t Offsets[3] = {
116*9880d681SAndroid Build Coastguard Worker MI.getOperand(6).getImm() & 0x1F,
117*9880d681SAndroid Build Coastguard Worker MI.getOperand(7).getImm() & 0x1F,
118*9880d681SAndroid Build Coastguard Worker MI.getOperand(8).getImm() & 0x1F
119*9880d681SAndroid Build Coastguard Worker };
120*9880d681SAndroid Build Coastguard Worker
121*9880d681SAndroid Build Coastguard Worker uint64_t Word01 = getBinaryCodeForInstr(MI, Fixups, STI);
122*9880d681SAndroid Build Coastguard Worker uint32_t Word2 = Sampler << 15 | SrcSelect[ELEMENT_X] << 20 |
123*9880d681SAndroid Build Coastguard Worker SrcSelect[ELEMENT_Y] << 23 | SrcSelect[ELEMENT_Z] << 26 |
124*9880d681SAndroid Build Coastguard Worker SrcSelect[ELEMENT_W] << 29 | Offsets[0] << 0 | Offsets[1] << 5 |
125*9880d681SAndroid Build Coastguard Worker Offsets[2] << 10;
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker Emit(Word01, OS);
128*9880d681SAndroid Build Coastguard Worker Emit(Word2, OS);
129*9880d681SAndroid Build Coastguard Worker Emit((uint32_t) 0, OS);
130*9880d681SAndroid Build Coastguard Worker } else {
131*9880d681SAndroid Build Coastguard Worker uint64_t Inst = getBinaryCodeForInstr(MI, Fixups, STI);
132*9880d681SAndroid Build Coastguard Worker if ((STI.getFeatureBits()[AMDGPU::FeatureR600ALUInst]) &&
133*9880d681SAndroid Build Coastguard Worker ((Desc.TSFlags & R600_InstFlag::OP1) ||
134*9880d681SAndroid Build Coastguard Worker Desc.TSFlags & R600_InstFlag::OP2)) {
135*9880d681SAndroid Build Coastguard Worker uint64_t ISAOpCode = Inst & (0x3FFULL << 39);
136*9880d681SAndroid Build Coastguard Worker Inst &= ~(0x3FFULL << 39);
137*9880d681SAndroid Build Coastguard Worker Inst |= ISAOpCode << 1;
138*9880d681SAndroid Build Coastguard Worker }
139*9880d681SAndroid Build Coastguard Worker Emit(Inst, OS);
140*9880d681SAndroid Build Coastguard Worker }
141*9880d681SAndroid Build Coastguard Worker }
142*9880d681SAndroid Build Coastguard Worker
Emit(uint32_t Value,raw_ostream & OS) const143*9880d681SAndroid Build Coastguard Worker void R600MCCodeEmitter::Emit(uint32_t Value, raw_ostream &OS) const {
144*9880d681SAndroid Build Coastguard Worker support::endian::Writer<support::little>(OS).write(Value);
145*9880d681SAndroid Build Coastguard Worker }
146*9880d681SAndroid Build Coastguard Worker
Emit(uint64_t Value,raw_ostream & OS) const147*9880d681SAndroid Build Coastguard Worker void R600MCCodeEmitter::Emit(uint64_t Value, raw_ostream &OS) const {
148*9880d681SAndroid Build Coastguard Worker support::endian::Writer<support::little>(OS).write(Value);
149*9880d681SAndroid Build Coastguard Worker }
150*9880d681SAndroid Build Coastguard Worker
getHWReg(unsigned RegNo) const151*9880d681SAndroid Build Coastguard Worker unsigned R600MCCodeEmitter::getHWReg(unsigned RegNo) const {
152*9880d681SAndroid Build Coastguard Worker return MRI.getEncodingValue(RegNo) & HW_REG_MASK;
153*9880d681SAndroid Build Coastguard Worker }
154*9880d681SAndroid Build Coastguard Worker
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const155*9880d681SAndroid Build Coastguard Worker uint64_t R600MCCodeEmitter::getMachineOpValue(const MCInst &MI,
156*9880d681SAndroid Build Coastguard Worker const MCOperand &MO,
157*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MCFixup> &Fixups,
158*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI) const {
159*9880d681SAndroid Build Coastguard Worker if (MO.isReg()) {
160*9880d681SAndroid Build Coastguard Worker if (HAS_NATIVE_OPERANDS(MCII.get(MI.getOpcode()).TSFlags))
161*9880d681SAndroid Build Coastguard Worker return MRI.getEncodingValue(MO.getReg());
162*9880d681SAndroid Build Coastguard Worker return getHWReg(MO.getReg());
163*9880d681SAndroid Build Coastguard Worker }
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker if (MO.isExpr()) {
166*9880d681SAndroid Build Coastguard Worker // We put rodata at the end of code section, then map the entire
167*9880d681SAndroid Build Coastguard Worker // code secetion as vtx buf. Thus the section relative address is the
168*9880d681SAndroid Build Coastguard Worker // correct one.
169*9880d681SAndroid Build Coastguard Worker // Each R600 literal instruction has two operands
170*9880d681SAndroid Build Coastguard Worker // We can't easily get the order of the current one, so compare against
171*9880d681SAndroid Build Coastguard Worker // the first one and adjust offset.
172*9880d681SAndroid Build Coastguard Worker const unsigned offset = (&MO == &MI.getOperand(0)) ? 0 : 4;
173*9880d681SAndroid Build Coastguard Worker Fixups.push_back(MCFixup::create(offset, MO.getExpr(), FK_SecRel_4, MI.getLoc()));
174*9880d681SAndroid Build Coastguard Worker return 0;
175*9880d681SAndroid Build Coastguard Worker }
176*9880d681SAndroid Build Coastguard Worker
177*9880d681SAndroid Build Coastguard Worker assert(MO.isImm());
178*9880d681SAndroid Build Coastguard Worker return MO.getImm();
179*9880d681SAndroid Build Coastguard Worker }
180*9880d681SAndroid Build Coastguard Worker
181*9880d681SAndroid Build Coastguard Worker #include "AMDGPUGenMCCodeEmitter.inc"
182