#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); } %%