static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, const MipsSubtarget &Subtarget ) { bool PicMode = Subtarget.getRelocationModel() == Reloc::PIC_; bool LE = Subtarget.isLittle(); LLVMContext &Context = M->getContext(); std::string Name = F->getName(); std::string SectionName = ".mips16.fn." + Name; std::string StubName = "__fn_stub_" + Name; std::string LocalName = "$$__fn_local_" + Name; Function *FStub = Function::Create (F->getFunctionType(), Function::InternalLinkage, StubName, M); FStub->addFnAttr("mips16_fp_stub"); FStub->addFnAttr(llvm::Attribute::Naked); FStub->addFnAttr(llvm::Attribute::NoUnwind); FStub->addFnAttr(llvm::Attribute::NoInline); FStub->addFnAttr("nomips16"); FStub->setSection(SectionName); BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub); InlineAsmHelper IAH(Context, BB); if (PicMode) { IAH.Out(".set noreorder"); IAH.Out(".cpload $$25"); IAH.Out(".set reorder"); IAH.Out(".reloc 0,R_MIPS_NONE," + Name); IAH.Out("la $$25," + LocalName); } else { IAH.Out("la $$25," + Name); } swapFPIntParams(PV, M, IAH, LE, false); IAH.Out("jr $$25"); IAH.Out(LocalName + " = " + Name); new UnreachableInst(FStub->getContext(), BB); }
static std::string computeDataLayout(const MipsSubtarget &ST) { std::string Ret = ""; // There are both little and big endian mips. if (ST.isLittle()) Ret += "e"; else Ret += "E"; Ret += "-m:m"; // Pointers are 32 bit on some ABIs. if (!ST.isABI_N64()) Ret += "-p:32:32"; // 8 and 16 bit integers only need no have natural alignment, but try to // align them to 32 bits. 64 bit integers have natural alignment. Ret += "-i8:8:32-i16:16:32-i64:64"; // 32 bit registers are always available and the stack is at least 64 bit // aligned. On N64 64 bit registers are also available and the stack is // 128 bit aligned. if (ST.isABI_N64() || ST.isABI_N32()) Ret += "-n32:64-S128"; else Ret += "-n32-S64"; return Ret; }
// // Make sure that we know we already need a stub for this function. // Having called needsFPHelperFromSig // static void assureFPCallStub(Function &F, Module *M, const MipsSubtarget &Subtarget){ // for now we only need them for static relocation if (Subtarget.getRelocationModel() == Reloc::PIC_) return; LLVMContext &Context = M->getContext(); bool LE = Subtarget.isLittle(); std::string Name = F.getName(); std::string SectionName = ".mips16.call.fp." + Name; std::string StubName = "__call_stub_fp_" + Name; // // see if we already have the stub // Function *FStub = M->getFunction(StubName); if (FStub && !FStub->isDeclaration()) return; FStub = Function::Create(F.getFunctionType(), Function::InternalLinkage, StubName, M); FStub->addFnAttr("mips16_fp_stub"); FStub->addFnAttr(llvm::Attribute::Naked); FStub->addFnAttr(llvm::Attribute::NoInline); FStub->addFnAttr(llvm::Attribute::NoUnwind); FStub->addFnAttr("nomips16"); FStub->setSection(SectionName); BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub); InlineAsmHelper IAH(Context, BB); IAH.Out(".set reorder"); FPReturnVariant RV = whichFPReturnVariant(FStub->getReturnType()); FPParamVariant PV = whichFPParamVariantNeeded(F); swapFPIntParams(PV, M, IAH, LE, true); if (RV != NoFPRet) { IAH.Out("move $$18, $$31"); IAH.Out("jal " + Name); } else { IAH.Out("lui $$25,%hi(" + Name + ")"); IAH.Out("addiu $$25,$$25,%lo(" + Name + ")" ); } switch (RV) { case FRet: IAH.Out("mfc1 $$2,$$f0"); break; case DRet: if (LE) { IAH.Out("mfc1 $$2,$$f0"); IAH.Out("mfc1 $$3,$$f1"); } else { IAH.Out("mfc1 $$3,$$f0"); IAH.Out("mfc1 $$2,$$f1"); } break; case CFRet: if (LE) { IAH.Out("mfc1 $$2,$$f0"); IAH.Out("mfc1 $$3,$$f2"); } else { IAH.Out("mfc1 $$3,$$f0"); IAH.Out("mfc1 $$3,$$f2"); } break; case CDRet: if (LE) { IAH.Out("mfc1 $$4,$$f2"); IAH.Out("mfc1 $$5,$$f3"); IAH.Out("mfc1 $$2,$$f0"); IAH.Out("mfc1 $$3,$$f1"); } else { IAH.Out("mfc1 $$5,$$f2"); IAH.Out("mfc1 $$4,$$f3"); IAH.Out("mfc1 $$3,$$f0"); IAH.Out("mfc1 $$2,$$f1"); } break; case NoFPRet: break; } if (RV != NoFPRet) IAH.Out("jr $$18"); else IAH.Out("jr $$25"); new UnreachableInst(Context, BB); }