diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td index b866a5d2253..77126bb6529 100644 --- a/lib/Target/Mips/Mips16InstrInfo.td +++ b/lib/Target/Mips/Mips16InstrInfo.td @@ -10,7 +10,19 @@ // This file describes Mips16 instructions. // //===----------------------------------------------------------------------===// +// +// This are pseudo formats for multiply +// This first one can be changed to non pseudo now. +//fmul +class FMULT16_ins : + MipsPseudo16<(outs), (ins CPU16Regs:$rx, CPU16Regs:$ry), + !strconcat(asmstr, "\t$rx, $ry"), []>; +class FMULT16_LO_ins : + MipsPseudo16<(outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry), + !strconcat(asmstr, "\t$rx, $ry\n\tmflo\t$rz"), []> { + let isCodeGenOnly=1; +} // // RRR-type instruction format // @@ -43,7 +55,11 @@ class FRR16_ins f, string asmstr, InstrItinClass itin> : FRR16 { } - +class FRR16_M_ins f, string asmstr, + InstrItinClass itin> : + FRR16; + class FRxRxRy16_ins f, string asmstr, InstrItinClass itin> : FRR16 _op, string asmstr, !strconcat(asmstr, "\t$rx, $imm"), [], itin> { let Constraints = "$rx_ = $rx"; } + // this has an explicit sp argument that we ignore to work around a problem // in the compiler class FEXT_RI16_SP_explicit_ins _op, string asmstr, InstrItinClass itin>: FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins CPUSPReg:$ry, simm16:$imm), - !strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin> { -} - + !strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin>; // // EXT-RRI instruction format @@ -244,6 +259,63 @@ def Move32R16: FI8_MOV32R16_ins<"move", IIAlu>; // def MoveR3216: FI8_MOVR3216_ins<"move", IIAlu>; +// +// Format: MFHI rx MIPS16e +// Purpose: Move From HI Register +// To copy the special purpose HI register to a GPR. +// +def Mfhi16: FRR16_M_ins<0b10000, "mfhi", IIAlu> { + let Uses = [HI]; + let neverHasSideEffects = 1; +} + +// +// Format: MFLO rx MIPS16e +// Purpose: Move From LO Register +// To copy the special purpose LO register to a GPR. +// +def Mflo16: FRR16_M_ins<0b10010, "mflo", IIAlu> { + let Uses = [LO]; + let neverHasSideEffects = 1; +} + +// +// Pseudo Instruction for mult +// +def MultRxRy16: FMULT16_ins<"mult", IIAlu> { + let isCommutable = 1; + let neverHasSideEffects = 1; + let Defs = [HI, LO]; +} + +def MultuRxRy16: FMULT16_ins<"multu", IIAlu> { + let isCommutable = 1; + let neverHasSideEffects = 1; + let Defs = [HI, LO]; +} + +// +// Format: MULT rx, ry MIPS16e +// Purpose: Multiply Word +// To multiply 32-bit signed integers. +// +def MultRxRyRz16: FMULT16_LO_ins<"mult", IIAlu> { + let isCommutable = 1; + let neverHasSideEffects = 1; + let Defs = [HI, LO]; +} + +// +// Format: MULTU rx, ry MIPS16e +// Purpose: Multiply Unsigned Word +// To multiply 32-bit unsigned integers. +// +def MultuRxRyRz16: FMULT16_LO_ins<"multu", IIAlu> { + let isCommutable = 1; + let neverHasSideEffects = 1; + let Defs = [HI, LO]; +} + // // Format: NEG rx, ry MIPS16e // Purpose: Negate @@ -413,6 +485,7 @@ class ArithLogic16_pat : def: ArithLogic16_pat; def: ArithLogic16_pat; +def: ArithLogic16_pat; def: ArithLogic16_pat; def: ArithLogic16_pat; def: ArithLogic16_pat; diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index ceff6dd9b9d..fceb63a1bc9 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -372,14 +372,16 @@ MipsDAGToDAGISel::SelectMULT(SDNode *N, unsigned Opc, DebugLoc dl, EVT Ty, SDValue InFlag = SDValue(Mul, 0); if (HasLo) { - Lo = CurDAG->getMachineNode(Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64, dl, - Ty, MVT::Glue, InFlag); + unsigned Opcode = Subtarget.inMips16Mode() ? Mips::Mflo16 : + (Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64); + Lo = CurDAG->getMachineNode(Opcode, dl, Ty, MVT::Glue, InFlag); InFlag = SDValue(Lo, 1); } - if (HasHi) - Hi = CurDAG->getMachineNode(Ty == MVT::i32 ? Mips::MFHI : Mips::MFHI64, dl, - Ty, InFlag); - + if (HasHi) { + unsigned Opcode = Subtarget.inMips16Mode() ? Mips::Mfhi16 : + (Ty == MVT::i32 ? Mips::MFHI : Mips::MFHI64); + Hi = CurDAG->getMachineNode(Opcode, dl, Ty, InFlag); + } return std::make_pair(Lo, Hi); } @@ -443,8 +445,13 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { /// Mul with two results case ISD::SMUL_LOHI: case ISD::UMUL_LOHI: { - if (NodeTy == MVT::i32) - MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT); + if (NodeTy == MVT::i32) { + if (Subtarget.inMips16Mode()) + MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MultuRxRy16 : + Mips::MultRxRy16); + else + MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT); + } else MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::DMULTu : Mips::DMULT); @@ -470,8 +477,13 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { } case ISD::MULHS: case ISD::MULHU: { - if (NodeTy == MVT::i32) - MultOpc = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT); + if (NodeTy == MVT::i32) { + if (Subtarget.inMips16Mode()) + MultOpc = (Opcode == ISD::MULHU ? + Mips::MultuRxRy16 : Mips::MultRxRy16); + else + MultOpc = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT); + } else MultOpc = (Opcode == ISD::MULHU ? Mips::DMULTu : Mips::DMULT); diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index d8097032caf..362317b2822 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -1746,8 +1746,10 @@ SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op, if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) { // %hi/%lo relocation - SDValue BAHi = DAG.getTargetBlockAddress(BA, MVT::i32, 0, MipsII::MO_ABS_HI); - SDValue BALo = DAG.getTargetBlockAddress(BA, MVT::i32, 0, MipsII::MO_ABS_LO); + SDValue BAHi = + DAG.getTargetBlockAddress(BA, MVT::i32, 0, MipsII::MO_ABS_HI); + SDValue BALo = + DAG.getTargetBlockAddress(BA, MVT::i32, 0, MipsII::MO_ABS_LO); SDValue Hi = DAG.getNode(MipsISD::Hi, dl, MVT::i32, BAHi); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, BALo); return DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo); diff --git a/test/CodeGen/Mips/mul.ll b/test/CodeGen/Mips/mul.ll new file mode 100644 index 00000000000..4ce801b1c9f --- /dev/null +++ b/test/CodeGen/Mips/mul.ll @@ -0,0 +1,17 @@ +; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16 + +@iiii = global i32 5, align 4 +@jjjj = global i32 -6, align 4 +@kkkk = common global i32 0, align 4 + +define void @test() nounwind { +entry: + %0 = load i32* @iiii, align 4 + %1 = load i32* @jjjj, align 4 + %mul = mul nsw i32 %1, %0 +; 16: mult ${{[0-9]+}}, ${{[0-9]+}} +; 16: mflo ${{[0-9]+}} + + store i32 %mul, i32* @kkkk, align 4 + ret void +} diff --git a/test/CodeGen/Mips/mulll.ll b/test/CodeGen/Mips/mulll.ll new file mode 100644 index 00000000000..e37b9197df8 --- /dev/null +++ b/test/CodeGen/Mips/mulll.ll @@ -0,0 +1,21 @@ +; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16 + +@iiii = global i64 5, align 8 +@jjjj = global i64 -6, align 8 +@kkkk = common global i64 0, align 8 + +define void @test() nounwind { +entry: + %0 = load i64* @iiii, align 8 + %1 = load i64* @jjjj, align 8 + %mul = mul nsw i64 %1, %0 + store i64 %mul, i64* @kkkk, align 8 +; 16: multu ${{[0-9]+}}, ${{[0-9]+}} +; 16: mfhi ${{[0-9]+}} +; 16: mult ${{[0-9]+}}, ${{[0-9]+}} +; 16: mflo ${{[0-9]+}} +; 16: mult ${{[0-9]+}}, ${{[0-9]+}} +; 16: mflo ${{[0-9]+}} + + ret void +} diff --git a/test/CodeGen/Mips/mulull.ll b/test/CodeGen/Mips/mulull.ll new file mode 100644 index 00000000000..4d23c693184 --- /dev/null +++ b/test/CodeGen/Mips/mulull.ll @@ -0,0 +1,21 @@ +; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16 + +@iiii = global i64 5, align 8 +@jjjj = global i64 6, align 8 +@kkkk = common global i64 0, align 8 +@.str = private unnamed_addr constant [20 x i8] c"%lld * %lld = %lld\0A\00", align 1 + +define void @test() nounwind { +entry: + %0 = load i64* @iiii, align 8 + %1 = load i64* @jjjj, align 8 + %mul = mul nsw i64 %1, %0 + store i64 %mul, i64* @kkkk, align 8 +; 16: multu ${{[0-9]+}}, ${{[0-9]+}} +; 16: mfhi ${{[0-9]+}} +; 16: mult ${{[0-9]+}}, ${{[0-9]+}} +; 16: mflo ${{[0-9]+}} +; 16: mult ${{[0-9]+}}, ${{[0-9]+}} +; 16: mflo ${{[0-9]+}} + ret void +}