Fix more 6809 instructions
authorNick Downing <nick@ndcode.org>
Sun, 31 Jul 2022 07:21:36 +0000 (17:21 +1000)
committerNick Downing <nick@ndcode.org>
Sun, 31 Jul 2022 10:09:46 +0000 (20:09 +1000)
cpu_6809.c
cpu_6809.h
decode_6809_pre.sed

index 8c2457e..e131a9e 100644 (file)
@@ -1022,7 +1022,7 @@ void cpu_6809_execute(struct cpu_6809 *self) {
     cpu_6809_rts(self);
     break;
   case 0x3a:
-    cpu_6809_add_word(self, CPU_6809_EA_X, self->regs.byte.b);
+    cpu_6809_abx(self);
     break;
   case 0x3b:
     cpu_6809_rti(self);
index ef4de8b..610ec5c 100644 (file)
@@ -213,22 +213,22 @@ static ALWAYS_INLINE int cpu_6809_fetch_word(struct cpu_6809 *self) {
   return data | cpu_6809_fetch_byte(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);
+static ALWAYS_INLINE void cpu_6809_push_byte(struct cpu_6809 *self, uint16_t *sp, int data) {
+  cpu_6809_write_byte(self, --*sp, data);
 }
 
-static ALWAYS_INLINE void cpu_6809_push_word(struct cpu_6809 *self, int data) {
-  cpu_6809_push_byte(self, data & 0xff);
-  cpu_6809_push_byte(self, data >> 8);
+static ALWAYS_INLINE void cpu_6809_push_word(struct cpu_6809 *self, uint16_t *sp, int data) {
+  cpu_6809_push_byte(self, sp, data & 0xff);
+  cpu_6809_push_byte(self, sp, data >> 8);
 }
 
-static ALWAYS_INLINE int cpu_6809_pop_byte(struct cpu_6809 *self) {
-  return cpu_6809_read_byte(self, self->regs.word.s++);
+static ALWAYS_INLINE int cpu_6809_pop_byte(struct cpu_6809 *self, uint16_t *sp) {
+  return cpu_6809_read_byte(self, (*sp)++);
 }
 
-static ALWAYS_INLINE int cpu_6809_pop_word(struct cpu_6809 *self) {
-  int data = cpu_6809_pop_byte(self) << 8;
-  return data | cpu_6809_pop_byte(self);
+static ALWAYS_INLINE int cpu_6809_pop_word(struct cpu_6809 *self, uint16_t *sp) {
+  int data = cpu_6809_pop_byte(self, sp) << 8;
+  return data | cpu_6809_pop_byte(self, sp);
 }
 
 // effective address calculation
@@ -249,6 +249,10 @@ static ALWAYS_INLINE int cpu_6809_ea_direct(struct cpu_6809 *self) {
 }
 
 // instruction execute
+static ALWAYS_INLINE void cpu_6809_abx(struct cpu_6809 *self) {
+  self->regs.word.x += self->regs.byte.b;
+}
+
 static ALWAYS_INLINE void cpu_6809_adc(struct cpu_6809 *self, int lvalue, int rvalue) {
   int data = cpu_6809_read_byte(self, lvalue);
 
@@ -282,16 +286,14 @@ static ALWAYS_INLINE void cpu_6809_add_byte(struct cpu_6809 *self, int lvalue, i
 static ALWAYS_INLINE void cpu_6809_add_word(struct cpu_6809 *self, int lvalue, int rvalue) {
   int data = cpu_6809_read_word(self, lvalue);
 
-  int result0 = (data & 0xfff) + (rvalue & 0xfff);
-  int result1 = result0 + (data & 0x7000) + (rvalue & 0x7000);
-  int result2 = result1 + (data & 0x8000) + (rvalue & 0x8000);
+  int result0 = (data & 0x7fff) + (rvalue & 0x7fff);
+  int result1 = result0 + (data & 0x8000) + (rvalue & 0x8000);
 
-  cpu_6809_write_word(self, lvalue, result2 & 0xffff);
-  self->regs.bit.hf = result0 >> 12;
-  self->regs.bit.nf = (result2 >> 15) & 1;
-  self->regs.bit.zf = (result2 & 0xffff) == 0;
-  self->regs.bit.vf = ((result1 >> 15) ^ (result2 >> 16)) & 1;
-  self->regs.bit.cf = result2 >> 16;
+  cpu_6809_write_word(self, lvalue, result1 & 0xffff);
+  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;
 }
 
 static ALWAYS_INLINE void cpu_6809_and(struct cpu_6809 *self, int lvalue, int rvalue) {
@@ -327,7 +329,6 @@ static ALWAYS_INLINE void cpu_6809_asr(struct cpu_6809 *self, int lvalue) {
   cpu_6809_write_byte(self, lvalue, result >> 1);
   self->regs.bit.nf = result >> 8;
   self->regs.bit.zf = (result & 0xfe) == 0;
-  self->regs.bit.vf = (result ^ (result >> 8)) & 1;
   self->regs.bit.cf = result & 1;
 }
 
@@ -347,7 +348,7 @@ static ALWAYS_INLINE void cpu_6809_bra(struct cpu_6809 *self, bool pred, int lva
 }
 
 static ALWAYS_INLINE void cpu_6809_bsr(struct cpu_6809 *self, int lvalue) {
-  cpu_6809_push_word(self, self->regs.word.pc);
+  cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.pc);
   self->cycles += ((self->regs.word.pc & 0xff) + (lvalue & 0xff)) >> 8;
   self->regs.word.pc += lvalue;
 }
@@ -393,11 +394,11 @@ static ALWAYS_INLINE void cpu_6809_com(struct cpu_6809 *self, int lvalue) {
 }
 
 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);
-  cpu_6809_push_byte(self, self->regs.byte.a);
-  cpu_6809_push_byte(self, self->regs.byte.b);
-  cpu_6809_push_byte(self, self->regs.byte.cc);
+  cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.pc);
+  cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.x);
+  cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.a);
+  cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.b);
+  cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.cc);
   self->regs.bit.wai_flag = true;
 }
 
