Index: lib/Target/NDS32/InstPrinter/NDS32InstPrinter.h =================================================================== --- lib/Target/NDS32/InstPrinter/NDS32InstPrinter.h +++ lib/Target/NDS32/InstPrinter/NDS32InstPrinter.h @@ -44,6 +44,9 @@ raw_ostream &O); void printAddrRegOffsetOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + + void printSPImplyAddrImmOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); }; } Index: lib/Target/NDS32/InstPrinter/NDS32InstPrinter.cpp =================================================================== --- lib/Target/NDS32/InstPrinter/NDS32InstPrinter.cpp +++ lib/Target/NDS32/InstPrinter/NDS32InstPrinter.cpp @@ -117,3 +117,20 @@ O << '$'; printRegName(O, MO1.getReg()); } + +// print sp base imply [+ Imm] addressing mode +void NDS32InstPrinter::printSPImplyAddrImmOperand(const MCInst *MI, + unsigned OpNum, + raw_ostream &O) { + const MCOperand &MO2 = MI->getOperand(OpNum + 1); + + O << markup("") << "]" << markup(">"); +} Index: lib/Target/NDS32/NDS32Instr16Bit.td =================================================================== --- lib/Target/NDS32/NDS32Instr16Bit.td +++ lib/Target/NDS32/NDS32Instr16Bit.td @@ -102,6 +102,14 @@ "lwi333\t$Rt, $addr", [(set lGPR:$Rt, (load addr_imm3u_word:$addr))]>, Requires<[Has16Bit]>; + +def LWI37: XWI37Form<(outs lGPR:$Rt), (ins addr_fp_base_offset_imm7u_word:$addr), + "lwi37\t$Rt, $addr", [], 0>, + Requires<[Has16Bit]>; + +def LWI37SP: XWI37SPForm<(outs lGPR:$Rt), (ins addr_sp_base_offset_imm7u_word:$addr), + "lwi37.sp\t$Rt, $addr", [], 0>, + Requires<[Has16Bit]>; } let AddedComplexity = 4, mayStore = 1 in { @@ -119,6 +127,14 @@ "swi333\t$Rt, $addr", [(store lGPR:$Rt, addr_imm3u_word:$addr)]>, Requires<[Has16Bit]>; + +def SWI37: XWI37Form<(outs), (ins lGPR:$Rt, addr_fp_base_offset_imm7u_word:$addr), + "swi37\t$Rt, $addr", [], 1>, + Requires<[Has16Bit]>; + +def SWI37SP: XWI37SPForm<(outs), (ins lGPR:$Rt, addr_sp_base_offset_imm7u_word:$addr), + "swi37.sp\t$Rt, $addr", [], 1>, + Requires<[Has16Bit]>; } Index: lib/Target/NDS32/NDS32Instr16Formats.td =================================================================== --- lib/Target/NDS32/NDS32Instr16Formats.td +++ lib/Target/NDS32/NDS32Instr16Formats.td @@ -196,6 +196,26 @@ let Inst{2-0} = addr{2-0}; // imm3u } +class XWI37Form pattern, + bit store> + : 16BitInst4BitOpcode<0b0111, outs, ins, asmstr, pattern> { + bits<3> Rt; + bits<7> addr; + let Inst{10-8} = Rt; + let Inst{7} = store; + let Inst{6-0} = addr; +} + +class XWI37SPForm pattern, + bit store> + : 16BitInst4BitOpcode<0b1110, outs, ins, asmstr, pattern> { + bits<3> Rt; + bits<7> addr; + let Inst{10-8} = Rt; + let Inst{7} = store; + let Inst{6-0} = addr; +} + class BEQZ38Form pattern> : 16BitInst4BitOpcode<0b1000, outs, ins, asmstr, pattern> { bits<3> Rt; Index: lib/Target/NDS32/NDS32Predicate.td =================================================================== --- lib/Target/NDS32/NDS32Predicate.td +++ lib/Target/NDS32/NDS32Predicate.td @@ -298,3 +298,17 @@ let MIOperandInfo = (ops lGPR:$base, i32imm:$offsimm); let PrintMethod = "printAddrImmOperand"; } + +// addr_sp_base_offset_imm7u_word := [+ imm7u << 2] +def AddrSPImm7uWordAsmOperand : AsmOperandClass { let Name = "AddrSPImm7uWord"; } +def addr_sp_base_offset_imm7u_word : MemOperand { + let MIOperandInfo = (ops SPReg:$base, i32imm:$offsimm); + let PrintMethod = "printSPImplyAddrImmOperand"; +} + +// addr_fp_base_offset_imm7u_word := [$fp + imm7u << 2] +def AddrFPImm7uWordAsmOperand : AsmOperandClass { let Name = "AddrFPImm7uWord"; } +def addr_fp_base_offset_imm7u_word : MemOperand { + let MIOperandInfo = (ops FPReg:$base, i32imm:$offsimm); + let PrintMethod = "printAddrImmOperand"; +} Index: lib/Target/NDS32/NDS32RegisterInfo.cpp =================================================================== --- lib/Target/NDS32/NDS32RegisterInfo.cpp +++ lib/Target/NDS32/NDS32RegisterInfo.cpp @@ -69,6 +69,33 @@ return &NDS32::GPRRegClass; } +// Return true if the instruction fit +// swi37.sp/lwi37.sp/swi37/lwi37 limitation. +static bool FitFrameBase16BitLoadStore (MachineInstr &MI, unsigned BaseReg, + int64_t Offset) { + unsigned Opc = MI.getOpcode(); + + // BaseReg must be SP or FP + if (BaseReg != NDS32::SP && BaseReg != NDS32::FP) + return false; + + // Offset limitation is (imm7u << 2) + if (!isUInt<9>(Offset)) + return false; + if (Offset % 4 != 0) + return false; + + if (Opc != NDS32::SWI && Opc != NDS32::LWI) + return false; + + // Operand 0 must be low register + unsigned Reg = MI.getOperand(0).getReg(); + if (!isNDS32LowRegister (Reg)) + return false; + + return true; +} + void NDS32RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, @@ -85,6 +112,7 @@ int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); uint64_t stackSize = MF.getFrameInfo().getStackSize(); int64_t Offset = MF.getFrameInfo().getObjectOffset(FrameIndex); + const NDS32Subtarget &Subtarget = MF.getSubtarget(); DEBUG(errs() << "\nFunction : " << MF.getName() << "\n"; errs() << "<--------->\n" << MI); @@ -119,7 +147,21 @@ // Use R15 as temp register unsigned Reg = NDS32::R15; - if (isInt<15>(Offset)) { + // Transfer to 16 bit format + // if the instruction fit swi37.sp/lwi37.sp/swi37/lwi37 limitation + if (FitFrameBase16BitLoadStore (MI, BasePtr, Offset) + && Subtarget.has16Bit()) { + unsigned OpcNew; + if (MI.getOpcode() == NDS32::LWI) + OpcNew = (BasePtr == NDS32::SP) ? NDS32::LWI37SP : NDS32::LWI37; + else + OpcNew = (BasePtr == NDS32::SP) ? NDS32::SWI37SP : NDS32::SWI37; + + MI.setDesc(TII.get(OpcNew)); + MI.getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); + return; + } else if (isInt<15>(Offset)) { MI.getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); return; Index: test/CodeGen/NDS32/by-val.ll =================================================================== --- test/CodeGen/NDS32/by-val.ll +++ test/CodeGen/NDS32/by-val.ll @@ -59,7 +59,7 @@ %c4 = getelementptr inbounds %struct.tiny, %struct.tiny* %arrayidx3, i32 0, i32 0 store i32 12, i32* %c4, align 4 ; CHECK: movi55 $r0, 10 -; CHECK: swi $r0, [$sp + (0)] +; CHECK: swi37.sp $r0, [+ (0)] ; CHECK: movi55 $r1, 4 ; CHECK: movi55 $r2, 11 ; CHECK: sw $r2, [$r1 + $r0] @@ -68,7 +68,7 @@ ; CHECK: sw $r3, [$r2 + $r0] ; CHECK: lw $r3, [$r2 + $r0] ; CHECK: lw $r2, [$r1 + $r0] -; CHECK: lwi $r1, [$sp + (0)] +; CHECK: lwi37.sp $r1, [+ (0)] %call = call i32 @f(i32 undef, %struct.tiny* byval nonnull align 4 %arrayidx, %struct.tiny* byval align 4 %arrayidx1, %struct.tiny* byval align 4 %arrayidx3) tail call void @exit(i32 0) #4 unreachable Index: test/CodeGen/NDS32/prolog-endprolog.ll =================================================================== --- test/CodeGen/NDS32/prolog-endprolog.ll +++ test/CodeGen/NDS32/prolog-endprolog.ll @@ -46,8 +46,8 @@ entry: ; CHECK: addi $sp, $sp, -16 ; CHECK: swi $lp, [$sp + (12)] -; CHECK: swi $r7, [$sp + (8)] -; CHECK: swi $r6, [$sp + (4)] +; CHECK: swi37.sp $r7, [+ (8)] +; CHECK: swi37.sp $r6, [+ (4)] %0 = load i32, i32* @baz1.l, align 4 %inc.i97 = add nsw i32 %0, 1 store i32 %inc.i97, i32* @baz1.l, align 4 @@ -128,8 +128,8 @@ while.end: ; preds = %while.end.loopexit168, %while.end.loopexit166, %while.end.loopexit, %entry ; CHECK: lwi $lp, [$sp + (12)] -; CHECK: lwi $r7, [$sp + (8)] -; CHECK: lwi $r6, [$sp + (4)] +; CHECK: lwi37.sp $r7, [+ (8)] +; CHECK: lwi37.sp $r6, [+ (4)] ; CHECK: addi $sp, $sp, 16 ret i32 0 } Index: test/CodeGen/NDS32/va-arg.ll =================================================================== --- test/CodeGen/NDS32/va-arg.ll +++ test/CodeGen/NDS32/va-arg.ll @@ -10,7 +10,7 @@ call void @llvm.lifetime.start(i64 4, i8* nonnull %0) #2 call void @llvm.va_start(i8* nonnull %0) ; CHECK: addi $r0, $sp, 20 -; CHECK: swi $r0, [$sp + (0)] +; CHECK: swi37.sp $r0, [+ (0)] %argp.cur = load i8*, i8** %select, align 4 %argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4 store i8* %argp.next, i8** %select, align 4