218 lines
5.0 KiB
C
218 lines
5.0 KiB
C
#include "./assembler.h"
|
|
#include "../emu/cpu_const.h"
|
|
#include "../emu/cpu_human.h"
|
|
#include "./asm_const.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
|
|
// 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));
|
|
uint32_t cSize = 0, mSize = ARRAY_SNAP_SIZE;
|
|
asmIA->instruction = malloc(sizeof(AsmInstruction) * ARRAY_SNAP_SIZE);
|
|
|
|
while (true)
|
|
{
|
|
loopStart:
|
|
if (cSize == mSize)
|
|
{
|
|
mSize += ARRAY_SNAP_SIZE;
|
|
asmIA->instruction = realloc(asmIA->instruction, mSize);
|
|
}
|
|
|
|
AsmInstruction current = *(asmIA->instruction + (cSize * sizeof(AsmInstruction)));
|
|
|
|
d = FindNextNonSpaceChar(d, false);
|
|
|
|
if (*d == '\0')
|
|
goto final;
|
|
if (*d == '\n')
|
|
{
|
|
d++;
|
|
goto loopStart;
|
|
}
|
|
|
|
if (*(FindNextSpaceChar(d, true) - 1) == ':')
|
|
{
|
|
memcpy(¤t.label, d, (FindNextSpaceChar(d, true) - 1) - d);
|
|
|
|
d = FindNextNonSpaceChar(d, true);
|
|
}
|
|
else
|
|
{
|
|
current.label[0] = '\0';
|
|
}
|
|
|
|
memcpy(¤t.instruction, d, 3);
|
|
|
|
d = FindNextNonSpaceChar(d, false);
|
|
|
|
if (*d == '\0')
|
|
goto final;
|
|
if (*d == '\n')
|
|
{
|
|
d++;
|
|
goto loopEnd;
|
|
}
|
|
|
|
char *comma = FindNextChar(d, ',', true),
|
|
*nline = FindNextChar(d, '\n', true);
|
|
|
|
bool a2 = comma < nline;
|
|
char *eoA1 = a2 ? comma : nline;
|
|
memcpy(¤t.arg1, d, eoA1 - d);
|
|
|
|
if (!a2)
|
|
goto loopEnd;
|
|
|
|
d = FindNextNonSpaceChar(eoA1 + 1, true);
|
|
memcpy(¤t.arg2, d, nline - d);
|
|
d = nline + 1;
|
|
|
|
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;
|
|
}
|
|
|
|
uint16_t *CompileAsembly(AsmInstructionArray *assembly, AsmLabelArray *labels)
|
|
{
|
|
uint16_t *ret = malloc(sizeof(uint16_t) * UINT16_MAX);
|
|
uint16_t cSize = 0, mSize = ARRAY_SNAP_SIZE;
|
|
|
|
for (int i = 0; i < assembly->length; i++)
|
|
{
|
|
BinaryInstruction binaryIns;
|
|
}
|
|
|
|
return ret;
|
|
}
|