Merge branch 'main' of https://chookspace.com/SpookyDervish/MyLittleCPU
This commit is contained in:
@@ -11,7 +11,9 @@ sources = files(
|
|||||||
|
|
||||||
asmSources = files(
|
asmSources = files(
|
||||||
'src/assembler/main.c',
|
'src/assembler/main.c',
|
||||||
'src/assembler/assemble.c'
|
'src/assembler/assemble.c',
|
||||||
|
'src/assembler/program.c',
|
||||||
|
'src/instruction.c'
|
||||||
)
|
)
|
||||||
|
|
||||||
args = ['-Wall', '-Wextra']
|
args = ['-Wall', '-Wextra']
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "../instruction.h"
|
#include "../instruction.h"
|
||||||
|
|
||||||
@@ -23,12 +24,12 @@ struct _stringToInstructionOpcodeTable {char* str; InstructionOpcode opcode;} st
|
|||||||
{"jiz", INST_JIZ},
|
{"jiz", INST_JIZ},
|
||||||
{"call", INST_CALL},
|
{"call", INST_CALL},
|
||||||
{"ret", INST_RET},
|
{"ret", INST_RET},
|
||||||
{"sys", INST_SYS},
|
{"port", INST_PORT},
|
||||||
{"hlt", INST_HLT},
|
{"hlt", INST_HLT},
|
||||||
};
|
};
|
||||||
|
|
||||||
InstructionOpcode stringToInstructionOpcode(const char* string) {
|
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) {
|
if (strcmp(stringToInstructionOpcodeTable[i].str, string) == 0) {
|
||||||
return stringToInstructionOpcodeTable[i].opcode;
|
return stringToInstructionOpcodeTable[i].opcode;
|
||||||
}
|
}
|
||||||
@@ -38,48 +39,6 @@ InstructionOpcode stringToInstructionOpcode(const char* string) {
|
|||||||
exit(1);
|
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.
|
* Essentially a lexer for the assembly language.
|
||||||
* @param [input] The text to create a program from. NOT the file name
|
* @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 createProgramFromText(const char* input) {
|
||||||
Program program = newProgram();
|
Program program = newProgram();
|
||||||
|
|
||||||
char buf[16] = {'\0'};
|
char buf[32] = {'\0'};
|
||||||
size_t bufSize = 0;
|
size_t bufSize = 0;
|
||||||
size_t programLen = strlen(input);
|
size_t programLen = strlen(input);
|
||||||
size_t current = 0;
|
size_t current = 0;
|
||||||
@@ -96,7 +55,7 @@ Program createProgramFromText(const char* input) {
|
|||||||
bool processingInstWord = true;
|
bool processingInstWord = true;
|
||||||
uint8_t processingArgNum = 0;
|
uint8_t processingArgNum = 0;
|
||||||
|
|
||||||
Instruction currentInst = {};
|
Instruction instruction = {};
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// scan through until we hit a space, colon or new line
|
// scan through until we hit a space, colon or new line
|
||||||
@@ -109,17 +68,75 @@ Program createProgramFromText(const char* input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (processingInstWord) {
|
if (processingInstWord) {
|
||||||
currentInst.opcode = stringToInstructionOpcode(buf);
|
instruction.opcode = stringToInstructionOpcode(buf);
|
||||||
|
processingInstWord = false;
|
||||||
} else {
|
} else {
|
||||||
if (processingArgNum >= 3) {
|
if (processingArgNum >= 3) {
|
||||||
fprintf(stderr, "expecting new line after instruction args, got %s\n", buf);
|
fprintf(stderr, "expecting new line after instruction args, got %s\n", buf);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
OperandType type = INSTRUCTION_OPERAND_TYPES[currentInst.opcode][processingArgNum];
|
OperandType type = INSTRUCTION_OPERAND_TYPES[instruction.opcode][processingArgNum];
|
||||||
if (type == OP_NONE) {
|
switch (type) {
|
||||||
fprintf(stderr, "expecting new line after instruction args, got %s\n", buf);
|
case OP_NONE: {
|
||||||
exit(1);
|
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';
|
buf[0] = '\0';
|
||||||
@@ -131,6 +148,10 @@ Program createProgramFromText(const char* input) {
|
|||||||
// Ignore extra new lines
|
// Ignore extra new lines
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
processingInstWord = true;
|
||||||
|
processingArgNum = 0;
|
||||||
|
buf[0] = '\0';
|
||||||
|
bufSize = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ':': {
|
case ':': {
|
||||||
@@ -149,6 +170,10 @@ Program createProgramFromText(const char* input) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
if (bufSize + 2 >= sizeof(buf)) {
|
||||||
|
fprintf(stderr, "text exceeds buffer size\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
buf[bufSize] = c;
|
buf[bufSize] = c;
|
||||||
buf[bufSize + 1] = '\0';
|
buf[bufSize + 1] = '\0';
|
||||||
bufSize++;
|
bufSize++;
|
||||||
|
|||||||
@@ -1,16 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../instruction.h"
|
#include "program.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);
|
|
||||||
|
|
||||||
Program createProgramFromText(const char* input);
|
Program createProgramFromText(const char* input);
|
||||||
|
|
||||||
|
|||||||
95
src/assembler/program.c
Normal file
95
src/assembler/program.c
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include "program.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
26
src/assembler/program.h
Normal file
26
src/assembler/program.h
Normal file
@@ -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);
|
||||||
|
|
||||||
Reference in New Issue
Block a user