Added a start address (equivalent to main) to assembler

Creates a jump address to the label delegated by "global" so program
starts at that point.
This commit is contained in:
2023-11-03 19:01:31 +00:00
parent 32d50a9342
commit b5a1582976
4 changed files with 104 additions and 38 deletions

View File

@@ -24,6 +24,8 @@ const char *token_type_as_cstr(token_type_t type)
{ {
switch (type) switch (type)
{ {
case TOKEN_GLOBAL:
return "GLOBAL";
case TOKEN_STAR: case TOKEN_STAR:
return "STAR"; return "STAR";
case TOKEN_LITERAL_NUMBER: case TOKEN_LITERAL_NUMBER:
@@ -331,6 +333,11 @@ token_t tokenise_symbol(buffer_t *buffer, size_t *column)
offset = 3; offset = 3;
type = TOKEN_RET; type = TOKEN_RET;
} }
else if (sym_size == 6 && strncmp(opcode, "GLOBAL", 6) == 0)
{
offset = 6;
type = TOKEN_GLOBAL;
}
else else
is_opcode = false; is_opcode = false;

View File

@@ -17,6 +17,7 @@
typedef enum TokenType typedef enum TokenType
{ {
TOKEN_GLOBAL,
TOKEN_STAR, TOKEN_STAR,
TOKEN_LITERAL_NUMBER, TOKEN_LITERAL_NUMBER,
TOKEN_LITERAL_CHAR, TOKEN_LITERAL_CHAR,

View File

@@ -35,6 +35,8 @@ const char *perr_as_cstr(perr_t perr)
return "EXPECTED_UTYPE"; return "EXPECTED_UTYPE";
case PERR_EXPECTED_SYMBOL: case PERR_EXPECTED_SYMBOL:
return "EXPECTED_SYMBOL"; return "EXPECTED_SYMBOL";
case PERR_EXPECTED_LABEL:
return "EXPECTED_LABEL";
case PERR_EXPECTED_OPERAND: case PERR_EXPECTED_OPERAND:
return "EXPECTED_OPERAND"; return "EXPECTED_OPERAND";
case PERR_UNKNOWN_LABEL: case PERR_UNKNOWN_LABEL:
@@ -141,7 +143,7 @@ perr_t parse_word_label_or_relative(token_stream_t *stream, presult_t *res)
res->type = PRES_RELATIVE_ADDRESS; res->type = PRES_RELATIVE_ADDRESS;
++stream->used; ++stream->used;
return parse_sword(TOKEN_STREAM_AT(stream->data, stream->used), return parse_sword(TOKEN_STREAM_AT(stream->data, stream->used),
&res->relative_address); &res->address);
} }
return PERR_EXPECTED_OPERAND; return PERR_EXPECTED_OPERAND;
} }
@@ -271,6 +273,18 @@ perr_t parse_next(token_stream_t *stream, presult_t *ret)
case TOKEN_LITERAL_NUMBER: case TOKEN_LITERAL_NUMBER:
case TOKEN_LITERAL_CHAR: case TOKEN_LITERAL_CHAR:
return PERR_EXPECTED_SYMBOL; return PERR_EXPECTED_SYMBOL;
case TOKEN_GLOBAL: {
if (stream->used + 1 >= stream->available ||
TOKEN_STREAM_AT(stream->data, stream->used + 1).type != TOKEN_SYMBOL)
return PERR_EXPECTED_LABEL;
++stream->used;
token_t label = TOKEN_STREAM_AT(stream->data, stream->used);
*ret = (presult_t){.type = PRES_GLOBAL_LABEL,
.label = malloc(label.str_size + 1)};
memcpy(ret->label, label.str, label.str_size);
ret->label[label.str_size] = '\0';
return PERR_OK;
}
case TOKEN_NOOP: case TOKEN_NOOP:
*ret = (presult_t){.instruction = INST_NOOP, .type = PRES_COMPLETE_RESULT}; *ret = (presult_t){.instruction = INST_NOOP, .type = PRES_COMPLETE_RESULT};
break; break;
@@ -448,12 +462,19 @@ perr_t parse_next(token_stream_t *stream, presult_t *ret)
return perr; return perr;
} }
struct LabelPair label_t search_labels(label_t *labels, size_t n, char *name)
{ {
char *label; size_t name_size = strlen(name);
size_t label_size; for (size_t i = 0; i < n; ++i)
word addr; {
}; label_t label = labels[i];
if (label.name_size == name_size &&
strncmp(label.name, name, name_size) == 0)
return label;
}
return (label_t){0};
}
perr_t process_presults(presult_t *results, size_t res_count, perr_t process_presults(presult_t *results, size_t res_count,
inst_t **instructions, size_t *inst_count) inst_t **instructions, size_t *inst_count)
@@ -474,10 +495,13 @@ perr_t process_presults(presult_t *results, size_t res_count,
printf("\n"); printf("\n");
break; break;
case PRES_RELATIVE_ADDRESS: case PRES_RELATIVE_ADDRESS:
printf("\tRELATIVE_CALL: addr=%lu, inst=", pres.relative_address); printf("\tRELATIVE_CALL: addr=%ld, inst=", pres.address);
inst_print(pres.instruction, stdout); inst_print(pres.instruction, stdout);
printf("\n"); printf("\n");
break; break;
case PRES_GLOBAL_LABEL:
printf("\tSET_GLOBAL_START: name=%s\n", pres.label);
break;
case PRES_COMPLETE_RESULT: case PRES_COMPLETE_RESULT:
printf("\tCOMPLETE: inst="); printf("\tCOMPLETE: inst=");
inst_print(pres.instruction, stdout); inst_print(pres.instruction, stdout);
@@ -486,8 +510,11 @@ perr_t process_presults(presult_t *results, size_t res_count,
} }
} }
#endif #endif
darr_t label_pairs = {0}; bool global_start_defined = false;
darr_init(&label_pairs, sizeof(struct LabelPair)); char *start_label = NULL;
darr_t label_registry = {0};
darr_init(&label_registry, sizeof(label_t));
*inst_count = 0; *inst_count = 0;
for (size_t i = 0; i < res_count; ++i) for (size_t i = 0; i < res_count; ++i)
{ {
@@ -495,35 +522,55 @@ perr_t process_presults(presult_t *results, size_t res_count,
switch (res.type) switch (res.type)
{ {
case PRES_LABEL: { case PRES_LABEL: {
struct LabelPair pair = {0}; label_t label = {.name = res.label,
pair.label = res.label; .name_size = strlen(res.label),
pair.addr = (*inst_count); .addr = (*inst_count) + 1};
pair.label_size = strlen(res.label); darr_append_bytes(&label_registry, (byte *)&label, sizeof(label));
darr_append_bytes(&label_pairs, (byte *)&pair, sizeof(pair));
break; break;
} }
case PRES_RELATIVE_ADDRESS: { case PRES_RELATIVE_ADDRESS: {
s_word offset = res.relative_address; s_word offset = res.address;
if (offset < 0 && ((word)(-offset)) > *inst_count) if (offset < 0 && ((word)(-offset)) > *inst_count)
{ {
free(label_pairs.data); free(label_registry.data);
return PERR_INVALID_RELATIVE_ADDRESS; return PERR_INVALID_RELATIVE_ADDRESS;
} }
results[i].instruction.operand.as_word = ((s_word)*inst_count) + offset; results[i].instruction.operand.as_word = ((s_word)*inst_count) + offset;
(*inst_count)++; (*inst_count)++;
break; break;
} }
case PRES_LABEL_ADDRESS: case PRES_GLOBAL_LABEL: {
case PRES_COMPLETE_RESULT: global_start_defined = true;
default: { start_label = res.label;
(*inst_count)++;
break; break;
} }
case PRES_LABEL_ADDRESS:
case PRES_COMPLETE_RESULT:
default:
(*inst_count)++;
break;
} }
} }
darr_t instr_darr = {0}; darr_t instr_darr = {0};
darr_init(&instr_darr, sizeof(**instructions)); darr_init(&instr_darr, sizeof(**instructions));
if (global_start_defined)
{
label_t label =
search_labels((label_t *)label_registry.data,
label_registry.used / sizeof(label_t), start_label);
if (!label.name)
{
free(instr_darr.data);
free(label_registry.data);
return PERR_UNKNOWN_LABEL;
}
inst_t initial_jump = INST_JUMP_ABS(label.addr);
darr_append_bytes(&instr_darr, (byte *)&initial_jump, sizeof(initial_jump));
(*inst_count)++;
}
for (size_t i = 0; i < res_count; ++i) for (size_t i = 0; i < res_count; ++i)
{ {
presult_t res = results[i]; presult_t res = results[i];
@@ -531,36 +578,34 @@ perr_t process_presults(presult_t *results, size_t res_count,
{ {
case PRES_LABEL_ADDRESS: { case PRES_LABEL_ADDRESS: {
inst_t inst = {0}; inst_t inst = {0};
for (size_t j = 0; j < (label_pairs.used / sizeof(struct LabelPair)); ++j) label_t label =
{ search_labels((label_t *)label_registry.data,
struct LabelPair pair = ((struct LabelPair *)label_pairs.data)[j]; label_registry.used / sizeof(label_t), res.label);
if (pair.label_size == strlen(res.label) &&
strncmp(pair.label, res.label, pair.label_size) == 0)
{
inst = res.instruction;
inst.operand = DWORD(pair.addr);
}
}
if (inst.opcode == OP_NOOP) if (!label.name)
{ {
free(instr_darr.data); free(instr_darr.data);
free(label_pairs.data); free(label_registry.data);
return PERR_UNKNOWN_LABEL; return PERR_UNKNOWN_LABEL;
} }
inst.opcode = res.instruction.opcode;
inst.operand = DWORD(label.addr);
darr_append_bytes(&instr_darr, (byte *)&inst, sizeof(inst)); darr_append_bytes(&instr_darr, (byte *)&inst, sizeof(inst));
break; break;
} }
case PRES_RELATIVE_ADDRESS: case PRES_RELATIVE_ADDRESS:
case PRES_COMPLETE_RESULT: case PRES_COMPLETE_RESULT: {
darr_append_bytes(&instr_darr, (byte *)&res.instruction, darr_append_bytes(&instr_darr, (byte *)&res.instruction,
sizeof(res.instruction)); sizeof(res.instruction));
}
case PRES_GLOBAL_LABEL:
case PRES_LABEL: case PRES_LABEL:
break; break;
} }
} }
free(label_pairs.data); free(label_registry.data);
*instructions = (inst_t *)instr_darr.data; *instructions = (inst_t *)instr_darr.data;
return PERR_OK; return PERR_OK;
} }
@@ -578,7 +623,8 @@ perr_t parse_stream(token_stream_t *stream, inst_t **ret, size_t *size)
for (size_t i = 0; i < (presults.used / sizeof(presult_t)); ++i) for (size_t i = 0; i < (presults.used / sizeof(presult_t)); ++i)
{ {
presult_t res = ((presult_t *)presults.data)[i]; presult_t res = ((presult_t *)presults.data)[i];
if (res.type == PRES_LABEL_ADDRESS || res.type == PRES_LABEL) if (res.type == PRES_LABEL_ADDRESS || res.type == PRES_LABEL ||
res.type == PRES_GLOBAL_LABEL)
free(res.label); free(res.label);
} }
free(presults.data); free(presults.data);
@@ -593,7 +639,8 @@ perr_t parse_stream(token_stream_t *stream, inst_t **ret, size_t *size)
for (size_t i = 0; i < (presults.used / sizeof(presult_t)); ++i) for (size_t i = 0; i < (presults.used / sizeof(presult_t)); ++i)
{ {
presult_t res = ((presult_t *)presults.data)[i]; presult_t res = ((presult_t *)presults.data)[i];
if (res.type == PRES_LABEL_ADDRESS || res.type == PRES_LABEL) if (res.type == PRES_LABEL_ADDRESS || res.type == PRES_LABEL ||
res.type == PRES_GLOBAL_LABEL)
free(res.label); free(res.label);
} }
free(presults.data); free(presults.data);

