Skip to content

Commit

Permalink
[M68k][MC] Add fmove.l from / to fp control registers
Browse files Browse the repository at this point in the history
Including splitting up the FPCR register class into classes with finer
granularities.
Right now we only support address / data registers as source /
destinations.
  • Loading branch information
mshockwave committed Dec 12, 2023
1 parent 8f1accf commit d2672a5
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 12 deletions.
42 changes: 35 additions & 7 deletions llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
17 changes: 13 additions & 4 deletions llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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 {
Expand Down
46 changes: 46 additions & 0 deletions llvm/lib/Target/M68k/M68kInstrData.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;
10 changes: 10 additions & 0 deletions llvm/lib/Target/M68k/M68kInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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)> {
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/M68k/M68kRegisterInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
24 changes: 24 additions & 0 deletions llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
Expand Down Expand Up @@ -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,
Expand Down
17 changes: 17 additions & 0 deletions llvm/test/MC/M68k/Data/Classes/MxFMove_FSYS.s
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit d2672a5

Please sign in to comment.