Skip to content

Commit

Permalink
[MC68000] Add MC68881 FPU assembler
Browse files Browse the repository at this point in the history
  • Loading branch information
tgtakaoka committed Dec 31, 2023
1 parent e3582d3 commit b006206
Show file tree
Hide file tree
Showing 8 changed files with 2,089 additions and 222 deletions.
442 changes: 371 additions & 71 deletions src/asm_mc68000.cpp

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions src/asm_mc68000.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ struct AsmMc68000 final : Assembler, Config {
Error parseOperand(StrScanner &scan, Operand &op) const;
Error checkAlignment(AsmInsn &insn, OprSize size, const Operand &op) const;

void emitBriefExtension(AsmInsn &insn, const Operand &op, Config::ptrdiff_t disp) const;
void emitDisplacement(AsmInsn &insn, const Operand &op, Config::ptrdiff_t disp) const;
void emitRelativeAddr(AsmInsn &insn, AddrMode mode, const Operand &op) const;
void emitImmediateData(AsmInsn &insn, const Operand &op, OprSize size, uint32_t data) const;
void emitRegisterList(AsmInsn &insn, const Operand &op, bool reverse = false) const;
Error emitEffectiveAddr(
void encodeBriefExtension(AsmInsn &insn, const Operand &op, Config::ptrdiff_t disp) const;
void encodeDisplacement(AsmInsn &insn, const Operand &op, Config::ptrdiff_t disp) const;
void encodeRelativeAddr(AsmInsn &insn, AddrMode mode, const Operand &op) const;
void encodeImmediate(AsmInsn &insn, const Operand &op, OprSize size) const;
void encodeFloatControlList(AsmInsn &insn, const Operand &o) const;
void encodeFloatRegisterList(AsmInsn &insn, const Operand &o) const;
void encodeRegisterList(AsmInsn &insn, const Operand &op, bool reverse = false) const;
Error encodeOperand(
AsmInsn &insn, OprSize size, const Operand &op, AddrMode mode, OprPos pos) const;

Error processPseudo(StrScanner &scan, Insn &insn) override;
Expand Down
1 change: 1 addition & 0 deletions src/entry_mc68000.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ enum AddrMode : uint8_t {
M_FPIAR = 45, // FPIAR register
M_IMROM = 46, // MC68881 ROM constant
M_REL32 = 47, // 32-bit Relative; 1111|ccc|01s|___|___: s=0 16bit, s=1 32bit
M_IMFLT = 48, // Floating point immediate
};

enum OprPos : uint8_t {
Expand Down
30 changes: 21 additions & 9 deletions src/insn_mc68000.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ struct EntryInsn : EntryInsnPostfix<Config, Entry> {
OprPos srcPos() const { return flags().srcPos(); }
OprPos dstPos() const { return flags().dstPos(); }
OprSize oprSize() const { return flags().oprSize(); }
InsnSize insnSize() const { return flags().insnSize(); }
bool hasPostVal() const { return flags().hasPostVal(); }
auto postVal() const { return flags().postVal(); }
};

struct AsmInsn;
Expand All @@ -41,39 +42,50 @@ struct Operand final : ErrorAt {
RegName indexReg;
InsnSize indexSize;
uint32_t val32;
long double float80;
StrScanner list;
Operand()
: mode(M_NONE),
reg(REG_UNDEF),
indexReg(REG_UNDEF),
indexSize(ISZ_NONE),
val32(0),
float80(0),
list() {}
Config::uintptr_t offset(const AsmInsn &insn) const;
};

struct AsmInsn final : AsmInsnImpl<Config>, EntryInsn {
AsmInsn(Insn &insn) : AsmInsnImpl(insn) {}
AsmInsn(Insn &insn) : AsmInsnImpl(insn), _isize(ISZ_NONE) { parseInsnSize(); }

Operand srcOp, dstOp;

void emitInsn() { emitUint16(opCode(), 0); }
InsnSize insnSize() const { return _isize; }
void emitInsn() {
emitUint16(opCode(), 0);
if (hasPostVal())
emitUint16(postfix() | postVal(), 2);
}
void emitOperand16(uint16_t val16) { emitUint16(val16, operandPos()); }
void emitOperand32(uint32_t val32) { emitUint32(val32, operandPos()); }

InsnSize parseInsnSize();

private:
void emitOperand64(uint64_t val64) { emitUint64(val64, operandPos()); }
uint8_t operandPos() const {
uint8_t pos = length();
auto pos = length();
if (pos == 0)
pos = sizeof(Config::opcode_t);
pos = 2;
if (hasPostVal() && pos < 4)
pos = 4;
return pos;
}

private:
InsnSize _isize;
void parseInsnSize();
};

struct DisInsn final : DisInsnImpl<Config>, EntryInsn {
DisInsn(Insn &insn, DisMemory &memory, const StrBuffer &out) : DisInsnImpl(insn, memory, out) {}
InsnSize insnSize() const { return flags().insnSize(); }

void readPostfix() {
if (!hasPostfix())
Expand Down
34 changes: 30 additions & 4 deletions src/reg_mc68000.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,27 +80,49 @@ StrBuffer &outRegName(StrBuffer &out, RegName name) {

bool isDataReg(RegName name) {
const auto num = int8_t(name);
return num >= 0 && num < 8;
return num >= REG_D0 && num <= REG_D7;
}

bool isAddrReg(RegName name) {
const auto num = int8_t(name) - 8;
return num >= 0 && num < 8;
const auto num = int8_t(name);
return num >= REG_A0 && num <= REG_A7;
}

bool isGeneralReg(RegName name) {
const auto num = int8_t(name);
return num >= 0 && num < 16;
return num >= REG_D0 && num <= REG_A7;
}

bool isFloatReg(RegName name) {
const auto num = int8_t(name);
return num >= REG_FP0 && num <= REG_FP7;
}

bool isFloatControlReg(RegName name) {
const auto num = int8_t(name);
return num >= REG_FPCR && num <= REG_FPIAR;
}

Config::opcode_t encodeGeneralRegNo(RegName name) {
return int8_t(name) & 7;
}

Config::opcode_t encodeFloatRegNo(RegName name) {
return int8_t(name) & 7;
}

uint8_t encodeGeneralRegPos(RegName name) {
return uint8_t(name);
}

uint8_t encodeFloatRegPos(RegName name) {
return REG_FP7 - int8_t(name);
}

uint8_t encodeFloatControlRegPos(RegName name) {
return REG_FPIAR - int8_t(name) + 10;
}

RegName decodeGeneralReg(uint8_t regno) {
return RegName(regno & 0xF);
}
Expand Down Expand Up @@ -168,11 +190,15 @@ char sizeSuffix(OprSize size) {
} // namespace reg

Config::opcode_t EaMc68000::encodeMode(AddrMode mode) {
if (mode == M_IMFLT)
mode = M_IMDAT;
const auto m = static_cast<uint8_t>(mode);
return m >= 8 ? 7 : m;
}

Config::opcode_t EaMc68000::encodeRegNo(AddrMode mode, RegName reg) {
if (mode == M_IMFLT)
mode = M_IMDAT;
const auto m = static_cast<uint8_t>(mode);
if (m < 8)
return reg::encodeGeneralRegNo(reg);
Expand Down
5 changes: 5 additions & 0 deletions src/reg_mc68000.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,13 @@ StrBuffer &outRegName(StrBuffer &out, RegName name);
bool isDataReg(RegName name);
bool isAddrReg(RegName name);
bool isGeneralReg(RegName name);
bool isFloatReg(RegName name);
bool isFloatControlReg(RegName name);
Config::opcode_t encodeGeneralRegNo(RegName name);
Config::opcode_t encodeFloatRegNo(RegName name);
uint8_t encodeGeneralRegPos(RegName name);
uint8_t encodeFloatRegPos(RegName name);
uint8_t encodeFloatControlRegPos(RegName name);
RegName decodeGeneralReg(uint8_t regno);
RegName decodeDataReg(uint8_t regno);
RegName decodeAddrReg(uint8_t regno);
Expand Down
142 changes: 30 additions & 112 deletions src/table_mc68000.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1187,103 +1187,6 @@ static constexpr uint8_t MC68881_TRAP_INDEX[] PROGMEM = {
40, // TEXT_FTRAPUN
72, // TEXT_FTRAPUN
104, // TEXT_FTRAPUN

1, // TEXT_FTRAPEQ
33, // TEXT_FTRAPEQ
65, // TEXT_FTRAPEQ
0, // TEXT_FTRAPF
32, // TEXT_FTRAPF
64, // TEXT_FTRAPF
19, // TEXT_FTRAPGE
51, // TEXT_FTRAPGE
83, // TEXT_FTRAPGE
22, // TEXT_FTRAPGL
54, // TEXT_FTRAPGL
86, // TEXT_FTRAPGL
23, // TEXT_FTRAPGLE
55, // TEXT_FTRAPGLE
87, // TEXT_FTRAPGLE
18, // TEXT_FTRAPGT
50, // TEXT_FTRAPGT
82, // TEXT_FTRAPGT
21, // TEXT_FTRAPLE
53, // TEXT_FTRAPLE
85, // TEXT_FTRAPLE
20, // TEXT_FTRAPLT
52, // TEXT_FTRAPLT
84, // TEXT_FTRAPLT
14, // TEXT_FTRAPNE
46, // TEXT_FTRAPNE
78, // TEXT_FTRAPNE
28, // TEXT_FTRAPNGE
60, // TEXT_FTRAPNGE
92, // TEXT_FTRAPNGE
25, // TEXT_FTRAPNGL
57, // TEXT_FTRAPNGL
89, // TEXT_FTRAPNGL
24, // TEXT_FTRAPNGLE
56, // TEXT_FTRAPNGLE
88, // TEXT_FTRAPNGLE
29, // TEXT_FTRAPNGT
61, // TEXT_FTRAPNGT
93, // TEXT_FTRAPNGT
26, // TEXT_FTRAPNLE
58, // TEXT_FTRAPNLE
90, // TEXT_FTRAPNLE
27, // TEXT_FTRAPNLT
59, // TEXT_FTRAPNLT
91, // TEXT_FTRAPNLT
3, // TEXT_FTRAPOGE
35, // TEXT_FTRAPOGE
67, // TEXT_FTRAPOGE
6, // TEXT_FTRAPOGL
38, // TEXT_FTRAPOGL
70, // TEXT_FTRAPOGL
2, // TEXT_FTRAPOGT
34, // TEXT_FTRAPOGT
66, // TEXT_FTRAPOGT
5, // TEXT_FTRAPOLE
37, // TEXT_FTRAPOLE
69, // TEXT_FTRAPOLE
4, // TEXT_FTRAPOLT
36, // TEXT_FTRAPOLT
68, // TEXT_FTRAPOLT
7, // TEXT_FTRAPOR
39, // TEXT_FTRAPOR
71, // TEXT_FTRAPOR
17, // TEXT_FTRAPSEQ
49, // TEXT_FTRAPSEQ
81, // TEXT_FTRAPSEQ
16, // TEXT_FTRAPSF
48, // TEXT_FTRAPSF
80, // TEXT_FTRAPSF
30, // TEXT_FTRAPSNE
62, // TEXT_FTRAPSNE
94, // TEXT_FTRAPSNE
31, // TEXT_FTRAPST
63, // TEXT_FTRAPST
95, // TEXT_FTRAPST
15, // TEXT_FTRAPT
47, // TEXT_FTRAPT
79, // TEXT_FTRAPT
9, // TEXT_FTRAPUEQ
41, // TEXT_FTRAPUEQ
73, // TEXT_FTRAPUEQ
11, // TEXT_FTRAPUGE
43, // TEXT_FTRAPUGE
75, // TEXT_FTRAPUGE
10, // TEXT_FTRAPUGT
42, // TEXT_FTRAPUGT
74, // TEXT_FTRAPUGT
13, // TEXT_FTRAPULE
45, // TEXT_FTRAPULE
77, // TEXT_FTRAPULE
12, // TEXT_FTRAPULT
44, // TEXT_FTRAPULT
76, // TEXT_FTRAPULT
8, // TEXT_FTRAPUN
40, // TEXT_FTRAPUN
72, // TEXT_FTRAPUN
};
// clang-format on

Expand Down Expand Up @@ -1334,7 +1237,7 @@ static const Fpu *fpu(FpuType fpuType) {
return Fpu::search(fpuType, ARRAY_RANGE(FPU_TABLE));
}

static bool acceptMode(AddrMode opr, AddrMode table) {
static bool acceptMode(AddrMode opr, AddrMode table, OprSize size) {
if (opr == table)
return true;
if (opr == M_DREG)
Expand All @@ -1352,36 +1255,51 @@ static bool acceptMode(AddrMode opr, AddrMode table) {
if (opr == M_PDEC)
return table == M_RADDR || table == M_RDATA || table == M_WADDR || table == M_WDATA ||
table == M_RMEM || table == M_WMEM || table == M_DADDR;
if (opr == M_LABEL)
return table == M_REL16 || table == M_REL8 || table == M_REL32;
if (opr == M_PCDSP || opr == M_PCIDX)
return table == M_RADDR || table == M_RDATA || table == M_RMEM || table == M_JADDR ||
table == M_IADDR;
if (opr == M_IMDAT)
return table == M_RADDR || table == M_RDATA || table == M_IMBIT || table == M_IM3 ||
table == M_IM8 || table == M_IMVEC || table == M_IMDSP || table == M_IMROM;
if (opr == M_LABEL)
return table == M_REL16 || table == M_REL8;
if (opr == M_IMFLT)
return table == M_RDATA && size == SZ_FDAT;
if (opr == M_FPREG)
return table == M_FPMLT;
if (opr == M_FPCR || opr == M_FPSR || opr == M_FPIAR)
return table == M_FCMLT;
return false;
}

static bool acceptSize(InsnSize insn, OprSize opr, InsnSize table) {
if (insn == InsnSize(opr))
static bool acceptSize(const AsmInsn &insn, const Entry::Flags &flags) {
const auto insnSize = insn.insnSize();
const auto opr = flags.oprSize();
if (insnSize == InsnSize(opr))
return true;
if (insn == ISZ_BYTE)
return opr == SZ_DATA;
if (insn == ISZ_WORD)
return opr == SZ_DATA || opr == SZ_ADDR || opr == SZ_ADR8;
if (insn == ISZ_LONG)
return opr == SZ_DATA || opr == SZ_ADDR || opr == SZ_ADR8;
if (insn == ISZ_NONE)
return opr == SZ_WORD || opr == SZ_DATA || opr == SZ_ADDR || opr == SZ_ADR8 ||
const auto src = flags.src();
if (src == M_REL8 || src == M_REL16 || src == M_REL32 || flags.dst() == M_REL16)
return insnSize == ISZ_NONE || insnSize == ISZ_BYTE || insnSize == ISZ_SNGL ||
insnSize == ISZ_WORD || insnSize == ISZ_LONG || insnSize == ISZ_XTND;
if (insnSize == ISZ_BYTE)
return opr == SZ_DATA || opr == SZ_FDAT;
if (insnSize == ISZ_WORD || insnSize == ISZ_LONG)
return opr == SZ_DATA || opr == SZ_ADDR || opr == SZ_ADR8 || opr == SZ_FDAT;
if (insnSize == ISZ_SNGL || insnSize == ISZ_DUBL || insnSize == ISZ_XTND ||
insnSize == ISZ_PBCD)
return opr == SZ_FDAT;
if (insnSize == ISZ_NONE) {
const auto table = flags.insnSize();
return opr == SZ_DATA || opr == SZ_ADDR || opr == SZ_ADR8 || opr == SZ_WORD ||
table == ISZ_NONE || table == ISZ_FIXD;
}
return false;
}

static bool acceptModes(AsmInsn &insn, const Entry *entry) {
const auto table = entry->flags();
return acceptMode(insn.srcOp.mode, table.src()) && acceptMode(insn.dstOp.mode, table.dst()) &&
acceptSize(insn.insnSize(), table.oprSize(), table.insnSize());
return acceptMode(insn.srcOp.mode, table.src(), table.oprSize()) &&
acceptMode(insn.dstOp.mode, table.dst(), table.oprSize()) && acceptSize(insn, table);
}

Error TableMc68000::searchName(const CpuSpec &cpuSpec, AsmInsn &insn) const {
Expand Down
Loading

0 comments on commit b006206

Please sign in to comment.