[llvm] d2672a5 - [M68k][MC] Add fmove.l from / to fp control registers

Min-Yih Hsu via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 11 23:06:50 PST 2023


Author: Min-Yih Hsu
Date: 2023-12-11T23:02:07-08:00
New Revision: d2672a550137c0d9c3f4d05c8eb41dc5ab51867b

URL: https://github.com/llvm/llvm-project/commit/d2672a550137c0d9c3f4d05c8eb41dc5ab51867b
DIFF: https://github.com/llvm/llvm-project/commit/d2672a550137c0d9c3f4d05c8eb41dc5ab51867b.diff

LOG: [M68k][MC] Add fmove.l from / to fp control registers

Including splitting up the FPCR register class into classes with finer
granularities.
Right now we only support address / data registers as source /
destinations.

Added: 
    llvm/test/MC/M68k/Data/Classes/MxFMove_FSYS.s

Modified: 
    llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
    llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
    llvm/lib/Target/M68k/M68kInstrData.td
    llvm/lib/Target/M68k/M68kInstrInfo.td
    llvm/lib/Target/M68k/M68kRegisterInfo.td
    llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp b/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
index 31e525ad4d796..b2c0fda1ccc24 100644
--- a/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
+++ b/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
@@ -156,6 +156,7 @@ class M68kOperand : public MCParsedAsmOperand {
   bool isAReg() const;
   bool isDReg() const;
   bool isFPDReg() const;
+  bool isFPCReg() const;
   unsigned getReg() const override;
   void addRegOperands(MCInst &Inst, unsigned N) const;
 
@@ -254,9 +255,13 @@ static inline unsigned getRegisterIndex(unsigned Register) {
     // SP is sadly not contiguous with the rest of the An registers
     return 15;
 
+  // We don't care about the indices of these registers.
   case M68k::PC:
   case M68k::CCR:
-    return 16;
+  case M68k::FPC:
+  case M68k::FPS:
+  case M68k::FPIAR:
+    return UINT_MAX;
 
   default:
     llvm_unreachable("unexpected register number");
@@ -488,7 +493,8 @@ void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
 }
 
 static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
-                                      bool SP, bool FPDR = false) {
+                                      bool SP, bool FPDR = false,
+                                      bool FPCR = false) {
   switch (RegNo) {
   case M68k::A0:
   case M68k::A1:
@@ -526,6 +532,11 @@ static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
   case M68k::FP7:
     return FPDR;
 
+  case M68k::FPC:
+  case M68k::FPS:
+  case M68k::FPIAR:
+    return FPCR;
+
   default:
     llvm_unreachable("unexpected register type");
     return false;
@@ -551,6 +562,13 @@ bool M68kOperand::isFPDReg() const {
                                        /*FPDR=*/true);
 }
 
+bool M68kOperand::isFPCReg() const {
+  return isReg() && checkRegisterClass(getReg(),
+                                       /*Data=*/false,
+                                       /*Address=*/false, /*SP=*/false,
+                                       /*FPDR=*/false, /*FPCR=*/true);
+}
+
 unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
                                                    unsigned Kind) {
   M68kOperand &Operand = (M68kOperand &)Op;
@@ -660,12 +678,22 @@ bool M68kAsmParser::parseRegisterName(MCRegister &RegNo, SMLoc Loc,
     }
   } else if (StringRef(RegisterNameLower).starts_with("fp") &&
              RegisterNameLower.size() > 2) {
-    // Floating point data register.
     auto RegIndex = unsigned(RegisterNameLower[2] - '0');
-    if (RegIndex >= 8 || RegisterNameLower.size() > 3)
-      return false;
-    RegNo = getRegisterByIndex(16 + RegIndex);
-    return true;
+    if (RegIndex < 8 && RegisterNameLower.size() == 3) {
+      // Floating point data register.
+      RegNo = getRegisterByIndex(16 + RegIndex);
+      return true;
+    } else {
+      // Floating point control register.
+      RegNo = StringSwitch<unsigned>(RegisterNameLower)
+                  .Cases("fpc", "fpcr", M68k::FPC)
+                  .Cases("fps", "fpsr", M68k::FPS)
+                  .Cases("fpi", "fpiar", M68k::FPIAR)
+                  .Default(M68k::NoRegister);
+      assert(RegNo != M68k::NoRegister &&
+             "Unrecognized FP control register name");
+      return true;
+    }
   }
 
   return false;

