In Z80, rationalize block instructions, implement block I/O instructions
authorNick Downing <nick@ndcode.org>
Sat, 23 Jul 2022 07:09:30 +0000 (17:09 +1000)
committerNick Downing <nick@ndcode.org>
Sat, 23 Jul 2022 07:09:30 +0000 (17:09 +1000)
cpu_z80.h

index b5b4c2e..a2e5853 100644 (file)
--- a/cpu_z80.h
+++ b/cpu_z80.h
@@ -440,67 +440,41 @@ static ALWAYS_INLINE void cpu_z80_cp(struct cpu_z80 *self, int rvalue) {
 
 static ALWAYS_INLINE void cpu_z80_cpd(struct cpu_z80 *self) {
   int data = cpu_z80_read_byte(self, self->regs.word.hl--);
+  --self->regs.word.bc;
 
   int result0 = (self->regs.byte.a & 0xf) - (data & 0xf);
   int result1 = result0 + (self->regs.byte.a & 0xf0) - (data & 0xf0);
-  int result2 = (self->regs.word.bc - 1) & 0xffff;
 
-  self->regs.word.bc = result2;
   self->regs.bit.nf = true;
-  self->regs.bit.pvf = result2 != 0;
+  self->regs.bit.pvf = self->regs.word.bc != 0;
   self->regs.bit.hf = (result0 >> 4) & 1;
   self->regs.bit.zf = (result1 & 0xff) == 0;
   self->regs.bit.sf = (result1 >> 7) & 1;
 }
 
 static ALWAYS_INLINE void cpu_z80_cpdr(struct cpu_z80 *self) {
-  int data = cpu_z80_read_byte(self, self->regs.word.hl--);
-
-  int result0 = (self->regs.byte.a & 0xf) - (data & 0xf);
-  int result1 = result0 + (self->regs.byte.a & 0xf0) - (data & 0xf0);
-  int result2 = (self->regs.word.bc - 1) & 0xffff;
-
-  self->regs.word.bc = result2;
-  self->regs.bit.nf = true;
-  self->regs.bit.pvf = result2 != 0;
-  self->regs.bit.hf = (result0 >> 4) & 1;
-  self->regs.bit.zf = (result1 & 0xff) == 0;
-  self->regs.bit.sf = (result1 >> 7) & 1;
-
-  if ((result1 & 0xff) && result2)
+  cpu_z80_cpd(self);
+  if (!self->regs.bit.zf && self->regs.word.bc)
     self->regs.word.pc -= 2;
 }
 
 static ALWAYS_INLINE void cpu_z80_cpi(struct cpu_z80 *self) {
   int data = cpu_z80_read_byte(self, self->regs.word.hl++);
+  --self->regs.word.bc;
 
   int result0 = (self->regs.byte.a & 0xf) - (data & 0xf);
   int result1 = result0 + (self->regs.byte.a & 0xf0) - (data & 0xf0);
-  int result2 = (self->regs.word.bc - 1) & 0xffff;
 
-  self->regs.word.bc = result2;
   self->regs.bit.nf = true;
-  self->regs.bit.pvf = result2 != 0;
+  self->regs.bit.pvf = self->regs.word.bc != 0;
   self->regs.bit.hf = (result0 >> 4) & 1;
   self->regs.bit.zf = (result1 & 0xff) == 0;
   self->regs.bit.sf = (result1 >> 7) & 1;
 }
 
 static ALWAYS_INLINE void cpu_z80_cpir(struct cpu_z80 *self) {
-  int data = cpu_z80_read_byte(self, self->regs.word.hl++);
-
-  int result0 = (self->regs.byte.a & 0xf) - (data & 0xf);
-  int result1 = result0 + (self->regs.byte.a & 0xf0) - (data & 0xf0);
-  int result2 = (self->regs.word.bc - 1) & 0xffff;
-
-  self->regs.word.bc = result2;
-  self->regs.bit.nf = true;
-  self->regs.bit.pvf = result2 != 0;
-  self->regs.bit.hf = (result0 >> 4) & 1;
-  self->regs.bit.zf = (result1 & 0xff) == 0;
-  self->regs.bit.sf = (result1 >> 7) & 1;
-
-  if ((result1 & 0xff) && result2)
+  cpu_z80_cpi(self);
+  if (!self->regs.bit.zf && self->regs.word.bc)
     self->regs.word.pc -= 2;
 }
 
@@ -685,19 +659,39 @@ static ALWAYS_INLINE void cpu_z80_inc_word(struct cpu_z80 *self, int lvalue) {
 }
 
 static ALWAYS_INLINE void cpu_z80_ind(struct cpu_z80 *self) {
-  abort();
+  cpu_z80_write_byte(
+    self,
+    self->regs.word.hl--,
+    cpu_z80_in_byte(self, self->regs.word.bc)
+  );
+  --self->regs.byte.b;
+
+  self->regs.bit.nf = true;
+  self->regs.bit.zf = self->regs.byte.b != 0;
 }
 
 static ALWAYS_INLINE void cpu_z80_indr(struct cpu_z80 *self) {
-  abort();
+  cpu_z80_ind(self);
+  if (self->regs.byte.b)
+    self->regs.word.pc -= 2;
 }
 
 static ALWAYS_INLINE void cpu_z80_ini(struct cpu_z80 *self) {
-  abort();
+  cpu_z80_write_byte(
+    self,
+    self->regs.word.hl++,
+    cpu_z80_in_byte(self, self->regs.word.bc)
+  );
+  --self->regs.byte.b;
+
+  self->regs.bit.nf = true;
+  self->regs.bit.zf = self->regs.byte.b != 0;
 }
 
 static ALWAYS_INLINE void cpu_z80_inir(struct cpu_z80 *self) {
-  abort();
+  cpu_z80_ini(self);
+  if (self->regs.byte.b)
+    self->regs.word.pc -= 2;
 }
 
 static ALWAYS_INLINE void cpu_z80_jp(struct cpu_z80 *self, bool pred, int rvalue) {
@@ -719,56 +713,40 @@ static ALWAYS_INLINE void cpu_z80_ld_word(struct cpu_z80 *self, int lvalue, int
 }
 
 static ALWAYS_INLINE void cpu_z80_ldd(struct cpu_z80 *self) {
-  int data = cpu_z80_read_byte(self, self->regs.word.hl--);
-  cpu_z80_write_byte(self, self->regs.word.de--, data);
-
-  int result = (self->regs.word.bc - 1) & 0xffff;
+  cpu_z80_write_byte(
+    self,
+    self->regs.word.de++,
+    cpu_z80_read_byte(self, self->regs.word.hl--)
+  );
+  --self->regs.word.bc;
 
-  self->regs.word.bc = result;
   self->regs.bit.nf = false;
-  self->regs.bit.pvf = result != 0;
+  self->regs.bit.pvf = self->regs.word.bc != 0;
   self->regs.bit.hf = false;
 }
 
 static ALWAYS_INLINE void cpu_z80_lddr(struct cpu_z80 *self) {
-  int data = cpu_z80_read_byte(self, self->regs.word.hl--);
-  cpu_z80_write_byte(self, self->regs.word.de--, data);
-
-  int result = (self->regs.word.bc - 1) & 0xffff;
-
-  self->regs.word.bc = result;
-  self->regs.bit.nf = false;
-  self->regs.bit.pvf = result != 0;
-  self->regs.bit.hf = false;
-
-  if (result)
+  cpu_z80_ldd(self);
+  if (self->regs.word.bc)
     self->regs.word.pc -= 2;
 }
 
 static ALWAYS_INLINE void cpu_z80_ldi(struct cpu_z80 *self) {
-  int data = cpu_z80_read_byte(self, self->regs.word.hl++);
-  cpu_z80_write_byte(self, self->regs.word.de++, data);
+  cpu_z80_write_byte(
+    self,
+    self->regs.word.de++,
+    cpu_z80_read_byte(self, self->regs.word.hl++)
+  );
+  --self->regs.word.bc;
 
-  int result = (self->regs.word.bc - 1) & 0xffff;
-
-  self->regs.word.bc = result;
   self->regs.bit.nf = false;
-  self->regs.bit.pvf = result != 0;
+  self->regs.bit.pvf = self->regs.word.bc != 0;
   self->regs.bit.hf = false;
 }
 
 static ALWAYS_INLINE void cpu_z80_ldir(struct cpu_z80 *self) {
-  int data = cpu_z80_read_byte(self, self->regs.word.hl++);
-  cpu_z80_write_byte(self, self->regs.word.de++, data);
-
-  int result = (self->regs.word.bc - 1) & 0xffff;
-
-  self->regs.word.bc = result;
-  self->regs.bit.nf = false;
-  self->regs.bit.pvf = result != 0;
-  self->regs.bit.hf = false;
-
-  if (result)
+  cpu_z80_ldi(self);
+  if (self->regs.word.bc)
     self->regs.word.pc -= 2;
 }
 
@@ -806,24 +784,44 @@ static ALWAYS_INLINE void cpu_z80_or(struct cpu_z80 *self, int rvalue) {
   self->regs.bit.sf = result >> 7;
 }
 
-static ALWAYS_INLINE void cpu_z80_otdr(struct cpu_z80 *self) {
-  abort();
-}
-
-static ALWAYS_INLINE void cpu_z80_otir(struct cpu_z80 *self) {
-  abort();
-}
-
 static ALWAYS_INLINE void cpu_z80_out(struct cpu_z80 *self, int lvalue, int rvalue) {
   cpu_z80_out_byte(self, lvalue, rvalue);
 }
 
 static ALWAYS_INLINE void cpu_z80_outd(struct cpu_z80 *self) {
-  abort();
+  --self->regs.byte.b;
+  cpu_z80_out_byte(
+    self,
+    self->regs.word.bc,
+    cpu_z80_read_byte(self, self->regs.word.hl--)
+  );
+
+  self->regs.bit.nf = true;
+  self->regs.bit.zf = self->regs.byte.b != 0;
+}
+
+static ALWAYS_INLINE void cpu_z80_otdr(struct cpu_z80 *self) {
+  cpu_z80_outd(self);
+  if (self->regs.byte.b)
+    self->regs.word.pc -= 2;
 }
 
 static ALWAYS_INLINE void cpu_z80_outi(struct cpu_z80 *self) {
-  abort();
+  --self->regs.byte.b;
+  cpu_z80_out_byte(
+    self,
+    self->regs.word.bc,
+    cpu_z80_read_byte(self, self->regs.word.hl++)
+  );
+
+  self->regs.bit.nf = true;
+  self->regs.bit.zf = self->regs.byte.b != 0;
+}
+
+static ALWAYS_INLINE void cpu_z80_otir(struct cpu_z80 *self) {
+  cpu_z80_outi(self);
+  if (self->regs.byte.b)
+    self->regs.word.pc -= 2;
 }
 
 static ALWAYS_INLINE void cpu_z80_pop(struct cpu_z80 *self, int lvalue) {