Skip to content

Commit d2672a5

Browse files
committed
[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.
1 parent 8f1accf commit d2672a5

File tree

7 files changed

+149
-12
lines changed

7 files changed

+149
-12
lines changed

llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ class M68kOperand : public MCParsedAsmOperand {
156156
bool isAReg() const;
157157
bool isDReg() const;
158158
bool isFPDReg() const;
159+
bool isFPCReg() const;
159160
unsigned getReg() const override;
160161
void addRegOperands(MCInst &Inst, unsigned N) const;
161162

@@ -254,9 +255,13 @@ static inline unsigned getRegisterIndex(unsigned Register) {
254255
// SP is sadly not contiguous with the rest of the An registers
255256
return 15;
256257

258+
// We don't care about the indices of these registers.
257259
case M68k::PC:
258260
case M68k::CCR:
259-
return 16;
261+
case M68k::FPC:
262+
case M68k::FPS:
263+
case M68k::FPIAR:
264+
return UINT_MAX;
260265

261266
default:
262267
llvm_unreachable("unexpected register number");
@@ -488,7 +493,8 @@ void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
488493
}
489494

490495
static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
491-
bool SP, bool FPDR = false) {
496+
bool SP, bool FPDR = false,
497+
bool FPCR = false) {
492498
switch (RegNo) {
493499
case M68k::A0:
494500
case M68k::A1:
@@ -526,6 +532,11 @@ static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
526532
case M68k::FP7:
527533
return FPDR;
528534

535+
case M68k::FPC:
536+
case M68k::FPS:
537+
case M68k::FPIAR:
538+
return FPCR;
539+
529540
default:
530541
llvm_unreachable("unexpected register type");
531542
return false;
@@ -551,6 +562,13 @@ bool M68kOperand::isFPDReg() const {
551562
/*FPDR=*/true);
552563
}
553564

565+
bool M68kOperand::isFPCReg() const {
566+
return isReg() && checkRegisterClass(getReg(),
567+
/*Data=*/false,
568+
/*Address=*/false, /*SP=*/false,
569+
/*FPDR=*/false, /*FPCR=*/true);
570+
}
571+
554572
unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
555573
unsigned Kind) {
556574
M68kOperand &Operand = (M68kOperand &)Op;
@@ -660,12 +678,22 @@ bool M68kAsmParser::parseRegisterName(MCRegister &RegNo, SMLoc Loc,
660678
}
661679
} else if (StringRef(RegisterNameLower).starts_with("fp") &&
662680
RegisterNameLower.size() > 2) {
663-
// Floating point data register.
664681
auto RegIndex = unsigned(RegisterNameLower[2] - '0');
665-
if (RegIndex >= 8 || RegisterNameLower.size() > 3)
666-
return false;
667-
RegNo = getRegisterByIndex(16 + RegIndex);
668-
return true;
682+
if (RegIndex < 8 && RegisterNameLower.size() == 3) {
683+
// Floating point data register.
684+
RegNo = getRegisterByIndex(16 + RegIndex);
685+
return true;
686+
} else {
687+
// Floating point control register.
688+
RegNo = StringSwitch<unsigned>(RegisterNameLower)
689+
.Cases("fpc", "fpcr", M68k::FPC)
690+
.Cases("fps", "fpsr", M68k::FPS)
691+
.Cases("fpi", "fpiar", M68k::FPIAR)
692+
.Default(M68k::NoRegister);
693+
assert(RegNo != M68k::NoRegister &&
694+
"Unrecognized FP control register name");
695+
return true;
696+
}
669697
}
670698

671699
return false;

llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ using namespace llvm;
3333
typedef MCDisassembler::DecodeStatus DecodeStatus;
3434

3535
static const unsigned RegisterDecode[] = {
36-
M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5,
37-
M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3,
38-
M68k::A4, M68k::A5, M68k::A6, M68k::SP, M68k::FP0, M68k::FP1,
39-
M68k::FP2, M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7};
36+
M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5,
37+
M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3,
38+
M68k::A4, M68k::A5, M68k::A6, M68k::SP, M68k::FP0, M68k::FP1,
39+
M68k::FP2, M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7,
40+
M68k::FPIAR, M68k::FPS, M68k::FPC};
4041

