+ `INSN_ALU8: begin
+ if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0)) begin
+ /* Sit on our asses. */
+ 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_SUB: begin
+ registers[`REG_A] <=
+ registers[`REG_A] - tmp;
+ registers[`REG_F] <=
+ { /* Z */ ((registers[`REG_A] - tmp) == 0) ? 1'b1 : 1'b0,
+ /* N */ 1'b1,
+ /* 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_SBC: 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'b1,
+ /* 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
+ `INSN_alu_CP: begin
+ registers[`REG_F] <=
+ { /* Z */ ((registers[`REG_A] - tmp) == 0) ? 1'b1 : 1'b0,
+ /* N */ 1'b1,
+ /* 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
+ default:
+ $stop;
+ endcase
+ end
+ end
+ `INSN_ALU_A: begin
+ case(opcode[5:3])
+ `INSN_alu_RLCA: begin
+ registers[`REG_A] <= {registers[`REG_A][6:0],registers[`REG_A][7]};
+ registers[`REG_F] <= {registers[`REG_F][7:5],registers[`REG_A][7],registers[`REG_F][3:0]};
+ end
+ `INSN_alu_RRCA: begin
+ registers[`REG_A] <= {registers[`REG_A][0],registers[`REG_A][7:1]};
+ registers[`REG_F] <= {registers[`REG_F][7:5],registers[`REG_A][0],registers[`REG_F][3:0]};
+ end
+ `INSN_alu_RLA: begin
+ registers[`REG_A] <= {registers[`REG_A][6:0],registers[`REG_F][4]};
+ registers[`REG_F] <= {registers[`REG_F][7:5],registers[`REG_A][7],registers[`REG_F][3:0]};
+ end
+ `INSN_alu_RRA: begin
+ registers[`REG_A] <= {registers[`REG_A][4],registers[`REG_A][7:1]};
+ registers[`REG_F] <= {registers[`REG_F][7:5],registers[`REG_A][0],registers[`REG_F][3:0]};
+ end
+ `INSN_alu_CPL: begin
+ registers[`REG_A] <= ~registers[`REG_A];
+ registers[`REG_F] <= {registers[`REG_F][7],1'b1,1'b1,registers[`REG_F][4:0]};
+ end
+ `INSN_alu_SCF: begin
+ registers[`REG_F] <= {registers[`REG_F][7:5],1,registers[`REG_F][3:0]};
+ end
+ `INSN_alu_CCF: begin
+ registers[`REG_F] <= {registers[`REG_F][7:5],~registers[`REG_F][4],registers[`REG_F][3:0]};
+ end
+ endcase
+ end
+ `INSN_NOP: begin /* NOP! */ end
+ `INSN_RST: begin
+ case (cycle)
+ 0: begin /* type F */ end
+ 1: begin /* type F */ end
+ 2: begin /* type F */ end
+ 3: {registers[`REG_SPH],registers[`REG_SPL]} <=
+ {registers[`REG_SPH],registers[`REG_SPL]}-2;
+ endcase
+ end
+ `INSN_RET,`INSN_RETCC: begin
+ case (cycle)
+ 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] && (opcode != `INSN_RETCC)) /* RETI */
+ ie <= 1;
+ end
+ endcase
+ end
+ `INSN_CALL,`INSN_CALLCC: begin
+ case (cycle)
+ 0: begin /* type F */ end
+ 1: tmp <= rdata; // tmp contains newpcl
+ 2: tmp2 <= rdata; // tmp2 contains newpch
+ 3: begin /* type F */ end
+ 4: registers[`REG_PCH] <= tmp2;
+ 5: begin
+ {registers[`REG_SPH],registers[`REG_SPL]} <=
+ {registers[`REG_SPH],registers[`REG_SPL]} - 2;
+ registers[`REG_PCL] <= tmp;
+ end
+ endcase
+ end
+ `INSN_JP_imm,`INSN_JPCC_imm: begin
+ case (cycle)
+ 0: begin /* type F */ end
+ 1: tmp <= rdata; // tmp contains newpcl
+ 2: tmp2 <= rdata; // tmp2 contains newpch
+ 3: {registers[`REG_PCH],registers[`REG_PCL]} <=
+ {tmp2,tmp};
+ endcase
+ end
+ `INSN_JP_HL: begin
+ {registers[`REG_PCH],registers[`REG_PCL]} <=
+ {registers[`REG_H],registers[`REG_L]};
+ end
+ `INSN_JR_imm,`INSN_JRCC_imm: begin
+ case (cycle)
+ 0: begin /* type F */ end
+ 1: tmp <= rdata;
+ 2: {registers[`REG_PCH],registers[`REG_PCL]} <=
+ {registers[`REG_PCH],registers[`REG_PCL]} +
+ {tmp[7]?8'hFF:8'h00,tmp};
+ endcase
+ end
+ default:
+ $stop;