View File

@@ -25,9 +25,10 @@ typedef enum
PERR_EXPECTED_UTYPE, PERR_EXPECTED_UTYPE,
PERR_EXPECTED_TYPE, PERR_EXPECTED_TYPE,
PERR_EXPECTED_SYMBOL, PERR_EXPECTED_SYMBOL,
PERR_EXPECTED_LABEL,
PERR_EXPECTED_OPERAND, PERR_EXPECTED_OPERAND,
PERR_UNKNOWN_OPERATOR,
PERR_INVALID_RELATIVE_ADDRESS, PERR_INVALID_RELATIVE_ADDRESS,
PERR_UNKNOWN_OPERATOR,
PERR_UNKNOWN_LABEL, PERR_UNKNOWN_LABEL,
} perr_t; } perr_t;
@@ -37,16 +38,26 @@ typedef struct
{ {
inst_t instruction; inst_t instruction;
char *label; char *label;
s_word relative_address; s_word address;
enum PResult_Type enum PResult_Type
{ {
PRES_LABEL = 0, PRES_LABEL = 0,
PRES_LABEL_ADDRESS, PRES_LABEL_ADDRESS,
PRES_GLOBAL_LABEL,
PRES_RELATIVE_ADDRESS, PRES_RELATIVE_ADDRESS,
PRES_COMPLETE_RESULT, PRES_COMPLETE_RESULT,
} type; } type;
} presult_t; } presult_t;
typedef struct
{
char *name;
size_t name_size;
word addr;
} label_t;
label_t search_labels(label_t *, size_t, char *);
perr_t parse_next(token_stream_t *, presult_t *); perr_t parse_next(token_stream_t *, presult_t *);
perr_t process_presults(presult_t *, size_t, inst_t **, size_t *); perr_t process_presults(presult_t *, size_t, inst_t **, size_t *);
perr_t parse_stream(token_stream_t *, inst_t **, size_t *); perr_t parse_stream(token_stream_t *, inst_t **, size_t *);