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(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; } +// Direction +defvar MxFMove_FP_EA = false; +defvar MxFMove_EA_FP = true; + +// Encoding scheme for FPSYS <-> R/M +class MxEncFSysMove { + 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("MxOp32AddrMode_"#src_reg), + MxOpBundle DstOpnd = !cond(!eq(src_reg, "d"): MxOp32AddrMode_fpcs, + !eq(src_reg, "a"): MxOp32AddrMode_fpi), + MxEncMemOp SrcEnc = !cast("MxMoveSrcOpEnc_"#src_reg)> + : MxFMove<"l", (outs DstOpnd.Op:$dst), (ins SrcOpnd.Op:$src), + [(null_frag)]> { + let Inst = MxEncFSysMove.Value; +} + +class MxFMove_R_FSYS("MxOp32AddrMode_"#dst_reg), + MxEncMemOp DstEnc = !cast("MxMoveDstOpEnc_"#dst_reg)> + : MxFMove<"l", (outs DstOpnd.Op:$dst), (ins SrcOpnd.Op:$src), + [(null_frag)]> { + let Inst = MxEncFSysMove.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 { @@ -242,6 +243,12 @@ let ParserMatchClass = MxFPDRegClass in { def MxFPR80 : MxRegOp; } +// FLOATING POINT SYSTEM CONTROL REGISTER +let ParserMatchClass = MxFPCRegClass in { + def MxFPCSR : MxRegOp; + def MxFPIR : MxRegOp; +} + class MxMemOp @@ -727,6 +734,9 @@ foreach size = [32, 64, 80] in def MxOp#size#AddrMode_fpr : MxOpBundle("MxFPR"#size), ?>; +def MxOp32AddrMode_fpcs : MxOpBundle<32, MxFPCSR, ?>; +def MxOp32AddrMode_fpi : MxOpBundle<32, MxFPIR, ?>; + class MxType8Class : MxType; 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 &Fixups, const MCSubtargetInfo &STI) const; + void encodeFPSYSSelect(const MCInst &MI, unsigned OpIdx, unsigned InsertPos, + APInt &Value, SmallVectorImpl &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 &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 &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