diff --git a/cpu/alu.v b/cpu/alu.v index 192f1c5..ec38d1e 100644 --- a/cpu/alu.v +++ b/cpu/alu.v @@ -1,8 +1,10 @@ `include "alu_header.v" -module ALU(input [15:0]A,input [15:0]B, input oe,output reg [15:0]OUT,input [`ALU_OP_BITS-1:0]op); +module ALU(input [15:0]A,input [15:0]B, input oe,output reg [15:0]OUT,input [`ALU_OP_BITS-1:0]op,output wire [7:0]FLAGS,input Wbit); reg C_FLAG; +assign FLAGS={(Wbit==1)?OUT[15:15]:OUT[7:7],(Wbit==1) ? (OUT[15:0]=='h0000) : (OUT[7:0]=='h00),5'b00000,C_FLAG}; + always @ ( * ) begin case (op) `ALU_OP_ADD: {C_FLAG,OUT}=A+B; diff --git a/cpu/processor.v b/cpu/processor.v index b3043ff..3dd4a1e 100644 --- a/cpu/processor.v +++ b/cpu/processor.v @@ -27,6 +27,30 @@ reg unaligned_access; reg [1:0]IN_MOD; reg [2:0]IN_RM; reg Wbit; +reg Suppress_ALU_Output; +reg [15:0]FLAGS; +/* . . . . O D I T S Z . A . P . C */ +// C - Carry flag : carry out or borrow into the high order bit (8bit/16bit) +// +// P - Parity flag : is set if result has even parity +// +// A - Auxiliary flag : carry out from the low nibble to the high nibble or +// an equiv borrow. Used by decimal arithmetic instructions +// +// Z - Zero flag : Set when result of Operation is zero +// +// S - Sign flag : set if the high order bit of the result is 1. aka the sign +// of the result +// +// T - Trap flag : Set the cpu into single step mode where it generates an +// interrupt after each instruction +// +// I - Interrupt flag : 0: interrupts are masked +// +// D - Direction flag : 1: string instructions decrement 0: they increment +// +// O - Overflow flag : set on arythmetic overflow + // Execution units reg [1:0] in1_sel; @@ -84,7 +108,8 @@ wire [15:0] ALU_1B; wire [15:0] ALU_1O; reg [`ALU_OP_BITS-1:0]ALU_1OP; reg ALU_1OE; -ALU ALU(ALU_1A,ALU_1B,ALU_1OE,ALU_1O,ALU_1OP); +wire [7:0] ALU_FLAGS; +ALU ALU(ALU_1A,ALU_1B,ALU_1OE,ALU_1O,ALU_1OP,ALU_FLAGS,Wbit); /*** Processor stages ***/ @@ -109,15 +134,19 @@ always @(negedge clock) begin state=`PROC_DE_STATE_ENTRY; end `PROC_EX_STATE_EXIT:begin - case(out_sel) - 2'b11:begin - reg_write_we=0; - state=`PROC_IF_STATE_ENTRY; - end - default:begin - `invalid_instruction - end - endcase + if(Suppress_ALU_Output==0)begin + case(out_sel) + 2'b11:begin + reg_write_we=0; + state=`PROC_IF_STATE_ENTRY; + end + default:begin + `invalid_instruction + end + endcase + end else begin + state=`PROC_IF_STATE_ENTRY; + end end `PROC_DE_LOAD_16_EXTRA_FETCH_SET:begin external_address_bus = ProgCount; @@ -136,6 +165,7 @@ always @(posedge clock) begin end `PROC_IF_STATE_ENTRY:begin ERROR=0; + Suppress_ALU_Output=0; external_address_bus <= ProgCount; read <= 0; write <= 1; @@ -176,7 +206,8 @@ always @(posedge clock) begin if(CIR[8:8]==1) state=`PROC_DE_LOAD_16_PARAM; else begin - `invalid_instruction /*do 8bit loads*/ + PARAM1[7:0]=CIR[7:0]; + state=`PROC_EX_STATE_ENTRY; end end else begin `invalid_instruction @@ -353,6 +384,36 @@ always @(posedge clock) begin endcase end + 6'b001111 : begin + if ( CIR[9:9] == 0 ) begin + /* CMP - Compare Immediate with accumulator */ + /* 0 0 1 1 1 1 0 W | DATA | DATA if W |*/ + /* */ + /* NOTE: 8086 doc doesn't show the third byte but the */ + /* W flag and my assembler seem to disagree */ + Wbit=CIR[8:8]; + if(Wbit) + `start_unaligning_instruction + else + `start_aligning_instruction + Suppress_ALU_Output=1; + IN_MOD=2'b11; + in1_sel=2'b00; + in2_sel=2'b01; + reg_read_addr={CIR[8:8],3'b000}; + reg_read_oe=0; + ALU_1OE=0; + ALU_1OP=`ALU_OP_SUB; + if(CIR[8:8]==1) + state=`PROC_DE_LOAD_16_PARAM; + else begin + PARAM1[7:0]=CIR[7:0]; + state=`PROC_EX_STATE_ENTRY; + end + end else begin + `invalid_instruction + end + end default:begin `invalid_instruction end @@ -436,6 +497,7 @@ always @(posedge clock) begin end `PROC_EX_STATE_ENTRY:begin reg_write_data=ALU_1O; + FLAGS[7:0] = ALU_FLAGS[7:0]; state=`PROC_EX_STATE_EXIT; ERROR=0; end