`define INSN_POP_reg 8'b11xx0001
`define INSN_LDH_AC 8'b111x0010 // Either LDH A,(C) or LDH (C),A
`define INSN_LDx_AHL 8'b001xx010 // LDD/LDI A,(HL) / (HL),A
+`define INSN_ALU8 8'b10xxxxxx // 10 xxx yyy
+`define INSN_NOP 8'b00000000
`define INSN_reg_A 3'b111
`define INSN_reg_B 3'b000
`define INSN_stack_BC 2'b00
`define INSN_stack_DE 2'b01
`define INSN_stack_HL 2'b10
+`define INSN_alu_ADD 3'b000
+`define INSN_alu_ADC 3'b001
+`define INSN_alu_SUB 3'b010
+`define INSN_alu_SBC 3'b011
+`define INSN_alu_AND 3'b100
+`define INSN_alu_XOR 3'b101
+`define INSN_alu_OR 3'b110
+`define INSN_alu_CP 3'b111 // Oh lawd, is dat some CP?
+
module GBZ80Core(
input clk,
output reg [15:0] busaddress, /* BUS_* is latched on STATE_FETCH. */
end
endcase
end
+ `INSN_ALU8: begin
+ if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0)) begin
+ // fffffffff fuck your shit, read from (HL) :(
+ rd <= 1;
+ address <= {registers[`REG_H], registers[`REG_L]};
+ end else begin
+ `EXEC_NEWCYCLE;
+ `EXEC_INC_PC;
+ case (opcode[2:0])
+ `INSN_reg_A: begin tmp <= registers[`REG_A]; end
+ `INSN_reg_B: begin tmp <= registers[`REG_B]; end
+ `INSN_reg_C: begin tmp <= registers[`REG_C]; end
+ `INSN_reg_D: begin tmp <= registers[`REG_D]; end
+ `INSN_reg_E: begin tmp <= registers[`REG_E]; end
+ `INSN_reg_H: begin tmp <= registers[`REG_H]; end
+ `INSN_reg_L: begin tmp <= registers[`REG_L]; end
+ `INSN_reg_dHL: begin tmp <= rdata; end
+ endcase
+ end
+ end
+ `INSN_NOP: begin
+ `EXEC_NEWCYCLE;
+ `EXEC_INC_PC;
+ end
default:
$stop;
endcase
end
endcase
end
+ `INSN_ALU8: begin
+ if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0)) begin
+ /* Sit on our asses. */
+ cycle <= 1;
+ end else begin /* Actually do the computation! */
+ case (opcode[5:3])
+ `INSN_alu_ADD: begin
+ registers[`REG_A] <=
+ registers[`REG_A] + tmp;
+ registers[`REG_F] <=
+ { /* Z */ ((registers[`REG_A] + tmp) == 0) ? 1'b1 : 1'b0,
+ /* N */ 1'b0,
+ /* H */ (({1'b0,registers[`REG_A][3:0]} + {1'b0,tmp[3:0]}) >> 4 == 1) ? 1'b1 : 1'b0,
+ /* C */ (({1'b0,registers[`REG_A]} + {1'b0,tmp}) >> 8 == 1) ? 1'b1 : 1'b0,
+ registers[`REG_F][3:0]
+ };
+ end
+ `INSN_alu_ADC: begin
+ registers[`REG_A] <=
+ registers[`REG_A] + tmp + {7'b0,registers[`REG_F][4]};
+ registers[`REG_F] <=
+ { /* Z */ ((registers[`REG_A] + tmp + {7'b0,registers[`REG_F][4]}) == 0) ? 1'b1 : 1'b0,
+ /* N */ 1'b0,
+ /* H */ (({1'b0,registers[`REG_A][3:0]} + {1'b0,tmp[3:0]} + {4'b0,registers[`REG_F][4]}) >> 4 == 1) ? 1'b1 : 1'b0,
+ /* C */ (({1'b0,registers[`REG_A]} + {1'b0,tmp} + {8'b0,registers[`REG_F][4]}) >> 8 == 1) ? 1'b1 : 1'b0,
+ registers[`REG_F][3:0]
+ };
+ end
+ `INSN_alu_AND: begin
+ registers[`REG_A] <=
+ registers[`REG_A] & tmp;
+ registers[`REG_F] <=
+ { /* Z */ ((registers[`REG_A] & tmp) == 0) ? 1'b1 : 1'b0,
+ 3'b010,
+ registers[`REG_F][3:0]
+ };
+ end
+ `INSN_alu_OR: begin
+ registers[`REG_A] <=
+ registers[`REG_A] | tmp;
+ registers[`REG_F] <=
+ { /* Z */ ((registers[`REG_A] | tmp) == 0) ? 1'b1 : 1'b0,
+ 3'b000,
+ registers[`REG_F][3:0]
+ };
+ end
+ `INSN_alu_XOR: begin
+ registers[`REG_A] <=
+ registers[`REG_A] ^ tmp;
+ registers[`REG_F] <=
+ { /* Z */ ((registers[`REG_A] ^ tmp) == 0) ? 1'b1 : 1'b0,
+ 3'b000,
+ registers[`REG_F][3:0]
+ };
+ end
+ default:
+ $stop;
+ endcase
+ end
+ end
+ `INSN_NOP: begin /* NOP! */ end
endcase
state <= `STATE_FETCH;
end