// ============================================================================
|
// ============================================================================
|
// DECODE
|
// DECODE
|
// - decode / dispatch instruction
|
// - decode / dispatch instruction
|
//
|
//
|
//
|
//
|
// (C) 2009-2012 Robert Finch
|
// (C) 2009-2012 Robert Finch
|
// Stratford
|
// Stratford
|
// robfinch[remove]@opencores.org
|
// robfinch[remove]@opencores.org
|
//
|
//
|
//
|
//
|
// This source file is free software: you can redistribute it and/or modify
|
// This source file is free software: you can redistribute it and/or modify
|
// it under the terms of the GNU Lesser General Public License as published
|
// it under the terms of the GNU Lesser General Public License as published
|
// by the Free Software Foundation, either version 3 of the License, or
|
// by the Free Software Foundation, either version 3 of the License, or
|
// (at your option) any later version.
|
// (at your option) any later version.
|
//
|
//
|
// This source file is distributed in the hope that it will be useful,
|
// This source file is distributed in the hope that it will be useful,
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
//
|
//
|
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
//
|
//
|
//
|
//
|
// Verilog
|
// Verilog
|
//
|
//
|
// Decode / dispatch instruction
|
// Decode / dispatch instruction
|
// ============================================================================
|
// ============================================================================
|
//
|
//
|
DECODE:
|
DECODE:
|
casex(ir)
|
casex(ir)
|
`MORE1: state <= XI_FETCH;
|
`MORE1: state <= XI_FETCH;
|
`MORE2: state <= XI_FETCH;
|
`MORE2: state <= XI_FETCH;
|
`EXTOP: state <= XI_FETCH;
|
`EXTOP: state <= XI_FETCH;
|
|
|
`DEC_REG,`INC_REG:
|
`DEC_REG,`INC_REG:
|
begin
|
begin
|
w <= 1'b1;
|
w <= 1'b1;
|
rrr <= ir[2:0];
|
rrr <= ir[2:0];
|
state <= REGFETCHA;
|
state <= REGFETCHA;
|
end
|
end
|
|
|
`LEA: state <= EXECUTE;
|
`LEA: state <= EXECUTE;
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Immediate Loads
|
// Immediate Loads
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
|
|
`MOV_I2AL,`MOV_I2DL,`MOV_I2CL,`MOV_I2BL,`MOV_I2AH,`MOV_I2DH,`MOV_I2CH,`MOV_I2BH:
|
`MOV_I2AL,`MOV_I2DL,`MOV_I2CL,`MOV_I2BL,`MOV_I2AH,`MOV_I2DH,`MOV_I2CH,`MOV_I2BH:
|
begin
|
begin
|
`INITIATE_CODE_READ
|
`INITIATE_CODE_READ
|
state <= MOV_I2BYTREG;
|
state <= MOV_I2BYTREG;
|
end
|
end
|
|
|
`MOV_I2AX,`MOV_I2DX,`MOV_I2CX,`MOV_I2BX,`MOV_I2SP,`MOV_I2BP,`MOV_I2SI,`MOV_I2DI:
|
`MOV_I2AX,`MOV_I2DX,`MOV_I2CX,`MOV_I2BX,`MOV_I2SP,`MOV_I2BP,`MOV_I2SI,`MOV_I2DI:
|
begin
|
begin
|
w <= 1'b1;
|
w <= 1'b1;
|
rrr <= ir[2:0];
|
rrr <= ir[2:0];
|
if (ip==16'hFFFF) begin
|
if (ip==16'hFFFF) begin
|
int_num <= 8'h0d;
|
int_num <= 8'h0d;
|
state <= INT2;
|
state <= INT2;
|
end
|
end
|
else
|
else
|
state <= FETCH_IMM16;
|
state <= FETCH_IMM16;
|
end
|
end
|
|
|
`XLAT:
|
`XLAT:
|
if (!cyc_o) begin
|
if (!cyc_o) begin
|
cyc_type <= `CT_RDMEM;
|
cyc_type <= `CT_RDMEM;
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
adr_o <= {seg_reg,`SEG_SHIFT} + bx + al;
|
adr_o <= {seg_reg,`SEG_SHIFT} + bx + al;
|
end
|
end
|
else if (ack_i) begin
|
else if (ack_i) begin
|
cyc_type <= `CT_PASSIVE;
|
cyc_type <= `CT_PASSIVE;
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
res <= dat_i;
|
res <= dat_i;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
w <= 1'b0;
|
w <= 1'b0;
|
rrr <= 3'd0;
|
rrr <= 3'd0;
|
state <= IFETCH;
|
state <= IFETCH;
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Arithmetic Operations
|
// Arithmetic Operations
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
`AAA,`AAS:
|
`AAA,`AAS:
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
w <= 1'b1;
|
w <= 1'b1;
|
rrr <= 3'd0;
|
rrr <= 3'd0;
|
res <= alu_o;
|
res <= alu_o;
|
af <= (al[3:0]>4'h9 || af);
|
af <= (al[3:0]>4'h9 || af);
|
cf <= (al[3:0]>4'h9 || af);
|
cf <= (al[3:0]>4'h9 || af);
|
end
|
end
|
`ADD_ALI8,`ADC_ALI8,`SUB_ALI8,`SBB_ALI8,`AND_ALI8,`OR_ALI8,`XOR_ALI8,`CMP_ALI8:
|
`ADD_ALI8,`ADC_ALI8,`SUB_ALI8,`SBB_ALI8,`AND_ALI8,`OR_ALI8,`XOR_ALI8,`CMP_ALI8:
|
begin
|
begin
|
w <= 1'b0;
|
w <= 1'b0;
|
a <= {{8{al[7]}},al};
|
a <= {{8{al[7]}},al};
|
rrr <= 3'd0;
|
rrr <= 3'd0;
|
state <= FETCH_IMM8;
|
state <= FETCH_IMM8;
|
end
|
end
|
`ADD_AXI16,`ADC_AXI16,`SUB_AXI16,`SBB_AXI16,`AND_AXI16,`OR_AXI16,`XOR_AXI16,`CMP_AXI16:
|
`ADD_AXI16,`ADC_AXI16,`SUB_AXI16,`SBB_AXI16,`AND_AXI16,`OR_AXI16,`XOR_AXI16,`CMP_AXI16:
|
begin
|
begin
|
w <= 1'b1;
|
w <= 1'b1;
|
a <= ax;
|
a <= ax;
|
rrr <= 3'd0;
|
rrr <= 3'd0;
|
if (ip==16'hFFFF) begin
|
if (ip==16'hFFFF) begin
|
int_num <= 8'h0d;
|
int_num <= 8'h0d;
|
state <= INT2;
|
state <= INT2;
|
end
|
end
|
else
|
else
|
state <= FETCH_IMM16;
|
state <= FETCH_IMM16;
|
end
|
end
|
`ALU_I2R8:
|
`ALU_I2R8:
|
begin
|
begin
|
state <= FETCH_IMM8;
|
state <= FETCH_IMM8;
|
a <= rrro;
|
a <= rrro;
|
end
|
end
|
`ALU_I2R16:
|
`ALU_I2R16:
|
begin
|
begin
|
state <= FETCH_IMM16;
|
state <= FETCH_IMM16;
|
a <= rrro;
|
a <= rrro;
|
end
|
end
|
`XCHG_AXR:
|
`XCHG_AXR:
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
w <= 1'b1;
|
w <= 1'b1;
|
rrr <= ir[2:0];
|
rrr <= ir[2:0];
|
res <= ax;
|
res <= ax;
|
case(ir[2:0])
|
case(ir[2:0])
|
3'd0: ax <= ax;
|
3'd0: ax <= ax;
|
3'd1: ax <= cx;
|
3'd1: ax <= cx;
|
3'd2: ax <= dx;
|
3'd2: ax <= dx;
|
3'd3: ax <= bx;
|
3'd3: ax <= bx;
|
3'd4: ax <= sp;
|
3'd4: ax <= sp;
|
3'd5: ax <= bp;
|
3'd5: ax <= bp;
|
3'd6: ax <= si;
|
3'd6: ax <= si;
|
3'd7: ax <= di;
|
3'd7: ax <= di;
|
endcase
|
endcase
|
end
|
end
|
`CBW: begin ax[15:8] <= {8{ax[7]}}; state <= IFETCH; end
|
`CBW: begin ax[15:8] <= {8{ax[7]}}; state <= IFETCH; end
|
`CWD:
|
`CWD:
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
w <= 1'b1;
|
w <= 1'b1;
|
rrr <= 3'd2;
|
rrr <= 3'd2;
|
res <= {16{ax[15]}};
|
res <= {16{ax[15]}};
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// String Operations
|
// String Operations
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
`LODSB: state <= LODS;
|
`LODSB: state <= LODS;
|
`LODSW: state <= LODS;
|
`LODSW: state <= LODS;
|
`STOSB: state <= STOS;
|
`STOSB: state <= STOS;
|
`STOSW: state <= STOS;
|
`STOSW: state <= STOS;
|
`MOVSB: state <= MOVS;
|
`MOVSB: state <= MOVS;
|
`MOVSW: state <= MOVS;
|
`MOVSW: state <= MOVS;
|
`CMPSB: state <= CMPSB;
|
`CMPSB: state <= CMPSB;
|
`CMPSW: state <= CMPSW;
|
`CMPSW: state <= CMPSW;
|
`SCASB: state <= SCASB;
|
`SCASB: state <= SCASB;
|
`SCASW: state <= SCASW;
|
`SCASW: state <= SCASW;
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Stack Operations
|
// Stack Operations
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
`PUSH_REG: begin sp <= sp_dec; state <= PUSH; end
|
`PUSH_REG: begin sp <= sp_dec; state <= PUSH; end
|
`PUSH_DS: begin sp <= sp_dec; state <= PUSH; end
|
`PUSH_DS: begin sp <= sp_dec; state <= PUSH; end
|
`PUSH_ES: begin sp <= sp_dec; state <= PUSH; end
|
`PUSH_ES: begin sp <= sp_dec; state <= PUSH; end
|
`PUSH_SS: begin sp <= sp_dec; state <= PUSH; end
|
`PUSH_SS: begin sp <= sp_dec; state <= PUSH; end
|
`PUSH_CS: begin sp <= sp_dec; state <= PUSH; end
|
`PUSH_CS: begin sp <= sp_dec; state <= PUSH; end
|
`PUSHF: begin sp <= sp_dec; state <= PUSH; end
|
`PUSHF: begin sp <= sp_dec; state <= PUSH; end
|
`POP_REG: state <= POP;
|
`POP_REG: state <= POP;
|
`POP_DS: state <= POP;
|
`POP_DS: state <= POP;
|
`POP_ES: state <= POP;
|
`POP_ES: state <= POP;
|
`POP_SS: state <= POP;
|
`POP_SS: state <= POP;
|
`POPF: state <= POP;
|
`POPF: state <= POP;
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Flow controls
|
// Flow controls
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
`NOP: state <= IFETCH;
|
`NOP: state <= IFETCH;
|
`HLT: if (pe_nmi | (irq_i & ie)) state <= IFETCH;
|
`HLT: if (pe_nmi | (irq_i & ie)) state <= IFETCH;
|
`WAI: if (!busy_i) state <= IFETCH;
|
`WAI: if (!busy_i) state <= IFETCH;
|
`LOOP: begin cx <= cx_dec; state <= BRANCH1; end
|
`LOOP: begin cx <= cx_dec; state <= BRANCH1; end
|
`LOOPZ: begin cx <= cx_dec; state <= BRANCH1; end
|
`LOOPZ: begin cx <= cx_dec; state <= BRANCH1; end
|
`LOOPNZ: begin cx <= cx_dec; state <= BRANCH1; end
|
`LOOPNZ: begin cx <= cx_dec; state <= BRANCH1; end
|
`Jcc: state <= BRANCH1;
|
`Jcc: state <= BRANCH1;
|
`JCXZ: state <= BRANCH1;
|
`JCXZ: state <= BRANCH1;
|
`JMPS: state <= BRANCH1;
|
`JMPS: state <= BRANCH1;
|
`JMPF: state <= FETCH_OFFSET;
|
`JMPF: state <= FETCH_OFFSET;
|
`CALL: begin sp <= sp_dec; state <= FETCH_DISP16; end
|
`CALL: begin sp <= sp_dec; state <= FETCH_DISP16; end
|
`CALLF: begin sp <= sp_dec; state <= FETCH_OFFSET; end
|
`CALLF: begin sp <= sp_dec; state <= FETCH_OFFSET; end
|
`RET: state <= RETPOP; // data16 is zero
|
`RET: state <= RETPOP; // data16 is zero
|
`RETPOP: state <= FETCH_STK_ADJ1;
|
`RETPOP: state <= FETCH_STK_ADJ1;
|
`RETF: state <= RETFPOP; // data16 is zero
|
`RETF: state <= RETFPOP; // data16 is zero
|
`RETFPOP: state <= FETCH_STK_ADJ1;
|
`RETFPOP: state <= FETCH_STK_ADJ1;
|
`IRET: state <= IRET1;
|
`IRET: state <= IRET1;
|
`INT: state <= INT;
|
`INT: state <= INT;
|
`INT3: begin int_num <= 8'd3; state <= INT2; end
|
`INT3: begin int_num <= 8'd3; state <= INT2; end
|
`INTO:
|
`INTO:
|
if (vf) begin
|
if (vf) begin
|
int_num <= 8'd4;
|
int_num <= 8'd4;
|
state <= INT2;
|
state <= INT2;
|
end
|
end
|
else
|
else
|
state <= IFETCH;
|
state <= IFETCH;
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Flag register operations
|
// Flag register operations
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
`STI: begin ie <= 1'b1; state <= IFETCH; end
|
`STI: begin ie <= 1'b1; state <= IFETCH; end
|
`CLI: begin ie <= 1'b0; state <= IFETCH; end
|
`CLI: begin ie <= 1'b0; state <= IFETCH; end
|
`STD: begin df <= 1'b1; state <= IFETCH; end
|
`STD: begin df <= 1'b1; state <= IFETCH; end
|
`CLD: begin df <= 1'b0; state <= IFETCH; end
|
`CLD: begin df <= 1'b0; state <= IFETCH; end
|
`STC: begin cf <= 1'b1; state <= IFETCH; end
|
`STC: begin cf <= 1'b1; state <= IFETCH; end
|
`CLC: begin cf <= 1'b0; state <= IFETCH; end
|
`CLC: begin cf <= 1'b0; state <= IFETCH; end
|
`CMC: begin cf <= !cf; state <= IFETCH; end
|
`CMC: begin cf <= !cf; state <= IFETCH; end
|
`LAHF:
|
`LAHF:
|
begin
|
begin
|
ax[15] <= sf;
|
ax[15] <= sf;
|
ax[14] <= zf;
|
ax[14] <= zf;
|
ax[12] <= af;
|
ax[12] <= af;
|
ax[10] <= pf;
|
ax[10] <= pf;
|
ax[8] <= cf;
|
ax[8] <= cf;
|
state <= IFETCH;
|
state <= IFETCH;
|
end
|
end
|
`SAHF:
|
`SAHF:
|
begin
|
begin
|
sf <= ah[7];
|
sf <= ah[7];
|
zf <= ah[6];
|
zf <= ah[6];
|
af <= ah[4];
|
af <= ah[4];
|
pf <= ah[2];
|
pf <= ah[2];
|
cf <= ah[0];
|
cf <= ah[0];
|
state <= IFETCH;
|
state <= IFETCH;
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// IO instructions
|
// IO instructions
|
// - fetch port number, then vector
|
// - fetch port number, then vector
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
`INB: state <= INB;
|
`INB: state <= INB;
|
`INW: state <= INW;
|
`INW: state <= INW;
|
`OUTB: state <= OUTB;
|
`OUTB: state <= OUTB;
|
`OUTW: state <= OUTW;
|
`OUTW: state <= OUTW;
|
`INB_DX: begin ea <= {`SEG_SHIFT,dx}; state <= INB1; end
|
`INB_DX: begin ea <= {`SEG_SHIFT,dx}; state <= INB1; end
|
`INW_DX: begin ea <= {`SEG_SHIFT,dx}; state <= INW1; end
|
`INW_DX: begin ea <= {`SEG_SHIFT,dx}; state <= INW1; end
|
`OUTB_DX: begin ea <= {`SEG_SHIFT,dx}; state <= OUTB1; end
|
`OUTB_DX: begin ea <= {`SEG_SHIFT,dx}; state <= OUTB1; end
|
`OUTW_DX: begin ea <= {`SEG_SHIFT,dx}; state <= OUTW1; end
|
`OUTW_DX: begin ea <= {`SEG_SHIFT,dx}; state <= OUTW1; end
|
`INSB: state <= INSB;
|
`INSB: state <= INSB;
|
`OUTSB: state <= OUTSB;
|
`OUTSB: state <= OUTSB;
|
`OUTSW: state <= OUTSW;
|
`OUTSW: state <= OUTSW;
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Control Prefix
|
// Control Prefix
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
`LOCK: begin lock_insn <= ir; state <= IFETCH; end
|
`LOCK: begin lock_insn <= ir; state <= IFETCH; end
|
`REPZ,`REPNZ,`CS,`DS,`ES,`SS: state <= IFETCH;
|
`REPZ,`REPNZ,`CS,`DS,`ES,`SS: state <= IFETCH;
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// disp16 instructions
|
// disp16 instructions
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
`MOV_M2AL,`MOV_M2AX,`MOV_AL2M,`MOV_AX2M,`CALL,`JMP:
|
`MOV_M2AL,`MOV_M2AX,`MOV_AL2M,`MOV_AX2M,`CALL,`JMP:
|
begin
|
begin
|
`INITIATE_CODE_READ
|
`INITIATE_CODE_READ
|
state <= FETCH_DISP16_ACK;
|
state <= FETCH_DISP16_ACK;
|
end
|
end
|
|
|
default:
|
default:
|
begin
|
begin
|
|
if (v) shftamt <= cl[3:0];
|
|
else shftamt <= 4'd1;
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// MOD/RM instructions
|
// MOD/RM instructions
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
$display("Fetching mod/rm");
|
$display("Fetching mod/rm");
|
if (ir==`MOV_R2S || ir==`MOV_S2R)
|
if (ir==`MOV_R2S || ir==`MOV_S2R)
|
w <= 1'b1;
|
w <= 1'b1;
|
if (ir==`LDS || ir==`LES)
|
if (ir==`LDS || ir==`LES)
|
w <= 1'b1;
|
w <= 1'b1;
|
if (fetch_modrm) begin
|
if (fetch_modrm) begin
|
`INITIATE_CODE_READ
|
`INITIATE_CODE_READ
|
state <= EACALC;
|
state <= EACALC;
|
end
|
end
|
else
|
else
|
state <= IFETCH;
|
state <= IFETCH;
|
end
|
end
|
endcase
|
endcase
|
|
|