From: Joshua Wise <joshua@rebirth.joshuawise.com>
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?hp=039167e484194ff9f12fca2cc474f866a212f0cd

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
-
+