// ============================================================================
|
// ============================================================================
|
// (C) 2009,2010,2012 Robert Finch
|
// (C) 2009,2010,2012 Robert Finch
|
// robfinch<remove>@opencores.org
|
// robfinch<remove>@opencores.org
|
//
|
//
|
// EXECUTE
|
// EXECUTE
|
// - execute instruction
|
// - execute instruction
|
//
|
//
|
//
|
//
|
// 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
|
//
|
//
|
// ============================================================================
|
// ============================================================================
|
//
|
//
|
EXECUTE:
|
EXECUTE:
|
begin
|
begin
|
casex(ir)
|
casex(ir)
|
|
|
`EXTOP:
|
`EXTOP:
|
casex(ir2)
|
casex(ir2)
|
`LxDT: state <= FETCH_DESC;
|
`LxDT: state <= FETCH_DESC;
|
endcase
|
endcase
|
|
|
`DAA:
|
`DAA:
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
end
|
end
|
|
|
`ALU_I2R8,`ALU_I2R16,`ADD,`ADD_ALI8,`ADD_AXI16,`ADC,`ADC_ALI8,`ADC_AXI16:
|
`ALU_I2R8,`ALU_I2R16,`ADD,`ADD_ALI8,`ADD_AXI16,`ADC,`ADC_ALI8,`ADC_AXI16:
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
res <= alu_o;
|
res <= alu_o;
|
pf <= pres;
|
pf <= pres;
|
af <= carry (1'b0,a[3],b[3],alu_o[3]);
|
af <= carry (1'b0,a[3],b[3],alu_o[3]);
|
cf <= carry (1'b0,amsb,bmsb,resn);
|
cf <= carry (1'b0,amsb,bmsb,resn);
|
vf <= overflow(1'b0,amsb,bmsb,resn);
|
vf <= overflow(1'b0,amsb,bmsb,resn);
|
sf <= resn;
|
sf <= resn;
|
zf <= resz;
|
zf <= resz;
|
end
|
end
|
|
|
`AND,`OR,`XOR,`AND_ALI8,`OR_ALI8,`XOR_ALI8,`AND_AXI16,`OR_AXI16,`XOR_AXI16:
|
`AND,`OR,`XOR,`AND_ALI8,`OR_ALI8,`XOR_ALI8,`AND_AXI16,`OR_AXI16,`XOR_AXI16:
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
res <= alu_o;
|
res <= alu_o;
|
pf <= pres;
|
pf <= pres;
|
cf <= 1'b0;
|
cf <= 1'b0;
|
vf <= 1'b0;
|
vf <= 1'b0;
|
sf <= resn;
|
sf <= resn;
|
zf <= resz;
|
zf <= resz;
|
end
|
end
|
|
|
`TEST:
|
`TEST:
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
res <= alu_o;
|
res <= alu_o;
|
pf <= pres;
|
pf <= pres;
|
cf <= 1'b0;
|
cf <= 1'b0;
|
vf <= 1'b0;
|
vf <= 1'b0;
|
sf <= resn;
|
sf <= resn;
|
zf <= resz;
|
zf <= resz;
|
end
|
end
|
|
|
`CMP,`CMP_ALI8,`CMP_AXI16:
|
`CMP,`CMP_ALI8,`CMP_AXI16:
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
pf <= pres;
|
pf <= pres;
|
af <= carry (1'b1,a[3],b[3],alu_o[3]);
|
af <= carry (1'b1,a[3],b[3],alu_o[3]);
|
cf <= carry (1'b1,amsb,bmsb,resn);
|
cf <= carry (1'b1,amsb,bmsb,resn);
|
vf <= overflow(1'b1,amsb,bmsb,resn);
|
vf <= overflow(1'b1,amsb,bmsb,resn);
|
sf <= resn;
|
sf <= resn;
|
zf <= resz;
|
zf <= resz;
|
end
|
end
|
|
|
`SBB,`SUB,`SBB_ALI8,`SUB_ALI8,`SBB_AXI16,`SUB_AXI16:
|
`SBB,`SUB,`SBB_ALI8,`SUB_ALI8,`SBB_AXI16,`SUB_AXI16:
|
begin
|
begin
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
state <= IFETCH;
|
state <= IFETCH;
|
res <= alu_o;
|
res <= alu_o;
|
pf <= pres;
|
pf <= pres;
|
af <= carry (1'b1,a[3],b[3],alu_o[3]);
|
af <= carry (1'b1,a[3],b[3],alu_o[3]);
|
cf <= carry (1'b1,amsb,bmsb,resn);
|
cf <= carry (1'b1,amsb,bmsb,resn);
|
vf <= overflow(1'b1,amsb,bmsb,resn);
|
vf <= overflow(1'b1,amsb,bmsb,resn);
|
sf <= resn;
|
sf <= resn;
|
zf <= resz;
|
zf <= resz;
|
end
|
end
|
|
|
8'hF6,8'hF7:
|
8'hF6,8'hF7:
|
begin
|
begin
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
state <= IFETCH;
|
state <= IFETCH;
|
case(rrr)
|
case(rrr)
|
3'd2: res <= ~b; // NOT
|
3'd2: res <= ~b; // NOT
|
3'd3: res <= -b; // NEG
|
3'd3: res <= -b; // NEG
|
endcase
|
endcase
|
end
|
end
|
`INC_REG:
|
`INC_REG:
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
w <= 1'b1;
|
w <= 1'b1;
|
res <= alu_o;
|
res <= alu_o;
|
pf <= pres;
|
pf <= pres;
|
af <= carry (1'b0,a[3],b[3],alu_o[3]);
|
af <= carry (1'b0,a[3],b[3],alu_o[3]);
|
vf <= overflow(1'b0,a[15],b[15],resnw);
|
vf <= overflow(1'b0,a[15],b[15],resnw);
|
sf <= resnw;
|
sf <= resnw;
|
zf <= reszw;
|
zf <= reszw;
|
end
|
end
|
`DEC_REG:
|
`DEC_REG:
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
w <= 1'b1;
|
w <= 1'b1;
|
res <= alu_o;
|
res <= alu_o;
|
pf <= pres;
|
pf <= pres;
|
af <= carry (1'b1,a[3],b[3],alu_o[3]);
|
af <= carry (1'b1,a[3],b[3],alu_o[3]);
|
vf <= overflow(1'b1,a[15],b[15],resnw);
|
vf <= overflow(1'b1,a[15],b[15],resnw);
|
sf <= resnw;
|
sf <= resnw;
|
zf <= reszw;
|
zf <= reszw;
|
end
|
end
|
`IMUL:
|
`IMUL:
|
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;
|
if (w) begin
|
if (w) begin
|
cf <= wp[31:16]!={16{resnw}};
|
cf <= wp[31:16]!={16{resnw}};
|
vf <= wp[31:16]!={16{resnw}};
|
vf <= wp[31:16]!={16{resnw}};
|
dx <= wp[31:16];
|
dx <= wp[31:16];
|
end
|
end
|
else begin
|
else begin
|
cf <= ah!={8{resnb}};
|
cf <= ah!={8{resnb}};
|
vf <= ah!={8{resnb}};
|
vf <= ah!={8{resnb}};
|
end
|
end
|
end
|
end
|
|
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Memory Operations
|
// Memory Operations
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
|
|
// registers not allowed on LEA
|
// registers not allowed on LEA
|
// invalid opcode
|
// invalid opcode
|
//
|
//
|
`LEA:
|
`LEA:
|
begin
|
begin
|
w <= 1'b1;
|
w <= 1'b1;
|
res <= ea;
|
res <= ea;
|
if (mod==2'b11) begin
|
if (mod==2'b11) begin
|
int_num <= 8'h06;
|
int_num <= 8'h06;
|
state <= INT;
|
state <= INT;
|
end
|
end
|
else begin
|
else begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
end
|
end
|
end
|
end
|
`LDS:
|
`LDS:
|
begin
|
begin
|
wrsregs <= 1'b1;
|
wrsregs <= 1'b1;
|
res <= alu_o;
|
res <= alu_o;
|
rrr <= 3'd3;
|
rrr <= 3'd3;
|
state <= IFETCH;
|
state <= IFETCH;
|
end
|
end
|
`LES:
|
`LES:
|
begin
|
begin
|
wrsregs <= 1'b1;
|
wrsregs <= 1'b1;
|
res <= alu_o;
|
res <= alu_o;
|
rrr <= 3'd0;
|
rrr <= 3'd0;
|
state <= IFETCH;
|
state <= IFETCH;
|
end
|
end
|
|
|
`MOV_RR8,`MOV_RR16,
|
`MOV_RR8,`MOV_RR16,
|
`MOV_MR,
|
`MOV_MR,
|
`MOV_M2AL,`MOV_M2AX,
|
`MOV_M2AL,`MOV_M2AX,
|
`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,
|
`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
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
res <= alu_o;
|
res <= alu_o;
|
end
|
end
|
`XCHG_MEM:
|
`XCHG_MEM:
|
begin
|
begin
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
if (mod==2'b11) rrr <= rm;
|
if (mod==2'b11) rrr <= rm;
|
res <= alu_o;
|
res <= alu_o;
|
b <= rrro;
|
b <= rrro;
|
state <= mod==2'b11 ? IFETCH : XCHG_MEM;
|
state <= mod==2'b11 ? IFETCH : XCHG_MEM;
|
end
|
end
|
`MOV_I8M,`MOV_I16M:
|
`MOV_I8M,`MOV_I16M:
|
begin
|
begin
|
res <= alu_o;
|
res <= alu_o;
|
state <= rrr==3'd0 ? STORE_DATA : INVALID_OPCODE;
|
state <= rrr==3'd0 ? STORE_DATA : INVALID_OPCODE;
|
end
|
end
|
|
|
`MOV_S2R:
|
`MOV_S2R:
|
begin
|
begin
|
w <= 1'b1;
|
w <= 1'b1;
|
rrr <= rm;
|
rrr <= rm;
|
res <= b;
|
res <= b;
|
if (mod==2'b11) begin
|
if (mod==2'b11) begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
end
|
end
|
else
|
else
|
state <= STORE_DATA;
|
state <= STORE_DATA;
|
end
|
end
|
`MOV_R2S:
|
`MOV_R2S:
|
begin
|
begin
|
wrsregs <= 1'b1;
|
wrsregs <= 1'b1;
|
res <= alu_o;
|
res <= alu_o;
|
state <= IFETCH;
|
state <= IFETCH;
|
end
|
end
|
|
|
`LODSB:
|
`LODSB:
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
w <= 1'b0;
|
w <= 1'b0;
|
rrr <= 3'd0;
|
rrr <= 3'd0;
|
res <= a[7:0];
|
res <= a[7:0];
|
if ( df) si <= si_dec;
|
if ( df) si <= si_dec;
|
if (!df) si <= si_inc;
|
if (!df) si <= si_inc;
|
end
|
end
|
`LODSW:
|
`LODSW:
|
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 <= a;
|
res <= a;
|
if ( df) si <= si - 16'd2;
|
if ( df) si <= si - 16'd2;
|
if (!df) si <= si + 16'd2;
|
if (!df) si <= si + 16'd2;
|
end
|
end
|
|
|
8'hD0,8'hD1,8'hD2,8'hD3,8'hC0,8'hC1:
|
8'hD0,8'hD1,8'hD2,8'hD3,8'hC0,8'hC1:
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
|
rrr <= rm;
|
if (w)
|
if (w)
|
case(rrr)
|
case(rrr)
|
3'b000: // ROL
|
3'b000: // ROL
|
begin
|
begin
|
res <= shlo[15:0]|shlo[31:16];
|
res <= shlo[15:0]|shlo[31:16];
|
cf <= bmsb;
|
cf <= bmsb;
|
vf <= bmsb^b[14];
|
vf <= bmsb^b[14];
|
end
|
end
|
3'b001: // ROR
|
3'b001: // ROR
|
begin
|
begin
|
res <= shruo[15:0]|shruo[31:16];
|
res <= shruo[15:0]|shruo[31:16];
|
cf <= b[0];
|
cf <= b[0];
|
vf <= cf^b[15];
|
vf <= cf^b[15];
|
end
|
end
|
3'b010: // RCL
|
3'b010: // RCL
|
begin
|
begin
|
res <= shlco[16:1]|shlco[32:17];
|
res <= shlco[16:1]|shlco[32:17];
|
cf <= b[15];
|
cf <= b[15];
|
vf <= b[15]^b[14];
|
vf <= b[15]^b[14];
|
end
|
end
|
3'b011: // RCR
|
3'b011: // RCR
|
begin
|
begin
|
res <= shrcuo[15:0]|shrcuo[31:16];
|
res <= shrcuo[15:0]|shrcuo[31:16];
|
cf <= b[0];
|
cf <= b[0];
|
vf <= cf^b[15];
|
vf <= cf^b[15];
|
end
|
end
|
3'b100: // SHL
|
3'b100: // SHL
|
begin
|
begin
|
|
$display("SHL:%h,%h,%d",shlo[15:0],b,shftamt);
|
res <= shlo[15:0];
|
res <= shlo[15:0];
|
cf <= shlo[16];
|
cf <= shlo[16];
|
vf <= b[15]^b[14];
|
vf <= b[15]^b[14];
|
end
|
end
|
3'b101: // SHR
|
3'b101: // SHR
|
begin
|
begin
|
|
$display("SHR:%h,%h,%d",shruo[31:16],b,shftamt);
|
res <= shruo[31:16];
|
res <= shruo[31:16];
|
cf <= shruo[15];
|
cf <= shruo[15];
|
vf <= b[15];
|
vf <= b[15];
|
end
|
end
|
3'b111: // SAR
|
3'b111: // SAR
|
begin
|
begin
|
res <= shro;
|
res <= shro;
|
cf <= b[0];
|
cf <= b[0];
|
vf <= 1'b0;
|
vf <= 1'b0;
|
end
|
end
|
endcase
|
endcase
|
else
|
else
|
case(rrr)
|
case(rrr)
|
3'b000: // ROL
|
3'b000: // ROL
|
begin
|
begin
|
res <= shlo8[7:0]|shlo8[15:8];
|
res <= shlo8[7:0]|shlo8[15:8];
|
cf <= b[7];
|
cf <= b[7];
|
vf <= b[7]^b[6];
|
vf <= b[7]^b[6];
|
end
|
end
|
3'b001: // ROR
|
3'b001: // ROR
|
begin
|
begin
|
res <= shruo8[15:8]|shruo8[7:0];
|
res <= shruo8[15:8]|shruo8[7:0];
|
cf <= b[0];
|
cf <= b[0];
|
vf <= cf^b[7];
|
vf <= cf^b[7];
|
end
|
end
|
3'b010: // RCL
|
3'b010: // RCL
|
begin
|
begin
|
res <= shlco8[8:1]|shlco8[16:9];
|
res <= shlco8[8:1]|shlco8[16:9];
|
cf <= b[7];
|
cf <= b[7];
|
vf <= b[7]^b[6];
|
vf <= b[7]^b[6];
|
end
|
end
|
3'b011: // RCR
|
3'b011: // RCR
|
begin
|
begin
|
res <= shrcuo8[15:8]|shrcuo8[7:0];
|
res <= shrcuo8[15:8]|shrcuo8[7:0];
|
cf <= b[0];
|
cf <= b[0];
|
vf <= cf^b[7];
|
vf <= cf^b[7];
|
end
|
end
|
3'b100: // SHL
|
3'b100: // SHL
|
begin
|
begin
|
res <= shlo8[7:0];
|
res <= shlo8[7:0];
|
cf <= shlo8[8];
|
cf <= shlo8[8];
|
vf <= b[7]^b[6];
|
vf <= b[7]^b[6];
|
end
|
end
|
3'b101: // SHR
|
3'b101: // SHR
|
begin
|
begin
|
res <= shruo8[15:8];
|
res <= shruo8[15:8];
|
cf <= shruo8[7];
|
cf <= shruo8[7];
|
vf <= b[7];
|
vf <= b[7];
|
end
|
end
|
3'b111: // SAR
|
3'b111: // SAR
|
begin
|
begin
|
res <= shro8;
|
res <= shro8;
|
cf <= b[0];
|
cf <= b[0];
|
vf <= 1'b0;
|
vf <= 1'b0;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
`GRPFF:
|
`GRPFF:
|
begin
|
begin
|
case(rrr)
|
case(rrr)
|
3'b000: // INC
|
3'b000: // INC
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
af <= carry (1'b0,a[3],b[3],alu_o[3]);
|
af <= carry (1'b0,a[3],b[3],alu_o[3]);
|
vf <= overflow(1'b0,a[15],b[15],alu_o[15]);
|
vf <= overflow(1'b0,a[15],b[15],alu_o[15]);
|
w <= 1'b1;
|
w <= 1'b1;
|
res <= alu_o;
|
res <= alu_o;
|
rrr <= rm;
|
rrr <= rm;
|
pf <= pres;
|
pf <= pres;
|
sf <= resnw;
|
sf <= resnw;
|
zf <= reszw;
|
zf <= reszw;
|
end
|
end
|
3'b001: // DEC
|
3'b001: // DEC
|
begin
|
begin
|
state <= IFETCH;
|
state <= IFETCH;
|
wrregs <= 1'b1;
|
wrregs <= 1'b1;
|
af <= carry (1'b1,a[3],b[3],alu_o[3]);
|
af <= carry (1'b1,a[3],b[3],alu_o[3]);
|
vf <= overflow(1'b1,a[15],b[15],alu_o[15]);
|
vf <= overflow(1'b1,a[15],b[15],alu_o[15]);
|
w <= 1'b1;
|
w <= 1'b1;
|
res <= alu_o;
|
res <= alu_o;
|
rrr <= rm;
|
rrr <= rm;
|
pf <= pres;
|
pf <= pres;
|
sf <= resnw;
|
sf <= resnw;
|
zf <= reszw;
|
zf <= reszw;
|
end
|
end
|
3'b010: begin sp <= sp_dec; state <= CALL_IN; end
|
3'b010: begin sp <= sp_dec; state <= CALL_IN; end
|
// These two should not be reachable here, as they would
|
// These two should not be reachable here, as they would
|
// be trapped by the EACALC.
|
// be trapped by the EACALC.
|
3'b011: state <= CALL_FIN; // CALL FAR indirect
|
3'b011: state <= CALL_FIN; // CALL FAR indirect
|
3'b101: // JMP FAR indirect
|
3'b101: // JMP FAR indirect
|
begin
|
begin
|
ip <= offset;
|
ip <= offset;
|
cs <= selector;
|
cs <= selector;
|
state <= IFETCH;
|
state <= IFETCH;
|
end
|
end
|
3'b110: begin sp <= sp_dec; state <= PUSH; end
|
3'b110: begin sp <= sp_dec; state <= PUSH; end
|
default:
|
default:
|
begin
|
begin
|
af <= carry (1'b0,a[3],b[3],alu_o[3]);
|
af <= carry (1'b0,a[3],b[3],alu_o[3]);
|
vf <= overflow(1'b0,a[15],b[15],alu_o[15]);
|
vf <= overflow(1'b0,a[15],b[15],alu_o[15]);
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
default:
|
default:
|
state <= IFETCH;
|
state <= IFETCH;
|
endcase
|
endcase
|
end
|
end
|
|
|
|
|