1e5d89e80SDylan McKay //===-- AVRMCInstLower.cpp - Convert AVR MachineInstr to an MCInst --------===// 2e5d89e80SDylan McKay // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5d89e80SDylan McKay // 7e5d89e80SDylan McKay //===----------------------------------------------------------------------===// 8e5d89e80SDylan McKay // 9e5d89e80SDylan McKay // This file contains code to lower AVR MachineInstrs to their corresponding 10e5d89e80SDylan McKay // MCInst records. 11e5d89e80SDylan McKay // 12e5d89e80SDylan McKay //===----------------------------------------------------------------------===// 13e5d89e80SDylan McKay 14e5d89e80SDylan McKay #include "AVRMCInstLower.h" 15e5d89e80SDylan McKay 16e5d89e80SDylan McKay #include "AVRInstrInfo.h" 17e5d89e80SDylan McKay #include "MCTargetDesc/AVRMCExpr.h" 18e5d89e80SDylan McKay 19e5d89e80SDylan McKay #include "llvm/CodeGen/AsmPrinter.h" 20e5d89e80SDylan McKay #include "llvm/IR/Mangler.h" 21e5d89e80SDylan McKay #include "llvm/MC/MCInst.h" 22e5d89e80SDylan McKay #include "llvm/Support/ErrorHandling.h" 23e5d89e80SDylan McKay 24e5d89e80SDylan McKay namespace llvm { 25e5d89e80SDylan McKay 26e5d89e80SDylan McKay MCOperand AVRMCInstLower::lowerSymbolOperand(const MachineOperand &MO, 27e5d89e80SDylan McKay MCSymbol *Sym) const { 28e5d89e80SDylan McKay unsigned char TF = MO.getTargetFlags(); 29e5d89e80SDylan McKay const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx); 30e5d89e80SDylan McKay 31e5d89e80SDylan McKay bool IsNegated = false; 32e5d89e80SDylan McKay if (TF & AVRII::MO_NEG) { IsNegated = true; } 33e5d89e80SDylan McKay 34e5d89e80SDylan McKay if (!MO.isJTI() && MO.getOffset()) { 35e5d89e80SDylan McKay Expr = MCBinaryExpr::createAdd( 36e5d89e80SDylan McKay Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 37e5d89e80SDylan McKay } 38e5d89e80SDylan McKay 399fb04071SDylan McKay bool IsFunction = MO.isGlobal() && isa<Function>(MO.getGlobal()); 409fb04071SDylan McKay 41e5d89e80SDylan McKay if (TF & AVRII::MO_LO) { 429fb04071SDylan McKay if (IsFunction) { 439fb04071SDylan McKay // N.B. Should we use _GS fixups here to cope with >128k progmem? 449fb04071SDylan McKay Expr = AVRMCExpr::create(AVRMCExpr::VK_AVR_PM_LO8, Expr, IsNegated, Ctx); 459fb04071SDylan McKay } else { 46e5d89e80SDylan McKay Expr = AVRMCExpr::create(AVRMCExpr::VK_AVR_LO8, Expr, IsNegated, Ctx); 479fb04071SDylan McKay } 48e5d89e80SDylan McKay } else if (TF & AVRII::MO_HI) { 499fb04071SDylan McKay if (IsFunction) { 509fb04071SDylan McKay // N.B. Should we use _GS fixups here to cope with >128k progmem? 519fb04071SDylan McKay Expr = AVRMCExpr::create(AVRMCExpr::VK_AVR_PM_HI8, Expr, IsNegated, Ctx); 529fb04071SDylan McKay } else { 53e5d89e80SDylan McKay Expr = AVRMCExpr::create(AVRMCExpr::VK_AVR_HI8, Expr, IsNegated, Ctx); 549fb04071SDylan McKay } 55e5d89e80SDylan McKay } else if (TF != 0) { 56e5d89e80SDylan McKay llvm_unreachable("Unknown target flag on symbol operand"); 57e5d89e80SDylan McKay } 58e5d89e80SDylan McKay 59e5d89e80SDylan McKay return MCOperand::createExpr(Expr); 60e5d89e80SDylan McKay } 61e5d89e80SDylan McKay 62e5d89e80SDylan McKay void AVRMCInstLower::lowerInstruction(const MachineInstr &MI, MCInst &OutMI) const { 63e5d89e80SDylan McKay OutMI.setOpcode(MI.getOpcode()); 64e5d89e80SDylan McKay 65e5d89e80SDylan McKay for (MachineOperand const &MO : MI.operands()) { 66e5d89e80SDylan McKay MCOperand MCOp; 67e5d89e80SDylan McKay 68e5d89e80SDylan McKay switch (MO.getType()) { 69e5d89e80SDylan McKay default: 700acfafdbSDylan McKay MI.print(errs()); 71e5d89e80SDylan McKay llvm_unreachable("unknown operand type"); 72e5d89e80SDylan McKay case MachineOperand::MO_Register: 73e5d89e80SDylan McKay // Ignore all implicit register operands. 74e5d89e80SDylan McKay if (MO.isImplicit()) 75e5d89e80SDylan McKay continue; 76e5d89e80SDylan McKay MCOp = MCOperand::createReg(MO.getReg()); 77e5d89e80SDylan McKay break; 78e5d89e80SDylan McKay case MachineOperand::MO_Immediate: 79e5d89e80SDylan McKay MCOp = MCOperand::createImm(MO.getImm()); 80e5d89e80SDylan McKay break; 81e5d89e80SDylan McKay case MachineOperand::MO_GlobalAddress: 82e5d89e80SDylan McKay MCOp = lowerSymbolOperand(MO, Printer.getSymbol(MO.getGlobal())); 83e5d89e80SDylan McKay break; 84e5d89e80SDylan McKay case MachineOperand::MO_ExternalSymbol: 85e5d89e80SDylan McKay MCOp = lowerSymbolOperand( 86e5d89e80SDylan McKay MO, Printer.GetExternalSymbolSymbol(MO.getSymbolName())); 87e5d89e80SDylan McKay break; 88e5d89e80SDylan McKay case MachineOperand::MO_MachineBasicBlock: 89e5d89e80SDylan McKay MCOp = MCOperand::createExpr( 90e5d89e80SDylan McKay MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx)); 91e5d89e80SDylan McKay break; 92e5d89e80SDylan McKay case MachineOperand::MO_RegisterMask: 93e5d89e80SDylan McKay continue; 94e5d89e80SDylan McKay case MachineOperand::MO_BlockAddress: 95e5d89e80SDylan McKay MCOp = lowerSymbolOperand( 96e5d89e80SDylan McKay MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress())); 97e5d89e80SDylan McKay break; 98e5d89e80SDylan McKay case MachineOperand::MO_JumpTableIndex: 99e5d89e80SDylan McKay MCOp = lowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex())); 100e5d89e80SDylan McKay break; 101e5d89e80SDylan McKay case MachineOperand::MO_ConstantPoolIndex: 102e5d89e80SDylan McKay MCOp = lowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex())); 103e5d89e80SDylan McKay break; 104e5d89e80SDylan McKay } 105e5d89e80SDylan McKay 106e5d89e80SDylan McKay OutMI.addOperand(MCOp); 107e5d89e80SDylan McKay } 108e5d89e80SDylan McKay } 109e5d89e80SDylan McKay 110e5d89e80SDylan McKay } // end of namespace llvm 111e5d89e80SDylan McKay 112