4142
static DecodeStatus DecodeRegisterClass(MCInst &Inst, uint64_t RegNo,
4243
uint64_t Address, const void *Decoder) {
@@ -97,6 +98,13 @@ static DecodeStatus DecodeFPDRRegisterClass(MCInst &Inst, uint64_t RegNo,
9798
#define DecodeFPDR64RegisterClass DecodeFPDRRegisterClass
9899
#define DecodeFPDR80RegisterClass DecodeFPDRRegisterClass
99100

101+
static DecodeStatus DecodeFPCSCRegisterClass(MCInst &Inst, uint64_t RegNo,
102+
uint64_t Address,
103+
const void *Decoder) {
104+
return DecodeRegisterClass(Inst, (RegNo >> 1) + 24, Address, Decoder);
105+
}
106+
#define DecodeFPICRegisterClass DecodeFPCSCRegisterClass
107+
100108
static DecodeStatus DecodeCCRCRegisterClass(MCInst &Inst, APInt &Insn,
101109
uint64_t Address,
102110
const void *Decoder) {
@@ -114,6 +122,7 @@ static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address,
114122
#undef DecodeFPDR32RegisterClass
115123
#undef DecodeFPDR64RegisterClass
116124
#undef DecodeFPDR80RegisterClass
125+
#undef DecodeFPICRegisterClass
117126

118127
/// A disassembler class for M68k.
119128
struct M68kDisassembler : public MCDisassembler {

llvm/lib/Target/M68k/M68kInstrData.td

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,3 +672,49 @@ foreach rounding = ["", "s", "d"] in {
672672
foreach size = [32, 64] in
673673
def F # !toupper(rounding) # MOV # size # fp_fp : MxFMove_FF<rounding, size>;
674674
}
675+
// Direction
676+
defvar MxFMove_FP_EA = false;
677+
defvar MxFMove_EA_FP = true;
678+
679+
// Encoding scheme for FPSYS <-> R/M
680+
class MxEncFSysMove<bit dir, MxEncMemOp EAEnc, string fsys_reg> {
681+
dag Value = (ascend
682+
(descend 0b1111,
683+
/*COPROCESSOR ID*/0b001,
684+
0b000,
685+
/*MODE + REGISTER*/
686+
EAEnc.EA
687+
),
688+
(descend 0b10, /*dir*/ dir,
689+
/*REGISTER SELECT*/
690+
(operand "$"#fsys_reg, 3, (encoder "encodeFPSYSSelect")),
691+
0b0000000000
692+
)
693+
);
694+
}
695+
696+
// FPSYS <-> R
697+
class MxFMove_FSYS_R<string src_reg,
698+
MxOpBundle SrcOpnd = !cast<MxOpBundle>("MxOp32AddrMode_"#src_reg),
699+
MxOpBundle DstOpnd = !cond(!eq(src_reg, "d"): MxOp32AddrMode_fpcs,
700+
!eq(src_reg, "a"): MxOp32AddrMode_fpi),
701+
MxEncMemOp SrcEnc = !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#src_reg)>
702+
: MxFMove<"l", (outs DstOpnd.Op:$dst), (ins SrcOpnd.Op:$src),
703+
[(null_frag)]> {
704+
let Inst = MxEncFSysMove<MxFMove_FP_EA, SrcEnc, "dst">.Value;
705+
}
706+
707+
class MxFMove_R_FSYS<string dst_reg,
708+
MxOpBundle SrcOpnd = !cond(!eq(dst_reg, "d"): MxOp32AddrMode_fpcs,
709+
!eq(dst_reg, "a"): MxOp32AddrMode_fpi),
710+
MxOpBundle DstOpnd = !cast<MxOpBundle>("MxOp32AddrMode_"#dst_reg),
711+
MxEncMemOp DstEnc = !cast<MxEncMemOp>("MxMoveDstOpEnc_"#dst_reg)>
712+
: MxFMove<"l", (outs DstOpnd.Op:$dst), (ins SrcOpnd.Op:$src),
713+
[(null_frag)]> {
714+
let Inst = MxEncFSysMove<MxFMove_EA_FP, DstEnc, "src">.Value;
715+
}
716+
717+
def FMOVE32fpcs_d : MxFMove_FSYS_R<"d">;
718+
def FMOVE32d_fpcs : MxFMove_R_FSYS<"d">;
719+
def FMOVE32fpi_a : MxFMove_FSYS_R<"a">;
720+
def FMOVE32a_fpi : MxFMove_R_FSYS<"a">;

llvm/lib/Target/M68k/M68kInstrInfo.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ let RenderMethod = "addRegOperands", SuperClasses = [MxRegClass]in {
186186
def MxDRegClass : MxOpClass<"DReg">;
187187

188188
def MxFPDRegClass : MxOpClass<"FPDReg">;
189+
def MxFPCRegClass : MxOpClass<"FPCReg">;
189190
}
190191

191192
class MxOperand<ValueType vt, MxSize size, string letter, RegisterClass rc, dag pat = (null_frag)> {
@@ -242,6 +243,12 @@ let ParserMatchClass = MxFPDRegClass in {
242243
def MxFPR80 : MxRegOp<f80, FPDR80, MxSizeF80, "fp">;
243244
}
244245

246+
// FLOATING POINT SYSTEM CONTROL REGISTER
247+
let ParserMatchClass = MxFPCRegClass in {
248+
def MxFPCSR : MxRegOp<i32, FPCSC, MxSize32, "fpcs">;
249+
def MxFPIR : MxRegOp<i32, FPIC, MxSize32, "fpi">;
250+
}
251+
245252
class MxMemOp<dag ops, MxSize size, string letter,
246253
string printMethod = "printOperand",
247254
AsmOperandClass parserMatchClass = ImmAsmOperand>
@@ -727,6 +734,9 @@ foreach size = [32, 64, 80] in
727734
def MxOp#size#AddrMode_fpr
728735
: MxOpBundle<size, !cast<MxOperand>("MxFPR"#size), ?>;
729736

737+
def MxOp32AddrMode_fpcs : MxOpBundle<32, MxFPCSR, ?>;
738+
def MxOp32AddrMode_fpi : MxOpBundle<32, MxFPIR, ?>;
739+
730740
class MxType8Class<string rLet, MxOperand reg>
731741
: MxType<i8, "b", "", rLet, reg,
732742
MxARI8, MxCP_ARI,

llvm/lib/Target/M68k/M68kRegisterInfo.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,10 @@ let CopyCost = -1 in {
125125
def CCRC : MxRegClass<[i8], 16, (add CCR)>;
126126
def SRC : MxRegClass<[i16], 16, (add SR)>;
127127

128-
def FPCR : MxRegClass<[i32], 32, (add FPC, FPS, FPIAR)>;
128+
// Float Point System Control Registers
129+
def FPIC : MxRegClass<[i32], 32, (add FPIAR)>;
130+
def FPCSC : MxRegClass<[i32], 32, (add FPC, FPS)>;
131+
def FPSYSC : MxRegClass<[i32], 32, (add FPCSC, FPIC)>;
129132
}
130133

131134
let isAllocatable = 0 in {

llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ class M68kMCCodeEmitter : public MCCodeEmitter {
5959
APInt &Value, SmallVectorImpl<MCFixup> &Fixups,
6060
const MCSubtargetInfo &STI) const;
6161

62+
void encodeFPSYSSelect(const MCInst &MI, unsigned OpIdx, unsigned InsertPos,
63+
APInt &Value, SmallVectorImpl<MCFixup> &Fixups,
64+
const MCSubtargetInfo &STI) const;
65+
6266
public:
6367
M68kMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
6468
: MCII(mcii), Ctx(ctx) {}
@@ -172,6 +176,26 @@ void M68kMCCodeEmitter::encodePCRelImm(const MCInst &MI, unsigned OpIdx,
172176
}
173177
}
174178

179+
void M68kMCCodeEmitter::encodeFPSYSSelect(const MCInst &MI, unsigned OpIdx,
180+
unsigned InsertPos, APInt &Value,
181+
SmallVectorImpl<MCFixup> &Fixups,
182+
const MCSubtargetInfo &STI) const {
183+
MCRegister FPSysReg = MI.getOperand(OpIdx).getReg();
184+
switch (FPSysReg) {
185+
case M68k::FPC:
186+
Value = 0b100;
187+
break;
188+
case M68k::FPS:
189+
Value = 0b010;
190+
break;
191+
case M68k::FPIAR:
192+
Value = 0b001;
193+
break;
194+
default:
195+
llvm_unreachable("Unrecognized FPSYS register");
196+
}
197+
}
198+
175199
void M68kMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &Op,
176200
unsigned InsertPos, APInt &Value,
177201
SmallVectorImpl<MCFixup> &Fixups,
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: llvm-mc -triple=m68k -mcpu=M68040 -show-encoding < %s | FileCheck %s
2+
3+
; CHECK: fmove.l %d0, %fpcr
4+
; CHECK-SAME: [0xf2,0x00,0x90,0x00]
5+
fmove.l %d0, %fpc
6+
7+
; CHECK: fmove.l %fpsr, %d2
8+
; CHECK-SAME: [0xf2,0x02,0xa8,0x00]
9+
fmove.l %fps, %d2
10+
11+
; CHECK: fmove.l %fpiar, %a3
12+
; CHECK-SAME: [0xf2,0x0b,0xa4,0x00]
13+
fmove.l %fpiar, %a3
14+
15+
; CHECK: fmove.l %a1, %fpiar
16+
; CHECK-SAME: [0xf2,0x09,0x84,0x00]
17+
fmove.l %a1, %fpi

0 commit comments

Comments
 (0)