#include "./assembler.h" #include "../emu/cpu_const.h" #include "../emu/cpu_human.h" #include "./asm_const.h" #include #include #include #include #include // i apologise for the next three functions, they are written very werirdly, // and are not as readable as they coudld be, sorry // the rough flow for each is just to loop along a string until you // encounter a specific char, or a non space / tab char // // again i apologise for the unreadability, they use way to many // goto's, but should be pretty efficient. char *FindNextChar(char *data, char toFind, bool careAboutNull) { begin: switch (*data) { case '\0': if (careAboutNull) { fprintf(stderr, "FOUND NULL CHAR BEFORE CHAR TO FIND\n"); exit(-1); } goto final; default: if (*data == toFind) { final: return data; } data++; goto begin; } } char *FindNextNonSpaceChar(char *data, bool careAboutNull) { begin: switch(*data) { case '\0': if (careAboutNull) { fprintf(stderr, "FOUND NULL CHAR BEFORE NON SPACE / TAB CHAR\n"); exit(-1); } goto final; case ' ': case '\t': data++; goto begin; default: final: return data; } } char *FindNextSpaceChar(char *data, bool careAboutNull) { begin: switch(*data) { case '\0': if (careAboutNull) { fprintf(stderr, "FOUND NULL CHAR BEFORE NON SPACE / TAB CHAR\n"); exit(-1); } case ' ': case '\t': return data; default: data++; goto begin; } } AsmInstructionArray *InterpretAssembly(char *data) { char *d = data; AsmInstructionArray *asmIA = malloc(sizeof(AsmInstructionArray)); asmIA->length = 0; asmIA->instruction = malloc(sizeof(AsmInstruction) * ARRAY_SNAP_SIZE); uint32_t cSize = 0, mSize = ARRAY_SNAP_SIZE; int gfususc = 0; while (true) { loopStart: printf("asmiloop: %d\n", gfususc++); if (cSize == mSize) { mSize += ARRAY_SNAP_SIZE; asmIA->instruction = realloc(asmIA->instruction, sizeof(AsmInstruction) * mSize); } AsmInstruction current = asmIA->instruction[cSize]; d = FindNextNonSpaceChar(d, false); if (*d == '\0') goto final; if (*d == '\n') { d++; goto loopStart; } if (*(FindNextSpaceChar(d, true) - 1) == ':') { size_t l = (FindNextSpaceChar(d, true) - 1) - d; memcpy(¤t.label, d, l); current.label[l] = '\0'; d = FindNextNonSpaceChar(d, true); } else { current.label[0] = '\0'; } memcpy(¤t.instruction, d, sizeof(char) * 3); current.instruction[3] = '\0'; d = FindNextNonSpaceChar(d, false); if (*d == '\0') goto final; if (*d == '\n') { d++; goto loopEnd; } char *comma = FindNextChar(d + 3, ',', true), *nline = FindNextChar(d + 3, '\n', true); bool a2 = comma < nline; char *eoA1 = a2 ? comma : nline; size_t s = eoA1 - (d + 3); memcpy(¤t.arg1, d + 3, s); current.arg1[s] = '\0'; if (!a2) goto loopEnd; d = FindNextNonSpaceChar(eoA1 + 1, true); s = nline - d; memcpy(¤t.arg2, d, s); current.arg2[s] = '\0'; d = nline + 1; printf("l: %s, i: %s, a1: %s, a2: %s\n", current.label, current.instruction, current.arg1, current.arg2); loopEnd: cSize++; } final: asmIA->instruction = realloc(asmIA->instruction, cSize); asmIA->length = cSize; return asmIA; } AsmLabelArray *GenerateLabels(AsmInstructionArray *assembly) { AsmLabelArray *labels = malloc(sizeof(AsmLabelArray)); uint32_t cSize = 0, mSize = ARRAY_SNAP_SIZE; labels->labels = malloc(sizeof(AsmLabel) * ARRAY_SNAP_SIZE); for (int i = 0; i < assembly->length; i++) { if (cSize == mSize) { mSize += ARRAY_SNAP_SIZE; labels->labels = realloc(labels->labels, mSize); } if (assembly->instruction[0].label[0] == '\0') continue; labels->labels[cSize].location = i; strcpy(labels->labels[cSize].label, assembly->instruction[0].label); cSize++; } labels->labels = realloc(labels->labels, cSize); labels->length = cSize; return labels; } uint16_t *BinaryInstructionToBin(BinaryInstruction instruction) { uint16_t *bin = malloc(sizeof(uint16_t) * 3); bin[0] = instruction.instruction + (instruction.arg1Info << 12) + (instruction.arg2Info << 14); bin[1] = instruction.arg1; bin[2] = instruction.arg2; return bin; } static void just() { } int WhereIn2DCharArray(int x, int y, char array[25][4], char* val) { for (int i = 0; i < x; i++) { if (strcmp(array[i], val) == 0) return i; } return -1; } void ParseArgument(char *argData, AsmLabelArray *labels, uint16_t labelOffset, ArgumentInfo *argInfoOut, uint16_t *argOut) { bool pointer, value, label; pointer = argData[0] == '*'; // location in ram / pointer in register if (pointer) argData++; value = argData[0] >= '0' && argData[0] <= '9'; label = !value && argData[0] == '['; if (!pointer && !value) // value in register / label { if (label) { *argInfoOut = value; // todo: something here probably?? } else { *argInfoOut = valueInRegister; // todo: something here probably?? } } else if (!pointer && value) // value { *argInfoOut = value; uint16_t modval = 0, total = 0; switch (argData[1]) { case 'x': case 'X': modval = 16; argData += 2; break; case 'b': case 'B': modval = 2; argData += 2; break; default: modval = 10; break; } for (char *a = argData; a < FindNextSpaceChar(argData, true); a++) { total *= modval; switch(*a) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': just(); total += '0' - *a; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': total += 10 + ('a' - *a); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': total += 10 + ('A' - *a); break; default: fprintf(stderr, "FATAL CHARACTER IN NUMBER STREAM\n"); exit(-1); } } *argOut = total; } else if (pointer && !value) // pointer in register { *argInfoOut = pointerInRegister; } else { fprintf(stderr, "FATAL ARGUMENT INFO\n"); exit(-1); } } uint16_t *CompileAsembly(AsmInstructionArray *assembly, AsmLabelArray *labels) { uint16_t *ret = malloc(sizeof(uint16_t) * UINT16_MAX); uint16_t cSize = 0; for (int i = 0; i < assembly->length; i++) { printf("cabii: %d\n", i); BinaryInstruction binaryIns; int instruction = WhereIn2DCharArray(LEN(CpuInstructionsHumanReadable), LEN(CpuInstructionsHumanReadable[0]), CpuInstructionsHumanReadable, assembly->instruction[i].instruction); if (instruction < 0) { fprintf(stderr, "INSTRUCTION NOT FOUND\n"); exit(-1); } binaryIns.instruction = instruction; cSize++; } ret = realloc(ret, cSize); return ret; }