Fix many 6809 instructions
authorNick Downing <nick@ndcode.org>
Sun, 31 Jul 2022 04:38:29 +0000 (14:38 +1000)
committerNick Downing <nick@ndcode.org>
Sun, 31 Jul 2022 10:09:46 +0000 (20:09 +1000)
cpu_6800.c
cpu_6800.h
cpu_6809.c
cpu_6809.h
decode_6800.py
decode_6809.py
decode_6809_pre.sed

index 228a045..fcffc2a 100644 (file)
@@ -453,7 +453,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_and(self, CPU_6800_EA_A, cpu_6800_fetch_byte(self));
     break;
   case 0x85:
-    cpu_6800_bit(self, CPU_6800_EA_A, cpu_6800_fetch_byte(self));
+    cpu_6800_bit(self, self->regs.byte.a, cpu_6800_fetch_byte(self));
     break;
   case 0x86:
     cpu_6800_ld_byte(self, CPU_6800_EA_A, cpu_6800_fetch_byte(self));
@@ -501,7 +501,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_and(self, CPU_6800_EA_A, cpu_6800_read_byte(self, cpu_6800_ea_direct(self)));
     break;
   case 0x95:
-    cpu_6800_bit(self, CPU_6800_EA_A, cpu_6800_read_byte(self, cpu_6800_ea_direct(self)));
+    cpu_6800_bit(self, self->regs.byte.a, cpu_6800_read_byte(self, cpu_6800_ea_direct(self)));
     break;
   case 0x96:
     cpu_6800_ld_byte(self, CPU_6800_EA_A, cpu_6800_read_byte(self, cpu_6800_ea_direct(self)));
@@ -549,7 +549,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_and(self, CPU_6800_EA_A, cpu_6800_read_byte(self, cpu_6800_ea_direct_indexed(self, self->regs.word.x)));
     break;
   case 0xa5:
-    cpu_6800_bit(self, CPU_6800_EA_A, cpu_6800_read_byte(self, cpu_6800_ea_direct_indexed(self, self->regs.word.x)));
+    cpu_6800_bit(self, self->regs.byte.a, cpu_6800_read_byte(self, cpu_6800_ea_direct_indexed(self, self->regs.word.x)));
     break;
   case 0xa6:
     cpu_6800_ld_byte(self, CPU_6800_EA_A, cpu_6800_read_byte(self, cpu_6800_ea_direct_indexed(self, self->regs.word.x)));
@@ -597,7 +597,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_and(self, CPU_6800_EA_A, cpu_6800_read_byte(self, cpu_6800_ea_extended(self)));
     break;
   case 0xb5:
-    cpu_6800_bit(self, CPU_6800_EA_A, cpu_6800_read_byte(self, cpu_6800_ea_extended(self)));
+    cpu_6800_bit(self, self->regs.byte.a, cpu_6800_read_byte(self, cpu_6800_ea_extended(self)));
     break;
   case 0xb6:
     cpu_6800_ld_byte(self, CPU_6800_EA_A, cpu_6800_read_byte(self, cpu_6800_ea_extended(self)));
@@ -645,7 +645,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_and(self, CPU_6800_EA_B, cpu_6800_fetch_byte(self));
     break;
   case 0xc5:
-    cpu_6800_bit(self, CPU_6800_EA_B, cpu_6800_fetch_byte(self));
+    cpu_6800_bit(self, self->regs.byte.b, cpu_6800_fetch_byte(self));
     break;
   case 0xc6:
     cpu_6800_ld_byte(self, CPU_6800_EA_B, cpu_6800_fetch_byte(self));
@@ -693,7 +693,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_and(self, CPU_6800_EA_B, cpu_6800_read_byte(self, cpu_6800_ea_direct(self)));
     break;
   case 0xd5:
-    cpu_6800_bit(self, CPU_6800_EA_B, cpu_6800_read_byte(self, cpu_6800_ea_direct(self)));
+    cpu_6800_bit(self, self->regs.byte.b, cpu_6800_read_byte(self, cpu_6800_ea_direct(self)));
     break;
   case 0xd6:
     cpu_6800_ld_byte(self, CPU_6800_EA_B, cpu_6800_read_byte(self, cpu_6800_ea_direct(self)));
@@ -741,7 +741,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_and(self, CPU_6800_EA_B, cpu_6800_read_byte(self, cpu_6800_ea_direct_indexed(self, self->regs.word.x)));
     break;
   case 0xe5:
