#include #include #include #include enum overture_mode { IMMEDIATE, CALCULATE, COPY, CONDITION }; enum overture_calculate_mode { OR, NAND, NOR, AND, ADD, SUB }; enum overture_condition_mode { NEVER, EQZ, LTZ, LTEQZ, ALWAYS, NEQZ, GTEQZ, GTZ }; enum overture_registers { R0, R1, R2, R3, R4, R5, INPUT_OUTPUT }; void overture_immediate(uint8_t immediate, uint8_t* r0) { *r0 = immediate; } void overture_alu_calculate(enum overture_calculate_mode mode, uint8_t r1, uint8_t r2, uint8_t* r3) { switch (mode) { case OR: *r3 = r1 | r2; break; case NAND: *r3 = ~(r1 & r2); break; case NOR: *r3 = ~(r1 | r2); break; case AND: *r3 = r1 & r2; break; case ADD: *r3 = r1 + r2; break; case SUB: *r3 = r1 - r2; break; } }; void overture_register_copy(uint8_t* source, uint8_t* destination) { *destination = *source; }; void overture_condition_jump(enum overture_condition_mode mode, uint8_t r0, uint8_t r3, uint8_t* program_counter) { switch (mode) { case NEVER: return; case EQZ: if (r3 == 0) *program_counter = r0; break; case LTZ: if (r3 < 0) *program_counter = r0; break; case LTEQZ: if (r3 <= 0) *program_counter = r0; break; case ALWAYS: *program_counter = r0; break; case NEQZ: if (r3 != 0) *program_counter = r0; break; case GTEQZ: if (r3 >= 0) *program_counter = r0; break; case GTZ: if (r3 > 0) *program_counter = r0; break; }; } typedef union overture_instruction { uint8_t instruction; union { struct { uint8_t combined_immediate : 6; uint8_t overture_mode : 2; }; struct { uint8_t right_operand : 3; uint8_t left_operand : 3; }; }; } overture_instruction; void overture_fetch_instruction(uint8_t program_counter, uint8_t* current_instruction, uint8_t rom[256]) { *current_instruction = rom[program_counter - 1]; } typedef struct overture { bool step_mode; int clock_speed_hz; uint8_t program_counter; uint8_t r0; uint8_t r1; uint8_t r2; uint8_t r3; uint8_t r4; uint8_t r5; uint8_t input; uint8_t output; bool output_enable; overture_instruction current_instruction; } overture; void sleep_hz(int hz) { usleep(1000000 / hz); }; uint8_t* multiplex_source(uint8_t operand, overture* cpu) { uint8_t* source; switch (operand) { case R0: source = &(cpu->r0); break; case R1: source = &(cpu->r1); break; case R2: source = &(cpu->r2); break; case R3: source = &(cpu->r3); break; case R4: source = &(cpu->r4); break; case R5: source = &(cpu->r5); break; case INPUT_OUTPUT: source = &(cpu->input); break; } return source; } uint8_t* multiplex_destination(uint8_t operand, overture* cpu) { uint8_t* destination; switch (operand) { case R0: destination = &(cpu->r0); break; case R1: destination = &(cpu->r1); break; case R2: destination = &(cpu->r2); break; case R3: destination = &(cpu->r3); break; case R4: destination = &(cpu->r4); break; case R5: destination = &(cpu->r5); break; case INPUT_OUTPUT: destination = &(cpu->output); break; } return destination; } void overture_execute_instruction(overture_instruction instruction, overture* cpu) { uint8_t* source_register = multiplex_source(instruction.left_operand, cpu); uint8_t* destination_register = multiplex_destination(instruction.right_operand, cpu); switch (instruction.overture_mode) { case IMMEDIATE: overture_immediate(instruction.combined_immediate, &(cpu->r0)); break; case CALCULATE: overture_alu_calculate(instruction.right_operand, cpu->r1, cpu->r2, &(cpu->r3)); break; case COPY: overture_register_copy(source_register, destination_register); if (instruction.right_operand == INPUT_OUTPUT) { cpu->output_enable = true; } break; case CONDITION: overture_condition_jump(instruction.right_operand, cpu->r0, cpu->r3, &(cpu->program_counter)); break; }; } void cpu_diagnostics(overture* cpu) { if (cpu->step_mode) { printf("Step mode\n"); } else { printf("Clock speed: %dhz\n", cpu->clock_speed_hz); } printf("Program counter: %d\n\n", cpu->program_counter); printf("r0: %d\n", cpu->r0); printf("r1: %d\n", cpu->r1); printf("r2: %d\n", cpu->r2); printf("r3: %d\n", cpu->r3); printf("r4: %d\n", cpu->r4); printf("r5: %d\n\n", cpu->r5); printf("input: %d\n", cpu->input); printf("output: %d\n", cpu->output); printf("Output enabled?: %d\n\n", cpu->output_enable); printf("Current instruction: %d\n", cpu->current_instruction.instruction); printf("Mode: %d\n", cpu->current_instruction.overture_mode); printf("Left Operand: %d\n", cpu->current_instruction.left_operand); printf("Right Operand: %d\n", cpu->current_instruction.right_operand); printf("Combined Immediate: %d\n\n", cpu->current_instruction.combined_immediate); } void overture_cycle(overture* cpu, uint8_t rom[256]) { if (cpu->program_counter == 255) { cpu->program_counter = 0; }; cpu->program_counter += 1; cpu->output_enable = false; overture_fetch_instruction(cpu->program_counter, &(cpu->current_instruction.instruction), rom); overture_execute_instruction(cpu->current_instruction, cpu); cpu_diagnostics(cpu); } void overture_start_clock(overture* cpu, uint8_t rom[256]) { while (true) { if (cpu->step_mode) { getchar(); } else { sleep_hz(cpu->clock_speed_hz); } overture_cycle(cpu, rom); }; } int main() { uint8_t rom[256] = { 63, 129, 7, 130, 68 , 158 }; overture cpu = { .step_mode = true, .clock_speed_hz = 1, .program_counter = 0, .r0 = 0, .r1 = 0, .r2 = 0, .r3 = 0, .r4 = 0, .r5 = 0, .input = 0, .output = 0, .output_enable = true, .current_instruction.instruction = 0 }; overture_start_clock(&cpu, rom); return 0; }