Compare commits

11 Commits

Author SHA1 Message Date
3641e7c928 Update README.md 2025-12-29 10:21:24 +01:00
076d2d0b07 Upload files to "/" 2025-12-29 10:21:04 +01:00
7196dfa42c Update README.md 2024-11-20 10:28:07 +01:00
xamidev
52fa99817c fix: JEQ bug 2024-10-24 17:28:48 +02:00
xamidev
accbdc38e7 minor fixes & error checking but still JE
Q bug?
2024-10-24 17:27:26 +02:00
xamidev
59688d05c4 fix R0 bug 2024-10-24 16:28:45 +02:00
xamidev
6eb02b3b58 fix doc + add 8 regs 2024-10-23 20:25:09 +02:00
xamidev
fd0d05003e add: MUL, DIV instructions 2024-10-23 20:21:02 +02:00
xamidev
ff5e9c07d7 add an example 2024-10-21 22:13:00 +02:00
xamidev
83efce74b9 Update README.md 2024-10-20 17:18:20 +02:00
xamidev
c31fdb2f29 Merge pull request #1 from xamidev/assembler
Add: PUT instruction, Assembler separation
2024-10-20 17:15:55 +02:00
10 changed files with 145 additions and 25 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@
dumb8
das
*.bin
examples/*.bin

View File

@@ -1,8 +1,11 @@
# Dumb8-CPU
![image](dumb8.png)
Continuing my exploration of the lower-level world...
This project is the implementation of a CPU in a high-level language, C. It aims to have a reduced (minimalist) instruction set and still be Turing complete.
In the future, I'd like to implement it in a hardware description language such as VHDL or Verilog.
## How to test
@@ -20,7 +23,7 @@ make
- 8-bit processing unit
- RISC (reduced instruction set computer)
- 4 general purpose registers (labeled R0 to R3)
- 8 general purpose registers (labeled Rx)
- 1 input port, 1 output port (via getchar and putchar)
- Turing-completeness: bitwise and arithmetic operations
@@ -30,9 +33,14 @@ make
; Move register RY to register RX
MOV RX, RY
; Arithmetic addition and substraction stored in RX
; Put value X in register RX
PUT RX, X
; Arithmetic operations. Result stored in RX
ADD RX, RY
SUB RX, RY
MUL RX, RY
DIV RX, RY
; Bitwise operations stored in RX
OR RX, RY
@@ -64,4 +72,4 @@ HLT
## Known bugs
- R0 is not usable (confusion with NOP opcode 0 in memory)
- If you find one, please open an issue. Contributions are highly appreciated!

View File

@@ -106,6 +106,24 @@ void assemble(char* filename)
buffer[i++] = reg1_n;
buffer[i++] = reg2_n;
}
else if (strncmp(line, "MUL", 3) == 0)
{
sscanf(line, "%s %[^,], %s", instruction, reg1, reg2);
int reg1_n = reg1[1] - '0';
int reg2_n = reg2[1] - '0';
buffer[i++] = MUL;
buffer[i++] = reg1_n;
buffer[i++] = reg2_n;
}
else if (strncmp(line, "DIV", 3) == 0)
{
sscanf(line, "%s %[^,], %s", instruction, reg1, reg2);
int reg1_n = reg1[1] - '0';
int reg2_n = reg2[1] - '0';
buffer[i++] = DIV;
buffer[i++] = reg1_n;
buffer[i++] = reg2_n;
}
else if (strncmp(line, "OR", 3) == 0)
{
sscanf(line, "%s %[^,], %s", instruction, reg1, reg2);
@@ -135,10 +153,8 @@ void assemble(char* filename)
}
else if (strncmp(line, "JEQ", 3) == 0)
{
sscanf(line, "%s %[^,], %d", instruction, reg1, &addr);
int reg1_n = reg1[1] - '0';
sscanf(line, "%s %d", instruction, &addr);
buffer[i++] = JEQ;
buffer[i++] = reg1_n;
buffer[i++] = addr;
}
else if (strncmp(line, "JMP", 3) == 0)

38
cpu.c
View File

@@ -26,6 +26,7 @@ void cpu_init()
cpu.halted = false;
cpu.equal_flag = false;
cpu.flag_clear_delay = 0;
cpu.increment = 0;
for (size_t i=0; i<NUM_REGISTERS; i++)
{
cpu.reg[i] = 0;
@@ -74,6 +75,16 @@ void cpu_exec(uint8_t opcode)
reg2 = cpu.memory[cpu.pc++];
cpu.reg[reg1] -= cpu.reg[reg2];
break;
case MUL:
reg1 = cpu.memory[cpu.pc++];
reg2 = cpu.memory[cpu.pc++];
cpu.reg[reg1] *= cpu.reg[reg2];
break;
case DIV:
reg1 = cpu.memory[cpu.pc++];
reg2 = cpu.memory[cpu.pc++];
cpu.reg[reg1] /= cpu.reg[reg2];
break;
case OR:
reg1 = cpu.memory[cpu.pc++];
reg2 = cpu.memory[cpu.pc++];
@@ -97,7 +108,6 @@ void cpu_exec(uint8_t opcode)
cpu.pc = addr;
break;
case JEQ:
reg1 = cpu.memory[cpu.pc++];
addr = cpu.memory[cpu.pc++];
if (cpu.equal_flag) {
cpu.pc = addr;
@@ -122,6 +132,7 @@ void cpu_exec(uint8_t opcode)
cpu.halted = true;
break;
}
cpu.increment++;
}
/*
@@ -175,6 +186,17 @@ void cpu_run()
{
uint8_t opcode = cpu.memory[cpu.pc++];
cpu_exec(opcode);
if (cpu.pc >= MEM_SIZE)
{
printf("\nProgram ended - program counter reached max memsize\n");
break;
}
if (cpu.increment > INF_LOOP_THRESHOLD)
{
printf("\nProgram ended - reached infinite loop threshold\n");
break;
}
}
printf("\n[END CPU OUTPUT]\n");
}
@@ -187,9 +209,9 @@ void cpu_dump()
{
printf("\n*** CPU state dump ***\nPC: 0x%x\nEqual flag: %d\nHalted: %d\n\n", cpu.pc, cpu.equal_flag, cpu.halted);
for (size_t i=0; i<NUM_REGISTERS; i++)
for (size_t i=0; i<NUM_REGISTERS; i+=2)
{
printf("R%lu: 0x%x\n", i, cpu.reg[i]);
printf("R%lu: 0x%04x R%lu: 0x%04x\n", i, cpu.reg[i], i+1, cpu.reg[i+1]);
}
puts("");
}
@@ -200,12 +222,12 @@ void cpu_dump()
void mem_dump()
{
printf("\n*** Memory dump ***\n");
printf("\n*** Memory dump ***");
for (size_t i=0; i<MEM_SIZE; i++)
{
if (i%20 == 0)
{
puts("");
printf("\n%04ld: ", i);
}
switch (cpu.memory[i])
@@ -218,6 +240,8 @@ void mem_dump()
case 0xb0:
case 0xb1:
case 0xb2:
case 0xb3:
printf("\e[43m%02x\e[0m ", cpu.memory[i]);
break;
@@ -242,10 +266,14 @@ void mem_dump()
break;
// General purpose registers (colored foreground)
//case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
printf("\e[36m%02x\e[0m ", cpu.memory[i]);
break;
default:

12
cpu.h
View File

@@ -2,8 +2,9 @@
#define CPU_H
#define MEM_SIZE 256
#define NUM_REGISTERS 4
#define NUM_REGISTERS 8
#define BUF_MAX 256
#define INF_LOOP_THRESHOLD 10000
/*
* Instruction set
@@ -13,9 +14,6 @@
typedef enum
{
// 0x00 -> No operation
NOP = 0,
// 0xA? -> Memory operations
MOV = 0xA0,
PUT = 0xA1,
@@ -23,6 +21,8 @@ typedef enum
// 0xB? -> Arithmetic operations
ADD = 0xB0,
SUB = 0xB1,
MUL = 0xB2,
DIV = 0xB3,
// 0xC? -> Bitwise operations
OR = 0xC0,
@@ -39,12 +39,13 @@ typedef enum
CMP = 0xE2,
// 0xF? -> Misc operations
NOP = 0xFE,
HLT = 0xFF
} instruction_set_t;
/*
* CPU structure definition
* Contains 4 8-bit registers, memory, a program counter, a halt switch, and flags.
* Contains 8-bit registers, memory, a program counter, a halt switch, and flags.
*/
typedef struct
@@ -55,6 +56,7 @@ typedef struct
bool halted;
bool equal_flag;
int flag_clear_delay;
int increment;
} CPU_t;
#endif

