Implement correct 8080-style port access (extends byte address to word with a)
authorNick Downing <nick@ndcode.org>
Fri, 22 Jul 2022 04:51:45 +0000 (14:51 +1000)
committerNick Downing <nick@ndcode.org>
Fri, 22 Jul 2022 04:51:45 +0000 (14:51 +1000)
cpu_z80.c
cpu_z80.h
decode_z80.sed

index 818d8d0..6f755ca 100644 (file)
--- a/cpu_z80.c
+++ b/cpu_z80.c
@@ -655,7 +655,7 @@ void cpu_z80_execute(struct cpu_z80 *self) {
     cpu_z80_jp(self, !self->regs.bit.cf, cpu_z80_fetch_word(self));
     break;
   case 0xd3:
-    cpu_z80_out(self, cpu_z80_fetch_byte(self), self->regs.byte.a);
+    cpu_z80_out(self, cpu_z80_port_word(self), self->regs.byte.a);
     break;
   case 0xd4:
     cpu_z80_call(self, !self->regs.bit.cf, cpu_z80_fetch_word(self));
@@ -681,7 +681,7 @@ void cpu_z80_execute(struct cpu_z80 *self) {
     cpu_z80_jp(self, self->regs.bit.cf, cpu_z80_fetch_word(self));
     break;
   case 0xdb:
-    cpu_z80_in_test(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_fetch_byte(self)));
+    cpu_z80_in(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_port_word(self)));
     break;
   case 0xdc:
     cpu_z80_call(self, self->regs.bit.cf, cpu_z80_fetch_word(self));
@@ -2206,7 +2206,7 @@ void cpu_z80_execute_dd(struct cpu_z80 *self) {
     cpu_z80_jp(self, !self->regs.bit.cf, cpu_z80_fetch_word(self));
     break;
   case 0xd3:
-    cpu_z80_out(self, cpu_z80_fetch_byte(self), self->regs.byte.a);
+    cpu_z80_out(self, cpu_z80_port_word(self), self->regs.byte.a);
     break;
   case 0xd4:
     cpu_z80_call(self, !self->regs.bit.cf, cpu_z80_fetch_word(self));
@@ -2232,7 +2232,7 @@ void cpu_z80_execute_dd(struct cpu_z80 *self) {
     cpu_z80_jp(self, self->regs.bit.cf, cpu_z80_fetch_word(self));
     break;
   case 0xdb:
-    cpu_z80_in_test(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_fetch_byte(self)));
+    cpu_z80_in(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_port_word(self)));
     break;
   case 0xdc:
     cpu_z80_call(self, self->regs.bit.cf, cpu_z80_fetch_word(self));
@@ -4531,7 +4531,7 @@ void cpu_z80_execute_fd(struct cpu_z80 *self) {
     cpu_z80_jp(self, !self->regs.bit.cf, cpu_z80_fetch_word(self));
     break;
   case 0xd3:
-    cpu_z80_out(self, cpu_z80_fetch_byte(self), self->regs.byte.a);
+    cpu_z80_out(self, cpu_z80_port_word(self), self->regs.byte.a);
     break;
   case 0xd4:
     cpu_z80_call(self, !self->regs.bit.cf, cpu_z80_fetch_word(self));
@@ -4557,7 +4557,7 @@ void cpu_z80_execute_fd(struct cpu_z80 *self) {
     cpu_z80_jp(self, self->regs.bit.cf, cpu_z80_fetch_word(self));
     break;
   case 0xdb:
-    cpu_z80_in(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_fetch_byte(self)));
+    cpu_z80_in(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_port_word(self)));
     break;
   case 0xdc:
     cpu_z80_call(self, self->regs.bit.cf, cpu_z80_fetch_word(self));
index bbbf137..18fea86 100644 (file)
--- a/cpu_z80.h
+++ b/cpu_z80.h
@@ -288,6 +288,11 @@ static ALWAYS_INLINE int cpu_z80_displacement(struct cpu_z80 *self, int base) {
   return (base + cpu_z80_relative(self)) & 0xffff;
 }
 
+// byte-addressed ports are extended to word using a as high 8 bits
+static ALWAYS_INLINE int cpu_z80_port_word(struct cpu_z80 *self) {
+  return cpu_z80_fetch_byte(self) | (self->regs.byte.a << 8);
+}
+
 // instruction execute
 static ALWAYS_INLINE void cpu_z80_adc_byte(struct cpu_z80 *self, int lvalue, int rvalue) {
   int data = cpu_z80_read_byte(self, lvalue);
index b438d56..fe8bc18 100644 (file)
@@ -1,8 +1,9 @@
 s/cpu_z80_rst(self/cpu_z80_call(self, true/
 s/(self, true, \(!\?self->regs\.bit\.\)/(self, \1/
 s/cpu_z80_in(self/cpu_z80_in_test(self/
-s/cpu_z80_in_test(self\(, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_fetch_byte(self))\))/cpu_z80_in(self\1)/
+s/cpu_z80_in_test(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_fetch_byte(self)))/cpu_z80_in(self, CPU_Z80_EA_A, cpu_z80_in_byte(self, cpu_z80_port_word(self)))/
 s/cpu_z80_in_test(self, CPU_Z80_EA_F/cpu_z80_in_test(self, CPU_Z80_EA_NONE/
+s/cpu_z80_out(self, cpu_z80_fetch_byte(self), self->regs\.byte\.a)/cpu_z80_out(self, cpu_z80_port_word(self), self->regs.byte.a)/
 s/^    \(cpu_z80_ld_byte(self, \)\(cpu_z80_displacement(self, self->regs\.word\.i[xy])\)\(, cpu_z80_fetch_byte(self));\)$/    {\n      int ea = \2;\n      \1ea\3\n    }/
 s/^    cpu_z80_exx(self);$/    cpu_z80_ex(self, CPU_Z80_EA_BC, CPU_Z80_EA_BC_PRIME);\n    cpu_z80_ex(self, CPU_Z80_EA_DE, CPU_Z80_EA_DE_PRIME);\n    cpu_z80_ex(self, CPU_Z80_EA_HL, CPU_Z80_EA_HL_PRIME);/
 /^void cpu_z80_execute_dd_cb(struct cpu_z80 \*self) {$/,/^}$/s/cpu_z80_displacement(self, self->regs\.word\.ix)/ea/