10b57cec5SDimitry Andric //===- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains code to lower Mips MachineInstrs to their corresponding
100b57cec5SDimitry Andric // MCInst records.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "MipsMCInstLower.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h"
160b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCExpr.h"
170b57cec5SDimitry Andric #include "MipsAsmPrinter.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
230b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric
MipsMCInstLower(MipsAsmPrinter & asmprinter)270b57cec5SDimitry Andric MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
280b57cec5SDimitry Andric : AsmPrinter(asmprinter) {}
290b57cec5SDimitry Andric
Initialize(MCContext * C)300b57cec5SDimitry Andric void MipsMCInstLower::Initialize(MCContext *C) {
310b57cec5SDimitry Andric Ctx = C;
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric
LowerSymbolOperand(const MachineOperand & MO,MachineOperandType MOTy,int64_t Offset) const340b57cec5SDimitry Andric MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
350b57cec5SDimitry Andric MachineOperandType MOTy,
36480093f4SDimitry Andric int64_t Offset) const {
370b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
380b57cec5SDimitry Andric MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
390b57cec5SDimitry Andric bool IsGpOff = false;
400b57cec5SDimitry Andric const MCSymbol *Symbol;
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric switch(MO.getTargetFlags()) {
430b57cec5SDimitry Andric default:
440b57cec5SDimitry Andric llvm_unreachable("Invalid target flag!");
450b57cec5SDimitry Andric case MipsII::MO_NO_FLAG:
460b57cec5SDimitry Andric break;
470b57cec5SDimitry Andric case MipsII::MO_GPREL:
480b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_GPREL;
490b57cec5SDimitry Andric break;
500b57cec5SDimitry Andric case MipsII::MO_GOT_CALL:
510b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_GOT_CALL;
520b57cec5SDimitry Andric break;
530b57cec5SDimitry Andric case MipsII::MO_GOT:
540b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_GOT;
550b57cec5SDimitry Andric break;
560b57cec5SDimitry Andric case MipsII::MO_ABS_HI:
570b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_HI;
580b57cec5SDimitry Andric break;
590b57cec5SDimitry Andric case MipsII::MO_ABS_LO:
600b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_LO;
610b57cec5SDimitry Andric break;
620b57cec5SDimitry Andric case MipsII::MO_TLSGD:
630b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_TLSGD;
640b57cec5SDimitry Andric break;
650b57cec5SDimitry Andric case MipsII::MO_TLSLDM:
660b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_TLSLDM;
670b57cec5SDimitry Andric break;
680b57cec5SDimitry Andric case MipsII::MO_DTPREL_HI:
690b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_DTPREL_HI;
700b57cec5SDimitry Andric break;
710b57cec5SDimitry Andric case MipsII::MO_DTPREL_LO:
720b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_DTPREL_LO;
730b57cec5SDimitry Andric break;
740b57cec5SDimitry Andric case MipsII::MO_GOTTPREL:
750b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_GOTTPREL;
760b57cec5SDimitry Andric break;
770b57cec5SDimitry Andric case MipsII::MO_TPREL_HI:
780b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_TPREL_HI;
790b57cec5SDimitry Andric break;
800b57cec5SDimitry Andric case MipsII::MO_TPREL_LO:
810b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_TPREL_LO;
820b57cec5SDimitry Andric break;
830b57cec5SDimitry Andric case MipsII::MO_GPOFF_HI:
840b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_HI;
850b57cec5SDimitry Andric IsGpOff = true;
860b57cec5SDimitry Andric break;
870b57cec5SDimitry Andric case MipsII::MO_GPOFF_LO:
880b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_LO;
890b57cec5SDimitry Andric IsGpOff = true;
900b57cec5SDimitry Andric break;
910b57cec5SDimitry Andric case MipsII::MO_GOT_DISP:
920b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_GOT_DISP;
930b57cec5SDimitry Andric break;
940b57cec5SDimitry Andric case MipsII::MO_GOT_HI16:
950b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_GOT_HI16;
960b57cec5SDimitry Andric break;
970b57cec5SDimitry Andric case MipsII::MO_GOT_LO16:
980b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_GOT_LO16;
990b57cec5SDimitry Andric break;
1000b57cec5SDimitry Andric case MipsII::MO_GOT_PAGE:
1010b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_GOT_PAGE;
1020b57cec5SDimitry Andric break;
1030b57cec5SDimitry Andric case MipsII::MO_GOT_OFST:
1040b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_GOT_OFST;
1050b57cec5SDimitry Andric break;
1060b57cec5SDimitry Andric case MipsII::MO_HIGHER:
1070b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_HIGHER;
1080b57cec5SDimitry Andric break;
1090b57cec5SDimitry Andric case MipsII::MO_HIGHEST:
1100b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_HIGHEST;
1110b57cec5SDimitry Andric break;
1120b57cec5SDimitry Andric case MipsII::MO_CALL_HI16:
1130b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_CALL_HI16;
1140b57cec5SDimitry Andric break;
1150b57cec5SDimitry Andric case MipsII::MO_CALL_LO16:
1160b57cec5SDimitry Andric TargetKind = MipsMCExpr::MEK_CALL_LO16;
1170b57cec5SDimitry Andric break;
1180b57cec5SDimitry Andric case MipsII::MO_JALR:
1190b57cec5SDimitry Andric return MCOperand();
1200b57cec5SDimitry Andric }
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric switch (MOTy) {
1230b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock:
1240b57cec5SDimitry Andric Symbol = MO.getMBB()->getSymbol();
1250b57cec5SDimitry Andric break;
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress:
1280b57cec5SDimitry Andric Symbol = AsmPrinter.getSymbol(MO.getGlobal());
1290b57cec5SDimitry Andric Offset += MO.getOffset();
1300b57cec5SDimitry Andric break;
1310b57cec5SDimitry Andric
1320b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress:
1330b57cec5SDimitry Andric Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
1340b57cec5SDimitry Andric Offset += MO.getOffset();
1350b57cec5SDimitry Andric break;
1360b57cec5SDimitry Andric
1370b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol:
1380b57cec5SDimitry Andric Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
1390b57cec5SDimitry Andric Offset += MO.getOffset();
1400b57cec5SDimitry Andric break;
1410b57cec5SDimitry Andric
1420b57cec5SDimitry Andric case MachineOperand::MO_MCSymbol:
1430b57cec5SDimitry Andric Symbol = MO.getMCSymbol();
1440b57cec5SDimitry Andric Offset += MO.getOffset();
1450b57cec5SDimitry Andric break;
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex:
1480b57cec5SDimitry Andric Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
1490b57cec5SDimitry Andric break;
1500b57cec5SDimitry Andric
1510b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex:
1520b57cec5SDimitry Andric Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
1530b57cec5SDimitry Andric Offset += MO.getOffset();
1540b57cec5SDimitry Andric break;
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric default:
1570b57cec5SDimitry Andric llvm_unreachable("<unknown operand type>");
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric if (Offset) {
163480093f4SDimitry Andric // Note: Offset can also be negative
1640b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
1650b57cec5SDimitry Andric *Ctx);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric if (IsGpOff)
1690b57cec5SDimitry Andric Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
1700b57cec5SDimitry Andric else if (TargetKind != MipsMCExpr::MEK_None)
1710b57cec5SDimitry Andric Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
1720b57cec5SDimitry Andric
1730b57cec5SDimitry Andric return MCOperand::createExpr(Expr);
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric
LowerOperand(const MachineOperand & MO,int64_t offset) const1760b57cec5SDimitry Andric MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
177480093f4SDimitry Andric int64_t offset) const {
1780b57cec5SDimitry Andric MachineOperandType MOTy = MO.getType();
1790b57cec5SDimitry Andric
1800b57cec5SDimitry Andric switch (MOTy) {
1810b57cec5SDimitry Andric default: llvm_unreachable("unknown operand type");
1820b57cec5SDimitry Andric case MachineOperand::MO_Register:
1830b57cec5SDimitry Andric // Ignore all implicit register operands.
1840b57cec5SDimitry Andric if (MO.isImplicit()) break;
1850b57cec5SDimitry Andric return MCOperand::createReg(MO.getReg());
1860b57cec5SDimitry Andric case MachineOperand::MO_Immediate:
1870b57cec5SDimitry Andric return MCOperand::createImm(MO.getImm() + offset);
1880b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock:
1890b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress:
1900b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol:
1910b57cec5SDimitry Andric case MachineOperand::MO_MCSymbol:
1920b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex:
1930b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex:
1940b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress:
1950b57cec5SDimitry Andric return LowerSymbolOperand(MO, MOTy, offset);
1960b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask:
1970b57cec5SDimitry Andric break;
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric
2000b57cec5SDimitry Andric return MCOperand();
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric
createSub(MachineBasicBlock * BB1,MachineBasicBlock * BB2,MipsMCExpr::MipsExprKind Kind) const2030b57cec5SDimitry Andric MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
2040b57cec5SDimitry Andric MachineBasicBlock *BB2,
2050b57cec5SDimitry Andric MipsMCExpr::MipsExprKind Kind) const {
2060b57cec5SDimitry Andric const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
2070b57cec5SDimitry Andric const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
2080b57cec5SDimitry Andric const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
2090b57cec5SDimitry Andric
2100b57cec5SDimitry Andric return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx));
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric
2130b57cec5SDimitry Andric void MipsMCInstLower::
lowerLongBranchLUi(const MachineInstr * MI,MCInst & OutMI) const2140b57cec5SDimitry Andric lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
2150b57cec5SDimitry Andric OutMI.setOpcode(Mips::LUi);
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andric // Lower register operand.
2180b57cec5SDimitry Andric OutMI.addOperand(LowerOperand(MI->getOperand(0)));
2190b57cec5SDimitry Andric
2200b57cec5SDimitry Andric MipsMCExpr::MipsExprKind Kind;
2210b57cec5SDimitry Andric unsigned TargetFlags = MI->getOperand(1).getTargetFlags();
2220b57cec5SDimitry Andric switch (TargetFlags) {
2230b57cec5SDimitry Andric case MipsII::MO_HIGHEST:
2240b57cec5SDimitry Andric Kind = MipsMCExpr::MEK_HIGHEST;
2250b57cec5SDimitry Andric break;
2260b57cec5SDimitry Andric case MipsII::MO_HIGHER:
2270b57cec5SDimitry Andric Kind = MipsMCExpr::MEK_HIGHER;
2280b57cec5SDimitry Andric break;
2290b57cec5SDimitry Andric case MipsII::MO_ABS_HI:
2300b57cec5SDimitry Andric Kind = MipsMCExpr::MEK_HI;
2310b57cec5SDimitry Andric break;
2320b57cec5SDimitry Andric case MipsII::MO_ABS_LO:
2330b57cec5SDimitry Andric Kind = MipsMCExpr::MEK_LO;
2340b57cec5SDimitry Andric break;
2350b57cec5SDimitry Andric default:
2360b57cec5SDimitry Andric report_fatal_error("Unexpected flags for lowerLongBranchLUi");
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric
2390b57cec5SDimitry Andric if (MI->getNumOperands() == 2) {
2400b57cec5SDimitry Andric const MCExpr *Expr =
2410b57cec5SDimitry Andric MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx);
2420b57cec5SDimitry Andric const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
2430b57cec5SDimitry Andric OutMI.addOperand(MCOperand::createExpr(MipsExpr));
2440b57cec5SDimitry Andric } else if (MI->getNumOperands() == 3) {
2450b57cec5SDimitry Andric // Create %hi($tgt-$baltgt).
2460b57cec5SDimitry Andric OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
2470b57cec5SDimitry Andric MI->getOperand(2).getMBB(), Kind));
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric
lowerLongBranchADDiu(const MachineInstr * MI,MCInst & OutMI,int Opcode) const2510b57cec5SDimitry Andric void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI,
2520b57cec5SDimitry Andric MCInst &OutMI, int Opcode) const {
2530b57cec5SDimitry Andric OutMI.setOpcode(Opcode);
2540b57cec5SDimitry Andric
2550b57cec5SDimitry Andric MipsMCExpr::MipsExprKind Kind;
2560b57cec5SDimitry Andric unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
2570b57cec5SDimitry Andric switch (TargetFlags) {
2580b57cec5SDimitry Andric case MipsII::MO_HIGHEST:
2590b57cec5SDimitry Andric Kind = MipsMCExpr::MEK_HIGHEST;
2600b57cec5SDimitry Andric break;
2610b57cec5SDimitry Andric case MipsII::MO_HIGHER:
2620b57cec5SDimitry Andric Kind = MipsMCExpr::MEK_HIGHER;
2630b57cec5SDimitry Andric break;
2640b57cec5SDimitry Andric case MipsII::MO_ABS_HI:
2650b57cec5SDimitry Andric Kind = MipsMCExpr::MEK_HI;
2660b57cec5SDimitry Andric break;
2670b57cec5SDimitry Andric case MipsII::MO_ABS_LO:
2680b57cec5SDimitry Andric Kind = MipsMCExpr::MEK_LO;
2690b57cec5SDimitry Andric break;
2700b57cec5SDimitry Andric default:
2710b57cec5SDimitry Andric report_fatal_error("Unexpected flags for lowerLongBranchADDiu");
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric
2740b57cec5SDimitry Andric // Lower two register operands.
2750b57cec5SDimitry Andric for (unsigned I = 0, E = 2; I != E; ++I) {
2760b57cec5SDimitry Andric const MachineOperand &MO = MI->getOperand(I);
2770b57cec5SDimitry Andric OutMI.addOperand(LowerOperand(MO));
2780b57cec5SDimitry Andric }
2790b57cec5SDimitry Andric
2800b57cec5SDimitry Andric if (MI->getNumOperands() == 3) {
2810b57cec5SDimitry Andric // Lower register operand.
2820b57cec5SDimitry Andric const MCExpr *Expr =
2830b57cec5SDimitry Andric MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx);
2840b57cec5SDimitry Andric const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
2850b57cec5SDimitry Andric OutMI.addOperand(MCOperand::createExpr(MipsExpr));
2860b57cec5SDimitry Andric } else if (MI->getNumOperands() == 4) {
2870b57cec5SDimitry Andric // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
2880b57cec5SDimitry Andric OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
2890b57cec5SDimitry Andric MI->getOperand(3).getMBB(), Kind));
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric
lowerLongBranch(const MachineInstr * MI,MCInst & OutMI) const2930b57cec5SDimitry Andric bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
2940b57cec5SDimitry Andric MCInst &OutMI) const {
2950b57cec5SDimitry Andric switch (MI->getOpcode()) {
2960b57cec5SDimitry Andric default:
2970b57cec5SDimitry Andric return false;
2980b57cec5SDimitry Andric case Mips::LONG_BRANCH_LUi:
2990b57cec5SDimitry Andric case Mips::LONG_BRANCH_LUi2Op:
3000b57cec5SDimitry Andric case Mips::LONG_BRANCH_LUi2Op_64:
3010b57cec5SDimitry Andric lowerLongBranchLUi(MI, OutMI);
3020b57cec5SDimitry Andric return true;
3030b57cec5SDimitry Andric case Mips::LONG_BRANCH_ADDiu:
3040b57cec5SDimitry Andric case Mips::LONG_BRANCH_ADDiu2Op:
3050b57cec5SDimitry Andric lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu);
3060b57cec5SDimitry Andric return true;
3070b57cec5SDimitry Andric case Mips::LONG_BRANCH_DADDiu:
3080b57cec5SDimitry Andric case Mips::LONG_BRANCH_DADDiu2Op:
3090b57cec5SDimitry Andric lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu);
3100b57cec5SDimitry Andric return true;
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric
Lower(const MachineInstr * MI,MCInst & OutMI) const3140b57cec5SDimitry Andric void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
3150b57cec5SDimitry Andric if (lowerLongBranch(MI, OutMI))
3160b57cec5SDimitry Andric return;
3170b57cec5SDimitry Andric
3180b57cec5SDimitry Andric OutMI.setOpcode(MI->getOpcode());
3190b57cec5SDimitry Andric
320*4824e7fdSDimitry Andric for (const MachineOperand &MO : MI->operands()) {
3210b57cec5SDimitry Andric MCOperand MCOp = LowerOperand(MO);
3220b57cec5SDimitry Andric
3230b57cec5SDimitry Andric if (MCOp.isValid())
3240b57cec5SDimitry Andric OutMI.addOperand(MCOp);
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric }
327