Example #1
0
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);
}
Example #2
0
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;
}
Example #3
0
//
// 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);
}