/* * Unnamed 8-bit processing unit * Made by github.com/xamidev * * This is free and unencumbered software released into the public domain. * For more information, please refer to */ #include #include #include #include #include #define MEM_SIZE 256 #define NUM_REGISTERS 4 /* * Instruction set * Here, we're making a RISC (reduced instruction set computer) * so we're staying minimalistic. */ typedef enum { // TODO: Bitwise operations (OR, AND, XOR, NOT, ...) NOP = 0, MOV = 1, ADD, SUB, LOAD, STORE, JMP, JEQ, CMP, HLT = 0xFF } instruction_set_t; /* * CPU structure definition * Contains 4 8-bit registers, memory, a program counter, a halt switch, and flags. */ typedef struct { uint8_t reg[NUM_REGISTERS]; uint8_t memory[MEM_SIZE]; uint16_t pc; bool halted; bool equal_flag; int flag_clear_delay; } CPU_t; CPU_t cpu; /* * Initializing the CPU: program counter and registers to zero, halted flag to false. */ void cpu_init() { cpu.pc = 0; cpu.halted = false; cpu.equal_flag = false; cpu.flag_clear_delay = 0; for (size_t i=0; i 0) { cpu.flag_clear_delay--; if (cpu.flag_clear_delay == 0) { cpu.equal_flag = false; } } switch (opcode) { case NOP: break; case MOV: reg1 = cpu.memory[cpu.pc++]; reg2 = cpu.memory[cpu.pc++]; cpu.reg[reg1] = cpu.reg[reg2]; break; case ADD: reg1 = cpu.memory[cpu.pc++]; reg2 = cpu.memory[cpu.pc++]; cpu.reg[reg1] += cpu.reg[reg2]; break; case HLT: cpu.halted = true; break; case JMP: addr = cpu.memory[cpu.pc++]; cpu.pc = addr; break; case JEQ: reg1 = cpu.memory[cpu.pc++]; addr = cpu.memory[cpu.pc++]; if (cpu.equal_flag) { cpu.pc = addr; } break; case CMP: reg1 = cpu.memory[cpu.pc++]; reg2 = cpu.memory[cpu.pc++]; cpu.equal_flag = (cpu.reg[reg1] == cpu.reg[reg2]); cpu.flag_clear_delay = 2; break; // TODO: complete instruction set default: printf("Unknown instruction: 0x%02X\n", opcode); cpu.halted = true; break; } } /* * Loading the program in memory */ void cpu_load(const uint8_t* program, size_t size) { for (size_t i=0; i\n", argv[0]); return -1; } assemble(argv[1]); // Dumping our program mem_dump(); reg_write(2, 0x10); cpu_run(); // Post-mortem analysis cpu_dump(); return 0; }