1 //===-- SICodeEmitter.cpp - TODO: Add brief description -------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // TODO: Add full description
12 //===----------------------------------------------------------------------===//
16 #include "AMDGPUUtil.h"
17 #include "AMDILCodeEmitter.h"
18 #include "SIInstrInfo.h"
19 #include "SIMachineFunctionInfo.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineInstr.h"
22 #include "llvm/Support/FormattedStream.h"
23 #include "llvm/Target/TargetMachine.h"
27 #define LITERAL_REG 255
28 #define VGPR_BIT(src_idx) (1 << (8 * (src_idx)))
33 class SICodeEmitter : public MachineFunctionPass, public AMDILCodeEmitter {
37 formatted_raw_ostream &_OS;
38 const TargetMachine *TM;
39 void emitState(MachineFunction & MF);
40 void emitInstr(MachineInstr &MI);
42 void outputBytes(uint64_t value, unsigned bytes);
43 unsigned GPRAlign(const MachineInstr &MI, unsigned OpNo, unsigned shift)
47 SICodeEmitter(formatted_raw_ostream &OS) : MachineFunctionPass(ID),
49 const char *getPassName() const { return "SI Code Emitter"; }
50 bool runOnMachineFunction(MachineFunction &MF);
51 virtual uint64_t getMachineOpValue(const MachineInstr &MI,
52 const MachineOperand &MO) const;
53 virtual unsigned GPR4AlignEncode(const MachineInstr &MI, unsigned OpNo)
55 virtual unsigned GPR2AlignEncode(const MachineInstr &MI, unsigned OpNo)
57 virtual uint64_t i32LiteralEncode(const MachineInstr &MI, unsigned OpNo)
59 virtual uint64_t VOPPostEncode(const MachineInstr &MI,
60 uint64_t Value) const;
64 char SICodeEmitter::ID = 0;
66 FunctionPass *llvm::createSICodeEmitterPass(formatted_raw_ostream &OS) {
67 return new SICodeEmitter(OS);
70 void SICodeEmitter::emitState(MachineFunction & MF)
75 const SIRegisterInfo * RI =
76 static_cast<const SIRegisterInfo*>(TM->getRegisterInfo());
77 SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
79 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
81 MachineBasicBlock &MBB = *BB;
82 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
84 MachineInstr &MI = *I;
85 unsigned numOperands = MI.getNumOperands();
86 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
87 MachineOperand & MO = MI.getOperand(op_idx);
97 if (reg == AMDIL::VCC) {
101 if (AMDIL::SReg_32RegClass.contains(reg)) {
104 } else if (AMDIL::VReg_32RegClass.contains(reg)) {
107 } else if (AMDIL::SReg_64RegClass.contains(reg)) {
110 } else if (AMDIL::VReg_64RegClass.contains(reg)) {
113 } else if (AMDIL::SReg_128RegClass.contains(reg)) {
116 } else if (AMDIL::VReg_128RegClass.contains(reg)) {
119 } else if (AMDIL::SReg_256RegClass.contains(reg)) {
123 assert("!Unknown register class");
125 hwReg = RI->getHWRegNum(reg);
126 maxUsed = ((hwReg + 1) * width) - 1;
128 maxSGPR = maxUsed > maxSGPR ? maxUsed : maxSGPR;
130 maxVGPR = maxUsed > maxVGPR ? maxUsed : maxVGPR;
138 outputBytes(maxSGPR + 1, 4);
139 outputBytes(maxVGPR + 1, 4);
140 outputBytes(MFI->spi_ps_input_addr, 4);
143 bool SICodeEmitter::runOnMachineFunction(MachineFunction &MF)
146 TM = &MF.getTarget();
147 const AMDGPUInstrInfo * TII =
148 static_cast<const AMDGPUInstrInfo*>(TM->getInstrInfo());
152 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
154 MachineBasicBlock &MBB = *BB;
155 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
157 MachineInstr &MI = *I;
158 if (!TII->isRegPreload(MI) && MI.getOpcode() != AMDIL::KILL
159 && MI.getOpcode() != AMDIL::RETURN) {
167 void SICodeEmitter::emitInstr(MachineInstr &MI)
169 const SIInstrInfo * SII = static_cast<const SIInstrInfo*>(TM->getInstrInfo());
171 uint64_t hwInst = getBinaryCodeForInstr(MI);
173 if ((hwInst & 0xffffffff) == 0xffffffff) {
174 fprintf(stderr, "Unsupported Instruction: \n");
179 // hwInst |= SII->getBinaryCode(MI);
181 unsigned bytes = SII->getEncodingBytes(MI);
182 outputBytes(hwInst, bytes);
185 uint64_t SICodeEmitter::getMachineOpValue(const MachineInstr &MI,
186 const MachineOperand &MO) const
188 const SIRegisterInfo * RI =
189 static_cast<const SIRegisterInfo*>(TM->getRegisterInfo());
191 switch(MO.getType()) {
192 case MachineOperand::MO_Register:
193 return RI->getBinaryCode(MO.getReg());
195 case MachineOperand::MO_Immediate:
198 case MachineOperand::MO_FPImmediate:
199 /* XXX: Not all instructions can use inline literals */
200 /* XXX: We should make sure this is a 32-bit constant */
201 return LITERAL_REG | (MO.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue() << 32);
203 llvm_unreachable("Encoding of this operand type is not supported yet.");
208 unsigned SICodeEmitter::GPRAlign(const MachineInstr &MI, unsigned OpNo,
209 unsigned shift) const
211 const SIRegisterInfo * RI =
212 static_cast<const SIRegisterInfo*>(TM->getRegisterInfo());
213 unsigned regCode = RI->getHWRegNum(MI.getOperand(OpNo).getReg());
214 return regCode >> shift;
217 unsigned SICodeEmitter::GPR4AlignEncode(const MachineInstr &MI,
220 return GPRAlign(MI, OpNo, 2);
223 unsigned SICodeEmitter::GPR2AlignEncode(const MachineInstr &MI,
226 return GPRAlign(MI, OpNo, 1);
229 uint64_t SICodeEmitter::i32LiteralEncode(const MachineInstr &MI,
232 return LITERAL_REG | (MI.getOperand(OpNo).getImm() << 32);
235 /* Set the "VGPR" bit for VOP args that can take either a VGPR or a SGPR.
236 * XXX: It would be nice if we could handle this without a PostEncode function.
238 uint64_t SICodeEmitter::VOPPostEncode(const MachineInstr &MI,
239 uint64_t Value) const
241 const SIInstrInfo * SII = static_cast<const SIInstrInfo*>(TM->getInstrInfo());
242 unsigned encodingType = SII->getEncodingType(MI);
244 unsigned vgprBitOffset;
246 if (encodingType == SIInstrEncodingType::VOP3) {
254 /* Add one to skip over the destination reg operand. */
255 for (unsigned opIdx = 1; opIdx < numSrcOps + 1; opIdx++) {
256 if (!MI.getOperand(opIdx).isReg()) {
259 unsigned reg = MI.getOperand(opIdx).getReg();
260 if (AMDIL::VReg_32RegClass.contains(reg)
261 || AMDIL::VReg_64RegClass.contains(reg)) {
262 Value |= (VGPR_BIT(opIdx)) << vgprBitOffset;
269 void SICodeEmitter::outputBytes(uint64_t value, unsigned bytes)
271 for (unsigned i = 0; i < bytes; i++) {
272 _OS.write((uint8_t) ((value >> (8 * i)) & 0xff));