r16/asm/assembler.c

245 lines
5.7 KiB
C
Raw Normal View History

2024-04-22 13:05:10 +00:00
#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>
2024-04-24 11:29:32 +00:00
#include <stdbool.h>
#include <string.h>
2024-04-22 13:05:10 +00:00
2024-04-24 11:29:32 +00:00
// 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)
2024-04-22 13:05:10 +00:00
{
2024-04-24 11:29:32 +00:00
begin:
switch (*data)
{
case '\0':
if (careAboutNull)
{
fprintf(stderr, "FOUND NULL CHAR BEFORE CHAR TO FIND\n");
exit(-1);
}
2024-04-22 13:05:10 +00:00
2024-04-24 11:29:32 +00:00
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));
2024-04-24 12:02:18 +00:00
uint32_t cSize = 0, mSize = ARRAY_SNAP_SIZE;
asmIA->instruction = malloc(sizeof(AsmInstruction) * ARRAY_SNAP_SIZE);
2024-04-22 13:05:10 +00:00
2024-04-24 11:29:32 +00:00
while (true)
{
loopStart:
if (cSize == mSize)
{
2024-04-24 12:02:18 +00:00
mSize += ARRAY_SNAP_SIZE;
2024-04-24 11:29:32 +00:00
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(&current.label, d, (FindNextSpaceChar(d, true) - 1) - d);
d = FindNextNonSpaceChar(d, true);
}
else
{
current.label[0] = '\0';
}
memcpy(&current.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(&current.arg1, d, eoA1 - d);
if (!a2)
goto loopEnd;
d = FindNextNonSpaceChar(eoA1 + 1, true);
memcpy(&current.arg2, d, nline - d);
d = nline + 1;
loopEnd:
cSize++;
}
final:
asmIA->instruction = realloc(asmIA->instruction, cSize);
asmIA->length = cSize;
return asmIA;
2024-04-24 12:02:18 +00:00
}
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);
2024-04-24 12:02:18 +00:00
}
if (assembly->instruction[0].label[0] == '\0')
continue;
labels->labels[cSize].location = i;
strcpy(labels->labels[cSize].label, assembly->instruction[0].label);
2024-04-24 12:02:18 +00:00
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;
}
2024-04-25 19:40:09 +00:00
int WhereIn2DCharArray(int x, int y, char array[x][y], char *val)
{
for (int i = 0; i < x; i++)
{
if (strcmp(array[i], val) == 0)
return i;
}
return -1;
}
2024-04-24 12:02:18 +00:00
uint16_t *CompileAsembly(AsmInstructionArray *assembly, AsmLabelArray *labels)
{
uint16_t *ret = malloc(sizeof(uint16_t) * UINT16_MAX);
2024-04-25 19:40:09 +00:00
uint16_t cSize = 0;
for (int i = 0; i < assembly->length; i++)
{
BinaryInstruction binaryIns;
2024-04-25 19:40:09 +00:00
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++;
}
2024-04-24 12:02:18 +00:00
2024-04-25 19:40:09 +00:00
ret = realloc(ret, cSize);
return ret;
2024-04-24 12:02:18 +00:00
}