@@ -513,7 +514,7 @@ static ALWAYS_INLINE void cpu_6809_jmp(struct cpu_6809 *self, int lvalue) {
 }
 
 static ALWAYS_INLINE void cpu_6809_jsr(struct cpu_6809 *self, int lvalue) {
-  cpu_6809_push_word(self, self->regs.word.pc);
+  cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.pc);
   self->regs.word.pc = lvalue;
 }
 
@@ -525,7 +526,7 @@ static ALWAYS_INLINE void cpu_6809_lbra(struct cpu_6809 *self, bool pred, int lv
 }
 
 static ALWAYS_INLINE void cpu_6809_lbsr(struct cpu_6809 *self, int lvalue) {
-  cpu_6809_push_word(self, self->regs.word.pc);
+  cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.pc);
   self->cycles += ((self->regs.word.pc & 0xff) + (lvalue & 0xff)) >> 8;
   self->regs.word.pc += lvalue;
 }
@@ -565,7 +566,6 @@ static ALWAYS_INLINE void cpu_6809_lsr(struct cpu_6809 *self, int lvalue) {
   cpu_6809_write_byte(self, lvalue, result >> 1);
   self->regs.bit.nf = result >> 8;
   self->regs.bit.zf = (result & 0xfe) == 0;
-  self->regs.bit.vf = (result ^ (result >> 8)) & 1;
   self->regs.bit.cf = result & 1;
 }
 
@@ -604,67 +604,51 @@ 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) {
   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(
+  if (postbyte & 0x80)
+    cpu_6809_push_word(self, &sp, self->regs.word.pc);
+  if (postbyte & 0x40)
+    cpu_6809_push_word(
       self,
-      sp,
+      &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 & 0x20)
+    cpu_6809_push_word(self, &sp, self->regs.word.y);
+  if (postbyte & 0x10)
+    cpu_6809_push_word(self, &sp, self->regs.word.x);
   if (postbyte & 8)
-    cpu_6809_write_byte(self, --sp, self->regs.byte.dp);
+    cpu_6809_push_byte(self, &sp, self->regs.byte.dp);
   if (postbyte & 4)
-    cpu_6809_write_byte(self, --sp, self->regs.byte.b);
+    cpu_6809_push_byte(self, &sp, self->regs.byte.b);
   if (postbyte & 2)
-    cpu_6809_write_byte(self, --sp, self->regs.byte.a);
+    cpu_6809_push_byte(self, &sp, self->regs.byte.a);
   if (postbyte & 1)
-    cpu_6809_write_byte(self, --sp, self->regs.byte.cc);
+    cpu_6809_push_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) {
   uint16_t sp = cpu_6809_read_word(self, lvalue);
   if (postbyte & 1)
-    self->regs.byte.cc = cpu_6809_read_byte(self, sp++);
+    self->regs.byte.cc = cpu_6809_pop_byte(self, &sp);
   if (postbyte & 2)
-    self->regs.byte.a = cpu_6809_read_byte(self, sp++);
+    self->regs.byte.a = cpu_6809_pop_byte(self, &sp);
   if (postbyte & 4)
-    self->regs.byte.b = cpu_6809_read_byte(self, sp++);
+    self->regs.byte.b = cpu_6809_pop_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) {
+    self->regs.byte.dp = cpu_6809_pop_byte(self, &sp);
+  if (postbyte & 0x10)
+    self->regs.word.x = cpu_6809_pop_word(self, &sp);
+  if (postbyte & 0x20)
+    self->regs.word.y = cpu_6809_pop_word(self, &sp);
+  if (postbyte & 0x40)
     cpu_6809_write_word(
       self,
       lvalue ^ (CPU_6809_EA_U ^ CPU_6809_EA_S),
-      cpu_6809_read_word(self, sp)
+      cpu_6809_pop_word(self, &sp)
     );
-    sp += 2;
-  }
-  if (postbyte & 0x80) {
-    self->regs.word.pc = cpu_6809_read_word(self, sp);
-    sp += 2;
-  }
+  if (postbyte & 0x80)
+    self->regs.word.pc = cpu_6809_pop_word(self, &sp);
   cpu_6809_write_word(self, lvalue, sp);
 }
 
