From f478e6c1223cc8370fa51d44b9244ec25be99788 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Sun, 13 Feb 2022 20:20:59 -0400 Subject: igen: Start work on writing an instruction handler generator. This will make it easier in the long run to modify instructions, add new instructions, and move the opcode tables around. --- igen/sux-igen/inst.igen | 245 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 igen/sux-igen/inst.igen (limited to 'igen/sux-igen/inst.igen') diff --git a/igen/sux-igen/inst.igen b/igen/sux-igen/inst.igen new file mode 100644 index 0000000..791ad2c --- /dev/null +++ b/igen/sux-igen/inst.igen @@ -0,0 +1,245 @@ +#include "utils.igen" +#include "addr-modes.igen" + +%% + +(ad|sb|breg(in|de))c, and, (or|st|ld|t[bxy]|p[hl])a, xor, (ls|ro)[lr], mul, div, asr, cmp { + reg = &cpu->a; +} + +(ld|st|cp|in|de|ta|p[hl])b { + reg = &cpu->b; +} + +(ld|st|cp|in|de|t[ays]|p[hl])x { + reg = &cpu->x; +} + +(ld|st|cp|in|de|t[ax]|p[hl])y { + reg = &cpu->y; +} + +txs { + reg = &cpu->sp; +} + +cps, (cl|se)[cio], clv, b(po|n[ge]|[cv][sc]|eq|r[ak]), p[hl]p { + reg = &cpu->ps; +} + +ta[bxy] { + reg2 = &cpu->a; +} + +tba, ~breg(div) { + reg2 = &cpu->b; +} + +tx[ay], breg(div) { + reg2 = &cpu->x; +} + +ty[ax] { + reg2 = &cpu->y; +} + +tsx { + reg2 = &cpu->sp; +} + +ld[abxy] { + *reg = value; + update_flags_nz(value); +} + +st[abxy] { + value = *reg; + write(value, addr, rs); +} + +(in|de)[cbxy] { + if (addr_mode == impl) { + value = *reg; + } + if (inst.match[0] == in) { + ++value; + } else if (inst.match[0] == de) { + --value; + } + if (addr_mode != impl) { + msb = rs*8; + write(value, addr, rs); + } else { + *reg = value; + } + update_flags_nz(value); +} + +ph[abxyp] { + if (inst == php) { + rs = 0; + } + push(*reg, rs); +} + +pl[abxyp] { + if (inst == plp) { + rs = 0; + } + *reg = pull(rs); +} + +/* +ora, and, xor { + switch (inst) { + case and: sum = *reg & value; break; + case ora: sum = *reg | value; break; + case xor: sum = *reg ^ value; break; + } + *reg = sum; + update_flags_nz(sum); +} +*/ + +ora { + sum = *reg | value; + *reg = sum; + update_flags_nz(sum); +} + +and { + sum = *reg & value; + *reg = sum; + update_flags_nz(sum); +} + +xor { + sum = *reg ^ value; + *reg = sum; + update_flags_nz(sum); +} + +(se|cl)c { + cpu->ps.C = (inst == sec); +} + +(se|cl)i { + cpu->ps.I = (inst == sei); +} + +(se|cl)o { + if (ext == base && mode == base) { + cpu->ps.O = (inst == seo); + } +} + +clv { + cpu->ps.V = 0; +} + +cps { + cpu->ps = 0; +} + +b(po|ng) { + cpu->pc = jump(addr, cpu->pc, get_flag(inst, bpo, cpu->ps.N)); +} + +bc[sc] { + cpu->pc = jump(addr, cpu->pc, get_flag(inst, bcs, cpu->ps.C)); +} + +b(ne|eq) { + cpu->pc = jump(addr, cpu->pc, get_flag(inst, beq, cpu->ps.Z)); +} + +bv[sc] { + cpu->pc = jump(addr, cpu->pc, get_flag(inst, bvs, cpu->ps.V)); +} + +bra, j(mp|sr) { + if (inst == jsr) { + push(cpu->pc, (rs) ? rs : 7); + } + cpu->pc = jump(addr, cpu->pc, 1); +} + +intr(irq|nmi|reset), brk, wai { + if (inst == nmi) { + addr = 0xFFA0; + } else if (inst == reset) { + addr = 0xFFC0; + } else if (inst == irq) { + addr = 0xFFE0; + } else { + addr = 0xFFF0; + } + + if (inst != reset) { + if (!cpu->is_wait) { + push(cpu->pc, 7); + push(cpu->ps, 0); + cpu->ps.I = 1; + } + cpu->is_wait = (inst == wai); + } + if (inst != wai) { + addr = read(addr, 7); + cpu->pc = jump(addr, cpu->pc, 1); + } +} + +rt[si] { + if (inst == rti) { + cpu->ps = pull(0); + } + cpu->pc = pull(7); +} + +(ad|sb)c { + if (inst == sbc) { + value = ~value; + } + *reg = adc(*reg, value, cpu->ps.C); +} + +c(mp|p[bxy]) { + adc(*reg, ~value, 1); +} + +(asr|ls[lr]) { + if (inst == lsl) { + sum = (value < msb) ? shift(*reg, value, 0, <<) : 0; + cpu->ps.C = (*reg >> (msb-(value+!value))) & 1; + } else { + if (inst == asr) { + sign = -(uint64_t)(*reg >> (msb-1)) << (msb-1)-value; + } + sum = (value < msb) ? shift(*reg, value, sign, >>) : 0; + cpu->ps.C = (*reg >> (value-(value != 0))) & 1; + } +} + +ro[lr] { + if (inst == rol) { + rotate(sum, *reg, value, <<, >>, cpu->ps.C, cpu->ps.C << (value-1)); + cpu->ps.C = (*reg >> (msb-(value+!value))) & 1; + } else { + rotate(sum, *reg, value, >>, <<, cpu->ps.C << (msb-1), cpu->ps.C << (msb-value)); + cpu->ps.C = (*reg >> (value-(value != 0))) & 1; + } +} + +mul { + *reg = mul(*reg, value); +} + +div { + *reg = div(*reg, value, reg2); +} + +t(a[bxy]|ba|x[ays]|y[ax]|sx) { + *reg = *reg2; + update_flags_nz(*reg); +} +%% -- cgit v1.2.3-13-gbd6f