Compare commits

...

2 Commits

2 changed files with 110 additions and 75 deletions

View File

@@ -42,6 +42,104 @@ InstructionOpcode stringToInstructionOpcode(const char* string) {
exit(1);
}
static void processBufferedToken(
char* buf,
size_t bufSize,
Instruction* instruction,
bool* processingInstWord,
uint8_t* processingArgNum
) {
if (*processingInstWord) {
instruction->opcode = stringToInstructionOpcode(buf);
*processingInstWord = false;
return;
}
if (*processingArgNum >= 3) {
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_IMM4: {
char* endptr;
long value = strtol(buf, &endptr, 0);
if (endptr == (char*)buf) {
fprintf(stderr, "couldn't convert %s to a number\n", buf);
exit(1);
}
if (value < 0 || value > 0xF) {
fprintf(stderr, "%s is out of range for a 4-bit immediate\n", buf);
exit(1);
}
instruction->operands[*processingArgNum] = (Register)value;
break;
}
case OP_IMM16: {
char* endptr;
instruction->immediate = strtol(buf, &endptr, 0);
instruction->hasImm16 = true;
if (endptr == (char*)buf) {
fprintf(stderr, "couldn't convert %s to a number\n", buf);
exit(1);
}
break;
}
}
(*processingArgNum)++;
}
/**
* Essentially a lexer for the assembly language.
* @param [input] The text to create a program from. NOT the file name
@@ -72,79 +170,7 @@ Program createProgramFromText(const char* input) {
break;
}
if (processingInstWord) {
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[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);
instruction.hasImm16 = true;
if (endptr == (char*)buf) {
fprintf(stderr, "couldn't convert %s to a number\n", buf);
exit(1);
}
break;
}
}
processingArgNum++;
}
processBufferedToken(buf, bufSize, &instruction, &processingInstWord, &processingArgNum);
buf[0] = '\0';
bufSize = 0;
@@ -155,6 +181,9 @@ Program createProgramFromText(const char* input) {
// Ignore extra new lines
break;
}
if (bufSize > 0) {
processBufferedToken(buf, bufSize, &instruction, &processingInstWord, &processingArgNum);
}
addInstructionToProgram(&program, instruction);
instruction = (Instruction){};
processingInstWord = true;
@@ -198,6 +227,12 @@ Program createProgramFromText(const char* input) {
current++;
if (current >= programLen) {
if (!(processingInstWord && bufSize == 0)) {
if (bufSize > 0) {
processBufferedToken(buf, bufSize, &instruction, &processingInstWord, &processingArgNum);
}
addInstructionToProgram(&program, instruction);
}
break;
}
}

View File

@@ -226,7 +226,7 @@ void startEmulator(Emulator* emu) {
}
Emulator* initEmulator(uint32_t memorySize) {
Emulator* newEmu = malloc(sizeof(Emulator));
Emulator* newEmu = calloc(1, sizeof(Emulator));
if (!newEmu)
return NULL;