summaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/Mips/MipsMCInstLower.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/Mips/MipsMCInstLower.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/Mips/MipsMCInstLower.cpp330
1 files changed, 330 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/Mips/MipsMCInstLower.cpp b/contrib/llvm-project/llvm/lib/Target/Mips/MipsMCInstLower.cpp
new file mode 100644
index 000000000000..fd984058a2bf
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/Target/Mips/MipsMCInstLower.cpp
@@ -0,0 +1,330 @@
+//===- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code to lower Mips MachineInstrs to their corresponding
+// MCInst records.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsMCInstLower.h"
+#include "MCTargetDesc/MipsBaseInfo.h"
+#include "MCTargetDesc/MipsMCExpr.h"
+#include "MipsAsmPrinter.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+
+using namespace llvm;
+
+MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
+ : AsmPrinter(asmprinter) {}
+
+void MipsMCInstLower::Initialize(MCContext *C) {
+ Ctx = C;
+}
+
+MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
+ MachineOperandType MOTy,
+ unsigned Offset) const {
+ MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
+ MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
+ bool IsGpOff = false;
+ const MCSymbol *Symbol;
+
+ switch(MO.getTargetFlags()) {
+ default:
+ llvm_unreachable("Invalid target flag!");
+ case MipsII::MO_NO_FLAG:
+ break;
+ case MipsII::MO_GPREL:
+ TargetKind = MipsMCExpr::MEK_GPREL;
+ break;
+ case MipsII::MO_GOT_CALL:
+ TargetKind = MipsMCExpr::MEK_GOT_CALL;
+ break;
+ case MipsII::MO_GOT:
+ TargetKind = MipsMCExpr::MEK_GOT;
+ break;
+ case MipsII::MO_ABS_HI:
+ TargetKind = MipsMCExpr::MEK_HI;
+ break;
+ case MipsII::MO_ABS_LO:
+ TargetKind = MipsMCExpr::MEK_LO;
+ break;
+ case MipsII::MO_TLSGD:
+ TargetKind = MipsMCExpr::MEK_TLSGD;
+ break;
+ case MipsII::MO_TLSLDM:
+ TargetKind = MipsMCExpr::MEK_TLSLDM;
+ break;
+ case MipsII::MO_DTPREL_HI:
+ TargetKind = MipsMCExpr::MEK_DTPREL_HI;
+ break;
+ case MipsII::MO_DTPREL_LO:
+ TargetKind = MipsMCExpr::MEK_DTPREL_LO;
+ break;
+ case MipsII::MO_GOTTPREL:
+ TargetKind = MipsMCExpr::MEK_GOTTPREL;
+ break;
+ case MipsII::MO_TPREL_HI:
+ TargetKind = MipsMCExpr::MEK_TPREL_HI;
+ break;
+ case MipsII::MO_TPREL_LO:
+ TargetKind = MipsMCExpr::MEK_TPREL_LO;
+ break;
+ case MipsII::MO_GPOFF_HI:
+ TargetKind = MipsMCExpr::MEK_HI;
+ IsGpOff = true;
+ break;
+ case MipsII::MO_GPOFF_LO:
+ TargetKind = MipsMCExpr::MEK_LO;
+ IsGpOff = true;
+ break;
+ case MipsII::MO_GOT_DISP:
+ TargetKind = MipsMCExpr::MEK_GOT_DISP;
+ break;
+ case MipsII::MO_GOT_HI16:
+ TargetKind = MipsMCExpr::MEK_GOT_HI16;
+ break;
+ case MipsII::MO_GOT_LO16:
+ TargetKind = MipsMCExpr::MEK_GOT_LO16;
+ break;
+ case MipsII::MO_GOT_PAGE:
+ TargetKind = MipsMCExpr::MEK_GOT_PAGE;
+ break;
+ case MipsII::MO_GOT_OFST:
+ TargetKind = MipsMCExpr::MEK_GOT_OFST;
+ break;
+ case MipsII::MO_HIGHER:
+ TargetKind = MipsMCExpr::MEK_HIGHER;
+ break;
+ case MipsII::MO_HIGHEST:
+ TargetKind = MipsMCExpr::MEK_HIGHEST;
+ break;
+ case MipsII::MO_CALL_HI16:
+ TargetKind = MipsMCExpr::MEK_CALL_HI16;
+ break;
+ case MipsII::MO_CALL_LO16:
+ TargetKind = MipsMCExpr::MEK_CALL_LO16;
+ break;
+ case MipsII::MO_JALR:
+ return MCOperand();
+ }
+
+ switch (MOTy) {
+ case MachineOperand::MO_MachineBasicBlock:
+ Symbol = MO.getMBB()->getSymbol();
+ break;
+
+ case MachineOperand::MO_GlobalAddress:
+ Symbol = AsmPrinter.getSymbol(MO.getGlobal());
+ Offset += MO.getOffset();
+ break;
+
+ case MachineOperand::MO_BlockAddress:
+ Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
+ Offset += MO.getOffset();
+ break;
+
+ case MachineOperand::MO_ExternalSymbol:
+ Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
+ Offset += MO.getOffset();
+ break;
+
+ case MachineOperand::MO_MCSymbol:
+ Symbol = MO.getMCSymbol();
+ Offset += MO.getOffset();
+ break;
+
+ case MachineOperand::MO_JumpTableIndex:
+ Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
+ break;
+
+ case MachineOperand::MO_ConstantPoolIndex:
+ Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
+ Offset += MO.getOffset();
+ break;
+
+ default:
+ llvm_unreachable("<unknown operand type>");
+ }
+
+ const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
+
+ if (Offset) {
+ // Assume offset is never negative.
+ assert(Offset > 0);
+
+ Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
+ *Ctx);
+ }
+
+ if (IsGpOff)
+ Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
+ else if (TargetKind != MipsMCExpr::MEK_None)
+ Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
+
+ return MCOperand::createExpr(Expr);
+}
+
+MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
+ unsigned offset) const {
+ MachineOperandType MOTy = MO.getType();
+
+ switch (MOTy) {
+ default: llvm_unreachable("unknown operand type");
+ case MachineOperand::MO_Register:
+ // Ignore all implicit register operands.
+ if (MO.isImplicit()) break;
+ return MCOperand::createReg(MO.getReg());
+ case MachineOperand::MO_Immediate:
+ return MCOperand::createImm(MO.getImm() + offset);
+ case MachineOperand::MO_MachineBasicBlock:
+ case MachineOperand::MO_GlobalAddress:
+ case MachineOperand::MO_ExternalSymbol:
+ case MachineOperand::MO_MCSymbol:
+ case MachineOperand::MO_JumpTableIndex:
+ case MachineOperand::MO_ConstantPoolIndex:
+ case MachineOperand::MO_BlockAddress:
+ return LowerSymbolOperand(MO, MOTy, offset);
+ case MachineOperand::MO_RegisterMask:
+ break;
+ }
+
+ return MCOperand();
+}
+
+MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
+ MachineBasicBlock *BB2,
+ MipsMCExpr::MipsExprKind Kind) const {
+ const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
+ const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
+ const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
+
+ return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx));
+}
+
+void MipsMCInstLower::
+lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
+ OutMI.setOpcode(Mips::LUi);
+
+ // Lower register operand.
+ OutMI.addOperand(LowerOperand(MI->getOperand(0)));
+
+ MipsMCExpr::MipsExprKind Kind;
+ unsigned TargetFlags = MI->getOperand(1).getTargetFlags();
+ switch (TargetFlags) {
+ case MipsII::MO_HIGHEST:
+ Kind = MipsMCExpr::MEK_HIGHEST;
+ break;
+ case MipsII::MO_HIGHER:
+ Kind = MipsMCExpr::MEK_HIGHER;
+ break;
+ case MipsII::MO_ABS_HI:
+ Kind = MipsMCExpr::MEK_HI;
+ break;
+ case MipsII::MO_ABS_LO:
+ Kind = MipsMCExpr::MEK_LO;
+ break;
+ default:
+ report_fatal_error("Unexpected flags for lowerLongBranchLUi");
+ }
+
+ if (MI->getNumOperands() == 2) {
+ const MCExpr *Expr =
+ MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx);
+ const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
+ OutMI.addOperand(MCOperand::createExpr(MipsExpr));
+ } else if (MI->getNumOperands() == 3) {
+ // Create %hi($tgt-$baltgt).
+ OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
+ MI->getOperand(2).getMBB(), Kind));
+ }
+}
+
+void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI,
+ MCInst &OutMI, int Opcode) const {
+ OutMI.setOpcode(Opcode);
+
+ MipsMCExpr::MipsExprKind Kind;
+ unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
+ switch (TargetFlags) {
+ case MipsII::MO_HIGHEST:
+ Kind = MipsMCExpr::MEK_HIGHEST;
+ break;
+ case MipsII::MO_HIGHER:
+ Kind = MipsMCExpr::MEK_HIGHER;
+ break;
+ case MipsII::MO_ABS_HI:
+ Kind = MipsMCExpr::MEK_HI;
+ break;
+ case MipsII::MO_ABS_LO:
+ Kind = MipsMCExpr::MEK_LO;
+ break;
+ default:
+ report_fatal_error("Unexpected flags for lowerLongBranchADDiu");
+ }
+
+ // Lower two register operands.
+ for (unsigned I = 0, E = 2; I != E; ++I) {
+ const MachineOperand &MO = MI->getOperand(I);
+ OutMI.addOperand(LowerOperand(MO));
+ }
+
+ if (MI->getNumOperands() == 3) {
+ // Lower register operand.
+ const MCExpr *Expr =
+ MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx);
+ const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
+ OutMI.addOperand(MCOperand::createExpr(MipsExpr));
+ } else if (MI->getNumOperands() == 4) {
+ // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
+ OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
+ MI->getOperand(3).getMBB(), Kind));
+ }
+}
+
+bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
+ MCInst &OutMI) const {
+ switch (MI->getOpcode()) {
+ default:
+ return false;
+ case Mips::LONG_BRANCH_LUi:
+ case Mips::LONG_BRANCH_LUi2Op:
+ case Mips::LONG_BRANCH_LUi2Op_64:
+ lowerLongBranchLUi(MI, OutMI);
+ return true;
+ case Mips::LONG_BRANCH_ADDiu:
+ case Mips::LONG_BRANCH_ADDiu2Op:
+ lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu);
+ return true;
+ case Mips::LONG_BRANCH_DADDiu:
+ case Mips::LONG_BRANCH_DADDiu2Op:
+ lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu);
+ return true;
+ }
+}
+
+void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
+ if (lowerLongBranch(MI, OutMI))
+ return;
+
+ OutMI.setOpcode(MI->getOpcode());
+
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+ MCOperand MCOp = LowerOperand(MO);
+
+ if (MCOp.isValid())
+ OutMI.addOperand(MCOp);
+ }
+}