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:
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
119
asm/parser.c
119
asm/parser.c
@@ -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);
|
||||||
|
|||||||
15
asm/parser.h
15
asm/parser.h
@@ -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 *);
|
||||||
|
|||||||
Reference in New Issue
Block a user