diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index fdf60d92a248..1df1291be611 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -17,12 +17,14 @@ #include "Mips.h" #include "MipsInstrInfo.h" #include "MipsTargetMachine.h" +#include "MipsMachineFunction.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" @@ -30,6 +32,7 @@ #include "llvm/Support/Mangler.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MathExtras.h" #include @@ -48,10 +51,25 @@ namespace { return "Mips Assembly Printer"; } + enum SetDirectiveFlags { + REORDER, // enables instruction reordering. + NOREORDER, // disables instruction reordering. + MACRO, // enables GAS macros. + NOMACRO // disables GAS macros. + }; + void printOperand(const MachineInstr *MI, int opNum); void printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier = 0); + void printHex32(unsigned int Value); + void emitFunctionStart(MachineFunction &MF); + void emitFunctionEnd(); + void emitFrameDirective(MachineFunction &MF); + void emitMaskDirective(MachineFunction &MF); + void emitFMaskDirective(); + void emitSetDirective(SetDirectiveFlags Flag); + bool printInstruction(const MachineInstr *MI); // autogenerated. bool runOnMachineFunction(MachineFunction &F); bool doInitialization(Module &M); @@ -71,6 +89,139 @@ FunctionPass *llvm::createMipsCodePrinterPass(std::ostream &o, return new MipsAsmPrinter(o, tm, tm.getTargetAsmInfo()); } +/// This pattern will be emitted : +/// .frame reg1, size, reg2 +/// It describes the stack frame. +/// reg1 - stack pointer +/// size - stack size allocated for the function +/// reg2 - return address register +void MipsAsmPrinter:: +emitFrameDirective(MachineFunction &MF) +{ + const MRegisterInfo &RI = *TM.getRegisterInfo(); + + unsigned stackReg = RI.getFrameRegister(MF); + unsigned returnReg = RI.getRARegister(); + unsigned stackSize = MF.getFrameInfo()->getStackSize(); + + + O << "\t.frame\t" << "$" << LowercaseString(RI.get(stackReg).Name) + << "," << stackSize << "," + << "$" << LowercaseString(RI.get(returnReg).Name) + << "\n"; +} + +/// This pattern will be emitted : +/// .mask bitmask, offset +/// Tells the assembler (and possibly linker) which registers are saved and where. +/// bitmask - mask of all GPRs (little endian) +/// offset - negative value. offset+stackSize should give where on the stack +/// the first GPR is saved. +/// TODO: consider calle saved GPR regs here, not hardcode register numbers. +void MipsAsmPrinter:: +emitMaskDirective(MachineFunction &MF) +{ + const MRegisterInfo &RI = *TM.getRegisterInfo(); + MipsFunctionInfo *MipsFI = MF.getInfo(); + + bool hasFP = RI.hasFP(MF); + bool saveRA = MF.getFrameInfo()->hasCalls(); + + int offset; + + if (!MipsFI->getTopSavedRegOffset()) + offset = 0; + else + offset = -(MF.getFrameInfo()->getStackSize() + -MipsFI->getTopSavedRegOffset()); + + #ifndef NDEBUG + DOUT << "<--ASM PRINTER--emitMaskDirective-->" << "\n"; + DOUT << "StackSize : " << MF.getFrameInfo()->getStackSize() << "\n"; + DOUT << "getTopSavedRegOffset() : " << MipsFI->getTopSavedRegOffset() << "\n"; + DOUT << "offset : " << offset << "\n\n"; + #endif + + unsigned int bitmask = 0; + + if (hasFP) + bitmask |= (1 << 30); + + if (saveRA) + bitmask |= (1 << 31); + + O << "\t.mask\t"; + printHex32(bitmask); + O << "," << offset << "\n"; +} + +/// This pattern will be emitted : +/// .fmask bitmask, offset +/// Tells the assembler (and possibly linker) which float registers are saved. +/// bitmask - mask of all Float Point registers (little endian) +/// offset - negative value. offset+stackSize should give where on the stack +/// the first Float Point register is saved. +/// TODO: implement this, dummy for now +void MipsAsmPrinter:: +emitFMaskDirective() +{ + O << "\t.fmask\t0x00000000,0" << "\n"; +} + +/// Print a 32 bit hex number filling with 0's on the left. +/// TODO: make this setfill and setw +void MipsAsmPrinter:: +printHex32(unsigned int Value) { + O << "0x" << std::hex << Value << std::dec; +} + +/// Emit Set directives. +void MipsAsmPrinter:: +emitSetDirective(SetDirectiveFlags Flag) { + + O << "\t.set\t"; + switch(Flag) { + case REORDER: O << "reorder" << "\n"; break; + case NOREORDER: O << "noreorder" << "\n"; break; + case MACRO: O << "macro" << "\n"; break; + case NOMACRO: O << "nomacro" << "\n"; break; + default: break; + } +} + +/// Emit the directives used by GAS on the start of functions +void MipsAsmPrinter:: +emitFunctionStart(MachineFunction &MF) +{ + // Print out the label for the function. + const Function *F = MF.getFunction(); + SwitchToTextSection(getSectionForFunction(*F).c_str(), F); + + // On Mips GAS, if .align #n is present, #n means the number of bits + // to be cleared. So, if we want 4 byte alignment, we must have .align 2 + EmitAlignment(1, F); + + O << "\t.globl\t" << CurrentFnName << "\n"; + O << "\t.ent\t" << CurrentFnName << "\n"; + O << "\t.type\t" << CurrentFnName << ", @function\n"; + O << CurrentFnName << ":\n"; + + emitFrameDirective(MF); + emitMaskDirective(MF); + emitFMaskDirective(); + + emitSetDirective(NOREORDER); + emitSetDirective(NOMACRO); +} + +/// Emit the directives used by GAS on the end of functions +void MipsAsmPrinter:: +emitFunctionEnd() { + emitSetDirective(MACRO); + emitSetDirective(REORDER); + O << "\t.end\t" << CurrentFnName << "\n"; +} + /// runOnMachineFunction - This uses the printMachineInstruction() /// method to print assembly for each instruction. bool MipsAsmPrinter:: @@ -86,20 +237,8 @@ runOnMachineFunction(MachineFunction &MF) // What's my mangled name? CurrentFnName = Mang->getValueName(MF.getFunction()); - // Print out the label for the function. - const Function *F = MF.getFunction(); - SwitchToTextSection(getSectionForFunction(*F).c_str(), F); - - // On Mips GAS if .align #n is present, #n means the number of bits - // to be cleared to align. So, if we want 4 byte alignment, we must - // have .align 2 - // TODO: - // add gas ".mask" and ".fmask" - EmitAlignment(1, F); - O << "\t.globl\t" << CurrentFnName << "\n"; - O << "\t.ent\t" << CurrentFnName << "\n"; - O << "\t.type\t" << CurrentFnName << ", @function\n"; - O << CurrentFnName << ":\n"; + // Emit the function start directives + emitFunctionStart(MF); // Print out code for the function. for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); @@ -120,8 +259,8 @@ runOnMachineFunction(MachineFunction &MF) } } - // close function with asm directive - O << "\t.end\t" << CurrentFnName << "\n"; + // Emit function end directives + emitFunctionEnd(); // We didn't modify anything. return false; @@ -156,10 +295,10 @@ printOperand(const MachineInstr *MI, int opNum) case MachineOperand::MO_Immediate: if ((MI->getOpcode() == Mips::SLTiu) || (MI->getOpcode() == Mips::ORi) || - (MI->getOpcode() == Mips::LUi) || (MI->getOpcode() == Mips::ANDi)) - O << (unsigned int)MO.getImmedValue(); + (MI->getOpcode() == Mips::LUi) || (MI->getOpcode() == Mips::ANDi)) + O << (unsigned short int)MO.getImmedValue(); else - O << (int)MO.getImmedValue(); + O << (short int)MO.getImmedValue(); break; case MachineOperand::MO_MachineBasicBlock: diff --git a/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp index e660f9cb857c..d6e383017203 100644 --- a/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -163,7 +163,7 @@ SelectAddr(SDOperand Op, SDOperand Addr, SDOperand &Offset, SDOperand &Base) } } - Base = Addr; + Base = Addr; Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; }