From 68b76677255688d7f1f6435894b7981e70c411b8 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Thu, 16 Jul 2026 14:01:36 +1000 Subject: [PATCH] refactor a couple things --- meson.build | 4 +- src/assembler/assemble.c | 127 +++++++++++++++++++++++---------------- src/assembler/assemble.h | 12 +--- src/assembler/program.c | 95 +++++++++++++++++++++++++++++ src/assembler/program.h | 26 ++++++++ 5 files changed, 201 insertions(+), 63 deletions(-) create mode 100644 src/assembler/program.c create mode 100644 src/assembler/program.h diff --git a/meson.build b/meson.build index fb0eeb3..3eefbc5 100644 --- a/meson.build +++ b/meson.build @@ -10,7 +10,9 @@ sources = files( asmSources = files( 'src/assembler/main.c', - 'src/assembler/assemble.c' + 'src/assembler/assemble.c', + 'src/assembler/program.c', + 'src/instruction.c' ) args = ['-Wall', '-Wextra'] diff --git a/src/assembler/assemble.c b/src/assembler/assemble.c index 90bb02e..4cf3641 100644 --- a/src/assembler/assemble.c +++ b/src/assembler/assemble.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "../instruction.h" @@ -23,12 +24,12 @@ struct _stringToInstructionOpcodeTable {char* str; InstructionOpcode opcode;} st {"jiz", INST_JIZ}, {"call", INST_CALL}, {"ret", INST_RET}, - {"sys", INST_SYS}, + {"port", INST_PORT}, {"hlt", INST_HLT}, }; InstructionOpcode stringToInstructionOpcode(const char* string) { - for (size_t i = 0; i < sizeof(stringToInstructionOpcodeTable) / sizeof(struct _stringToInstructionOpcodeTable)); i++) { + for (size_t i = 0; i < 16; i++) { if (strcmp(stringToInstructionOpcodeTable[i].str, string) == 0) { return stringToInstructionOpcodeTable[i].opcode; } @@ -38,48 +39,6 @@ InstructionOpcode stringToInstructionOpcode(const char* string) { exit(1); } -Program newProgram(void) { - Program program = { - .at = malloc(sizeof(Instruction) * 16), - .len = 0, - .capacity = 16 - }; - - if (program.at == NULL) { - fprintf(stderr, "malloc failed while creating new program\n"); - exit(1); - } - return program; -} - -void addInstructionToProgram(Program* program, Instruction inst) { - if (program->at == NULL) { - fprintf(stderr, "unexpected NULL value when adding instruction to program\n"); - exit(1); - } - - if (program->len + 1 >= program->capacity) { - Instruction* tmp = malloc(sizeof(Instruction) * program->capacity * 2); - if (tmp == NULL) { - fprintf(stderr, "malloc failed while expanding program\n"); - exit(1); - } - program->at = tmp; - program->capacity *= 2; - } - - program->at[program->len] = inst; - program->len++; -} - -void freeProgram(Program* program) { - if (program->at != NULL) { - free(program->at); - } - program->capacity = 0; - program->len = 0; -} - /** * Essentially a lexer for the assembly language. * @param [input] The text to create a program from. NOT the file name @@ -88,7 +47,7 @@ void freeProgram(Program* program) { Program createProgramFromText(const char* input) { Program program = newProgram(); - char buf[16] = {'\0'}; + char buf[32] = {'\0'}; size_t bufSize = 0; size_t programLen = strlen(input); size_t current = 0; @@ -96,7 +55,7 @@ Program createProgramFromText(const char* input) { bool processingInstWord = true; uint8_t processingArgNum = 0; - Instruction currentInst = {}; + Instruction instruction = {}; for (;;) { // scan through until we hit a space, colon or new line @@ -109,17 +68,75 @@ Program createProgramFromText(const char* input) { } if (processingInstWord) { - currentInst.opcode = stringToInstructionOpcode(buf); + instruction.opcode = stringToInstructionOpcode(buf); + processingInstWord = false; } else { if (processingArgNum >= 3) { fprintf(stderr, "expecting new line after instruction args, got %s\n", buf); exit(1); } - OperandType type = INSTRUCTION_OPERAND_TYPES[currentInst.opcode][processingArgNum]; - if (type == OP_NONE) { - fprintf(stderr, "expecting new line after instruction args, got %s\n", buf); - exit(1); + OperandType type = INSTRUCTION_OPERAND_TYPES[instruction.opcode][processingArgNum]; + switch (type) { + case OP_NONE: { + fprintf(stderr, "expecting new line after instruction args, got %s\n", buf); + exit(1); + } + case OP_REG: { + if (bufSize > 1) { + fprintf(stderr, "expecting register identifier, got %s\n", buf); + exit(1); + } + switch (buf[0]) { + case 'a': + case 'A': + instruction.operands[processingArgNum] = REG_A; + break; + case 'b': + case 'B': + instruction.operands[processingArgNum] = REG_B; + break; + case 'c': + case 'C': + instruction.operands[processingArgNum] = REG_C; + break; + case 'x': + case 'X': + instruction.operands[processingArgNum] = REG_X; + break; + case 'y': + case 'Y': + instruction.operands[processingArgNum] = REG_Y; + break; + case 'z': + case 'Z': + instruction.operands[processingArgNum] = REG_Z; + break; + case 'r': + case 'R': + instruction.operands[processingArgNum] = REG_R; + break; + case 'f': + case 'F': + instruction.operands[processingArgNum] = REG_F; + break; + + default: { + fprintf(stderr, "expecting register identifier, got %s\n", buf); + exit(1); + } + } + break; + } + case OP_IMM16: { + char* endptr; + instruction.immediate = strtol(buf, &endptr, 0); + if (endptr == (char*)buf) { + fprintf(stderr, "couldn't convert %s to a number\n", buf); + exit(1); + } + } } + processingArgNum++; } buf[0] = '\0'; @@ -131,6 +148,10 @@ Program createProgramFromText(const char* input) { // Ignore extra new lines break; } + processingInstWord = true; + processingArgNum = 0; + buf[0] = '\0'; + bufSize = 0; break; } case ':': { @@ -149,6 +170,10 @@ Program createProgramFromText(const char* input) { break; } default: { + if (bufSize + 2 >= sizeof(buf)) { + fprintf(stderr, "text exceeds buffer size\n"); + exit(1); + } buf[bufSize] = c; buf[bufSize + 1] = '\0'; bufSize++; diff --git a/src/assembler/assemble.h b/src/assembler/assemble.h index a17c380..3ce457b 100644 --- a/src/assembler/assemble.h +++ b/src/assembler/assemble.h @@ -1,16 +1,6 @@ #pragma once -#include "../instruction.h" - -typedef struct { - Instruction* at; - size_t len; - size_t capacity; -} Program; - -Program newProgram(void); -void addInstructionToProgram(Program* program, Instruction inst); -void freeProgram(Program* program); +#include "program.h" Program createProgramFromText(const char* input); diff --git a/src/assembler/program.c b/src/assembler/program.c new file mode 100644 index 0000000..248ab72 --- /dev/null +++ b/src/assembler/program.c @@ -0,0 +1,95 @@ +#include "program.h" + +#include +#include +#include + +Program newProgram(void) { + Program program = { + .at = malloc(sizeof(Instruction) * 16), + .len = 0, + .capacity = 16, + .labels = { + .at = malloc(sizeof(Instruction) * 16), + .len = 0, + .capacity = 16, + } + }; + + if (program.at == NULL || program.labels.at == NULL) { + fprintf(stderr, "malloc failed while creating new program\n"); + exit(1); + } + return program; +} + +void addInstructionToProgram(Program* program, Instruction inst) { + if (program->at == NULL) { + fprintf(stderr, "unexpected NULL value when adding instruction to program\n"); + exit(1); + } + + if (program->len + 1 >= program->capacity) { + Instruction* tmp = malloc(sizeof(Instruction) * program->capacity * 2); + if (tmp == NULL) { + fprintf(stderr, "malloc failed while expanding program\n"); + exit(1); + } + program->at = tmp; + program->capacity *= 2; + } + + program->at[program->len] = inst; + program->len++; +} + +void addLabelToProgram(Program* program, const char* name, uint8_t position) { + if (program->labels.at == NULL) { + fprintf(stderr, "unexpected NULL value when adding label to program\n"); + exit(1); + } + + if (program->labels.len + 1 >= program->labels.capacity) { + Label* tmp = malloc(sizeof(Label) * program->labels.capacity * 2); + if (tmp == NULL) { + fprintf(stderr, "malloc failed while expanding program labels\n"); + exit(1); + } + program->labels.at = tmp; + program->labels.capacity *= 2; + } + + char* nameCopy = malloc(strlen(name) + 1); + if (nameCopy == NULL) { + fprintf(stderr, "malloc failed while expanding program labels\n"); + exit(1); + } + + strcpy(nameCopy, name); + + program->labels.at[program->labels.len] = (Label) { + .name = nameCopy, + .position = position + }; + program->labels.len++; +} + +void freeProgram(Program* program) { + if (program->at != NULL) { + free(program->at); + } + program->at = NULL; + program->capacity = 0; + program->len = 0; + + if (program->labels.at != NULL) { + for (size_t i = 0; i < program->labels.len; i++) { + free(program->labels.at[i].name); + } + free(program->labels.at); + } + program->labels.at = NULL; + program->labels.capacity = 0; + program->labels.len = 0; +} + diff --git a/src/assembler/program.h b/src/assembler/program.h new file mode 100644 index 0000000..fb07468 --- /dev/null +++ b/src/assembler/program.h @@ -0,0 +1,26 @@ +#pragma once + +#include "../instruction.h" + +typedef struct { + char* name; + uint8_t position; +} Label; + +typedef struct { + Instruction* at; + size_t len; + size_t capacity; + + struct { + Label* at; + size_t len; + size_t capacity; + } labels; +} Program; + +Program newProgram(void); +void addInstructionToProgram(Program* program, Instruction inst); +void addLabelToProgram(Program* program, const char* name, uint8_t position); +void freeProgram(Program* program); +