Index: llvm/lib/Target/M68k/M68kFrameLowering.cpp =================================================================== --- llvm/lib/Target/M68k/M68kFrameLowering.cpp +++ llvm/lib/Target/M68k/M68kFrameLowering.cpp @@ -546,9 +546,9 @@ // Update the frame offset adjustment. MFI.setOffsetAdjustment(-NumBytes); - // Save FP into the appropriate stack slot. - BuildMI(MBB, MBBI, DL, TII.get(M68k::PUSH32r)) - .addReg(MachineFramePtr, RegState::Kill) + BuildMI(MBB, MBBI, DL, TII.get(M68k::LINK16)) + .addReg(M68k::WA6, RegState::Kill) + .addImm(-NumBytes) .setMIFlag(MachineInstr::FrameSetup); if (NeedsDwarfCFI) { @@ -566,11 +566,6 @@ 2 * stackGrowth)); } - // Update FP with the new base value. - BuildMI(MBB, MBBI, DL, TII.get(M68k::MOV32aa), FramePtr) - .addReg(StackPtr) - .setMIFlag(MachineInstr::FrameSetup); - if (NeedsDwarfCFI) { // Mark effective beginning of when frame pointer becomes valid. // Define the current CFA to use the FP register. @@ -619,7 +614,8 @@ NumBytes -= mergeSPUpdates(MBB, MBBI, true); // Adjust stack pointer: ESP -= numbytes. - emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, /*InEpilogue=*/false); + if (!HasFP) + emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, /*InEpilogue=*/false); unsigned SPOrEstablisher = StackPtr; @@ -702,9 +698,6 @@ if (TRI->hasStackRealignment(MF)) NumBytes = alignTo(FrameSize, MaxAlign); - // Pop FP. - BuildMI(MBB, MBBI, DL, TII.get(M68k::POP32r), MachineFramePtr) - .setMIFlag(MachineInstr::FrameDestroy); } else { NumBytes = StackSize - CSSize; } @@ -749,10 +742,15 @@ LEAAmount); --MBBI; } else { - unsigned Opc = (M68k::MOV32rr); - BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr).addReg(FramePtr); + BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK)) + .addReg(MachineFramePtr, RegState::Kill) + .setMIFlag(MachineInstr::FrameDestroy); --MBBI; } + } else if (hasFP(MF)) { + BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK)) + .addReg(MachineFramePtr, RegState::Kill) + .setMIFlag(MachineInstr::FrameDestroy); } else if (NumBytes) { // Adjust stack pointer back: SP += numbytes. emitSPUpdate(MBB, MBBI, NumBytes, /*InEpilogue=*/true); Index: llvm/lib/Target/M68k/M68kInstrData.td =================================================================== --- llvm/lib/Target/M68k/M68kInstrData.td +++ llvm/lib/Target/M68k/M68kInstrData.td @@ -437,6 +437,35 @@ def LEA32 # AM : MxLEA("MxOp32AddrMode_"#AM), !cast("MxMoveSrcOpEnc_"#AM)>; +//===----------------------------------------------------------------------===// +// LINK/UNLK +//===----------------------------------------------------------------------===// + +let Uses = [SP], Defs = [SP] in { +let mayStore = 1 in { + +def LINK16 : MxInst<(outs), (ins MxARD16:$src, Mxi16imm:$disp), "link.w\t$src, $disp", []> { + let Inst = (ascend + (descend 0b0100111001010, (operand "$src", 3)), + (operand "$disp", 16) + ); +} + +def LINK32 : MxInst<(outs), (ins MxARD16:$src, Mxi32imm:$disp), "link.l\t$src, $disp", []> { + let Inst = (ascend + (descend 0b0100100000001, (operand "$src", 3)), + (slice "$disp", 31, 16), + (slice "$disp", 15, 0) + ); +} + +def UNLK : MxInst<(outs), (ins MxARD32:$src), "unlk\t$src", []> { + let Inst = (descend 0b0100111001011, (operand "$src", 3)); +} + +} // let mayStore = 1 +} // let Uses = [SP], Defs = [SP] + //===----------------------------------------------------------------------===// // Pseudos //===----------------------------------------------------------------------===// Index: llvm/test/CodeGen/M68k/Alloc/dyn_alloca_aligned.ll =================================================================== --- llvm/test/CodeGen/M68k/Alloc/dyn_alloca_aligned.ll +++ llvm/test/CodeGen/M68k/Alloc/dyn_alloca_aligned.ll @@ -4,15 +4,13 @@ ; CHECK-LABEL: A: ; CHECK: .cfi_startproc ; CHECK-NEXT: ; %bb.0: -; CHECK-NEXT: move.l %a6, -(%sp) +; CHECK-NEXT: link.w %a6, #-128 ; CHECK-NEXT: .cfi_def_cfa_offset -8 ; CHECK-NEXT: .cfi_offset %a6, -8 -; CHECK-NEXT: move.l %sp, %a6 ; CHECK-NEXT: .cfi_def_cfa_register %a6 ; CHECK-NEXT: move.l %sp, %d0 ; CHECK-NEXT: and.l #-128, %d0 ; CHECK-NEXT: move.l %d0, %sp -; CHECK-NEXT: suba.l #128, %sp ; CHECK-NEXT: move.l %sp, %a4 ; CHECK-NEXT: movem.l %a4, (116,%a4) ; 8-byte Folded Spill ; CHECK-NEXT: move.l (8,%a6), %d1 @@ -23,8 +21,7 @@ ; CHECK-NEXT: and.l #-128, %d0 ; CHECK-NEXT: move.l %d0, %sp ; CHECK-NEXT: movem.l (116,%a4), %a4 ; 8-byte Folded Reload -; CHECK-NEXT: move.l %a6, %sp -; CHECK-NEXT: move.l (%sp)+, %a6 +; CHECK-NEXT: unlk %a6 ; CHECK-NEXT: rts %A = alloca i8, i32 %Size, align 128 %A_addr = ptrtoint i8* %A to i32 Index: llvm/test/CodeGen/M68k/link-unlnk.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M68k/link-unlnk.ll @@ -0,0 +1,71 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=m68k-linux-gnu %s -verify-machineinstrs -o - | FileCheck %s + +define i32 @fib(i32 %a, i32 %b) #0 { +; CHECK-LABEL: fib: +; CHECK: .cfi_startproc +; CHECK-NEXT: ; %bb.0: ; %entry +; CHECK-NEXT: link.w %a6, #-32 +; CHECK-NEXT: .cfi_def_cfa_offset -8 +; CHECK-NEXT: .cfi_offset %a6, -8 +; CHECK-NEXT: .cfi_def_cfa_register %a6 +; CHECK-NEXT: move.l (8,%a6), %d1 +; CHECK-NEXT: move.l %d1, (-32,%a6) +; CHECK-NEXT: move.l (12,%a6), %d0 +; CHECK-NEXT: add.l %d0, %d1 +; CHECK-NEXT: move.l %d0, (0,%a6) +; CHECK-NEXT: add.l %d1, %d0 +; CHECK-NEXT: move.l %d1, (32,%a6) +; CHECK-NEXT: add.l %d0, %d1 +; CHECK-NEXT: move.l %d0, (64,%a6) +; CHECK-NEXT: move.l %d1, (96,%a6) +; CHECK-NEXT: add.l %d1, %d0 +; CHECK-NEXT: move.l %d0, (128,%a6) +; CHECK-NEXT: add.l %d0, %d1 +; CHECK-NEXT: move.l %d1, (160,%a6) +; CHECK-NEXT: add.l %d1, %d0 +; CHECK-NEXT: move.l %d0, (192,%a6) +; CHECK-NEXT: unlk %a6 +; CHECK-NEXT: rts +entry: + %arr = alloca [8 x i32], align 4 + %s0 = getelementptr [8 x i32], ptr %arr, i32 0 + %s1 = getelementptr [8 x i32], ptr %arr, i32 1 + store i32 %a, i32* %s0 + store i32 %b, i32* %s1 + + %ptr0 = getelementptr [8 x i32], ptr %arr, i32 0 + %ptr1 = getelementptr [8 x i32], ptr %arr, i32 1 + %ptr2 = getelementptr [8 x i32], ptr %arr, i32 2 + %ptr3 = getelementptr [8 x i32], ptr %arr, i32 3 + %ptr4 = getelementptr [8 x i32], ptr %arr, i32 4 + %ptr5 = getelementptr [8 x i32], ptr %arr, i32 5 + %ptr6 = getelementptr [8 x i32], ptr %arr, i32 6 + %ptr7 = getelementptr [8 x i32], ptr %arr, i32 7 + + %res0 = load i32, i32 * %ptr0 + %res1 = load i32, i32 * %ptr1 + + %res2 = add i32 %res0, %res1 + store i32 %res2, i32 * %ptr2 + + %res3 = add i32 %res1, %res2 + store i32 %res3, i32 * %ptr3 + + %res4 = add i32 %res2, %res3 + store i32 %res4, i32 * %ptr4 + + %res5 = add i32 %res3, %res4 + store i32 %res5, i32 * %ptr5 + + %res6 = add i32 %res4, %res5 + store i32 %res6, i32 * %ptr6 + + %res7 = add i32 %res5, %res6 + store i32 %res7, i32 * %ptr7 + + ret i32 %res7 +} + +attributes #0 = {"frame-pointer"="all"} + Index: llvm/test/MC/Disassembler/M68k/data.txt =================================================================== --- llvm/test/MC/Disassembler/M68k/data.txt +++ llvm/test/MC/Disassembler/M68k/data.txt @@ -2,6 +2,7 @@ # CHECK: move.l %a1, %a0 0x20 0x49 + # CHECK: lea (50,%a0), %a1 0x43 0xe8 0x00 0x32 @@ -52,3 +53,11 @@ # CHECK: move.l (129,%pc,%d2), %d3 0x26 0x3b 0x28 0x81 +# CHECK: link.w %a3, #31 +0x4e 0x53 0x00 0x1f + +# CHECK: link.l %a6, #65537 +0x48 0x0e 0x00 0x01 0x00 0x01 + +# CHECK: unlk %a0 +0x4e 0x58 Index: llvm/test/MC/M68k/Data/Classes/MxLink.s =================================================================== --- /dev/null +++ llvm/test/MC/M68k/Data/Classes/MxLink.s @@ -0,0 +1,13 @@ +; RUN: llvm-mc -assemble --show-encoding -triple=m68k %s | FileCheck %s + +# CHECK: link.w %a2, #1023 +# CHECK-SAME: encoding: [0x4e,0x52,0x03,0xff] +link.w %a2, #1023 + +# CHECK: link.l %a1, #1073741823 +# CHECK-SAME: encoding: [0x48,0x09,0x3f,0xff,0xff,0xff] +link.l %a1, #1073741823 + +# CHECK: unlk %a5 +# CHECK-SAME: encoding: [0x4e,0x5d] +unlk %a5 \ No newline at end of file