diff  --git a/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp b/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
index 2124a35cc65a4..7f0f737faccd0 100644
--- a/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
+++ b/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
@@ -33,10 +33,11 @@ using namespace llvm;
 typedef MCDisassembler::DecodeStatus DecodeStatus;
 
 static const unsigned RegisterDecode[] = {
-    M68k::D0,  M68k::D1,  M68k::D2,  M68k::D3,  M68k::D4,  M68k::D5,
-    M68k::D6,  M68k::D7,  M68k::A0,  M68k::A1,  M68k::A2,  M68k::A3,
-    M68k::A4,  M68k::A5,  M68k::A6,  M68k::SP,  M68k::FP0, M68k::FP1,
-    M68k::FP2, M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7};
+    M68k::D0,    M68k::D1,  M68k::D2,  M68k::D3,  M68k::D4,  M68k::D5,
+    M68k::D6,    M68k::D7,  M68k::A0,  M68k::A1,  M68k::A2,  M68k::A3,
+    M68k::A4,    M68k::A5,  M68k::A6,  M68k::SP,  M68k::FP0, M68k::FP1,
+    M68k::FP2,   M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7,
+    M68k::FPIAR, M68k::FPS, M68k::FPC};
 
 static DecodeStatus DecodeRegisterClass(MCInst &Inst, uint64_t RegNo,
                                         uint64_t Address, const void *Decoder) {
@@ -97,6 +98,13 @@ static DecodeStatus DecodeFPDRRegisterClass(MCInst &Inst, uint64_t RegNo,
 #define DecodeFPDR64RegisterClass DecodeFPDRRegisterClass
 #define DecodeFPDR80RegisterClass DecodeFPDRRegisterClass
 
+static DecodeStatus DecodeFPCSCRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                             uint64_t Address,
+                                             const void *Decoder) {
+  return DecodeRegisterClass(Inst, (RegNo >> 1) + 24, Address, Decoder);
+}
+#define DecodeFPICRegisterClass DecodeFPCSCRegisterClass
+
 static DecodeStatus DecodeCCRCRegisterClass(MCInst &Inst, APInt &Insn,
                                             uint64_t Address,
                                             const void *Decoder) {
@@ -114,6 +122,7 @@ static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address,
 #undef DecodeFPDR32RegisterClass
 #undef DecodeFPDR64RegisterClass
 #undef DecodeFPDR80RegisterClass
+#undef DecodeFPICRegisterClass
 
 /// A disassembler class for M68k.
 struct M68kDisassembler : public MCDisassembler {

diff  --git a/llvm/lib/Target/M68k/M68kInstrData.td b/llvm/lib/Target/M68k/M68kInstrData.td
index e6d4471f7aab6..624093661d19f 100644
--- a/llvm/lib/Target/M68k/M68kInstrData.td
+++ b/llvm/lib/Target/M68k/M68kInstrData.td
@@ -672,3 +672,49 @@ foreach rounding = ["", "s", "d"] in {
   foreach size = [32, 64] in
     def F # !toupper(rounding) # MOV # size # fp_fp : MxFMove_FF<rounding, size>;
 }
+// Direction
+defvar MxFMove_FP_EA = false;
+defvar MxFMove_EA_FP = true;
+
+// Encoding scheme for FPSYS <-> R/M
+class MxEncFSysMove<bit dir, MxEncMemOp EAEnc, string fsys_reg> {
+  dag Value = (ascend
+    (descend 0b1111,
+      /*COPROCESSOR ID*/0b001,
+      0b000,
+      /*MODE + REGISTER*/
+      EAEnc.EA
+    ),
+    (descend 0b10, /*dir*/ dir,
+      /*REGISTER SELECT*/
+      (operand "$"#fsys_reg, 3, (encoder "encodeFPSYSSelect")),
+      0b0000000000
+    )
+  );
+}
+
+// FPSYS <-> R
+class MxFMove_FSYS_R<string src_reg,
+                     MxOpBundle SrcOpnd = !cast<MxOpBundle>("MxOp32AddrMode_"#src_reg),
+                     MxOpBundle DstOpnd = !cond(!eq(src_reg, "d"): MxOp32AddrMode_fpcs,
+                                                !eq(src_reg, "a"): MxOp32AddrMode_fpi),
+                     MxEncMemOp SrcEnc = !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#src_reg)>
+    : MxFMove<"l", (outs DstOpnd.Op:$dst), (ins SrcOpnd.Op:$src),
+              [(null_frag)]> {
+  let Inst = MxEncFSysMove<MxFMove_FP_EA, SrcEnc, "dst">.Value;
+}
+
+class MxFMove_R_FSYS<string dst_reg,
+                     MxOpBundle SrcOpnd = !cond(!eq(dst_reg, "d"): MxOp32AddrMode_fpcs,
+                                                !eq(dst_reg, "a"): MxOp32AddrMode_fpi),
+                     MxOpBundle DstOpnd = !cast<MxOpBundle>("MxOp32AddrMode_"#dst_reg),
+                     MxEncMemOp DstEnc = !cast<MxEncMemOp>("MxMoveDstOpEnc_"#dst_reg)>
+    : MxFMove<"l", (outs DstOpnd.Op:$dst), (ins SrcOpnd.Op:$src),
+              [(null_frag)]> {
+  let Inst = MxEncFSysMove<MxFMove_EA_FP, DstEnc, "src">.Value;
+}
+
+def FMOVE32fpcs_d : MxFMove_FSYS_R<"d">;
+def FMOVE32d_fpcs : MxFMove_R_FSYS<"d">;
+def FMOVE32fpi_a  : MxFMove_FSYS_R<"a">;
+def FMOVE32a_fpi  : MxFMove_R_FSYS<"a">;

diff  --git a/llvm/lib/Target/M68k/M68kInstrInfo.td b/llvm/lib/Target/M68k/M68kInstrInfo.td
index 6d3370d5ee90d..dc66e103361a4 100644
--- a/llvm/lib/Target/M68k/M68kInstrInfo.td
+++ b/llvm/lib/Target/M68k/M68kInstrInfo.td
@@ -186,6 +186,7 @@ let RenderMethod = "addRegOperands", SuperClasses = [MxRegClass]in {
   def MxDRegClass : MxOpClass<"DReg">;
 
   def MxFPDRegClass : MxOpClass<"FPDReg">;
+  def MxFPCRegClass : MxOpClass<"FPCReg">;
 }
 
 class MxOperand<ValueType vt, MxSize size, string letter, RegisterClass rc, dag pat = (null_frag)> {
@@ -242,6 +243,12 @@ let ParserMatchClass = MxFPDRegClass in {
   def MxFPR80 : MxRegOp<f80, FPDR80, MxSizeF80, "fp">;
 }
 
+// FLOATING POINT SYSTEM CONTROL REGISTER
+let ParserMatchClass = MxFPCRegClass in {
+  def MxFPCSR : MxRegOp<i32, FPCSC, MxSize32, "fpcs">;
+  def MxFPIR  : MxRegOp<i32, FPIC,  MxSize32, "fpi">;
+}
+
 class MxMemOp<dag ops, MxSize size, string letter,
               string printMethod = "printOperand",
               AsmOperandClass parserMatchClass = ImmAsmOperand>
@@ -727,6 +734,9 @@ foreach size = [32, 64, 80] in
 def MxOp#size#AddrMode_fpr
   : MxOpBundle<size, !cast<MxOperand>("MxFPR"#size), ?>;
 
+def MxOp32AddrMode_fpcs : MxOpBundle<32, MxFPCSR, ?>;
+def MxOp32AddrMode_fpi  : MxOpBundle<32, MxFPIR, ?>;
+
 class MxType8Class<string rLet, MxOperand reg>
     : MxType<i8, "b", "", rLet, reg,
              MxARI8,   MxCP_ARI,

diff  --git a/llvm/lib/Target/M68k/M68kRegisterInfo.td b/llvm/lib/Target/M68k/M68kRegisterInfo.td
index 1567bcbb73196..45b492eba4ec0 100644
--- a/llvm/lib/Target/M68k/M68kRegisterInfo.td
+++ b/llvm/lib/Target/M68k/M68kRegisterInfo.td
@@ -125,7 +125,10 @@ let CopyCost = -1 in {
   def CCRC : MxRegClass<[i8],  16, (add CCR)>;
   def SRC  : MxRegClass<[i16], 16, (add SR)>;
 
-  def FPCR : MxRegClass<[i32], 32, (add FPC, FPS, FPIAR)>;
+  // Float Point System Control Registers
+  def FPIC   : MxRegClass<[i32], 32, (add FPIAR)>;
+  def FPCSC  : MxRegClass<[i32], 32, (add FPC, FPS)>;
+  def FPSYSC : MxRegClass<[i32], 32, (add FPCSC, FPIC)>;
 }
 
 let isAllocatable = 0 in {

diff  --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp
index a9ff059bc990b..e6bc3af6e191a 100644
--- a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp
@@ -59,6 +59,10 @@ class M68kMCCodeEmitter : public MCCodeEmitter {
                       APInt &Value, SmallVectorImpl<MCFixup> &Fixups,
                       const MCSubtargetInfo &STI) const;
 
+  void encodeFPSYSSelect(const MCInst &MI, unsigned OpIdx, unsigned InsertPos,
+                         APInt &Value, SmallVectorImpl<MCFixup> &Fixups,
+                         const MCSubtargetInfo &STI) const;
+
 public:
   M68kMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
       : MCII(mcii), Ctx(ctx) {}
@@ -172,6 +176,26 @@ void M68kMCCodeEmitter::encodePCRelImm(const MCInst &MI, unsigned OpIdx,
   }
 }
 
+void M68kMCCodeEmitter::encodeFPSYSSelect(const MCInst &MI, unsigned OpIdx,
+                                          unsigned InsertPos, APInt &Value,
+                                          SmallVectorImpl<MCFixup> &Fixups,
+                                          const MCSubtargetInfo &STI) const {
+  MCRegister FPSysReg = MI.getOperand(OpIdx).getReg();
+  switch (FPSysReg) {
+  case M68k::FPC:
+    Value = 0b100;
+    break;
+  case M68k::FPS:
+    Value = 0b010;
+    break;
+  case M68k::FPIAR:
+    Value = 0b001;
+    break;
+  default:
+    llvm_unreachable("Unrecognized FPSYS register");
+  }
+}
+
 void M68kMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &Op,
                                           unsigned InsertPos, APInt &Value,
                                           SmallVectorImpl<MCFixup> &Fixups,

diff  --git a/llvm/test/MC/M68k/Data/Classes/MxFMove_FSYS.s b/llvm/test/MC/M68k/Data/Classes/MxFMove_FSYS.s
new file mode 100644
index 0000000000000..a02ce97e28c28
--- /dev/null
+++ b/llvm/test/MC/M68k/Data/Classes/MxFMove_FSYS.s
@@ -0,0 +1,17 @@
+; RUN: llvm-mc -triple=m68k -mcpu=M68040 -show-encoding < %s | FileCheck %s
+
+; CHECK: fmove.l %d0, %fpcr
+; CHECK-SAME: [0xf2,0x00,0x90,0x00]
+fmove.l %d0, %fpc
+
+; CHECK: fmove.l %fpsr, %d2
+; CHECK-SAME: [0xf2,0x02,0xa8,0x00]
+fmove.l %fps, %d2
+
+; CHECK: fmove.l %fpiar, %a3
+; CHECK-SAME: [0xf2,0x0b,0xa4,0x00]
+fmove.l %fpiar, %a3
+
+; CHECK: fmove.l %a1, %fpiar
+; CHECK-SAME: [0xf2,0x09,0x84,0x00]
+fmove.l %a1, %fpi


        


More information about the llvm-commits mailing list