[M68k] Add MC support for link/unlk
authorSheng <ox59616e@gmail.com>
Mon, 8 Aug 2022 01:56:04 +0000 (09:56 +0800)
committerSheng <ox59616e@gmail.com>
Mon, 8 Aug 2022 03:00:11 +0000 (11:00 +0800)
Reviewers: myhsu

Differential Revision: https://reviews.llvm.org/D125444

llvm/lib/Target/M68k/M68kFrameLowering.cpp
llvm/lib/Target/M68k/M68kInstrData.td
llvm/test/CodeGen/M68k/Alloc/dyn_alloca_aligned.ll
llvm/test/CodeGen/M68k/link-unlnk.ll [new file with mode: 0644]
llvm/test/MC/Disassembler/M68k/data.txt
llvm/test/MC/M68k/Data/Classes/MxLink.s [new file with mode: 0644]

index 643e156..5ecda43 100644 (file)
@@ -546,9 +546,9 @@ void M68kFrameLowering::emitPrologue(MachineFunction &MF,
     // 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 @@ void M68kFrameLowering::emitPrologue(MachineFunction &MF,
                                               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 @@ void M68kFrameLowering::emitPrologue(MachineFunction &MF,
   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 @@ void M68kFrameLowering::emitEpilogue(MachineFunction &MF,
     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 @@ void M68kFrameLowering::emitEpilogue(MachineFunction &MF,
           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 863432b..5949ba2 100644 (file)
@@ -438,6 +438,35 @@ def LEA32 # AM : MxLEA<!cast<MxOpBundle>("MxOp32AddrMode_"#AM),
                        !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
 //===----------------------------------------------------------------------===//
 
index b3d8f8d..4ca05c8 100644 (file)
@@ -4,15 +4,13 @@ define i32 @A(i32 %Size) {
 ; 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 @@ define i32 @A(i32 %Size) {
 ; 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
diff --git a/llvm/test/CodeGen/M68k/link-unlnk.ll b/llvm/test/CodeGen/M68k/link-unlnk.ll
new file mode 100644 (file)
index 0000000..9f9911f
--- /dev/null
@@ -0,0 +1,96 @@
+; 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
+}
index 1a428fd..6a8460f 100644 (file)
@@ -2,6 +2,7 @@
 
 # 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
diff --git a/llvm/test/MC/M68k/Data/Classes/MxLink.s b/llvm/test/MC/M68k/Data/Classes/MxLink.s
new file mode 100644 (file)
index 0000000..3e759f0
--- /dev/null
@@ -0,0 +1,13 @@
+; 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