@@ -686,20 +670,19 @@ static ALWAYS_INLINE void cpu_6809_ror(struct cpu_6809 *self, int lvalue) {
 
   self->regs.bit.nf = result >> 8;
   self->regs.bit.zf = (result & 0x1fe) == 0;
-  self->regs.bit.vf = (result ^ (result >> 8)) & 1;
   self->regs.bit.cf = result & 1;
 }
 
 static ALWAYS_INLINE void cpu_6809_rti(struct cpu_6809 *self) {
-  self->regs.byte.cc = cpu_6809_pop_byte(self);
-  self->regs.byte.b = cpu_6809_pop_byte(self);
-  self->regs.byte.a = cpu_6809_pop_byte(self);
-  self->regs.word.x = cpu_6809_pop_word(self);
-  self->regs.word.pc = cpu_6809_pop_word(self);
+  self->regs.byte.cc = cpu_6809_pop_byte(self, &self->regs.word.s);
+  self->regs.byte.b = cpu_6809_pop_byte(self, &self->regs.word.s);
+  self->regs.byte.a = cpu_6809_pop_byte(self, &self->regs.word.s);
+  self->regs.word.x = cpu_6809_pop_word(self, &self->regs.word.s);
+  self->regs.word.pc = cpu_6809_pop_word(self, &self->regs.word.s);
 }
 
 static ALWAYS_INLINE void cpu_6809_rts(struct cpu_6809 *self) {
-  self->regs.word.pc = cpu_6809_pop_word(self);
+  self->regs.word.pc = cpu_6809_pop_word(self, &self->regs.word.s);
 }
 
 static ALWAYS_INLINE void cpu_6809_sbc(struct cpu_6809 *self, int lvalue, int rvalue) {
@@ -762,21 +745,21 @@ static ALWAYS_INLINE void cpu_6809_sub_word(struct cpu_6809 *self, int lvalue, i
 }
 
 static ALWAYS_INLINE void cpu_6809_swi(struct cpu_6809 *self) {
-  cpu_6809_push_word(self, self->regs.word.pc);
-  cpu_6809_push_word(self, self->regs.word.x);
-  cpu_6809_push_byte(self, self->regs.byte.a);
-  cpu_6809_push_byte(self, self->regs.byte.b);
-  cpu_6809_push_byte(self, self->regs.byte.cc);
+  cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.pc);
+  cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.x);
+  cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.a);
+  cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.b);
+  cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.cc);
   self->regs.word.pc = cpu_6809_read_word(self, CPU_6809_SWI_VECTOR);
   self->regs.bit._if = true;
 }
 
 static ALWAYS_INLINE void cpu_6809_swi_n(struct cpu_6809 *self, int n) {
-  cpu_6809_push_word(self, self->regs.word.pc);
-  cpu_6809_push_word(self, self->regs.word.x);
-  cpu_6809_push_byte(self, self->regs.byte.a);
-  cpu_6809_push_byte(self, self->regs.byte.b);
-  cpu_6809_push_byte(self, self->regs.byte.cc);
+  cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.pc);
+  cpu_6809_push_word(self, &self->regs.word.s, self->regs.word.x);
+  cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.a);
+  cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.b);
+  cpu_6809_push_byte(self, &self->regs.word.s, self->regs.byte.cc);
   self->regs.word.pc = cpu_6809_read_word(self, CPU_6809_SWI_VECTOR);
   self->regs.bit._if = true;
 }
index 9a02ad6..dc4e99a 100644 (file)
@@ -14,7 +14,7 @@ s/^lbr a/lbra/
 s/^\(inc\|dec\)/\1_byte/
 s/^\(ld\)\([abdusxy]\)/\1 \2/
 s/^\(st\)\([abdusxy]\)/\1 \2/
-s/^ab\([ax]\)/add \1 b/
+s/^aba/add a b/
 s/^sba/sub a b/
 s/^cba/cmp a b/
 s/^\(swi\)\([23]\)/\1_n \2/