[llvm] 7486b7b - [M68k] Basic FP register files and FMOVE implementations
Min-Yih Hsu via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 8 10:44:16 PDT 2023
Author: Min-Yih Hsu
Date: 2023-04-08T10:42:47-07:00
New Revision: 7486b7b6bac5c3046090da8356777cff412853fc
URL: https://github.com/llvm/llvm-project/commit/7486b7b6bac5c3046090da8356777cff412853fc
DIFF: https://github.com/llvm/llvm-project/commit/7486b7b6bac5c3046090da8356777cff412853fc.diff
LOG: [M68k] Basic FP register files and FMOVE implementations
- FP registers and register classes definitions
- MC support for FP registers
- MC support for the FPDR -> FPDR variant of FMOVE/FSMOVE/FDSMOVE
Note that we don't implement 32/64-bit FP registers with subregisters since
f32/f64 values will be converted to f80 upon storing into a register,
rather than occupying part of the register.
So we only use register classes with different value types to distinguish
them.
Differential Revision: https://reviews.llvm.org/D147480
Added:
llvm/test/MC/Disassembler/M68k/fp-data.txt
llvm/test/MC/M68k/Data/Classes/MxFMove_FF.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
Removed:
################################################################################
diff --git a/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp b/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
index 59fa782829fde..c606eaa9af13e 100644
--- a/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
+++ b/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
@@ -158,6 +158,7 @@ class M68kOperand : public MCParsedAsmOperand {
bool isReg() const override;
bool isAReg() const;
bool isDReg() const;
+ bool isFPDReg() const;
unsigned getReg() const override;
void addRegOperands(MCInst &Inst, unsigned N) const;
@@ -234,10 +235,10 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser() {
static inline unsigned getRegisterByIndex(unsigned RegisterIndex) {
static unsigned RegistersByIndex[] = {
- 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::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};
assert(RegisterIndex <=
sizeof(RegistersByIndex) / sizeof(RegistersByIndex[0]));
return RegistersByIndex[RegisterIndex];
@@ -248,6 +249,8 @@ static inline unsigned getRegisterIndex(unsigned Register) {
return Register - M68k::D0;
if (Register >= M68k::A0 && Register <= M68k::A6)
return Register - M68k::A0 + 8;
+ if (Register >= M68k::FP0 && Register <= M68k::FP7)
+ return Register - M68k::FP0 + 16;
switch (Register) {
case M68k::SP:
@@ -488,7 +491,7 @@ void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
}
static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
- bool SP) {
+ bool SP, bool FPDR = false) {
switch (RegNo) {
case M68k::A0:
case M68k::A1:
@@ -516,6 +519,16 @@ static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
case M68k::CCR:
return false;
+ case M68k::FP0:
+ case M68k::FP1:
+ case M68k::FP2:
+ case M68k::FP3:
+ case M68k::FP4:
+ case M68k::FP5:
+ case M68k::FP6:
+ case M68k::FP7:
+ return FPDR;
+
default:
llvm_unreachable("unexpected register type");
return false;
@@ -534,6 +547,13 @@ bool M68kOperand::isDReg() const {
/*Address=*/false, /*SP=*/false);
}
+bool M68kOperand::isFPDReg() const {
+ return isReg() && checkRegisterClass(getReg(),
+ /*Data=*/false,
+ /*Address=*/false, /*SP=*/false,
+ /*FPDR=*/true);
+}
+
unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
unsigned Kind) {
M68kOperand &Operand = (M68kOperand &)Op;
@@ -641,6 +661,14 @@ bool M68kAsmParser::parseRegisterName(MCRegister &RegNo, SMLoc Loc,
}
break;
}
+ } 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;
}
return false;
diff --git a/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp b/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
index ffe4869e8fe56..2124a35cc65a4 100644
--- a/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
+++ b/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
@@ -33,14 +33,14 @@ 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::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};
static DecodeStatus DecodeRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address, const void *Decoder) {
- if (RegNo >= 16)
+ if (RegNo >= 24)
return DecodeStatus::Fail;
Inst.addOperand(MCOperand::createReg(RegisterDecode[RegNo]));
return DecodeStatus::Success;
@@ -88,6 +88,15 @@ static DecodeStatus DecodeXR16RegisterClass(MCInst &Inst, uint64_t RegNo,
return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
}
+static DecodeStatus DecodeFPDRRegisterClass(MCInst &Inst, uint64_t RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ return DecodeRegisterClass(Inst, RegNo | 16ULL, Address, Decoder);
+}
+#define DecodeFPDR32RegisterClass DecodeFPDRRegisterClass
+#define DecodeFPDR64RegisterClass DecodeFPDRRegisterClass
+#define DecodeFPDR80RegisterClass DecodeFPDRRegisterClass
+
static DecodeStatus DecodeCCRCRegisterClass(MCInst &Inst, APInt &Insn,
uint64_t Address,
const void *Decoder) {
@@ -102,6 +111,10 @@ static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address,
#include "M68kGenDisassemblerTable.inc"
+#undef DecodeFPDR32RegisterClass
+#undef DecodeFPDR64RegisterClass
+#undef DecodeFPDR80RegisterClass
+
/// A disassembler class for M68k.
struct M68kDisassembler : public MCDisassembler {
M68kDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
diff --git a/llvm/lib/Target/M68k/M68kInstrData.td b/llvm/lib/Target/M68k/M68kInstrData.td
index ed37bd1f3daeb..00fcb3db8eb68 100644
--- a/llvm/lib/Target/M68k/M68kInstrData.td
+++ b/llvm/lib/Target/M68k/M68kInstrData.td
@@ -614,3 +614,54 @@ def : Pat<(i8 (trunc i32:$src)),
(EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex8Lo)>;
def : Pat<(i8 (trunc i16:$src)),
(EXTRACT_SUBREG MxXRD16:$src, MxSubRegIndex8Lo)>;
+
+//===----------------------------------------------------------------------===//
+// FMOVE
+//===----------------------------------------------------------------------===//
+
+let Defs = [FPS] in
+class MxFMove<string size, dag outs, dag ins, list<dag> pattern,
+ string rounding = "">
+ : MxInst<outs, ins,
+ "f"#rounding#"move."#size#"\t$src, $dst", pattern> {
+ // Only FMOVE uses FPC
+ let Uses = !if(!eq(rounding, ""), [FPC], []);
+
+ // FSMOVE and FDMOVE are only available after M68040
+ let Predicates = [!if(!eq(rounding, ""), AtLeastM68881, AtLeastM68040)];
+}
+
+// FPDR <- FPDR
+class MxFMove_FF<string rounding, int size,
+ MxOpBundle Opnd = !cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr")>
+ : MxFMove<"x", (outs Opnd.Op:$dst), (ins Opnd.Op:$src),
+ [(null_frag)], rounding> {
+ let Inst = (ascend
+ (descend 0b1111,
+ /*COPROCESSOR ID*/0b001,
+ 0b000,
+ /*MODE + REGISTER*/0b000000
+ ),
+ (descend 0b0, /* R/M */0b0, 0b0,
+ /*SOURCE SPECIFIER*/
+ (operand "$src", 3),
+ /*DESTINATION*/
+ (operand "$dst", 3),
+ /*OPMODE*/
+ !cond(!eq(rounding, "s"): 0b1000000,
+ !eq(rounding, "d"): 0b1000100,
+ true: 0b0000000)
+ )
+ );
+}
+
+foreach rounding = ["", "s", "d"] in {
+ def F # !toupper(rounding) # MOV80fp_fp : MxFMove_FF<rounding, 80>;
+
+ // We don't have `fmove.s` or `fmove.d` because values will be converted to
+ // f80 upon storing into the register, but FMOV32/64fp_fp are still needed
+ // to make codegen easier.
+ let isCodeGenOnly = true in
+ foreach size = [32, 64] in
+ def F # !toupper(rounding) # MOV # size # fp_fp : MxFMove_FF<rounding, size>;
+}
diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.td b/llvm/lib/Target/M68k/M68kInstrInfo.td
index 4a7bea5763fed..6d3370d5ee90d 100644
--- a/llvm/lib/Target/M68k/M68kInstrInfo.td
+++ b/llvm/lib/Target/M68k/M68kInstrInfo.td
@@ -164,6 +164,9 @@ class MxSize<int num, string id, string full> {
def MxSize8 : MxSize<8, "b", "byte">;
def MxSize16 : MxSize<16, "w", "word">;
def MxSize32 : MxSize<32, "l", "long">;
+def MxSizeF32 : MxSize<32, "s", "f32">;
+def MxSizeF64 : MxSize<64, "d", "f64">;
+def MxSizeF80 : MxSize<80, "x", "f80">;
class MxOpClass<string name,
list<AsmOperandClass> superClasses = []> : AsmOperandClass {
@@ -181,6 +184,8 @@ def MxRegClass : MxOpClass<"Reg">;
let RenderMethod = "addRegOperands", SuperClasses = [MxRegClass]in {
def MxARegClass : MxOpClass<"AReg">;
def MxDRegClass : MxOpClass<"DReg">;
+
+ def MxFPDRegClass : MxOpClass<"FPDReg">;
}
class MxOperand<ValueType vt, MxSize size, string letter, RegisterClass rc, dag pat = (null_frag)> {
@@ -230,6 +235,13 @@ let ParserMatchClass = MxARegClass in {
def MxARD32_TC : MxRegOp<i32, AR32_TC, MxSize32, "a">;
}
+// FLOATING POINT DATA REGISTER.
+let ParserMatchClass = MxFPDRegClass in {
+ def MxFPR32 : MxRegOp<f32, FPDR32, MxSizeF32, "fp">;
+ def MxFPR64 : MxRegOp<f64, FPDR64, MxSizeF64, "fp">;
+ def MxFPR80 : MxRegOp<f80, FPDR80, MxSizeF80, "fp">;
+}
+
class MxMemOp<dag ops, MxSize size, string letter,
string printMethod = "printOperand",
AsmOperandClass parserMatchClass = ImmAsmOperand>
@@ -711,6 +723,10 @@ foreach size = [16, 32] in {
: MxOpBundle<size, !cast<MxOperand>("MxXRD"#size), ?>;
} // foreach size = [16, 32]
+foreach size = [32, 64, 80] in
+def MxOp#size#AddrMode_fpr
+ : MxOpBundle<size, !cast<MxOperand>("MxFPR"#size), ?>;
+
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 49874a2b1099c..1567bcbb73196 100644
--- a/llvm/lib/Target/M68k/M68kRegisterInfo.td
+++ b/llvm/lib/Target/M68k/M68kRegisterInfo.td
@@ -68,6 +68,19 @@ defm A5 : MxAddressRegister<5, "a5", ["bp"]>;
defm A6 : MxAddressRegister<6, "a6", ["fp"]>;
defm SP : MxAddressRegister<7, "sp", ["usp", "ssp", "isp", "a7"]>;
+// Floating Point Registers
+class MxFPRegister<int INDEX, string REG_NAME, list<string> ALTNAMES = []>
+ : MxReg<REG_NAME, INDEX, /*SUBREGS=*/[], /*SUBIDX=*/[],
+ /*DWREGS=*/[!add(18,INDEX)], ALTNAMES>;
+
+foreach i = {0-7} in
+ def FP#i : MxFPRegister<i, "fp"#i>;
+
+// Unlike their counterparts in integer registers, these
+// control registers can be accessed and modified by instructions.
+def FPC : MxFPRegister<8, "fpcr", ["fpc"]>;
+def FPS : MxFPRegister<9, "fpsr", ["fps"]>;
+def FPIAR : MxFPRegister<10, "fpiar", ["fpi"]>;
// Pseudo Registers
class MxPseudoReg<string N, list<Register> SUBREGS = [], list<SubRegIndex> SUBIDX = []>
@@ -103,9 +116,16 @@ def XR32 : MxRegClass<[i32], 32, (add DR32, AR32)>;
def SPC : MxRegClass<[i32], 32, (add SP)>;
+// Floating Point Data Registers
+def FPDR32 : MxRegClass<[f32], 32, (sequence "FP%u", 0, 7)>;
+def FPDR64 : MxRegClass<[f64], 32, (add FPDR32)>;
+def FPDR80 : MxRegClass<[f80], 32, (add FPDR32)>;
+
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)>;
}
let isAllocatable = 0 in {
diff --git a/llvm/test/MC/Disassembler/M68k/fp-data.txt b/llvm/test/MC/Disassembler/M68k/fp-data.txt
new file mode 100644
index 0000000000000..4e953793c7eae
--- /dev/null
+++ b/llvm/test/MC/Disassembler/M68k/fp-data.txt
@@ -0,0 +1,10 @@
+# RUN: llvm-mc -disassemble -triple m68k -mcpu=M68040 %s | FileCheck %s
+
+# CHECK: fmove.x %fp7, %fp2
+0xf2 0x00 0x1d 0x00
+
+# CHECK: fsmove.x %fp6, %fp1
+0xf2 0x00 0x18 0xc0
+
+# CHECK: fdmove.x %fp3, %fp0
+0xf2 0x00 0x0c 0x44
diff --git a/llvm/test/MC/M68k/Data/Classes/MxFMove_FF.s b/llvm/test/MC/M68k/Data/Classes/MxFMove_FF.s
new file mode 100644
index 0000000000000..e3fef6079beea
--- /dev/null
+++ b/llvm/test/MC/M68k/Data/Classes/MxFMove_FF.s
@@ -0,0 +1,13 @@
+; RUN: llvm-mc -triple=m68k -mcpu=M68040 -show-encoding < %s | FileCheck %s
+
+; CHECK: fmove.x %fp7, %fp2
+; CHECK-SAME: [0xf2,0x00,0x1d,0x00]
+fmove.x %fp7, %fp2
+
+; CHECK: fsmove.x %fp6, %fp1
+; CHECK-SAME: [0xf2,0x00,0x18,0xc0]
+fsmove.x %fp6, %fp1
+
+; CHECK: fdmove.x %fp3, %fp0
+; CHECK-SAME: [0xf2,0x00,0x0c,0x44]
+fdmove.x %fp3, %fp0
More information about the llvm-commits
mailing list