1f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===- AMDGPUMCInstLower.cpp - Lower AMDGPU MachineInstr to an MCInst -----===//
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 Code to lower AMDGPU MachineInstrs to their corresponding MCInst.
12f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
13f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===----------------------------------------------------------------------===//
14f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
15f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
16f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "AMDGPUMCInstLower.h"
17f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "AMDGPUAsmPrinter.h"
18cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "AMDGPUTargetMachine.h"
19f9318673178309288f9320efe02d529419ac32a2Tom Stellard#include "InstPrinter/AMDGPUInstPrinter.h"
20f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "R600InstrInfo.h"
21dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "SIInstrInfo.h"
22f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "llvm/CodeGen/MachineBasicBlock.h"
23f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "llvm/CodeGen/MachineInstr.h"
240b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Constants.h"
25f9318673178309288f9320efe02d529419ac32a2Tom Stellard#include "llvm/MC/MCCodeEmitter.h"
2658a2cbef4aac9ee7d530dfb690c78d6fc11a2371Chandler Carruth#include "llvm/MC/MCExpr.h"
27f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "llvm/MC/MCInst.h"
28f9318673178309288f9320efe02d529419ac32a2Tom Stellard#include "llvm/MC/MCObjectStreamer.h"
29f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "llvm/MC/MCStreamer.h"
30f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "llvm/Support/ErrorHandling.h"
31f9318673178309288f9320efe02d529419ac32a2Tom Stellard#include "llvm/Support/Format.h"
32f9318673178309288f9320efe02d529419ac32a2Tom Stellard#include <algorithm>
33f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
34f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardusing namespace llvm;
35f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
36dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAMDGPUMCInstLower::AMDGPUMCInstLower(MCContext &ctx, const AMDGPUSubtarget &st):
37dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Ctx(ctx), ST(st)
383ee6391e0cddf8d94e2fa441d661c23e494a8489Tom Stellard{ }
39f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
40dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesenum AMDGPUMCInstLower::SISubtarget
41dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAMDGPUMCInstLower::AMDGPUSubtargetToSISubtarget(unsigned) const {
42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  return AMDGPUMCInstLower::SI;
43dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
44dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
45dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesunsigned AMDGPUMCInstLower::getMCOpcode(unsigned MIOpcode) const {
46dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
47dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  int MCOpcode = AMDGPU::getMCOpcode(MIOpcode,
48dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                              AMDGPUSubtargetToSISubtarget(ST.getGeneration()));
49dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (MCOpcode == -1)
50dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    MCOpcode = MIOpcode;
51dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
52dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  return MCOpcode;
53dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
54dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
55f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardvoid AMDGPUMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
56f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
57dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  OutMI.setOpcode(getMCOpcode(MI->getOpcode()));
58f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
59dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  for (const MachineOperand &MO : MI->explicit_operands()) {
60f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MCOperand MCOp;
61f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    switch (MO.getType()) {
62f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    default:
63f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      llvm_unreachable("unknown operand type");
64f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MachineOperand::MO_FPImmediate: {
65f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      const APFloat &FloatValue = MO.getFPImm()->getValueAPF();
66f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      assert(&FloatValue.getSemantics() == &APFloat::IEEEsingle &&
67f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard             "Only floating point immediates are supported at the moment.");
68f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      MCOp = MCOperand::CreateFPImm(FloatValue.convertToFloat());
69f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
70f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
71f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MachineOperand::MO_Immediate:
72f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      MCOp = MCOperand::CreateImm(MO.getImm());
73f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
74f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MachineOperand::MO_Register:
75f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      MCOp = MCOperand::CreateReg(MO.getReg());
76f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
773ee6391e0cddf8d94e2fa441d661c23e494a8489Tom Stellard    case MachineOperand::MO_MachineBasicBlock:
783ee6391e0cddf8d94e2fa441d661c23e494a8489Tom Stellard      MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
793ee6391e0cddf8d94e2fa441d661c23e494a8489Tom Stellard                                   MO.getMBB()->getSymbol(), Ctx));
80f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
81f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    OutMI.addOperand(MCOp);
82f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
83f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
84f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
85f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardvoid AMDGPUAsmPrinter::EmitInstruction(const MachineInstr *MI) {
86dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  AMDGPUMCInstLower MCInstLowering(OutContext,
87dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                               MF->getTarget().getSubtarget<AMDGPUSubtarget>());
88f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#ifdef _DEBUG
9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  StringRef Err;
9136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (!TM.getInstrInfo()->verifyInstruction(MI, Err)) {
9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    errs() << "Warning: Illegal instruction detected: " << Err << "\n";
9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MI->dump();
9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
9536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#endif
96f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (MI->isBundle()) {
97f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    const MachineBasicBlock *MBB = MI->getParent();
98f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineBasicBlock::const_instr_iterator I = MI;
99f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    ++I;
100f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    while (I != MBB->end() && I->isInsideBundle()) {
101f9318673178309288f9320efe02d529419ac32a2Tom Stellard      EmitInstruction(I);
102f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      ++I;
103f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
104f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
105f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MCInst TmpInst;
106f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MCInstLowering.lower(MI, TmpInst);
10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    EmitToStreamer(OutStreamer, TmpInst);
108f9318673178309288f9320efe02d529419ac32a2Tom Stellard
109f9318673178309288f9320efe02d529419ac32a2Tom Stellard    if (DisasmEnabled) {
110f9318673178309288f9320efe02d529419ac32a2Tom Stellard      // Disassemble instruction/operands to text.
111f9318673178309288f9320efe02d529419ac32a2Tom Stellard      DisasmLines.resize(DisasmLines.size() + 1);
112f9318673178309288f9320efe02d529419ac32a2Tom Stellard      std::string &DisasmLine = DisasmLines.back();
113f9318673178309288f9320efe02d529419ac32a2Tom Stellard      raw_string_ostream DisasmStream(DisasmLine);
114f9318673178309288f9320efe02d529419ac32a2Tom Stellard
115f9318673178309288f9320efe02d529419ac32a2Tom Stellard      AMDGPUInstPrinter InstPrinter(*TM.getMCAsmInfo(), *TM.getInstrInfo(),
116f9318673178309288f9320efe02d529419ac32a2Tom Stellard                                    *TM.getRegisterInfo());
117f9318673178309288f9320efe02d529419ac32a2Tom Stellard      InstPrinter.printInst(&TmpInst, DisasmStream, StringRef());
118f9318673178309288f9320efe02d529419ac32a2Tom Stellard
119f9318673178309288f9320efe02d529419ac32a2Tom Stellard      // Disassemble instruction/operands to hex representation.
120f9318673178309288f9320efe02d529419ac32a2Tom Stellard      SmallVector<MCFixup, 4> Fixups;
121f9318673178309288f9320efe02d529419ac32a2Tom Stellard      SmallVector<char, 16> CodeBytes;
122f9318673178309288f9320efe02d529419ac32a2Tom Stellard      raw_svector_ostream CodeStream(CodeBytes);
123f9318673178309288f9320efe02d529419ac32a2Tom Stellard
124f9318673178309288f9320efe02d529419ac32a2Tom Stellard      MCObjectStreamer &ObjStreamer = (MCObjectStreamer &)OutStreamer;
125f9318673178309288f9320efe02d529419ac32a2Tom Stellard      MCCodeEmitter &InstEmitter = ObjStreamer.getAssembler().getEmitter();
12636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      InstEmitter.EncodeInstruction(TmpInst, CodeStream, Fixups,
12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                    TM.getSubtarget<MCSubtargetInfo>());
128f9318673178309288f9320efe02d529419ac32a2Tom Stellard      CodeStream.flush();
129f9318673178309288f9320efe02d529419ac32a2Tom Stellard
130f9318673178309288f9320efe02d529419ac32a2Tom Stellard      HexLines.resize(HexLines.size() + 1);
131f9318673178309288f9320efe02d529419ac32a2Tom Stellard      std::string &HexLine = HexLines.back();
132f9318673178309288f9320efe02d529419ac32a2Tom Stellard      raw_string_ostream HexStream(HexLine);
133f9318673178309288f9320efe02d529419ac32a2Tom Stellard
134f9318673178309288f9320efe02d529419ac32a2Tom Stellard      for (size_t i = 0; i < CodeBytes.size(); i += 4) {
135f9318673178309288f9320efe02d529419ac32a2Tom Stellard        unsigned int CodeDWord = *(unsigned int *)&CodeBytes[i];
136f9318673178309288f9320efe02d529419ac32a2Tom Stellard        HexStream << format("%s%08X", (i > 0 ? " " : ""), CodeDWord);
137f9318673178309288f9320efe02d529419ac32a2Tom Stellard      }
138f9318673178309288f9320efe02d529419ac32a2Tom Stellard
139f9318673178309288f9320efe02d529419ac32a2Tom Stellard      DisasmStream.flush();
140f9318673178309288f9320efe02d529419ac32a2Tom Stellard      DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLine.size());
141f9318673178309288f9320efe02d529419ac32a2Tom Stellard    }
142f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
143f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
144