In 6800, implement daa and interrupt system (untested), and clean up a bit
authorNick Downing <nick@ndcode.org>
Mon, 25 Jul 2022 12:36:30 +0000 (22:36 +1000)
committerNick Downing <nick@ndcode.org>
Mon, 25 Jul 2022 12:36:30 +0000 (22:36 +1000)
cpu_6800.c
cpu_6800.h
decode_6800.sed

index b159ea4..a7c69b6 100644 (file)
@@ -29,24 +29,25 @@ void cpu_6800_reset(struct cpu_6800 *self) {
 void cpu_6800_execute(struct cpu_6800 *self) {
   if (self->regs.bit.nmi_pending) {
     self->regs.bit.nmi_pending = false;
+    if (!self->regs.bit.wai_flag)
+      cpu_6800_wai(self);
     self->regs.bit.wai_flag = false;
-    cpu_6800_swi(self, CPU_6800_NMI_VECTOR);
+    self->regs.word.pc = cpu_6800_read_word(self, CPU_6800_NMI_VECTOR);
+    self->regs.bit._if = true;
     return;
   }
 
-  if (self->regs.bit.irq_pending) {
-    if (self->regs.bit._if == 0) {
-      self->regs.bit.irq_pending = false;
-      self->regs.bit.wai_flag = false;
-      cpu_6800_swi(self, CPU_6800_IRQ_VECTOR);
-      return;
-    }
-    if (self->regs.bit.wai_flag) {
-      self->regs.bit.irq_pending = false;
-      self->regs.bit.wai_flag = false;
-    }
+  if (self->regs.bit.irq_pending && !self->regs.bit._if) {
+    self->regs.bit.irq_pending = false;
+    if (!self->regs.bit.wai_flag)
+      cpu_6800_wai(self);
+    self->regs.bit.wai_flag = false;
+    self->regs.word.pc = cpu_6800_read_word(self, CPU_6800_IRQ_VECTOR);
+    self->regs.bit._if = true;
+    return;
   }
-  else if (self->regs.bit.wai_flag) {
+
+  if (self->regs.bit.wai_flag) {
     ++self->cycles;
     return;
   }
@@ -242,7 +243,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_wai(self);
     break;
   case 0x3f:
-    cpu_6800_swi(self, CPU_6800_SWI_VECTOR);
+    cpu_6800_swi(self);
     break;
   case 0x40:
     cpu_6800_neg(self, CPU_6800_EA_A);
@@ -269,7 +270,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_asr(self, CPU_6800_EA_A);
     break;
   case 0x48:
-    cpu_6800_lsl(self, CPU_6800_EA_A);
+    cpu_6800_asl(self, CPU_6800_EA_A);
     break;
   case 0x49:
     cpu_6800_rol(self, CPU_6800_EA_A);
@@ -317,7 +318,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_asr(self, CPU_6800_EA_B);
     break;
   case 0x58:
-    cpu_6800_lsl(self, CPU_6800_EA_B);
+    cpu_6800_asl(self, CPU_6800_EA_B);
     break;
   case 0x59:
     cpu_6800_rol(self, CPU_6800_EA_B);
@@ -365,7 +366,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_asr(self, cpu_6800_ea_direct_indexed(self, self->regs.word.x));
     break;
   case 0x68:
-    cpu_6800_lsl(self, cpu_6800_ea_direct_indexed(self, self->regs.word.x));
+    cpu_6800_asl(self, cpu_6800_ea_direct_indexed(self, self->regs.word.x));
     break;
   case 0x69:
     cpu_6800_rol(self, cpu_6800_ea_direct_indexed(self, self->regs.word.x));
@@ -413,7 +414,7 @@ void cpu_6800_execute(struct cpu_6800 *self) {
     cpu_6800_asr(self, cpu_6800_ea_extended(self));
     break;
   case 0x78:
-    cpu_6800_lsl(self, cpu_6800_ea_extended(self));
+    cpu_6800_asl(self, cpu_6800_ea_extended(self));
     break;
   case 0x79:
     cpu_6800_rol(self, cpu_6800_ea_extended(self));
index 0360052..b15bd1f 100644 (file)
@@ -252,6 +252,17 @@ static ALWAYS_INLINE void cpu_6800_and(struct cpu_6800 *self, int lvalue, int rv
   self->regs.bit.vf = false;
 }
 
+static ALWAYS_INLINE void cpu_6800_asl(struct cpu_6800 *self, int lvalue) {
+  int result = cpu_6800_read_byte(self, lvalue) << 1;
+  ++self->cycles;
+
+  cpu_6800_write_byte(self, lvalue, result & 0xff);
+  self->regs.bit.nf = (result >> 7) & 1;
+  self->regs.bit.zf = (result & 0xff) == 0;
+  self->regs.bit.vf = ((result >> 7) ^ (result >> 8)) & 1;
+  self->regs.bit.cf = result >> 8;
+}
+
 static ALWAYS_INLINE void cpu_6800_asr(struct cpu_6800 *self, int lvalue) {
   int data = cpu_6800_read_byte(self, lvalue);
 
@@ -268,13 +279,9 @@ static ALWAYS_INLINE void cpu_6800_asr(struct cpu_6800 *self, int lvalue) {
 static ALWAYS_INLINE void cpu_6800_bit(struct cpu_6800 *self, int rvalue0, int rvalue1) {
   int result = rvalue0 & rvalue1;
 
-  self->regs.bit.zf = result == 0;
   self->regs.bit.nf = result >> 7;
-}
-
-static ALWAYS_INLINE void cpu_6800_bit_imm(struct cpu_6800 *self, int rvalue) {
-  int result = self->regs.byte.a & rvalue;
   self->regs.bit.zf = result == 0;
+  self->regs.bit.vf = false;
 }
 
 static ALWAYS_INLINE void cpu_6800_bra(struct cpu_6800 *self, bool pred, int lvalue) {
@@ -333,20 +340,22 @@ static ALWAYS_INLINE void cpu_6800_cp(struct cpu_6800 *self, int rvalue0, int rv
 }
 
 static ALWAYS_INLINE void cpu_6800_daa(struct cpu_6800 *self) {
-  abort();
-}
-
-static ALWAYS_INLINE void cpu_6800_des(struct cpu_6800 *self) {
-  --self->regs.word.s;
-  ++self->cycles;
-}
+  int correction = 0;
+  if (self->regs.bit.hf || (self->regs.byte.a & 0xf) >= 0xa)
+    correction = 6;
+  if (self->regs.bit.cf || self->regs.byte.a >= 0x9a) {
+    correction |= 0x60;
+    self->regs.bit.cf = true;
+  }
 
-static ALWAYS_INLINE void cpu_6800_dex(struct cpu_6800 *self) {
-  int result = (self->regs.word.x - 1) & 0xffff;
-  ++self->cycles;
+  int result0 = (self->regs.byte.a & 0x7f) + correction;
+  int result1 = result0 + (self->regs.byte.a & 0x80);
 
-  self->regs.word.x = result;
-  self->regs.bit.zf = result == 0;
+  self->regs.byte.a = result1 & 0xff;
+  self->regs.bit.nf = (result1 >> 7) & 1;
+  self->regs.bit.zf = (result1 & 0xff) == 0;
+  self->regs.bit.vf = ((result0 >> 7) ^ (result1 >> 8)) & 1;
+  //self->regs.bit.cf |= result1 >> 8;
 }
 
 static ALWAYS_INLINE void cpu_6800_dec(struct cpu_6800 *self, int lvalue) {
@@ -362,6 +371,19 @@ static ALWAYS_INLINE void cpu_6800_dec(struct cpu_6800 *self, int lvalue) {
   self->regs.bit.vf = ((result0 >> 7) ^ (result1 >> 8)) & 1;
 }
 
+static ALWAYS_INLINE void cpu_6800_des(struct cpu_6800 *self) {
+  --self->regs.word.s;
+  ++self->cycles;
+}
+
+static ALWAYS_INLINE void cpu_6800_dex(struct cpu_6800 *self) {
+  int result = (self->regs.word.x - 1) & 0xffff;
+  ++self->cycles;
+
+  self->regs.word.x = result;
+  self->regs.bit.zf = result == 0;
+}
+
 static ALWAYS_INLINE void cpu_6800_eor(struct cpu_6800 *self, int lvalue, int rvalue) {
   int result = cpu_6800_read_byte(self, lvalue) ^ rvalue;
 
@@ -375,19 +397,6 @@ static ALWAYS_INLINE void cpu_6800_ill(struct cpu_6800 *self) {
   abort();
 }
 
-static ALWAYS_INLINE void cpu_6800_ins(struct cpu_6800 *self) {
-  ++self->regs.word.s;
-  ++self->cycles;
-}
-
-static ALWAYS_INLINE void cpu_6800_inx(struct cpu_6800 *self) {
-  int result = (self->regs.word.x + 1) & 0xffff;
-  ++self->cycles;
-
-  self->regs.word.x = result;
-  self->regs.bit.zf = result == 0;
-}
-
 static ALWAYS_INLINE void cpu_6800_inc(struct cpu_6800 *self, int lvalue) {
   int data = cpu_6800_read_byte(self, lvalue);
 
@@ -401,11 +410,26 @@ static ALWAYS_INLINE void cpu_6800_inc(struct cpu_6800 *self, int lvalue) {
   self->regs.bit.vf = ((result0 >> 7) ^ (result1 >> 8)) & 1;
 }
 
-static ALWAYS_INLINE void cpu_6800_swi(struct cpu_6800 *self, int lvalue) {
+static ALWAYS_INLINE void cpu_6800_ins(struct cpu_6800 *self) {
+  ++self->regs.word.s;
+  ++self->cycles;
+}
+
+static ALWAYS_INLINE void cpu_6800_inx(struct cpu_6800 *self) {
+  int result = (self->regs.word.x + 1) & 0xffff;
   ++self->cycles;
+
+  self->regs.word.x = result;
+  self->regs.bit.zf = result == 0;
+}
+
+static ALWAYS_INLINE void cpu_6800_swi(struct cpu_6800 *self) {
   cpu_6800_push_word(self, self->regs.word.pc);
+  cpu_6800_push_word(self, self->regs.word.x);
+  cpu_6800_push_byte(self, self->regs.byte.a);
+  cpu_6800_push_byte(self, self->regs.byte.b);
   cpu_6800_push_byte(self, self->regs.byte.p);
-  self->regs.word.pc = cpu_6800_read_word(self, lvalue);
+  self->regs.word.pc = cpu_6800_read_word(self, CPU_6800_SWI_VECTOR);
   self->regs.bit._if = true;
 }
 
@@ -434,17 +458,6 @@ static ALWAYS_INLINE void cpu_6800_lda(struct cpu_6800 *self, int lvalue, int rv
   self->regs.bit.vf = false;
 }
 
-static ALWAYS_INLINE void cpu_6800_lsl(struct cpu_6800 *self, int lvalue) {
-  int result = cpu_6800_read_byte(self, lvalue) << 1;
-  ++self->cycles;
-
-  cpu_6800_write_byte(self, lvalue, result & 0xff);
-  self->regs.bit.nf = (result >> 7) & 1;
-  self->regs.bit.zf = (result & 0xff) == 0;
-  self->regs.bit.vf = ((result >> 7) ^ (result >> 8)) & 1;
-  self->regs.bit.cf = result >> 8;
-}
-
 static ALWAYS_INLINE void cpu_6800_lsr(struct cpu_6800 *self, int lvalue) {
   int data = cpu_6800_read_byte(self, lvalue);
 
@@ -515,6 +528,9 @@ static ALWAYS_INLINE void cpu_6800_ror(struct cpu_6800 *self, int lvalue) {
 
 static ALWAYS_INLINE void cpu_6800_rti(struct cpu_6800 *self) {
   self->regs.byte.p = cpu_6800_pop_byte(self) | 0xc0;
+  self->regs.byte.b = cpu_6800_pop_byte(self);
+  self->regs.byte.a = cpu_6800_pop_byte(self);
+  self->regs.word.x = cpu_6800_pop_word(self);
   self->regs.word.pc = cpu_6800_pop_word(self);
 }
 
@@ -576,11 +592,6 @@ static ALWAYS_INLINE void cpu_6800_tpa(struct cpu_6800 *self) {
   self->regs.byte.a = self->regs.byte.p;
 }
 
-static ALWAYS_INLINE void cpu_6800_tst(struct cpu_6800 *self, int rvalue) {
-  self->regs.bit.zf = rvalue == 0;
-  self->regs.bit.nf = rvalue >> 7;
-}
-
 static ALWAYS_INLINE void cpu_6800_tsx(struct cpu_6800 *self) {
   self->regs.word.x = (self->regs.word.s + 1) & 0xffff;
 }
@@ -590,6 +601,11 @@ static ALWAYS_INLINE void cpu_6800_txs(struct cpu_6800 *self) {
 }
 
 static ALWAYS_INLINE void cpu_6800_wai(struct cpu_6800 *self) {
+  cpu_6800_push_word(self, self->regs.word.pc);
+  cpu_6800_push_word(self, self->regs.word.x);
+  cpu_6800_push_byte(self, self->regs.byte.a);
+  cpu_6800_push_byte(self, self->regs.byte.b);
+  cpu_6800_push_byte(self, self->regs.byte.p);
   self->regs.bit.wai_flag = true;
 }
 
index 666b40c..7c0ab02 100644 (file)
@@ -23,7 +23,7 @@ s/cpu_6800_cl\([cidv]\)(self/cpu_6800_cl(self, CPU_6800_REG_P_BIT_\1/
 s/cpu_6800_se\([cidv]\)(self/cpu_6800_se(self, CPU_6800_REG_P_BIT_\1/
 s/cpu_6800_cp\([xs]\)(self\(.*\)byte/cpu_6800_cp(self, self->regs.word.\1\2word/
 s/cpu_6800_cp\([xs]\)(self/cpu_6800_cp(self, self->regs.word.\1/
-s/cpu_6800_swi(self/cpu_6800_swi(self, CPU_6800_SWI_VECTOR/
+s/cpu_6800_lsl(self/cpu_6800_asl(self/
 s/cpu_6800_tst(self\(.*\));/cpu_6800_cmp(self\1, 0);/
 s/CPU_6800_EA_a/CPU_6800_EA_A/g
 s/CPU_6800_EA_b/CPU_6800_EA_B/g