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));
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)));
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)));
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)));
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));
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)));
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)));
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)));
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;
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)
#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,
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;
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;
}
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));
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));
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);
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);
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));
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));
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));
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)));
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)));
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)));
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));
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)));
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)));
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)));
#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
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;
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;
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;
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;
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;
uint16_t d;
uint16_t pc;
} word;
- uint8_t mem_le[0xe];
+ uint8_t mem_le[0x10];
#endif
};
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)
}
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) {
}
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) {
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;
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);
}
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) {
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) {
}
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) {
}
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(
'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),
'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),
'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
'asl',
'asr',
'bit',
- 'cl',
'clr',
'cmp_byte',
'com',
'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
'lbra',
'lbsr',
'lea',
+ 'lea_zf',
'psh',
'pul',
'tfr',
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 == '???':
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/