diff options
Diffstat (limited to 'llvm/lib/Target/VE/VEAsmPrinter.cpp')
-rw-r--r-- | llvm/lib/Target/VE/VEAsmPrinter.cpp | 283 |
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 { |