RETCC that breaks everything. Why?
authorJoshua Wise <joshua@rebirth.joshuawise.com>
Fri, 4 Apr 2008 05:50:36 +0000 (01:50 -0400)
committerJoshua Wise <joshua@rebirth.joshuawise.com>
Fri, 4 Apr 2008 05:50:36 +0000 (01:50 -0400)
FPGABoy.ise
GBZ80Core.v
rom.asm

index bd62a30..b09f383 100644 (file)
Binary files a/FPGABoy.ise and b/FPGABoy.ise differ
index 77c3649..cd7f4d1 100644 (file)
@@ -36,6 +36,7 @@
 `define INSN_NOP                               8'b00000000
 `define INSN_RST                               8'b11xxx111
 `define INSN_RET                               8'b110x1001     // 1 = RETI, 0 = RET
+`define INSN_RETCC                     8'b110xx000
 `define INSN_CALL                              8'b11001101
 `define INSN_CALLCC                    8'b110xx100     // Not that call/cc.
 `define INSN_JP_imm                    8'b11000011
@@ -406,12 +407,25 @@ module GBZ80Core(
                                                rd <= 1;
                                                address <= {registers[`REG_SPH],registers[`REG_SPL]};
                                        end
-                               1:      begin
+                               1:      begin   // SPECIAL CASE: cycle does NOT increase linearly with ret!
+                                               `EXEC_INC_PC;
+                                               if (opcode != `INSN_RETCC)
+                                                       $stop;
+                                               case (opcode[4:3])      // cycle 1 is skipped if we are not retcc
+                                               `INSN_cc_NZ:    if (registers[`REG_F][7]) begin `EXEC_NEWCYCLE; end
+                                               `INSN_cc_Z:             if (~registers[`REG_F][7]) begin `EXEC_NEWCYCLE; end
+                                               `INSN_cc_NC:    if (registers[`REG_F][4]) begin `EXEC_NEWCYCLE; end
+                                               `INSN_cc_C:             if (~registers[`REG_F][4]) begin `EXEC_NEWCYCLE; end
+                                               endcase
+                                               rd <= 1;
+                                               address <= {registers[`REG_SPH],registers[`REG_SPL]};
+                                       end
+                               2:      begin
                                                rd <= 1;
                                                address <= {registers[`REG_SPH],registers[`REG_SPL]} + 1;
                                        end
-                               2:      begin /* twiddle thumbs */ end
-                               3:      begin
+                               3:      begin /* twiddle thumbs */ end
+                               4:      begin
                                                `EXEC_NEWCYCLE;
                                                // do NOT increment PC!
                                        end
@@ -778,15 +792,17 @@ module GBZ80Core(
                                                {registers[`REG_SPH],registers[`REG_SPL]}-2;
                                endcase
                        end
-                       `INSN_RET: begin
+                       `INSN_RET,`INSN_RETCC: begin
                                case (cycle)
-                               0:      begin /* type F */ end
-                               1:      registers[`REG_PCL] <= rdata;
-                               2:      registers[`REG_PCH] <= rdata;
-                               3:      begin
+                               0:      if (opcode != `INSN_RETCC)
+                                               cycle <= 1;     // Skip cycle 1; it gets incremented on the next round.
+                               1: begin /* Nothing need happen here. */ end
+                               2:      registers[`REG_PCL] <= rdata;
+                               3:      registers[`REG_PCH] <= rdata;
+                               4:      begin
                                                {registers[`REG_SPH],registers[`REG_SPL]} <=
                                                        {registers[`REG_SPH],registers[`REG_SPL]} + 2;
-                                               if (opcode[4])  /* RETI */
+                                               if (opcode[4] && (opcode != `INSN_RETCC))       /* RETI */
                                                        ie <= 1;
                                        end
                                endcase
diff --git a/rom.asm b/rom.asm
index cd3cf2d..aa070ff 100644 (file)
--- a/rom.asm
+++ b/rom.asm
@@ -191,24 +191,28 @@ insntest:
        call puts
        ret
 .fail:
+       call puts
+       ld hl, .testfailed
        call puts
        ret
 .insnteststr:
-       db "Testing instructions... ",$0
+       db "Testing instructions... ",0
 .pushpopfail:
-       db "PUSH/POP test failed.",$0D,$0A,0
+       db "PUSH/POP",0
 .ff:
        db $FF
 .xorhlfail:
-       db "XOR [HL] test failed.",$0D,$0A,0
+       db "XOR [HL]",0
 .jphlfail:
-       db "JP [HL] test failed.",$0D,$0A,0
+       db "JP [HL]",0
 .jrfail:
-       db "JR test failed.",$0D,$0A,0
+       db "JR",0
 .cpfail:
-       db "CP test failed.",$0D,$0A,0
+       db "CP",0
 .cplfail:
-       db "CPL test failed.",$0D,$0A,0
+       db "CPL",0
+.testfailed:
+       db "test failed.",$0D,$0A,0
 .ok:
        db "OK!",$0D,$0A,0
 
@@ -234,4 +238,4 @@ puts:
        jr puts
 .done:
        ret
-
+       
This page took 0.030852 seconds and 4 git commands to generate.