summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/VE/VEAsmPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/VE/VEAsmPrinter.cpp')
-rw-r--r--llvm/lib/Target/VE/VEAsmPrinter.cpp283
1 files changed, 280 insertions, 3 deletions
diff --git a/llvm/lib/Target/VE/VEAsmPrinter.cpp b/llvm/lib/Target/VE/VEAsmPrinter.cpp
index 918f2a1acdaff..86e3aa3d3fa13 100644
--- a/llvm/lib/Target/VE/VEAsmPrinter.cpp
+++ b/llvm/lib/Target/VE/VEAsmPrinter.cpp
@@ -11,8 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "InstPrinter/VEInstPrinter.h"
+#include "MCTargetDesc/VEInstPrinter.h"
+#include "MCTargetDesc/VEMCExpr.h"
#include "MCTargetDesc/VETargetStreamer.h"
+#include "TargetInfo/VETargetInfo.h"
#include "VE.h"
#include "VEInstrInfo.h"
#include "VETargetMachine.h"
@@ -46,7 +48,14 @@ public:
StringRef getPassName() const override { return "VE Assembly Printer"; }
- void EmitInstruction(const MachineInstr *MI) override;
+ void lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
+ const MCSubtargetInfo &STI);
+ void lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
+ const MCSubtargetInfo &STI);
+ void lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
+ const MCSubtargetInfo &STI);
+
+ void emitInstruction(const MachineInstr *MI) override;
static const char *getRegisterName(unsigned RegNo) {
return VEInstPrinter::getRegisterName(RegNo);
@@ -54,7 +63,265 @@ public:
};
} // end of anonymous namespace
-void VEAsmPrinter::EmitInstruction(const MachineInstr *MI) {
+static MCOperand createVEMCOperand(VEMCExpr::VariantKind Kind, MCSymbol *Sym,
+ MCContext &OutContext) {
+ const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext);
+ const VEMCExpr *expr = VEMCExpr::create(Kind, MCSym, OutContext);
+ return MCOperand::createExpr(expr);
+}
+
+static MCOperand createGOTRelExprOp(VEMCExpr::VariantKind Kind,
+ MCSymbol *GOTLabel, MCContext &OutContext) {
+ const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
+ const VEMCExpr *expr = VEMCExpr::create(Kind, GOT, OutContext);
+ return MCOperand::createExpr(expr);
+}
+
+static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,
+ const MCSubtargetInfo &STI) {
+ MCInst SICInst;
+ SICInst.setOpcode(VE::SIC);
+ SICInst.addOperand(RD);
+ OutStreamer.emitInstruction(SICInst, STI);
+}
+
+static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,
+ const MCSubtargetInfo &STI) {
+ MCInst BSICInst;
+ BSICInst.setOpcode(VE::BSICrii);
+ BSICInst.addOperand(R1);
+ BSICInst.addOperand(R2);
+ MCOperand czero = MCOperand::createImm(0);
+ BSICInst.addOperand(czero);
+ BSICInst.addOperand(czero);
+ OutStreamer.emitInstruction(BSICInst, STI);
+}
+
+static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
+ const MCSubtargetInfo &STI) {
+ MCInst LEAInst;
+ LEAInst.setOpcode(VE::LEAzii);
+ LEAInst.addOperand(RD);
+ MCOperand CZero = MCOperand::createImm(0);
+ LEAInst.addOperand(CZero);
+ LEAInst.addOperand(CZero);
+ LEAInst.addOperand(Imm);
+ OutStreamer.emitInstruction(LEAInst, STI);
+}
+
+static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
+ const MCSubtargetInfo &STI) {
+ MCInst LEASLInst;
+ LEASLInst.setOpcode(VE::LEASLzii);
+ LEASLInst.addOperand(RD);
+ MCOperand CZero = MCOperand::createImm(0);
+ LEASLInst.addOperand(CZero);
+ LEASLInst.addOperand(CZero);
+ LEASLInst.addOperand(Imm);
+ OutStreamer.emitInstruction(LEASLInst, STI);
+}
+
+static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
+ MCOperand &RD, const MCSubtargetInfo &STI) {
+ MCInst LEAInst;
+ LEAInst.setOpcode(VE::LEAzii);
+ LEAInst.addOperand(RD);
+ MCOperand CZero = MCOperand::createImm(0);
+ LEAInst.addOperand(CZero);
+ LEAInst.addOperand(RS1);
+ LEAInst.addOperand(Imm);
+ OutStreamer.emitInstruction(LEAInst, STI);
+}
+
+static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,
+ MCOperand &RS2, MCOperand &Imm, MCOperand &RD,
+ const MCSubtargetInfo &STI) {
+ MCInst LEASLInst;
+ LEASLInst.setOpcode(VE::LEASLrri);
+ LEASLInst.addOperand(RD);
+ LEASLInst.addOperand(RS1);
+ LEASLInst.addOperand(RS2);
+ LEASLInst.addOperand(Imm);
+ OutStreamer.emitInstruction(LEASLInst, STI);
+}
+
+static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,
+ MCOperand &Src2, MCOperand &RD,
+ const MCSubtargetInfo &STI) {
+ MCInst Inst;
+ Inst.setOpcode(Opcode);
+ Inst.addOperand(RD);
+ Inst.addOperand(RS1);
+ Inst.addOperand(Src2);
+ OutStreamer.emitInstruction(Inst, STI);
+}
+
+static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
+ MCOperand &RD, const MCSubtargetInfo &STI) {
+ emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI);
+}
+
+static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
+ VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind,
+ MCOperand &RD, MCContext &OutContext,
+ const MCSubtargetInfo &STI) {
+
+ MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext);
+ MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext);
+ emitLEAzzi(OutStreamer, lo, RD, STI);
+ MCOperand M032 = MCOperand::createImm(M0(32));
+ emitANDrm(OutStreamer, RD, M032, RD, STI);
+ emitLEASLzzi(OutStreamer, hi, RD, STI);
+}
+
+void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
+ const MCSubtargetInfo &STI) {
+ MCSymbol *GOTLabel =
+ OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
+
+ const MachineOperand &MO = MI->getOperand(0);
+ MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
+
+ if (!isPositionIndependent()) {
+ // Just load the address of GOT to MCRegOP.
+ switch (TM.getCodeModel()) {
+ default:
+ llvm_unreachable("Unsupported absolute code model");
+ case CodeModel::Small:
+ case CodeModel::Medium:
+ case CodeModel::Large:
+ emitHiLo(*OutStreamer, GOTLabel, VEMCExpr::VK_VE_HI32,
+ VEMCExpr::VK_VE_LO32, MCRegOP, OutContext, STI);
+ break;
+ }
+ return;
+ }
+
+ MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT
+ MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
+
+ // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24)
+ // and %got, %got, (32)0
+ // sic %plt
+ // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%got, %plt)
+ MCOperand cim24 = MCOperand::createImm(-24);
+ MCOperand loImm =
+ createGOTRelExprOp(VEMCExpr::VK_VE_PC_LO32, GOTLabel, OutContext);
+ emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
+ MCOperand M032 = MCOperand::createImm(M0(32));
+ emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
+ emitSIC(*OutStreamer, RegPLT, STI);
+ MCOperand hiImm =
+ createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext);
+ emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);
+}
+
+void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
+ const MCSubtargetInfo &STI) {
+ const MachineOperand &MO = MI->getOperand(0);
+ MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
+ const MachineOperand &Addr = MI->getOperand(1);
+ MCSymbol *AddrSym = nullptr;
+
+ switch (Addr.getType()) {
+ default:
+ llvm_unreachable("<unknown operand type>");
+ return;
+ case MachineOperand::MO_MachineBasicBlock:
+ report_fatal_error("MBB is not supported yet");
+ return;
+ case MachineOperand::MO_ConstantPoolIndex:
+ report_fatal_error("ConstantPool is not supported yet");
+ return;
+ case MachineOperand::MO_ExternalSymbol:
+ AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
+ break;
+ case MachineOperand::MO_GlobalAddress:
+ AddrSym = getSymbol(Addr.getGlobal());
+ break;
+ }
+
+ if (!isPositionIndependent()) {
+ llvm_unreachable("Unsupported uses of %plt in not PIC code");
+ return;
+ }
+
+ MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
+
+ // lea %dst, %plt_lo(func)(-24)
+ // and %dst, %dst, (32)0
+ // sic %plt ; FIXME: is it safe to use %plt here?
+ // lea.sl %dst, %plt_hi(func)(%dst, %plt)
+ MCOperand cim24 = MCOperand::createImm(-24);
+ MCOperand loImm =
+ createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, AddrSym, OutContext);
+ emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
+ MCOperand M032 = MCOperand::createImm(M0(32));
+ emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
+ emitSIC(*OutStreamer, RegPLT, STI);
+ MCOperand hiImm =
+ createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext);
+ emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);
+}
+
+void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
+ const MCSubtargetInfo &STI) {
+ const MachineOperand &Addr = MI->getOperand(0);
+ MCSymbol *AddrSym = nullptr;
+
+ switch (Addr.getType()) {
+ default:
+ llvm_unreachable("<unknown operand type>");
+ return;
+ case MachineOperand::MO_MachineBasicBlock:
+ report_fatal_error("MBB is not supported yet");
+ return;
+ case MachineOperand::MO_ConstantPoolIndex:
+ report_fatal_error("ConstantPool is not supported yet");
+ return;
+ case MachineOperand::MO_ExternalSymbol:
+ AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
+ break;
+ case MachineOperand::MO_GlobalAddress:
+ AddrSym = getSymbol(Addr.getGlobal());
+ break;
+ }
+
+ MCOperand RegLR = MCOperand::createReg(VE::SX10); // LR
+ MCOperand RegS0 = MCOperand::createReg(VE::SX0); // S0
+ MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12
+ MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));
+
+ // lea %s0, sym@tls_gd_lo(-24)
+ // and %s0, %s0, (32)0
+ // sic %lr
+ // lea.sl %s0, sym@tls_gd_hi(%s0, %lr)
+ // lea %s12, __tls_get_addr@plt_lo(8)
+ // and %s12, %s12, (32)0
+ // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)
+ // bsic %lr, (, %s12)
+ MCOperand cim24 = MCOperand::createImm(-24);
+ MCOperand loImm =
+ createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_LO32, AddrSym, OutContext);
+ emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);
+ MCOperand M032 = MCOperand::createImm(M0(32));
+ emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI);
+ emitSIC(*OutStreamer, RegLR, STI);
+ MCOperand hiImm =
+ createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext);
+ emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);
+ MCOperand ci8 = MCOperand::createImm(8);
+ MCOperand loImm2 =
+ createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext);
+ emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);
+ emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);
+ MCOperand hiImm2 =
+ createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext);
+ emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);
+ emitBSIC(*OutStreamer, RegLR, RegS12, STI);
+}
+
+void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {
switch (MI->getOpcode()) {
default:
@@ -62,7 +329,17 @@ void VEAsmPrinter::EmitInstruction(const MachineInstr *MI) {
case TargetOpcode::DBG_VALUE:
// FIXME: Debug Value.
return;
+ case VE::GETGOT:
+ lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());
+ return;
+ case VE::GETFUNPLT:
+ lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());
+ return;
+ case VE::GETTLSADDR:
+ lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());
+ return;
}
+
MachineBasicBlock::const_instr_iterator I = MI->getIterator();
MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
do {