BIN
dumb8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

48
examples/hello.asm Normal file
View File

@@ -0,0 +1,48 @@
; Hello, world!
PUT R1, 72
PUT R2, 101
PUT R3, 108
OUT R1
OUT R2
OUT R3
OUT R3
XOR R1, R1
XOR R2, R2
XOR R3, R3
PUT R1, 111
PUT R2, 44
PUT R3, 32
OUT R1
OUT R2
OUT R3
XOR R1, R1
XOR R2, R2
XOR R3, R3
PUT R1, 119
PUT R2, 111
PUT R3, 114
OUT R1
OUT R2
OUT R3
XOR R1, R1
XOR R2, R2
XOR R3, R3
PUT R1, 108
PUT R2, 100
PUT R3, 33
OUT R1
OUT R2
OUT R3
HLT

10
examples/looptext.asm Normal file
View File

@@ -0,0 +1,10 @@
; Loop a "Hi!"
PUT R1, 104
PUT R2, 105
PUT R3, 32
OUT R1
OUT R2
OUT R3
JMP 0
HLT

View File

@@ -7,5 +7,9 @@ all: asm
asm:
$(CC) assembler/*.c $(CFLAGS) -o das
run:
./das program.asm
./dumb8 program.bin
clean:
rm dumb8 das

View File

@@ -1,7 +1,10 @@
;this is a comment
PUT R2, 5
MOV R1, R2
ADD R1, R2
PUT R0, 2
PUT R1, 2
CMP R0, R1
JEQ 12
HLT
PUT R7, 10
HLT