From: Joshua Wise Date: Fri, 4 Apr 2008 05:50:36 +0000 (-0400) Subject: RETCC that breaks everything. Why? X-Git-Url: http://git.joshuawise.com/fpgaboy.git/commitdiff_plain/611e4a90d4f4c5b5e2cadde0da57639bfbaca6a8?ds=sidebyside RETCC that breaks everything. Why? --- diff --git a/FPGABoy.ise b/FPGABoy.ise index bd62a30..b09f383 100644 Binary files a/FPGABoy.ise and b/FPGABoy.ise differ diff --git a/GBZ80Core.v b/GBZ80Core.v index 77c3649..cd7f4d1 100644 --- a/GBZ80Core.v +++ b/GBZ80Core.v @@ -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 --- 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 - +