10b57cec5SDimitry Andric //===-- AVRMCInstLower.cpp - Convert AVR MachineInstr to an 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 AVR MachineInstrs to their corresponding
100b57cec5SDimitry Andric // MCInst records.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "AVRMCInstLower.h"
150b57cec5SDimitry Andric #include "AVRInstrInfo.h"
160b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCExpr.h"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
190b57cec5SDimitry Andric #include "llvm/IR/Mangler.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
210b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric namespace llvm {
240b57cec5SDimitry Andric 
25bdd1243dSDimitry Andric MCOperand
lowerSymbolOperand(const MachineOperand & MO,MCSymbol * Sym,const AVRSubtarget & Subtarget) const26bdd1243dSDimitry Andric AVRMCInstLower::lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
27bdd1243dSDimitry Andric                                    const AVRSubtarget &Subtarget) const {
280b57cec5SDimitry Andric   unsigned char TF = MO.getTargetFlags();
290b57cec5SDimitry Andric   const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx);
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric   bool IsNegated = false;
32349cc55cSDimitry Andric   if (TF & AVRII::MO_NEG) {
33349cc55cSDimitry Andric     IsNegated = true;
34349cc55cSDimitry Andric   }
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   if (!MO.isJTI() && MO.getOffset()) {
370b57cec5SDimitry Andric     Expr = MCBinaryExpr::createAdd(
380b57cec5SDimitry Andric         Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
390b57cec5SDimitry Andric   }
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   bool IsFunction = MO.isGlobal() && isa<Function>(MO.getGlobal());
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   if (TF & AVRII::MO_LO) {
440b57cec5SDimitry Andric     if (IsFunction) {
45bdd1243dSDimitry Andric       Expr =
46bdd1243dSDimitry Andric           AVRMCExpr::create(Subtarget.hasEIJMPCALL() ? AVRMCExpr::VK_AVR_LO8_GS
47bdd1243dSDimitry Andric                                                      : AVRMCExpr::VK_AVR_PM_LO8,
48bdd1243dSDimitry Andric                             Expr, IsNegated, Ctx);
490b57cec5SDimitry Andric     } else {
500b57cec5SDimitry Andric       Expr = AVRMCExpr::create(AVRMCExpr::VK_AVR_LO8, Expr, IsNegated, Ctx);
510b57cec5SDimitry Andric     }
520b57cec5SDimitry Andric   } else if (TF & AVRII::MO_HI) {
530b57cec5SDimitry Andric     if (IsFunction) {
54bdd1243dSDimitry Andric       Expr =
55bdd1243dSDimitry Andric           AVRMCExpr::create(Subtarget.hasEIJMPCALL() ? AVRMCExpr::VK_AVR_HI8_GS
56bdd1243dSDimitry Andric                                                      : AVRMCExpr::VK_AVR_PM_HI8,
57bdd1243dSDimitry Andric                             Expr, IsNegated, Ctx);
580b57cec5SDimitry Andric     } else {
590b57cec5SDimitry Andric       Expr = AVRMCExpr::create(AVRMCExpr::VK_AVR_HI8, Expr, IsNegated, Ctx);
600b57cec5SDimitry Andric     }
610b57cec5SDimitry Andric   } else if (TF != 0) {
620b57cec5SDimitry Andric     llvm_unreachable("Unknown target flag on symbol operand");
630b57cec5SDimitry Andric   }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   return MCOperand::createExpr(Expr);
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
lowerInstruction(const MachineInstr & MI,MCInst & OutMI) const68349cc55cSDimitry Andric void AVRMCInstLower::lowerInstruction(const MachineInstr &MI,
69349cc55cSDimitry Andric                                       MCInst &OutMI) const {
70bdd1243dSDimitry Andric   auto &Subtarget = MI.getParent()->getParent()->getSubtarget<AVRSubtarget>();
710b57cec5SDimitry Andric   OutMI.setOpcode(MI.getOpcode());
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   for (MachineOperand const &MO : MI.operands()) {
740b57cec5SDimitry Andric     MCOperand MCOp;
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric     switch (MO.getType()) {
770b57cec5SDimitry Andric     default:
780b57cec5SDimitry Andric       MI.print(errs());
790b57cec5SDimitry Andric       llvm_unreachable("unknown operand type");
800b57cec5SDimitry Andric     case MachineOperand::MO_Register:
810b57cec5SDimitry Andric       // Ignore all implicit register operands.
820b57cec5SDimitry Andric       if (MO.isImplicit())
830b57cec5SDimitry Andric         continue;
840b57cec5SDimitry Andric       MCOp = MCOperand::createReg(MO.getReg());
850b57cec5SDimitry Andric       break;
860b57cec5SDimitry Andric     case MachineOperand::MO_Immediate:
870b57cec5SDimitry Andric       MCOp = MCOperand::createImm(MO.getImm());
880b57cec5SDimitry Andric       break;
890b57cec5SDimitry Andric     case MachineOperand::MO_GlobalAddress:
90bdd1243dSDimitry Andric       MCOp =
91bdd1243dSDimitry Andric           lowerSymbolOperand(MO, Printer.getSymbol(MO.getGlobal()), Subtarget);
920b57cec5SDimitry Andric       break;
930b57cec5SDimitry Andric     case MachineOperand::MO_ExternalSymbol:
940b57cec5SDimitry Andric       MCOp = lowerSymbolOperand(
95bdd1243dSDimitry Andric           MO, Printer.GetExternalSymbolSymbol(MO.getSymbolName()), Subtarget);
960b57cec5SDimitry Andric       break;
970b57cec5SDimitry Andric     case MachineOperand::MO_MachineBasicBlock:
980b57cec5SDimitry Andric       MCOp = MCOperand::createExpr(
990b57cec5SDimitry Andric           MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
1000b57cec5SDimitry Andric       break;
1010b57cec5SDimitry Andric     case MachineOperand::MO_RegisterMask:
1020b57cec5SDimitry Andric       continue;
1030b57cec5SDimitry Andric     case MachineOperand::MO_BlockAddress:
1040b57cec5SDimitry Andric       MCOp = lowerSymbolOperand(
105bdd1243dSDimitry Andric           MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()), Subtarget);
1060b57cec5SDimitry Andric       break;
1070b57cec5SDimitry Andric     case MachineOperand::MO_JumpTableIndex:
108bdd1243dSDimitry Andric       MCOp = lowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()),
109bdd1243dSDimitry Andric                                 Subtarget);
1100b57cec5SDimitry Andric       break;
1110b57cec5SDimitry Andric     case MachineOperand::MO_ConstantPoolIndex:
112bdd1243dSDimitry Andric       MCOp = lowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()),
113bdd1243dSDimitry Andric                                 Subtarget);
1140b57cec5SDimitry Andric       break;
1150b57cec5SDimitry Andric     }
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric     OutMI.addOperand(MCOp);
1180b57cec5SDimitry Andric   }
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric } // end of namespace llvm
122