summaryrefslogtreecommitdiff
path: root/igen/sux-igen/inst.igen
diff options
context:
space:
mode:
Diffstat (limited to 'igen/sux-igen/inst.igen')
-rw-r--r--igen/sux-igen/inst.igen245
1 files changed, 245 insertions, 0 deletions
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);
+}
+%%