Added support for some more instructions, fixed a bug in CMP and also added a program that uses them

This commit is contained in:
(Tim) Efthimis Kritikos 2023-05-19 17:59:20 +01:00
parent 64f5da82b0
commit 021dd06e9a
6 changed files with 222 additions and 12 deletions

8
.gitignore vendored
View File

@ -6,12 +6,8 @@
*.swp *.swp
*.memdump *.memdump
*.json *.json
boot_code/brainfuck_interpreted.bin boot_code/*.bin
boot_code/brainfuck_interpreted.txt boot_code/*.txt
boot_code/brainfuck_mandelbrot.bin
boot_code/brainfuck_mandelbrot.txt
boot_code/brainfuck_compiled.bin
boot_code/brainfuck_compiled.txt
system/boot_code.bin system/boot_code.bin
system/boot_code.txt system/boot_code.txt
system/obj_dir/ system/obj_dir/

View File

@ -21,7 +21,7 @@ VERILATOR_BIN=system/obj_dir/Vsystem
BOOT_CODE=boot_code/brainfuck_mandelbrot.txt BOOT_CODE=boot_code/brainfuck_mandelbrot.txt
GTKWSAVE=./gtkwave_savefile.gtkw GTKWSAVE=./gtkwave_savefile.gtkw
MICROCODE=system/ucode.txt MICROCODE=system/ucode.txt
BOOTABLES=boot_code/brainfuck_compiled.txt boot_code/brainfuck_interpreted.txt ${BOOT_CODE} BOOTABLES=boot_code/brainfuck_compiled.txt boot_code/brainfuck_interpreted.txt boot_code/pipeline_ideal.txt boot_code/fibonacci.txt ${BOOT_CODE}
NO_ASM=1 NO_ASM=1
include common.mk include common.mk

View File

@ -1,4 +1,4 @@
SOURCE=brainfuck_interpreted.asm brainfuck_compiled.asm brainfuck_mandelbrot.asm pipeline_ideal.asm SOURCE=brainfuck_interpreted.asm brainfuck_compiled.asm brainfuck_mandelbrot.asm pipeline_ideal.asm fibonacci.asm
BINARIES=$(subst .asm,.txt,${SOURCE}) BINARIES=$(subst .asm,.txt,${SOURCE})
BUILD_FILES=${BINARIES} BUILD_FILES=${BINARIES}
BUILD_FILES+=$(subst .asm,.memdump,${SOURCE}) BUILD_FILES+=$(subst .asm,.memdump,${SOURCE})

113
boot_code/fibonacci.asm Normal file
View File

@ -0,0 +1,113 @@
INCLUDE dos_layer.asm
org 0x100
mov sp,#STACK
MOV AX,#0x1
MOV BX,#0x1
CALL PRINT_HEX
push bx
MAIN_LOOP:
pop bx
CALL PRINT_HEX
push AX
ADD AX,BX
JNC MAIN_LOOP
pop bx
MOV AH,#0x02
MOV DL,#0x0a
INT #0x21
hlt
;Input AX
PRINT_HEX:
PUSH DX
TEST AH,#0xF0
jz NOT_FIRST_NIBBLE
MOV DL,AH
CALL PRINT_HIGH
JMP SKIP1
NOT_FIRST_NIBBLE:
TEST AH,#0x0F
jz NOT_SECOND_NIBBLE
SKIP1:
MOV DL,AH
CALL PRINT_LOW
JMP SKIP2
NOT_SECOND_NIBBLE:
TEST AL,#0xF0
jz NOT_THIRD_NIBBLE
SKIP2:
MOV DL,AL
CALL PRINT_HIGH
NOT_THIRD_NIBBLE:
MOV DL,AL
CALL PRINT_LOW
PUSH AX
MOV AH,#0x02
MOV DL,#0x20
INT #0x21
POP AX
POP DX
RET
PRINT_HIGH:
AND DL,#0xF0
TEST DL,#0x80
jz NOT1
OR DL,#0x08
NOT1:
TEST DL,#0x40
jz NOT2
OR DL,#0x04
NOT2:
TEST DL,#0x20
jz NOT3
OR DL,#0x02
NOT3:
TEST DL,#0x10
jz DONE
OR DL,#0x01
DONE:
PRINT_LOW:
PUSH AX
AND DL,#0x0F
CMP DL,#0x0A
JNS LETTERS
ADD DL,#0x30
MOV AH,#0x02
INT #0x21
POP AX
RET
LETTERS:
ADD DL,#0x37
MOV AH,#0x02
INT #0x21
POP AX
RET
.BLKB 200
STACK:
.ORG 0xFFF0
MOV AX,#0x0100
JMP AX

View File

@ -108,6 +108,7 @@ wire [`UCODE_DATA_BITS-1:0] ucode_data;
microcode ucode(seq_addr_input,ucode_data); microcode ucode(seq_addr_input,ucode_data);
`define invalid_instruction next_state=`EXEC_WAIT;ERROR<=`ERR_UNIMPL_INSTRUCTION;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION; `define invalid_instruction next_state=`EXEC_WAIT;ERROR<=`ERR_UNIMPL_INSTRUCTION;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION;
`define unimpl_addressing_mode next_state=`EXEC_WAIT;ERROR <= `ERR_UNIMPL_ADDRESSING_MODE;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION;
//TODO: A possible optimisation for instruction with 8bit parameter and //TODO: A possible optimisation for instruction with 8bit parameter and
@ -203,7 +204,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
in_alu_sel1=2'b00; in_alu_sel1=2'b00;
OUT_MOD=3'b100; OUT_MOD=3'b100;
MEM_OR_IO=0; MEM_OR_IO=0;
ALU_OP=`ALU_OP_SUB; ALU_OP=`ALU_OP_SUB_REVERSE;
memio_address_select=0; memio_address_select=0;
if(IN_MOD==3'b011)begin if(IN_MOD==3'b011)begin
/*compare register with param*/ /*compare register with param*/
@ -379,7 +380,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
in_alu_sel2=2'b01; in_alu_sel2=2'b01;
reg_read_port2_addr={Wbit,3'b000}; reg_read_port2_addr={Wbit,3'b000};
OUT_MOD=3'b100; OUT_MOD=3'b100;
ALU_OP=`ALU_OP_SUB; ALU_OP=`ALU_OP_SUB_REVERSE;
MEM_OR_IO=0; MEM_OR_IO=0;
if(Wbit==1) if(Wbit==1)
next_state=`EXEC_DE_LOAD_16_PARAM; next_state=`EXEC_DE_LOAD_16_PARAM;
@ -438,6 +439,13 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
else else
next_state=`EXEC_WRITE_ENTRY; next_state=`EXEC_WRITE_ENTRY;
end end
3'b001: begin
/* Jump on (not) Carry */
if(FLAGS[0:0]==CIR[8:8])
next_state=`EXEC_NEXT_INSTRUCTION;
else
next_state=`EXEC_WRITE_ENTRY;
end
default:begin default:begin
`invalid_instruction; /*We don't support that condition*/ `invalid_instruction; /*We don't support that condition*/
end end
@ -517,7 +525,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
DEPENDS_ON_PREVIOUS<=0; DEPENDS_ON_PREVIOUS<=0;
end end
11'b1111_011?_000:begin 11'b1111_011?_000:begin
/* TEST - Bitwise AND affecting only flags */ /* TEST - Bitwise AND of immediate and registers/memmory affecting only flags */
/* 1 1 1 1 0 1 1 W | MOD 0 0 0 R/M | < DISP-LO > | < DISP-HI > | DATA | DATA if W */ /* 1 1 1 1 0 1 1 W | MOD 0 0 0 R/M | < DISP-LO > | < DISP-HI > | DATA | DATA if W */
opcode_size=1; opcode_size=1;
Wbit=CIR[8:8]; Wbit=CIR[8:8];
@ -545,6 +553,28 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
DEPENDS_ON_PREVIOUS<=0; DEPENDS_ON_PREVIOUS<=0;
memio_address_select=0; memio_address_select=0;
end end
11'b1010_100?_???:begin
/* TEST - Bitwise AND of immediate and accumulator affecting only flags */
/* 1 0 1 0 1 0 0 W | DATA | DATA if W | */
opcode_size=0;
Wbit=CIR[8:8];
IN_MOD=3'b011;
RM=3'b000;
MEM_OR_IO=0;
if(Wbit==1)begin
next_state=`EXEC_DE_LOAD_16_PARAM;
end else begin
next_state=`EXEC_DE_LOAD_8_PARAM;
end
in_alu_sel1=2'b00; /* PARAM1 */
ALU_OP=`ALU_OP_AND;
in_alu_sel2=2'b01;
reg_read_port2_addr={Wbit,RM};
OUT_MOD=3'b100;/*NULL*/
`normal_instruction;
DEPENDS_ON_PREVIOUS<=0;
memio_address_select=0;
end
11'b0101_1???_???:begin 11'b0101_1???_???:begin
/* POP - REG=[SP]; SP+=2 */ /* POP - REG=[SP]; SP+=2 */
/* | 0 1 0 1 1 REG | */ /* | 0 1 0 1 1 REG | */
@ -651,6 +681,71 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
DEPENDS_ON_PREVIOUS<=0; DEPENDS_ON_PREVIOUS<=0;
memio_address_select=0; memio_address_select=0;
end end
11'b1000_000?_100,11'b1000_000?_001:begin
/* OR - Bitwise OR immediate and register/mem */
/* 1 0 0 0 0 0 0 W | MOD 0 0 1 R/M | < DISP-LO > | < DISP-HI > | DATA | DATA if W */
/* AND - Bitwise AND immediate and register/mem */
/* 1 0 0 0 0 0 0 W | MOD 1 0 0 R/M | < DISP-LO > | < DISP-HI > | DATA | DATA if W */
opcode_size=1;
Wbit=CIR[8:8];
IN_MOD={1'b0,CIR[7:6]};
RM={CIR[2:0]};
MEM_OR_IO=0;
if(Wbit==1)begin
next_state=`EXEC_DE_LOAD_16_PARAM;
end else begin
next_state=`EXEC_DE_LOAD_8_PARAM;
end
in_alu_sel1=2'b00; /* PARAM1 */
case(CIR[5:3])
3'b100: ALU_OP=`ALU_OP_AND;
3'b001: ALU_OP=`ALU_OP_OR;
default:begin end
endcase
case(IN_MOD)
3'b011:begin
in_alu_sel2=2'b01;
reg_read_port2_addr={Wbit,RM};
reg_write_addr={Wbit,RM};
end
default:begin
`unimpl_addressing_mode
end
endcase
OUT_MOD=IN_MOD;
DEPENDS_ON_PREVIOUS<=0;
memio_address_select=0;
`normal_instruction;
end
11'b0000_00??_???:begin
/* ADD - Reg/memory with register to either */
/* 0 0 0 0 0 0 D W | MOD REG R/M | < DISP LO > | < DISP HI > | */
opcode_size=1;
Wbit=CIR[8:8];
Sbit=0;
OUT_MOD={1'b0,CIR[7:6]};
IN_MOD=3'b011;
RM=CIR[2:0];
in_alu_sel1=2'b01;//constantly register
reg_read_port1_addr={Wbit,CIR[5:3]};
if(IN_MOD==3'b011)begin
in_alu_sel2=2'b01;
reg_read_port2_addr={Wbit,RM};
reg_write_addr={Wbit,RM};
next_state=`EXEC_WRITE_ENTRY;
end else begin
in_alu_sel2=2'b00;
if(Wbit)
next_state=`EXEC_DE_LOAD_16_PARAM;
else
next_state=`EXEC_DE_LOAD_8_PARAM;
end
MEM_OR_IO=0;
memio_address_select=0;
ALU_OP=`ALU_OP_ADD;
DEPENDS_ON_PREVIOUS<=0;
`normal_instruction;
end
default:begin default:begin
`invalid_instruction `invalid_instruction
end end
@ -732,6 +827,10 @@ module InstrSize ( input [10:0] IN, output reg [2:0] VERDICT );
11'b1100_1101_??? : VERDICT <= 3'd2; /* INT - execute interrupt handler */ 11'b1100_1101_??? : VERDICT <= 3'd2; /* INT - execute interrupt handler */
11'b1110_011?_??? : VERDICT <= 3'd2; /* OUT - write AL or AX to a defined output port */ 11'b1110_011?_??? : VERDICT <= 3'd2; /* OUT - write AL or AX to a defined output port */
11'b1100_1111_??? : VERDICT <= 3'd1; /* IRET - Return from interrupt */ 11'b1100_1111_??? : VERDICT <= 3'd1; /* IRET - Return from interrupt */
11'b1000_000?_100 : VERDICT <= 3'd3+{2'b0,IN[3:3]}; /* AND - Bitwise AND immediate and register/mem */
11'b1000_000?_001 : VERDICT <= 3'd3+{2'b0,IN[3:3]}; /* OR - Bitwise OR immediate and register/mem */
11'b1010_100?_??? : VERDICT <= 3'd2+{2'b0,IN[3:3]}; /* TEST - Bitwise AND affecting only flags */
11'b0000_00??_??? : VERDICT <= 3'd2; /* ADD - Reg/memory with register to either */
default:begin end default:begin end
endcase endcase
end end
@ -753,3 +852,5 @@ module Is1 ( input [7:0] IN, output reg VERDICT );
end end
endmodule endmodule
`endif `endif
`undef unimpl_addressing_mode

View File

@ -336,6 +336,6 @@ always @(posedge clock) begin
end end
endcase endcase
end end
`undef unimpl_addressing_mode
endmodule endmodule
`undef unimpl_addressing_mode