// 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) {
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.
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;
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;
}
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);
!cast<MxEncMemOp>("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
//===----------------------------------------------------------------------===//
; 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
; 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
--- /dev/null
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -frame-pointer=all -mtriple=m68k-linux-gnu %s -verify-machineinstrs -o - \
+; RUN: | FileCheck --check-prefix=FP %s
+
+; RUN: llc -frame-pointer=none -mtriple=m68k-linux-gnu %s -verify-machineinstrs -o - \
+; RUN: | FileCheck --check-prefix=NO-FP %s
+
+define i32 @fib(i32 %a, i32 %b) {
+; FP-LABEL: fib:
+; FP: .cfi_startproc
+; FP-NEXT: ; %bb.0: ; %entry
+; FP-NEXT: link.w %a6, #-32
+; FP-NEXT: .cfi_def_cfa_offset -8
+; FP-NEXT: .cfi_offset %a6, -8
+; FP-NEXT: .cfi_def_cfa_register %a6
+; FP-NEXT: move.l (8,%a6), %d1
+; FP-NEXT: move.l %d1, (-32,%a6)
+; FP-NEXT: move.l (12,%a6), %d0
+; FP-NEXT: add.l %d0, %d1
+; FP-NEXT: move.l %d0, (0,%a6)
+; FP-NEXT: add.l %d1, %d0
+; FP-NEXT: move.l %d1, (32,%a6)
+; FP-NEXT: add.l %d0, %d1
+; FP-NEXT: move.l %d0, (64,%a6)
+; FP-NEXT: move.l %d1, (96,%a6)
+; FP-NEXT: add.l %d1, %d0
+; FP-NEXT: move.l %d0, (128,%a6)
+; FP-NEXT: add.l %d0, %d1
+; FP-NEXT: move.l %d1, (160,%a6)
+; FP-NEXT: add.l %d1, %d0
+; FP-NEXT: move.l %d0, (192,%a6)
+; FP-NEXT: unlk %a6
+; FP-NEXT: rts
+;
+; NO-FP-LABEL: fib:
+; NO-FP: .cfi_startproc
+; NO-FP-NEXT: ; %bb.0: ; %entry
+; NO-FP-NEXT: suba.l #32, %sp
+; NO-FP-NEXT: .cfi_def_cfa_offset -36
+; NO-FP-NEXT: move.l (36,%sp), %d1
+; NO-FP-NEXT: move.l %d1, (0,%sp)
+; NO-FP-NEXT: move.l (40,%sp), %d0
+; NO-FP-NEXT: add.l %d0, %d1
+; NO-FP-NEXT: move.l %d0, (32,%sp)
+; NO-FP-NEXT: add.l %d1, %d0
+; NO-FP-NEXT: move.l %d1, (64,%sp)
+; NO-FP-NEXT: add.l %d0, %d1
+; NO-FP-NEXT: move.l %d0, (96,%sp)
+; NO-FP-NEXT: move.l %d1, (128,%sp)
+; NO-FP-NEXT: add.l %d1, %d0
+; NO-FP-NEXT: move.l %d0, (160,%sp)
+; NO-FP-NEXT: add.l %d0, %d1
+; NO-FP-NEXT: move.l %d1, (192,%sp)
+; NO-FP-NEXT: add.l %d1, %d0
+; NO-FP-NEXT: move.l %d0, (224,%sp)
+; NO-FP-NEXT: adda.l #32, %sp
+; NO-FP-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
+}
# CHECK: move.l %a1, %a0
0x20 0x49
+
# CHECK: lea (50,%a0), %a1
0x43 0xe8 0x00 0x32
# 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
--- /dev/null
+; RUN: llvm-mc --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