[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