-    cpu_6800_bit(self, CPU_6800_EA_B, cpu_6800_read_byte(self, cpu_6800_ea_direct_indexed(self, self->regs.word.x)));
+    cpu_6800_bit(self, self->regs.byte.b, cpu_6800_read_byte(self, cpu_6800_ea_direct_indexed(self, self->regs.word.x)));
     break;
   case 0xe6:
     cpu_6800_ld_byte(self, CPU_6800_EA_B, cpu_6800_read_byte(self, cpu_6800_ea_direct_indexed(self, self->regs.word.x)));
@@ -789,7 +789,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_and(self, CPU_6800_EA_B, cpu_6800_read_byte(self, cpu_6800_ea_extended(self)));
     break;
   case 0xf5:
-    cpu_6800_bit(self, CPU_6800_EA_B, cpu_6800_read_byte(self, cpu_6800_ea_extended(self)));
+    cpu_6800_bit(self, self->regs.byte.b, cpu_6800_read_byte(self, cpu_6800_ea_extended(self)));
     break;
   case 0xf6:
     cpu_6800_ld_byte(self, CPU_6800_EA_B, cpu_6800_read_byte(self, cpu_6800_ea_extended(self)));
index 5f9b09b..bd6387d 100644 (file)
@@ -320,6 +320,15 @@ static ALWAYS_INLINE void cpu_6800_cmp_byte(struct cpu_6800 *self, int rvalue0,
   self->regs.bit.cf = (result1 >> 8) & 1;
 }
 
