aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@mips.com>2012-07-23 23:45:54 +0000
committerAkira Hatanaka <ahatanaka@mips.com>2012-07-23 23:45:54 +0000
commit3ee306cbc0a295409c464ffaad5ef694de8eb09a (patch)
tree0f0cb3e4eac9c89a2931eeb2bfc7e6c8a5615e1a
parent581a739226381450ea2271cc794618043b6aeb4a (diff)
Add basic ability to setup call frame, and make procedure calls.
Hello world will compile and execute with this patch. Patch by Reed Kotler. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160651 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Mips/Mips16InstrFormats.td4
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.td233
-rw-r--r--lib/Target/Mips/MipsFrameLowering.cpp21
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp34
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp5
-rw-r--r--lib/Target/Mips/MipsInstrInfo.cpp18
-rw-r--r--lib/Target/Mips/MipsInstrInfo.h5
-rw-r--r--lib/Target/Mips/MipsMachineFunction.cpp11
-rw-r--r--test/CodeGen/Mips/helloworld_call.ll17
-rw-r--r--test/CodeGen/Mips/helloworld_pe.ll18
-rw-r--r--test/CodeGen/Mips/helloworld_sr.ll16
11 files changed, 338 insertions, 44 deletions
diff --git a/lib/Target/Mips/Mips16InstrFormats.td b/lib/Target/Mips/Mips16InstrFormats.td
index 6babee918d..61602b62fb 100644
--- a/lib/Target/Mips/Mips16InstrFormats.td
+++ b/lib/Target/Mips/Mips16InstrFormats.td
@@ -529,14 +529,16 @@ class FEXT_RRI16<bits<5> _op, dag outs, dag ins, string asmstr,
list<dag> pattern, InstrItinClass itin>:
MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, FrmEXT_RRI16>
{
+ bits<5> op;
bits<16> imm16;
bits<3> rx;
bits<3> ry;
+ let op=_op;
let Inst{26-21} = imm16{10-5};
let Inst{20-16} = imm16{15-11};
- let Inst{15-11} = _op;
+ let Inst{15-11} = op;
let Inst{10-8} = rx;
let Inst{7-5} = ry;
let Inst{4-0} = imm16{4-0};
diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td
index 71801ca6f2..c85204278b 100644
--- a/lib/Target/Mips/Mips16InstrInfo.td
+++ b/lib/Target/Mips/Mips16InstrInfo.td
@@ -11,35 +11,209 @@
//
//===----------------------------------------------------------------------===//
+def uimm5 : Operand<i8> {
+ let DecoderMethod= "DecodeSimm16";
+}
+
+//
+// RRR-type instruction format
+//
+
+class FRRR16_ins<bits<2> _f, string asmstr, InstrItinClass itin> :
+ FRRR16<_f, (outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry),
+ !strconcat(asmstr, "\t$rz, $rx, $ry"), [], itin>;
+
+//
+// I8_MOV32R instruction format (used only by MOV32R instruction)
+//
+class FI8_MOV32R16_ins<string asmstr, InstrItinClass itin>:
+ FI8_MOV32R16<(outs CPURegs:$r32), (ins CPU16Regs:$rz),
+ !strconcat(asmstr, "\t$r32, $rz"), [], itin>;
+
+//
+// EXT-RI instruction format
+//
+
+class FEXT_RI16_ins_base<bits<5> _op, string asmstr, string asmstr2,
+ InstrItinClass itin>:
+ FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins simm16:$imm),
+ !strconcat(asmstr, asmstr2), [], itin>;
+
+class FEXT_RI16_ins<bits<5> _op, string asmstr,
+ InstrItinClass itin>:
+ FEXT_RI16_ins_base<_op, asmstr, "\t$rx, $imm", itin>;
+
+class FEXT_RI16_PC_ins<bits<5> _op, string asmstr, InstrItinClass itin>:
+ FEXT_RI16_ins_base<_op, asmstr, "\t$rx, $$pc, $imm", itin>;
+
+//
+// RR-type instruction format
+//
+let rx=0 in
+class FRR16_JALRC_RA_only_ins<bits<1> nd_, bits<1> l_,
+ string asmstr, InstrItinClass itin>:
+ FRR16_JALRC<nd_, l_, 1, (outs), (ins), !strconcat(asmstr, "\t $$ra"),
+ [], itin> ;
+
+//
+// EXT-RRI instruction format
+//
+
+class FEXT_RRI16_mem_ins<bits<5> op, string asmstr, Operand MemOpnd,
+ InstrItinClass itin>:
+ FEXT_RRI16<op, (outs CPU16Regs:$ry), (ins MemOpnd:$addr),
+ !strconcat(asmstr, "\t$ry, $addr"), [], itin>;
+
+//
+// EXT-SHIFT instruction format
+//
+class FEXT_SHIFT16_ins<bits<2> _f, string asmstr, InstrItinClass itin>:
+ FEXT_SHIFT16<_f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry, uimm5:$sa),
+ !strconcat(asmstr, "\t$rx, $ry, $sa"), [], itin>;
+
+//
+// Address operand
+def mem16 : Operand<i32> {
+ let PrintMethod = "printMemOperand";
+ let MIOperandInfo = (ops CPU16Regs, simm16);
+ let EncoderMethod = "getMemEncoding";
+}
+
+//
+// Format: ADDIU rx, pc, immediate MIPS16e
+// Purpose: Add Immediate Unsigned Word (3-Operand, PC-Relative, Extended)
+// To add a constant to the program counter.
+//
+class AddiuRxPcImmX16_base : FEXT_RI16_PC_ins<0b00001, "addiu", IIAlu>;
+def AddiuRxPcImmX16 : AddiuRxPcImmX16_base;
+//
+// Format: ADDU rz, rx, ry MIPS16e
+// Purpose: Add Unsigned Word (3-Operand)
+// To add 32-bit integers.
+//
+
+class AdduRxRyRz16_base: FRRR16_ins<01, "addu", IIAlu>;
+def AdduRxRyRz16: AdduRxRyRz16_base;
+
+//
+// Format: JR ra MIPS16e
+// Purpose: Jump Register Through Register ra
+// To execute a branch to the instruction address in the return
+// address register.
+//
+
+def JrRa16: FRR16_JALRC_RA_only_ins<0, 0, "jr", IIAlu>;
+
+//
+// Format: LI rx, immediate MIPS16e
+// Purpose: Load Immediate (Extended)
+// To load a constant into a GPR.
+//
+def LiRxImmX16: FEXT_RI16_ins<0b01101, "li", IIAlu>;
+
+//
+// Format: LW ry, offset(rx) MIPS16e
+// Purpose: Load Word (Extended)
+// To load a word from memory as a signed value.
+//
+class LwRxRyOffMemX16_base: FEXT_RRI16_mem_ins<0b10011, "lw", mem16, IIAlu>;
+def LwRxRyOffMemX16: LwRxRyOffMemX16_base;
+
+//
+// Format: MOVE r32, rz MIPS16e
+// Purpose: Move
+// To move the contents of a GPR to a GPR.
+//
+def Mov32R16: FI8_MOV32R16_ins<"move", IIAlu>;
+//
+// Format: RESTORE {ra,}{s0/s1/s0-1,}{framesize}
+// (All args are optional) MIPS16e
+// Purpose: Restore Registers and Deallocate Stack Frame
+// To deallocate a stack frame before exit from a subroutine,
+// restoring return address and static registers, and adjusting
+// stack
+//
+
+// fixed form for restoring RA and the frame
+// for direct object emitter, encoding needs to be adjusted for the
+// frame size
+//
+let ra=1, s=0,s0=0,s1=0 in
+def RestoreRaF16:
+ FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
+ "restore \t$$ra, $frame_size", [], IILoad >;
+
+//
+// Format: SAVE {ra,}{s0/s1/s0-1,}{framesize} (All arguments are optional)
+// MIPS16e
+// Purpose: Save Registers and Set Up Stack Frame
+// To set up a stack frame on entry to a subroutine,
+// saving return address and static registers, and adjusting stack
+//
+let ra=1, s=1,s0=0,s1=0 in
+def SaveRaF16:
+ FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
+ "save \t$$ra, $frame_size", [], IILoad >;
+
+//
+// Format: SLL rx, ry, sa MIPS16e
+// Purpose: Shift Word Left Logical (Extended)
+// To execute a left-shift of a word by a fixed number of bits—0 to 31 bits.
+//
+def SllX16: FEXT_SHIFT16_ins<0b00, "sll", IIAlu>;
+
+//
+// Format: SW ry, offset(rx) MIPS16e
+// Purpose: Store Word (Extended)
+// To store a word to memory.
+//
+class SwRxRyOffMemX16_base: FEXT_RRI16_mem_ins<0b11011, "sw", mem16, IIAlu>;
+def SwRxRyOffMemX16: SwRxRyOffMemX16_base;
+
class Mips16Pat<dag pattern, dag result> : Pat<pattern, result> {
let Predicates = [InMips16Mode];
}
-// Mips16 pseudos
-let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1,
- hasExtraSrcRegAllocReq = 1 in
-def RetRA16 : MipsPseudo16<(outs), (ins), "", [(MipsRet)]>;
+class ArithLogicR16Defs<SDNode OpNode, bit isComm = 0> {
+ dag OutOperandList = (outs CPU16Regs:$rz);
+ dag InOperandList = (ins CPU16Regs:$rx, CPU16Regs:$ry);
+ list<dag> Pattern = [(set CPU16Regs:$rz,
+ (OpNode CPU16Regs:$rx, CPU16Regs:$ry))];
+}
-def LI16E : FEXT_RI16<0b01101, (outs CPU16Regs:$rx),
- (ins uimm16:$amt),
- !strconcat("li", "\t$rx, $amt"),
- [(set CPU16Regs:$rx, immZExt16:$amt )],IILoad>;
+multiclass ArithLogicR16_base {
+ def _add: AdduRxRyRz16_base, ArithLogicR16Defs<add, 1>;
+}
-let isReturn=1, isTerminator=1, hasDelaySlot=1, isCodeGenOnly=1,
- isBarrier=1, hasCtrlDep=1, rx=0 in
-def RET16 : FRR16_JALRC
- <0,0,0, (outs), (ins CPURAReg:$target), "jr\t$target", [], IIBranch>;
+defm ArithLogicR16_patt : ArithLogicR16_base;
-// As stack alignment is always done with addiu, we need a 16-bit immediate
-let Defs = [SP], Uses = [SP] in {
-def ADJCALLSTACKDOWN16 : MipsPseudo16<(outs), (ins uimm16:$amt),
- "!ADJCALLSTACKDOWN $amt",
- [(callseq_start timm:$amt)]>;
-def ADJCALLSTACKUP16 : MipsPseudo16<(outs), (ins uimm16:$amt1, uimm16:$amt2),
- "!ADJCALLSTACKUP $amt1",
- [(callseq_end timm:$amt1, timm:$amt2)]>;
+class LoadM16Defs<PatFrag OpNode, Operand _MemOpnd, bit Pseudo=0> {
+ bit isPseudo = Pseudo;
+ Operand MemOpnd = _MemOpnd;
+ dag OutOperandList = (outs CPU16Regs:$ry);
+ dag InOperandList = (ins MemOpnd:$addr);
+ list<dag> Pattern = [(set CPU16Regs:$ry, (OpNode addr:$addr))];
+}
+
+multiclass LoadM16_base {
+ def _LwRxRyOffMemX16: LwRxRyOffMemX16_base, LoadM16Defs<load_a, mem16>;
+}
+
+defm LoadM16: LoadM16_base;
+
+class StoreM16Defs<PatFrag OpNode, Operand _MemOpnd, bit Pseudo=0> {
+ bit isPseudo = Pseudo;
+ Operand MemOpnd = _MemOpnd;
+ dag OutOperandList = (outs );
+ dag InOperandList = (ins CPU16Regs:$ry, MemOpnd:$addr);
+ list<dag> Pattern = [(OpNode CPU16Regs:$ry, addr:$addr)];
+}
+
+multiclass StoreM16_base {
+ def _SwRxRyOffMemX16: SwRxRyOffMemX16_base, StoreM16Defs<store_a, mem16>;
}
+defm StoreM16: StoreM16_base;
// Jump and Link (Call)
let isCall=1, hasDelaySlot=1 in
@@ -47,6 +221,23 @@ def JumpLinkReg16:
FRR16_JALRC<0, 0, 0, (outs), (ins CPU16Regs:$rs),
"jalr \t$rs", [(MipsJmpLink CPU16Regs:$rs)], IIBranch>;
+// Mips16 pseudos
+let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1,
+ hasExtraSrcRegAllocReq = 1 in
+def RetRA16 : MipsPseudo16<(outs), (ins), "", [(MipsRet)]>;
+
+// As stack alignment is always done with addiu, we need a 16-bit immediate
+// This is basically deprecated code but needs to be there for things
+// to work.
+let Defs = [SP], Uses = [SP] in {
+def ADJCALLSTACKDOWN16 : MipsPseudo16<(outs), (ins uimm16:$amt),
+ ";",
+ [(callseq_start timm:$amt)]>;
+def ADJCALLSTACKUP16 : MipsPseudo16<(outs), (ins uimm16:$amt1, uimm16:$amt2),
+ ";",
+ [(callseq_end timm:$amt1, timm:$amt2)]>;
+}
// Small immediates
-def : Mips16Pat<(i32 immZExt16:$in), (LI16E immZExt16:$in)>;
+def : Mips16Pat<(i32 immZExt16:$in), (LiRxImmX16 immZExt16:$in)>;
+def : Mips16Pat<(MipsLo tglobaladdr:$in), (LiRxImmX16 tglobaladdr:$in)>;
diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp
index cb55995404..6338f3c4ea 100644
--- a/lib/Target/Mips/MipsFrameLowering.cpp
+++ b/lib/Target/Mips/MipsFrameLowering.cpp
@@ -114,7 +114,7 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
unsigned StackAlign = getStackAlignment();
uint64_t StackSize = RoundUpToAlignment(MFI->getStackSize(), StackAlign);
- if (MipsFI->globalBaseRegSet())
+ if (MipsFI->globalBaseRegSet())
StackSize += MFI->getObjectOffset(MipsFI->getGlobalRegFI()) + StackAlign;
else
StackSize += RoundUpToAlignment(MipsFI->getMaxCallFrameSize(), StackAlign);
@@ -130,8 +130,13 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
MachineLocation DstML, SrcML;
// Adjust stack.
- if (isInt<16>(-StackSize)) // addi sp, sp, (-stacksize)
- BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize);
+ if (isInt<16>(-StackSize)) {// addi sp, sp, (-stacksize)
+ if (STI.inMips16Mode())
+ BuildMI(MBB, MBBI, dl,
+ TII.get(Mips::SaveRaF16)).addImm(StackSize); // cleanup
+ else
+ BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize);
+ }
else { // Expand immediate that doesn't fit in 16-bit.
unsigned ATReg = STI.isABI_N64() ? Mips::AT_64 : Mips::AT;
@@ -237,8 +242,14 @@ void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
return;
// Adjust stack.
- if (isInt<16>(StackSize)) // addi sp, sp, (-stacksize)
- BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(StackSize);
+ if (isInt<16>(StackSize)) { // addi sp, sp, (-stacksize)
+ if (STI.inMips16Mode())
+ // assumes stacksize multiple of 8
+ BuildMI(MBB, MBBI, dl,
+ TII.get(Mips::RestoreRaF16)).addImm(StackSize);
+ else
+ BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(StackSize);
+ }
else { // Expand immediate that doesn't fit in 16-bit.
unsigned ATReg = STI.isABI_N64() ? Mips::AT_64 : Mips::AT;
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index c409e57021..ea33b74a75 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -128,18 +128,21 @@ void MipsDAGToDAGISel::InitGlobalBaseReg(MachineFunction &MF) {
const MipsInstrInfo *MII = TM.getInstrInfo();
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
- unsigned V0, V1, GlobalBaseReg = MipsFI->getGlobalBaseReg();
- int FI = 0;
+ unsigned V0, V1, V2, GlobalBaseReg = MipsFI->getGlobalBaseReg();
+ int FI = 0;
- if (!Subtarget.inMips16Mode())
- FI= MipsFI->initGlobalRegFI();
+ FI= MipsFI->initGlobalRegFI();
const TargetRegisterClass *RC = Subtarget.isABI_N64() ?
(const TargetRegisterClass*)&Mips::CPU64RegsRegClass :
(const TargetRegisterClass*)&Mips::CPURegsRegClass;
+ if (Subtarget.inMips16Mode())
+ RC=(const TargetRegisterClass*)&Mips::CPU16RegsRegClass;
+
V0 = RegInfo.createVirtualRegister(RC);
V1 = RegInfo.createVirtualRegister(RC);
+ V2 = RegInfo.createVirtualRegister(RC);
if (Subtarget.isABI_N64()) {
MF.getRegInfo().addLiveIn(Mips::T9_64);
@@ -160,6 +163,21 @@ void MipsDAGToDAGISel::InitGlobalBaseReg(MachineFunction &MF) {
return;
}
+ if (Subtarget.inMips16Mode()) {
+ BuildMI(MBB, I, DL, TII.get(Mips::LiRxImmX16), V0)
+ .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI);
+ BuildMI(MBB, I, DL, TII.get(Mips::AddiuRxPcImmX16),
+ V1)
+ .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO);
+ BuildMI(MBB, I, DL, TII.get(Mips::SllX16),
+ V2 ).addReg(V0).addImm(16);
+ BuildMI(MBB, I, DL, TII.get(Mips::AdduRxRyRz16), GlobalBaseReg)
+ .addReg(V1).addReg(V2);
+
+
+ return;
+ }
+
if (MF.getTarget().getRelocationModel() == Reloc::Static) {
// Set global register to __gnu_local_gp.
//
@@ -169,8 +187,6 @@ void MipsDAGToDAGISel::InitGlobalBaseReg(MachineFunction &MF) {
.addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI);
BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0)
.addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO);
- MII->storeRegToStackSlot(MBB, I, GlobalBaseReg, false, FI, RC,
- TargetRegInfo);
return;
}
@@ -194,8 +210,10 @@ void MipsDAGToDAGISel::InitGlobalBaseReg(MachineFunction &MF) {
assert(Subtarget.isABI_O32());
- if (Subtarget.inMips16Mode())
- return; // no need to load GP. It can be calculated anywhere
+
+ //if (Subtarget.inMips16Mode())
+ // return; // no need to load GP. It can be calculated anywhere
+
// For O32 ABI, the following instruction sequence is emitted to initialize
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index 6b80e3fe3e..7741f9f982 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -2645,6 +2645,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins;
SDValue InChain = CLI.Chain;
SDValue Callee = CLI.Callee;
+ SDValue CalleeSave = CLI.Callee;
bool &isTailCall = CLI.IsTailCall;
CallingConv::ID CallConv = CLI.CallConv;
bool isVarArg = CLI.IsVarArg;
@@ -2901,7 +2902,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
SmallVector<SDValue, 8> Ops;
Ops.push_back(Chain);
- Ops.push_back(Callee);
+ Ops.push_back(Subtarget->inMips16Mode()? CalleeSave: Callee);
// Add argument registers to the end of the list so that they are
// known live into the call.
@@ -2909,6 +2910,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
Ops.push_back(DAG.getRegister(RegsToPass[i].first,
RegsToPass[i].second.getValueType()));
+ if (Subtarget->inMips16Mode())
+ Ops.push_back(Callee);
// Add a register mask operand representing the call-preserved registers.
const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo();
const uint32_t *Mask = TRI->getCallPreservedMask(CallConv);
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp
index 7d8488f0b8..458e4f7d1f 100644
--- a/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/lib/Target/Mips/MipsInstrInfo.cpp
@@ -30,6 +30,7 @@ using namespace llvm;
MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm)
: MipsGenInstrInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP),
TM(tm), IsN64(TM.getSubtarget<MipsSubtarget>().isABI_N64()),
+ InMips16Mode(TM.getSubtarget<MipsSubtarget>().inMips16Mode()),
RI(*TM.getSubtargetImpl(), *this),
UncondBrOpc(TM.getRelocationModel() == Reloc::PIC_ ? Mips::B : Mips::J) {}
@@ -107,8 +108,13 @@ copyPhysReg(MachineBasicBlock &MBB,
unsigned Opc = 0, ZeroReg = 0;
if (Mips::CPURegsRegClass.contains(DestReg)) { // Copy to CPU Reg.
- if (Mips::CPURegsRegClass.contains(SrcReg))
- Opc = Mips::ADDu, ZeroReg = Mips::ZERO;
+ if (Mips::CPURegsRegClass.contains(SrcReg)) {
+ if (InMips16Mode)
+ Opc=Mips::Mov32R16;
+ else {
+ Opc = Mips::ADDu, ZeroReg = Mips::ZERO;
+ }
+ }
else if (Mips::CCRRegClass.contains(SrcReg))
Opc = Mips::CFC1;
else if (Mips::FGR32RegClass.contains(SrcReg))
@@ -240,6 +246,12 @@ void MipsInstrInfo::ExpandRetRA(MachineBasicBlock &MBB,
.addReg(Mips::RA);
}
+void MipsInstrInfo::ExpandRetRA16(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ unsigned Opc) const {
+ BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(Opc));
+}
+
void MipsInstrInfo::ExpandExtractElementF64(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
const TargetInstrInfo *TII = TM.getInstrInfo();
@@ -283,7 +295,7 @@ bool MipsInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
ExpandRetRA(MBB, MI, Mips::RET);
break;
case Mips::RetRA16:
- ExpandRetRA(MBB, MI, Mips::RET16);
+ ExpandRetRA16(MBB, MI, Mips::JrRa16);
break;
case Mips::BuildPairF64:
ExpandBuildPairF64(MBB, MI);
diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h
index b4721a7b39..358f8173a0 100644
--- a/lib/Target/Mips/MipsInstrInfo.h
+++ b/lib/Target/Mips/MipsInstrInfo.h
@@ -27,7 +27,7 @@ namespace llvm {
class MipsInstrInfo : public MipsGenInstrInfo {
MipsTargetMachine &TM;
- bool IsN64;
+ bool IsN64; bool InMips16Mode;
const MipsRegisterInfo RI;
unsigned UncondBrOpc;
public:
@@ -65,6 +65,9 @@ public:
private:
void ExpandRetRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
unsigned Opc) const;
+ void ExpandRetRA16(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+ unsigned Opc) const;
+
void BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, DebugLoc DL,
const SmallVectorImpl<MachineOperand>& Cond) const;
void ExpandExtractElementF64(MachineBasicBlock &MBB,
diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp
index e3746d4a42..362173eda3 100644
--- a/lib/Target/Mips/MipsMachineFunction.cpp
+++ b/lib/Target/Mips/MipsMachineFunction.cpp
@@ -33,10 +33,13 @@ unsigned MipsFunctionInfo::getGlobalBaseReg() {
const MipsSubtarget &ST = MF.getTarget().getSubtarget<MipsSubtarget>();
- const TargetRegisterClass *RC = ST.isABI_N64() ?
- (const TargetRegisterClass*)&Mips::CPU64RegsRegClass :
- (const TargetRegisterClass*)&Mips::CPURegsRegClass;
-
+ const TargetRegisterClass *RC;
+ if (ST.inMips16Mode())
+ RC=(const TargetRegisterClass*)&Mips::CPU16RegsRegClass;
+ else
+ RC = ST.isABI_N64() ?
+ (const TargetRegisterClass*)&Mips::CPU64RegsRegClass :
+ (const TargetRegisterClass*)&Mips::CPURegsRegClass;
return GlobalBaseReg = MF.getRegInfo().createVirtualRegister(RC);
}
diff --git a/test/CodeGen/Mips/helloworld_call.ll b/test/CodeGen/Mips/helloworld_call.ll
new file mode 100644
index 0000000000..61c0446083
--- /dev/null
+++ b/test/CodeGen/Mips/helloworld_call.ll
@@ -0,0 +1,17 @@
+; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16
+
+@.str = private unnamed_addr constant [13 x i8] c"hello world\0A\00", align 1
+
+define i32 @main() nounwind {
+entry:
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.str, i32 0, i32 0))
+ ret i32 0
+
+; 16: .set mips16 # @main
+
+; 16: move $gp, ${{[0-9]+}}
+; 16: jalr ${{[0-9]+}}
+; 16: li $2, 0
+}
+
+declare i32 @printf(i8*, ...)
diff --git a/test/CodeGen/Mips/helloworld_pe.ll b/test/CodeGen/Mips/helloworld_pe.ll
new file mode 100644
index 0000000000..ba46662d52
--- /dev/null
+++ b/test/CodeGen/Mips/helloworld_pe.ll
@@ -0,0 +1,18 @@
+; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16
+
+@.str = private unnamed_addr constant [13 x i8] c"hello world\0A\00", align 1
+
+define i32 @main() nounwind {
+entry:
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.str, i32 0, i32 0))
+ ret i32 0
+
+; 16: .set mips16 # @main
+
+; 16: li $[[T1:[0-9]+]], %hi(_gp_disp)
+; 16: addiu $[[T2:[0-9]+]], $pc, %lo(_gp_disp)
+; 16: sll $[[T3:[0-9]+]], $[[T1]], 16
+; 16: li $2, 0
+}
+
+declare i32 @printf(i8*, ...)
diff --git a/test/CodeGen/Mips/helloworld_sr.ll b/test/CodeGen/Mips/helloworld_sr.ll
new file mode 100644
index 0000000000..641ee274e0
--- /dev/null
+++ b/test/CodeGen/Mips/helloworld_sr.ll
@@ -0,0 +1,16 @@
+; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16
+
+@.str = private unnamed_addr constant [13 x i8] c"hello world\0A\00", align 1
+
+define i32 @main() nounwind {
+entry:
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.str, i32 0, i32 0))
+ ret i32 0
+
+; 16: .set mips16 # @main
+
+; 16: save $ra, [[FS:[0-9]+]]
+; 16: restore $ra, [[FS]]
+}
+
+declare i32 @printf(i8*, ...)