From: Joshua Wise Date: Sat, 19 Apr 2008 09:45:12 +0000 (-0400) Subject: Add bit instruction X-Git-Url: http://git.joshuawise.com/fpgaboy.git/commitdiff_plain/decafd62efeba345e3ff285662021f36c9c3ae2f?hp=341cd5fd179c196bb105f611d662a6339bc33ef0 Add bit instruction --- diff --git a/GBZ80Core.v b/GBZ80Core.v index 3931bdd..45870d1 100644 --- a/GBZ80Core.v +++ b/GBZ80Core.v @@ -40,40 +40,45 @@ `define STATE_EXECUTE 2'h2 `define STATE_WRITEBACK 2'h3 -`define INSN_LD_reg_imm8 8'b00xxx110 -`define INSN_HALT 8'b01110110 -`define INSN_LD_HL_reg 8'b01110xxx -`define INSN_LD_reg_HL 8'b01xxx110 -`define INSN_LD_reg_reg 8'b01xxxxxx -`define INSN_LD_reg_imm16 8'b00xx0001 -`define INSN_LD_SP_HL 8'b11111001 -`define INSN_PUSH_reg 8'b11xx0101 -`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_ALU8IMM 8'b11xxx110 -`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 -`define INSN_JPCC_imm 8'b110xx010 -`define INSN_ALU_A 8'b00xxx111 -`define INSN_JP_HL 8'b11101001 -`define INSN_JR_imm 8'b00011000 -`define INSN_JRCC_imm 8'b001xx000 -`define INSN_INCDEC16 8'b00xxx011 -`define INSN_VOP_INTR 8'b11111100 // 0xFC is grabbed by the fetch if there is an interrupt pending. -`define INSN_DI 8'b11110011 -`define INSN_EI 8'b11111011 -`define INSN_INCDEC_HL 8'b0011010x -`define INSN_INCDEC_reg8 8'b00xxx10x -`define INSN_LD8M_A 8'b111x0000 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8 -`define INSN_LD16M_A 8'b111x1010 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8 -`define INSN_LDBCDE_A 8'b000xx010 // 0000 for BC, 0001 for DE, 1010 for A,(x), 0010 for (x),A +`define INSN_LD_reg_imm8 9'b000xxx110 +`define INSN_HALT 9'b001110110 +`define INSN_LD_HL_reg 9'b001110xxx +`define INSN_LD_reg_HL 9'b001xxx110 +`define INSN_LD_reg_reg 9'b001xxxxxx +`define INSN_LD_reg_imm16 9'b000xx0001 +`define INSN_LD_SP_HL 9'b011111001 +`define INSN_PUSH_reg 9'b011xx0101 +`define INSN_POP_reg 9'b011xx0001 +`define INSN_LDH_AC 9'b0111x0010 // Either LDH A,(C) or LDH (C),A +`define INSN_LDx_AHL 9'b0001xx010 // LDD/LDI A,(HL) / (HL),A +`define INSN_ALU8 9'b010xxxxxx // 10 xxx yyy +`define INSN_ALU8IMM 9'b011xxx110 +`define INSN_NOP 9'b000000000 +`define INSN_RST 9'b011xxx111 +`define INSN_RET 9'b0110x1001 // 1 = RETI, 0 = RET +`define INSN_RETCC 9'b0110xx000 +`define INSN_CALL 9'b011001101 +`define INSN_CALLCC 9'b0110xx100 // Not that call/cc. +`define INSN_JP_imm 9'b011000011 +`define INSN_JPCC_imm 9'b0110xx010 +`define INSN_ALU_A 9'b000xxx111 +`define INSN_JP_HL 9'b011101001 +`define INSN_JR_imm 9'b000011000 +`define INSN_JRCC_imm 9'b0001xx000 +`define INSN_INCDEC16 9'b000xxx011 +`define INSN_VOP_INTR 9'b011111100 // 0xFC is grabbed by the fetch if there is an interrupt pending. +`define INSN_DI 9'b011110011 +`define INSN_EI 9'b011111011 +`define INSN_INCDEC_HL 9'b00011010x +`define INSN_INCDEC_reg8 9'b000xxx10x +`define INSN_LD8M_A 9'b0111x0000 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8 +`define INSN_LD16M_A 9'b0111x1010 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8 +`define INSN_LDBCDE_A 9'b0000xx010 +`define INSN_TWO_BYTE 9'b011001011 // prefix for two-byte opqodes +`define INSN_ALU_EXT 9'b100xxxxxx +`define INSN_BIT 9'b101xxxxxx +`define INSN_RES 9'b110xxxxxx +`define INSN_SET 9'b111xxxxxx `define INSN_cc_NZ 2'b00 `define INSN_cc_Z 2'b01 @@ -112,10 +117,19 @@ `define INSN_alu_CPL 3'b101 `define INSN_alu_SCF 3'b110 `define INSN_alu_CCF 3'b111 +`define INSN_alu_RLC 3'b000 +`define INSN_alu_RRC 3'b001 +`define INSN_alu_RL 3'b010 +`define INSN_alu_RR 3'b011 +`define INSN_alu_DA_SLA 3'b100 +`define INSN_alu_CPL_SRA 3'b101 +`define INSN_alu_SCF_SWAP 3'b110 +`define INSN_alu_CCF_SRL 3'b111 `define EXEC_INC_PC `_PC <= `_PC + 1; `define EXEC_NEXTADDR_PCINC address <= `_PC + 1; `define EXEC_NEWCYCLE begin newcycle <= 1; rd <= 1; wr <= 0; end +`define EXEC_NEWCYCLE_TWOBYTE begin newcycle <= 1; rd <= 1; wr <= 0; twobyte <= 1; end `define EXEC_WRITE(ad, da) begin address <= (ad); wdata <= (da); wr <= 1; end end `define EXEC_READ(ad) begin address <= (ad); rd <= 1; end end @@ -126,7 +140,7 @@ module GBZ80Core( output reg buswr, output reg busrd, input irq, input [7:0] jaddr, output reg [1:0] state); - + // reg [1:0] state; /* State within this bus cycle (see STATE_*). */ reg [2:0] cycle; /* Cycle for instructions. */ @@ -134,18 +148,77 @@ module GBZ80Core( reg [15:0] address; /* Address for the next bus operation. */ - reg [7:0] opcode; /* Opcode from the current machine cycle. */ - + reg [8:0] opcode; /* Opcode from the current machine cycle. */ + reg [7:0] rdata, wdata; /* Read data from this bus cycle, or write data for the next. */ - reg rd, wr, newcycle; + reg rd, wr, newcycle, twobyte; reg [7:0] tmp, tmp2; /* Generic temporary regs. */ reg [7:0] buswdata; assign busdata = buswr ? buswdata : 8'bzzzzzzzz; - + reg ie, iedelay; - + + wire [7:0] rlc,rrc,rl,rr,sla,sra,swap,srl; + wire [3:0] rlcf,rrcf,rlf,rrf,slaf,sraf,swapf,srlf; + wire [7:0] alu_res; + wire [3:0] f_res; + + assign rlc = {tmp[6:0],tmp[7]}; + assign rlcf = {(tmp == 0 ? 1'b1 : 1'b0) + ,2'b0, + tmp[7]}; + + assign rrc = {tmp[0],tmp[7:1]}; + assign rrcf = {(tmp == 0 ? 1'b1 : 1'b0), + 2'b0, + tmp[0]}; + + assign rl = {tmp[6:0],`_F[4]}; + assign rlf = {({tmp[6:0],`_F[4]} == 0 ? 1'b1 : 1'b0), + 2'b0, + tmp[7]}; + + assign rr = {`_F[4],tmp[7:1]}; + assign rrf = {({tmp[4],tmp[7:1]} == 0 ? 1'b1 : 1'b0), + 2'b0, + tmp[0]}; + + assign sla = {tmp[6:0],0}; + assign slaf = {(tmp[6:0] == 0 ? 1'b1 : 1'b0), + 2'b0, + tmp[7]}; + + assign sra = {tmp[7],tmp[7:1]}; +// assign sraf = {(tmp[7:1] == 0 ? 1'b1 : 1'b0),2'b0,tmp[0]}; now in assign srlf = + + assign swap = {tmp[3:0],tmp[7:4]}; + assign swapf = {(tmp == 0 ? 1'b1 : 1'b0), + 3'b0}; + + assign srl = {0,tmp[7:1]}; + assign srlf = {(tmp[7:1] == 0 ? 1'b1 : 1'b0), + 2'b0, + tmp[0]}; + assign sraf = srlf; + + /* Y U Q */ + assign {alu_res,f_res} = + opcode[5] ? ( + opcode[4] ? ( + opcode[3] ? {srl,srlf} : {swap,swapf} + ) : ( + opcode[3] ? {sra,sraf} : {sla,slaf} + ) + ) : ( + opcode[4] ? ( + opcode[3] ? {rr,rrf} : {rl,rlf} + ) : ( + opcode[3] ? {rrc,rrcf} : {rlc,rlcf} + ) + ); + initial begin registers[ 0] <= 0; registers[ 1] <= 0; @@ -172,13 +245,14 @@ module GBZ80Core( opcode <= 0; state <= `STATE_WRITEBACK; cycle <= 0; + twobyte <= 0; end always @(posedge clk) case (state) `STATE_FETCH: begin if (newcycle) begin - busaddress <= {registers[`REG_PCH], registers[`REG_PCL]}; + busaddress <= `_PC; buswr <= 0; busrd <= 1; end else begin @@ -192,10 +266,13 @@ module GBZ80Core( end `STATE_DECODE: begin if (newcycle) begin - if (ie && irq) + if (twobyte) begin + opcode <= {1,busdata}; + twobyte <= 0; + end else if (ie && irq) opcode <= `INSN_VOP_INTR; else - opcode <= busdata; + opcode <= {0,busdata}; rdata <= busdata; newcycle <= 0; cycle <= 0; diff --git a/allinsns.v b/allinsns.v index 0a62af3..5ca51d6 100644 --- a/allinsns.v +++ b/allinsns.v @@ -25,4 +25,6 @@ `include "insn_incdec_reg8.v" `include "insn_ldm8_a.v" `include "insn_ldm16_a.v" -`include "insn_ldbcde_a.v" \ No newline at end of file +`include "insn_ldbcde_a.v" +`include "insn_two_byte.v" +`include "insn_bit.v" diff --git a/insn_bit.v b/insn_bit.v new file mode 100644 index 0000000..c4b1fe5 --- /dev/null +++ b/insn_bit.v @@ -0,0 +1,30 @@ +`ifdef EXECUTE + `INSN_BIT: begin + if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0)) begin + `EXEC_READ(`_HL) + end else if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 2)) begin + `EXEC_NEWCYCLE + end else begin + case (opcode[2:0]) + `INSN_reg_A: tmp <= `_A; + `INSN_reg_B: tmp <= `_B; + `INSN_reg_C: tmp <= `_C; + `INSN_reg_D: tmp <= `_D; + `INSN_reg_E: tmp <= `_E; + `INSN_reg_H: tmp <= `_H; + `INSN_reg_L: tmp <= `_L; + `INSN_reg_dHL: tmp <= rdata; + endcase + if (opcode[2:0] != `INSN_reg_dHL) begin + `EXEC_NEWCYCLE + end + end + end +`endif + +`ifdef WRITEBACK + `INSN_BIT: begin + if ((opcode[2:0] != `INSN_reg_dHL) || (cycle == 1)) + `_F <= {~tmp[opcode[5:3]], 2'b01, `_F[4:0]}; + end +`endif