+static ALWAYS_INLINE void cpu_6800_cmp_word(struct cpu_6800 *self, int rvalue0, int rvalue1) {
+  int result0 = (rvalue0 & 0x7fff) - (rvalue1 & 0x7fff);
+  int result1 = result0 + (rvalue0 & 0x8000) - (rvalue1 & 0x8000);
+
+  self->regs.bit.nf = (result1 >> 15) & 1;
+  self->regs.bit.zf = (result1 & 0xffff) == 0;
+  self->regs.bit.vf = ((result0 >> 15) ^ (result1 >> 16)) & 1;
+}
+
 static ALWAYS_INLINE void cpu_6800_com(struct cpu_6800 *self, int lvalue) {
   int result = cpu_6800_read_byte(self, lvalue) ^ 0xff;
 
@@ -330,15 +339,6 @@ static ALWAYS_INLINE void cpu_6800_com(struct cpu_6800 *self, int lvalue) {
   self->regs.bit.cf = true;
 }
 
-static ALWAYS_INLINE void cpu_6800_cmp_word(struct cpu_6800 *self, int rvalue0, int rvalue1) {
-  int result0 = (rvalue0 & 0x7fff) - (rvalue1 & 0x7fff);
-  int result1 = result0 + (rvalue0 & 0x8000) - (rvalue1 & 0x8000);
-
-  self->regs.bit.nf = (result1 >> 15) & 1;
-  self->regs.bit.zf = (result1 & 0xffff) == 0;
-  self->regs.bit.vf = ((result0 >> 15) ^ (result1 >> 16)) & 1;
-}
-
 static ALWAYS_INLINE void cpu_6800_daa(struct cpu_6800 *self) {
   int correction = 0;
   if (self->regs.bit.hf || (self->regs.byte.a & 0xf) >= 0xa)
index b8f7a7f..8c2457e 100644 (file)
@@ -3,6 +3,45 @@
 #include <string.h>
 #include "cpu_6809.h"
 
+// tables
+int cpu_6809_ea_src[0x10][2] = {
+  {CPU_6809_EA_D, CPU_6809_EA_D + 1},
+  {CPU_6809_EA_X, CPU_6809_EA_X + 1},
+  {CPU_6809_EA_Y, CPU_6809_EA_Y + 1},
+  {CPU_6809_EA_U, CPU_6809_EA_U + 1},
+  {CPU_6809_EA_S, CPU_6809_EA_S + 1},
+  {CPU_6809_EA_PC, CPU_6809_EA_PC + 1},
+  {CPU_6809_EA_M1, CPU_6809_EA_M1},
+  {CPU_6809_EA_M1, CPU_6809_EA_M1},
+  {CPU_6809_EA_A, CPU_6809_EA_M1},
+  {CPU_6809_EA_B, CPU_6809_EA_M1},
+  {CPU_6809_EA_CC, CPU_6809_EA_CC},
+  {CPU_6809_EA_DP, CPU_6809_EA_DP},
+  {CPU_6809_EA_M1, CPU_6809_EA_M1},
+  {CPU_6809_EA_M1, CPU_6809_EA_M1},
+  {CPU_6809_EA_M1, CPU_6809_EA_M1},
+  {CPU_6809_EA_M1, CPU_6809_EA_M1},
+}; 
+
+int cpu_6809_ea_dest[0x10][2] = {
+  {CPU_6809_EA_D, CPU_6809_EA_D + 1},
+  {CPU_6809_EA_X, CPU_6809_EA_X + 1},
+  {CPU_6809_EA_Y, CPU_6809_EA_Y + 1},
+  {CPU_6809_EA_U, CPU_6809_EA_U + 1},
+  {CPU_6809_EA_S, CPU_6809_EA_S + 1},
+  {CPU_6809_EA_PC, CPU_6809_EA_PC + 1},
+  {CPU_6809_EA_SINK, CPU_6809_EA_SINK},
+  {CPU_6809_EA_SINK, CPU_6809_EA_SINK},
+  {CPU_6809_EA_A, CPU_6809_EA_SINK},
+  {CPU_6809_EA_B, CPU_6809_EA_SINK},
+  {CPU_6809_EA_CC, CPU_6809_EA_SINK},
+  {CPU_6809_EA_DP, CPU_6809_EA_SINK},
+  {CPU_6809_EA_SINK, CPU_6809_EA_SINK},
+  {CPU_6809_EA_SINK, CPU_6809_EA_SINK},
+  {CPU_6809_EA_SINK, CPU_6809_EA_SINK},
+  {CPU_6809_EA_SINK, CPU_6809_EA_SINK},
+}; 
+
 // initialization
 void cpu_6809_init(
   struct cpu_6809 *self,
@@ -12,6 +51,7 @@ void cpu_6809_init(
   void *write_byte_context
 ) {
   memset(self, 0, sizeof(struct cpu_6809));
+  self->regs.byte.m1 = 0xff;
   self->read_byte = read_byte;
   self->read_byte_context = read_byte_context;
   self->write_byte = write_byte;
@@ -21,6 +61,7 @@ void cpu_6809_init(
 void cpu_6809_reset(struct cpu_6809 *self) {
   self->regs.word.pc = cpu_6809_read_word(self, CPU_6809_RESET_VECTOR);
   self->regs.byte.iflags = 0;
+  self->regs.bit.ff = true;
   self->regs.bit._if = true;
 }
 
@@ -846,7 +887,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_inc_byte(self, cpu_6809_ea_direct(self));
     break;
   case 0x0d:
-    cpu_6809_cmp_byte(self, cpu_6809_read_byte(self, cpu_6809_ea_direct(self)), 0);
+    cpu_6809_tst(self, cpu_6809_read_byte(self, cpu_6809_ea_direct(self)));
     break;
   case 0x0e:
     cpu_6809_jmp(self, cpu_6809_ea_direct(self));
@@ -951,10 +992,10 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_bra(self, self->regs.bit.nf || self->regs.bit.vf || self->regs.bit.zf, cpu_6809_ea_relative(self));
     break;
   case 0x30:
-    cpu_6809_lea(self, CPU_6809_EA_X, cpu_6809_addressing_mode(self));
+    cpu_6809_lea_zf(self, CPU_6809_EA_X, cpu_6809_addressing_mode(self));
     break;
   case 0x31:
-    cpu_6809_lea(self, CPU_6809_EA_Y, cpu_6809_addressing_mode(self));
+    cpu_6809_lea_zf(self, CPU_6809_EA_Y, cpu_6809_addressing_mode(self));
     break;
   case 0x32:
     cpu_6809_lea(self, CPU_6809_EA_S, cpu_6809_addressing_mode(self));
@@ -1038,7 +1079,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_inc_byte(self, CPU_6809_EA_A);
     break;
   case 0x4d:
-    cpu_6809_cmp_byte(self, self->regs.byte.a, 0);
+    cpu_6809_tst(self, self->regs.byte.a);
     break;
   case 0x4e:
     cpu_6809_illegal_opcode(self);
@@ -1086,7 +1127,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_inc_byte(self, CPU_6809_EA_B);
     break;
   case 0x5d:
-    cpu_6809_cmp_byte(self, self->regs.byte.b, 0);
+    cpu_6809_tst(self, self->regs.byte.b);
     break;
   case 0x5e:
     cpu_6809_illegal_opcode(self);
@@ -1134,7 +1175,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_inc_byte(self, cpu_6809_addressing_mode(self));
     break;
   case 0x6d:
-    cpu_6809_cmp_byte(self, cpu_6809_read_byte(self, cpu_6809_addressing_mode(self)), 0);
+    cpu_6809_tst(self, cpu_6809_read_byte(self, cpu_6809_addressing_mode(self)));
     break;
   case 0x6e:
     cpu_6809_jmp(self, cpu_6809_addressing_mode(self));
@@ -1182,7 +1223,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_inc_byte(self, cpu_6809_ea_extended(self));
     break;
   case 0x7d:
-    cpu_6809_cmp_byte(self, cpu_6809_read_byte(self, cpu_6809_ea_extended(self)), 0);
+    cpu_6809_tst(self, cpu_6809_read_byte(self, cpu_6809_ea_extended(self)));
     break;
   case 0x7e:
     cpu_6809_jmp(self, cpu_6809_ea_extended(self));
@@ -1206,7 +1247,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_and(self, CPU_6809_EA_A, cpu_6809_fetch_byte(self));
     break;
   case 0x85:
-    cpu_6809_bit(self, CPU_6809_EA_A, cpu_6809_fetch_byte(self));
+    cpu_6809_bit(self, self->regs.byte.a, cpu_6809_fetch_byte(self));
     break;
   case 0x86:
     cpu_6809_ld_byte(self, CPU_6809_EA_A, cpu_6809_fetch_byte(self));
@@ -1254,7 +1295,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_and(self, CPU_6809_EA_A, cpu_6809_read_byte(self, cpu_6809_ea_direct(self)));
     break;
   case 0x95:
-    cpu_6809_bit(self, CPU_6809_EA_A, cpu_6809_read_byte(self, cpu_6809_ea_direct(self)));
+    cpu_6809_bit(self, self->regs.byte.a, cpu_6809_read_byte(self, cpu_6809_ea_direct(self)));
     break;
   case 0x96:
     cpu_6809_ld_byte(self, CPU_6809_EA_A, cpu_6809_read_byte(self, cpu_6809_ea_direct(self)));
@@ -1302,7 +1343,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_and(self, CPU_6809_EA_A, cpu_6809_read_byte(self, cpu_6809_addressing_mode(self)));
     break;
   case 0xa5:
-    cpu_6809_bit(self, CPU_6809_EA_A, cpu_6809_read_byte(self, cpu_6809_addressing_mode(self)));
+    cpu_6809_bit(self, self->regs.byte.a, cpu_6809_read_byte(self, cpu_6809_addressing_mode(self)));
     break;
   case 0xa6:
     cpu_6809_ld_byte(self, CPU_6809_EA_A, cpu_6809_read_byte(self, cpu_6809_addressing_mode(self)));
@@ -1350,7 +1391,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_and(self, CPU_6809_EA_A, cpu_6809_read_byte(self, cpu_6809_ea_extended(self)));
     break;
   case 0xb5:
-    cpu_6809_bit(self, CPU_6809_EA_A, cpu_6809_read_byte(self, cpu_6809_ea_extended(self)));
+    cpu_6809_bit(self, self->regs.byte.a, cpu_6809_read_byte(self, cpu_6809_ea_extended(self)));
     break;
   case 0xb6:
     cpu_6809_ld_byte(self, CPU_6809_EA_A, cpu_6809_read_byte(self, cpu_6809_ea_extended(self)));
@@ -1398,7 +1439,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_and(self, CPU_6809_EA_B, cpu_6809_fetch_byte(self));
     break;
   case 0xc5:
-    cpu_6809_bit(self, CPU_6809_EA_B, cpu_6809_fetch_byte(self));
+    cpu_6809_bit(self, self->regs.byte.b, cpu_6809_fetch_byte(self));
     break;
   case 0xc6:
     cpu_6809_ld_byte(self, CPU_6809_EA_B, cpu_6809_fetch_byte(self));
@@ -1446,7 +1487,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_and(self, CPU_6809_EA_B, cpu_6809_read_byte(self, cpu_6809_ea_direct(self)));
     break;
   case 0xd5:
-    cpu_6809_bit(self, CPU_6809_EA_B, cpu_6809_read_byte(self, cpu_6809_ea_direct(self)));
+    cpu_6809_bit(self, self->regs.byte.b, cpu_6809_read_byte(self, cpu_6809_ea_direct(self)));
     break;
   case 0xd6:
     cpu_6809_ld_byte(self, CPU_6809_EA_B, cpu_6809_read_byte(self, cpu_6809_ea_direct(self)));
@@ -1494,7 +1535,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_and(self, CPU_6809_EA_B, cpu_6809_read_byte(self, cpu_6809_addressing_mode(self)));
     break;
   case 0xe5:
-    cpu_6809_bit(self, CPU_6809_EA_B, cpu_6809_read_byte(self, cpu_6809_addressing_mode(self)));
+    cpu_6809_bit(self, self->regs.byte.b, cpu_6809_read_byte(self, cpu_6809_addressing_mode(self)));
     break;
   case 0xe6:
     cpu_6809_ld_byte(self, CPU_6809_EA_B, cpu_6809_read_byte(self, cpu_6809_addressing_mode(self)));
@@ -1542,7 +1583,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_and(self, CPU_6809_EA_B, cpu_6809_read_byte(self, cpu_6809_ea_extended(self)));
     break;
   case 0xf5:
-    cpu_6809_bit(self, CPU_6809_EA_B, cpu_6809_read_byte(self, cpu_6809_ea_extended(self)));
+    cpu_6809_bit(self, self->regs.byte.b, cpu_6809_read_byte(self, cpu_6809_ea_extended(self)));
     break;
   case 0xf6:
     cpu_6809_ld_byte(self, CPU_6809_EA_B, cpu_6809_read_byte(self, cpu_6809_ea_extended(self)));
index e48fce8..ef4de8b 100644 (file)
 #define CPU_6809_REG_CC_BIT_C 0
 
 // special memory locations (negative address)
-#define CPU_6809_EA_PC (-0xe)
-#define CPU_6809_EA_D (-0xc)
-#define CPU_6809_EA_A (-0xc)
-#define CPU_6809_EA_B (-0xb)
-#define CPU_6809_EA_U (-0xa)
-#define CPU_6809_EA_S (-8)
-#define CPU_6809_EA_X (-6)
-#define CPU_6809_EA_Y (-4)
-#define CPU_6809_EA_P (-2)
-#define CPU_6809_EA_IFLAGS (-1)
+// m1 and sink are used to implement undefined registers for TFR/EXG
+#define CPU_6809_EA_PC (-0x12)
+#define CPU_6809_EA_D (-0x10)
+#define CPU_6809_EA_A (-0x10)
+#define CPU_6809_EA_B (-0xf)
+#define CPU_6809_EA_U (-0xe)
+#define CPU_6809_EA_S (-0xc)
+#define CPU_6809_EA_X (-0xa)
+#define CPU_6809_EA_Y (-8)
+#define CPU_6809_EA_CC (-6)
+#define CPU_6809_EA_DP (-5)
+#define CPU_6809_EA_IFLAGS (-4)
+#define CPU_6809_EA_M1 (-3)
+#define CPU_6809_EA_SINK (-2)
 
 // registers, in same order as special memory locations, but reversed on
 // little endian hardware where special memory address will be complemented
@@ -55,10 +59,14 @@ union cpu_6809_regs {
     uint8_t zf : 1;
     uint8_t vf : 1;
     uint8_t cf : 1;
+    uint8_t _fill_dp;
     uint8_t _fill_iflags : 5;
     uint8_t wai_flag : 1;
     uint8_t irq_pending : 1;
     uint8_t nmi_pending : 1;
+    uint8_t _fill_m1;
+    uint8_t _fill_sink;
+    uint8_t _pad;
   } bit;
   struct {
     uint16_t _fill_pc;
@@ -69,7 +77,11 @@ union cpu_6809_regs {
     uint16_t _fill_x;
     uint16_t _fill_y;
     uint8_t cc;
+    uint8_t dp;
     uint8_t iflags;
+    uint8_t m1;
+    uint8_t sink;
+    uint8_t _pad;
   } byte;
   struct {
     uint16_t pc;
@@ -79,15 +91,23 @@ union cpu_6809_regs {
     uint16_t x;
     uint16_t y;
     uint8_t _fill_cc;
+    uint8_t _fill_dp;
     uint8_t _fill_iflags;
+    uint8_t _fill_m1;
+    uint8_t _fill_sink;
+    uint8_t _pad;
   } word;
-  uint8_t mem_be[0xe];
+  uint8_t mem_be[0x10];
 #else
   struct {
+    uint8_t _pad;
+    uint8_t _fill_sink;
+    uint8_t _fill_m1;
     uint8_t nmi_pending : 1;
     uint8_t irq_pending : 1;
     uint8_t wai_flag : 1;
     uint8_t _fill_iflags : 5;
+    uint8_t _fill_dp;
     uint8_t cf : 1;
     uint8_t vf : 1;
     uint8_t zf : 1;
@@ -104,7 +124,11 @@ union cpu_6809_regs {
     uint16_t _fill_pc;
   } bit;
   struct {
+    uint8_t _pad;
+    uint8_t sink;
+    uint8_t m1;
     uint8_t iflags;
+    uint8_t dp;
     uint8_t cc;
     uint16_t _fill_y;
     uint16_t _fill_x;
@@ -115,7 +139,11 @@ union cpu_6809_regs {
     uint16_t _fill_pc;
   } byte;
   struct {
+    uint8_t _pad;
+    uint8_t _fill_sink;
+    uint8_t _fill_m1;
     uint8_t _fill_iflags;
+    uint8_t _fill_dp;
     uint8_t _fill_cc;
     uint16_t y;
     uint16_t x;
@@ -124,7 +152,7 @@ union cpu_6809_regs {
     uint16_t d;
     uint16_t pc;
   } word;
-  uint8_t mem_le[0xe];
+  uint8_t mem_le[0x10];
 #endif
 };
 
@@ -137,6 +165,10 @@ struct cpu_6809 {
   union cpu_6809_regs regs;
 };
 
+// tables
+extern int cpu_6809_ea_src[0x10][2];
+extern int cpu_6809_ea_dest[0x10][2];
 // memory or special memory access
 static ALWAYS_INLINE int cpu_6809_read_byte(struct cpu_6809 *self, int addr) {
   if (addr < 0)
@@ -182,7 +214,7 @@ static ALWAYS_INLINE int cpu_6809_fetch_word(struct cpu_6809 *self) {
 }
 
 static ALWAYS_INLINE void cpu_6809_push_byte(struct cpu_6809 *self, int data) {
-  cpu_6809_write_byte(self, self->regs.word.s--, data);
+  cpu_6809_write_byte(self, --self->regs.word.s, data);
 }
 
 static ALWAYS_INLINE void cpu_6809_push_word(struct cpu_6809 *self, int data) {
@@ -191,7 +223,7 @@ static ALWAYS_INLINE void cpu_6809_push_word(struct cpu_6809 *self, int data) {
 }
 
 static ALWAYS_INLINE int cpu_6809_pop_byte(struct cpu_6809 *self) {
-  return cpu_6809_read_byte(self, ++self->regs.word.s);
+  return cpu_6809_read_byte(self, self->regs.word.s++);
 }
 
 static ALWAYS_INLINE int cpu_6809_pop_word(struct cpu_6809 *self) {
@@ -340,6 +372,16 @@ static ALWAYS_INLINE void cpu_6809_cmp_byte(struct cpu_6809 *self, int rvalue0,
   self->regs.bit.cf = (result1 >> 8) & 1;
 }
 
+static ALWAYS_INLINE void cpu_6809_cmp_word(struct cpu_6809 *self, int rvalue0, int rvalue1) {
+  int result0 = (rvalue0 & 0x7fff) - (rvalue1 & 0x7fff);
+  int result1 = result0 + (rvalue0 & 0x8000) - (rvalue1 & 0x8000);
+
+  self->regs.bit.nf = (result1 >> 15) & 1;
+  self->regs.bit.zf = (result1 & 0xffff) == 0;
+  self->regs.bit.vf = ((result0 >> 15) ^ (result1 >> 16)) & 1;
+  self->regs.bit.cf = (result1 >> 16) & 1;
+}
+
 static ALWAYS_INLINE void cpu_6809_com(struct cpu_6809 *self, int lvalue) {
   int result = cpu_6809_read_byte(self, lvalue) ^ 0xff;
 
@@ -350,15 +392,6 @@ static ALWAYS_INLINE void cpu_6809_com(struct cpu_6809 *self, int lvalue) {
   self->regs.bit.cf = true;
 }
 
-static ALWAYS_INLINE void cpu_6809_cmp_word(struct cpu_6809 *self, int rvalue0, int rvalue1) {
-  int result0 = (rvalue0 & 0x7fff) - (rvalue1 & 0x7fff);
-  int result1 = result0 + (rvalue0 & 0x8000) - (rvalue1 & 0x8000);
-
-  self->regs.bit.nf = (result1 >> 15) & 1;
-  self->regs.bit.zf = (result1 & 0xffff) == 0;
-  self->regs.bit.vf = ((result0 >> 15) ^ (result1 >> 16)) & 1;
-}
-
 static ALWAYS_INLINE void cpu_6809_cwai(struct cpu_6809 *self, int rvalue) {
   cpu_6809_push_word(self, self->regs.word.pc);
   cpu_6809_push_word(self, self->regs.word.x);
@@ -427,7 +460,18 @@ static ALWAYS_INLINE void cpu_6809_eor(struct cpu_6809 *self, int lvalue, int rv
 }
 
 static ALWAYS_INLINE void cpu_6809_exg(struct cpu_6809 *self, int postbyte) {
-  abort();
+  int reg0 = postbyte >> 4;
+  int reg1 = postbyte & 0xf;
+
+  int rvalue00 = cpu_6809_read_byte(self, cpu_6809_ea_src[reg0][0]);
+  int rvalue10 = cpu_6809_read_byte(self, cpu_6809_ea_src[reg1][0]);
+  cpu_6809_write_byte(self, cpu_6809_ea_dest[reg1][0], rvalue00);
+  cpu_6809_write_byte(self, cpu_6809_ea_dest[reg0][0], rvalue10);
+
+  int rvalue01 = cpu_6809_read_byte(self, cpu_6809_ea_src[reg0][1]);
+  int rvalue11 = cpu_6809_read_byte(self, cpu_6809_ea_src[reg1][1]);
+  cpu_6809_write_byte(self, cpu_6809_ea_dest[reg1][1], rvalue01);
+  cpu_6809_write_byte(self, cpu_6809_ea_dest[reg0][1], rvalue11);
 }
 
 static ALWAYS_INLINE void cpu_6809_illegal_opcode(struct cpu_6809 *self) {
@@ -504,10 +548,12 @@ static ALWAYS_INLINE void cpu_6809_ld_byte(struct cpu_6809 *self, int lvalue, in
 
 static ALWAYS_INLINE void cpu_6809_lea(struct cpu_6809 *self, int lvalue0, int lvalue1) {
   cpu_6809_write_word(self, lvalue0, lvalue1);
+}
+
+static ALWAYS_INLINE void cpu_6809_lea_zf(struct cpu_6809 *self, int lvalue0, int lvalue1) {
+  cpu_6809_write_word(self, lvalue0, lvalue1);
 
-  self->regs.bit.nf = (lvalue1 >> 15) & 1;
   self->regs.bit.zf = lvalue1 == 0;
-  self->regs.bit.vf = false;
 }
 
 static ALWAYS_INLINE void cpu_6809_lsr(struct cpu_6809 *self, int lvalue) {
@@ -557,11 +603,69 @@ static ALWAYS_INLINE void cpu_6809_orcc(struct cpu_6809 *self, int rvalue) {
 }
 
 static ALWAYS_INLINE void cpu_6809_psh(struct cpu_6809 *self, int lvalue, int postbyte) {
-  abort();
+  uint16_t sp = cpu_6809_read_word(self, lvalue);
+  if (postbyte & 0x80) {
+    sp -= 2;
+    cpu_6809_write_word(self, sp, self->regs.word.pc);
+  }
+  if (postbyte & 0x40) {
+    sp -= 2;
+    cpu_6809_write_word(
+      self,
+      sp,
+      cpu_6809_read_word(self, lvalue ^ (CPU_6809_EA_U ^ CPU_6809_EA_S))
+    );
+  }
+  if (postbyte & 0x20) {
+    sp -= 2;
+    cpu_6809_write_word(self, sp, self->regs.word.y);
+  }
+  if (postbyte & 0x10) {
+    sp -= 2;
+    cpu_6809_write_word(self, sp, self->regs.word.x);
+  }
+  if (postbyte & 8)
+    cpu_6809_write_byte(self, --sp, self->regs.byte.dp);
+  if (postbyte & 4)
+    cpu_6809_write_byte(self, --sp, self->regs.byte.b);
+  if (postbyte & 2)
+    cpu_6809_write_byte(self, --sp, self->regs.byte.a);
+  if (postbyte & 1)
+    cpu_6809_write_byte(self, --sp, self->regs.byte.cc);
+  cpu_6809_write_word(self, lvalue, sp);
 }
 
 static ALWAYS_INLINE void cpu_6809_pul(struct cpu_6809 *self, int lvalue, int postbyte) {
-  abort();
+  uint16_t sp = cpu_6809_read_word(self, lvalue);
+  if (postbyte & 1)
+    self->regs.byte.cc = cpu_6809_read_byte(self, sp++);
+  if (postbyte & 2)
+    self->regs.byte.a = cpu_6809_read_byte(self, sp++);
+  if (postbyte & 4)
+    self->regs.byte.b = cpu_6809_read_byte(self, sp++);
+  if (postbyte & 8)
+    self->regs.byte.dp = cpu_6809_read_byte(self, sp++);
+  if (postbyte & 0x10) {
+    self->regs.word.x = cpu_6809_read_word(self, sp);
+    sp += 2;
+  }
+  if (postbyte & 0x20) {
+    self->regs.word.y = cpu_6809_read_word(self, sp);
+    sp += 2;
+  }
+  if (postbyte & 0x40) {
+    cpu_6809_write_word(
+      self,
+      lvalue ^ (CPU_6809_EA_U ^ CPU_6809_EA_S),
+      cpu_6809_read_word(self, sp)
+    );
+    sp += 2;
+  }
+  if (postbyte & 0x80) {
+    self->regs.word.pc = cpu_6809_read_word(self, sp);
+    sp += 2;
+  }
+  cpu_6809_write_word(self, lvalue, sp);
 }
 
 static ALWAYS_INLINE void cpu_6809_rol(struct cpu_6809 *self, int lvalue) {
@@ -682,9 +786,26 @@ static ALWAYS_INLINE void cpu_6809_sync(struct cpu_6809 *self) {
 }
 
 static ALWAYS_INLINE void cpu_6809_tfr(struct cpu_6809 *self, int postbyte) {
-  abort();
+  int reg0 = postbyte >> 4;
+  int reg1 = postbyte & 0xf;
+
+  cpu_6809_write_byte(
+    self,
+    cpu_6809_ea_dest[reg1][0],
+    cpu_6809_read_byte(self, cpu_6809_ea_src[reg0][0])
+  );
+  cpu_6809_write_byte(
+    self,
+    cpu_6809_ea_dest[reg1][1],
+    cpu_6809_read_byte(self, cpu_6809_ea_src[reg0][1])
+  );
 }
 
+static ALWAYS_INLINE void cpu_6809_tst(struct cpu_6809 *self, int rvalue) {
+  self->regs.bit.nf = (rvalue >> 7) & 1;
+  self->regs.bit.zf = rvalue == 0;
+  self->regs.bit.vf = false;
+}
 
 // prototypes
 void cpu_6809_init(
index 0de9923..e054963 100755 (executable)
@@ -7,7 +7,7 @@ rvalue_opcodes = {
   'add': (-1, 0),
   'adc': (-1, 0),
   'and': (-1, 0),
-  'bit': (-1, 0),
+  'bit': (-2, 0),
   'cmp': (-2, 0),
   'cmp_byte': (-2, 0),
   'eor': (-1, 0),
index 7d4d42d..067235a 100755 (executable)
@@ -38,7 +38,7 @@ rvalue_opcodes = {
   'adc': (-1, 0),
   'and': (-1, 0),
   'andcc': (-1, 0),
-  'bit': (-1, 0),
+  'bit': (-2, 0),
   'cmp': (-2, 0),
   'cmp_byte': (-2, 0),
   'cwai': (-1, 0),
@@ -49,6 +49,7 @@ rvalue_opcodes = {
   'sub': (-1, 0),
   'sbc': (-1, 0),
   'st': (-2, -1),
+  'tst': (-1, 0),
 }
 
 # if it is in byte_opcodes it is treated as byte and has no suffix
@@ -59,7 +60,6 @@ byte_opcodes = {
   'asl',
   'asr',
   'bit',
-  'cl',
   'clr',
   'cmp_byte',
   'com',
@@ -74,7 +74,7 @@ byte_opcodes = {
   'rol',
   'ror',
   'sbc',
-  'se',
+  'tst',
 }
 # if any operand is in byte_operands it is treated as byte and has suffix
 # in this case another operand which is word can upgrade the size to word
@@ -108,6 +108,7 @@ word_opcodes = {
   'lbra',
   'lbsr',
   'lea',
+  'lea_zf',
   'psh',
   'pul',
   'tfr',
@@ -174,7 +175,7 @@ for i in range(0x100):
 
   print(f'  case 0x{i:02x}:')
   instr = line.split()
-  assert instr[:2] == ['lea', 'x']
+  assert instr[:2] == ['lea_zf', 'x']
   mode = instr[2]
 
   if mode == '???':
index fa29ba4..9a02ad6 100644 (file)
@@ -7,18 +7,14 @@ s/^b\(hi\|ls\|cc\|cs\|ne\|eq\|vc\|vs\|pl\|mi\|ge\|lt\|gt\|le\)/bra \1/
 s/^lbra/lbra true/
 s/^lbrn/lbra false/
 s/^lb\(hi\|ls\|cc\|cs\|ne\|eq\|vc\|vs\|pl\|mi\|ge\|lt\|gt\|le\)/lbra \1/
+s/^\(lea\)\([xy]\)/\1_zf \2/
 s/^\(or\)\([ab]\)/\1 \2/
 s/^\([a-z][a-z][a-z]\)\([abdusxy]\)/\1 \2/
 s/^lbr a/lbra/
 s/^\(inc\|dec\)/\1_byte/
-s/^de\([us]\)/dec \1/
-s/^de\([xy]\)/dec_word_zf \1/
-s/^in\([us]\)/inc \1/
-s/^in\([xy]\)/inc_word_zf \1/
 s/^\(ld\)\([abdusxy]\)/\1 \2/
 s/^\(st\)\([abdusxy]\)/\1 \2/
 s/^ab\([ax]\)/add \1 b/
 s/^sba/sub a b/
 s/^cba/cmp a b/
-s/^tst \(.*\)/cmp_byte \1 0/
 s/^\(swi\)\([23]\)/\1_n \2/