diff options
| -rw-r--r-- | asm/lexer.c | 7 | ||||
| -rw-r--r-- | asm/lexer.h | 1 | ||||
| -rw-r--r-- | asm/parser.c | 115 | ||||
| -rw-r--r-- | asm/parser.h | 15 | 
4 files changed, 102 insertions, 36 deletions
| diff --git a/asm/lexer.c b/asm/lexer.c index 525deb2..7f37ce7 100644 --- a/asm/lexer.c +++ b/asm/lexer.c @@ -24,6 +24,8 @@ const char *token_type_as_cstr(token_type_t type)  {    switch (type)    { +  case TOKEN_GLOBAL: +    return "GLOBAL";    case TOKEN_STAR:      return "STAR";    case TOKEN_LITERAL_NUMBER: @@ -331,6 +333,11 @@ token_t tokenise_symbol(buffer_t *buffer, size_t *column)      offset = 3;      type   = TOKEN_RET;    } +  else if (sym_size == 6 && strncmp(opcode, "GLOBAL", 6) == 0) +  { +    offset = 6; +    type   = TOKEN_GLOBAL; +  }    else      is_opcode = false; diff --git a/asm/lexer.h b/asm/lexer.h index cdddb6a..0ced4ca 100644 --- a/asm/lexer.h +++ b/asm/lexer.h @@ -17,6 +17,7 @@  typedef enum TokenType  { +  TOKEN_GLOBAL,    TOKEN_STAR,    TOKEN_LITERAL_NUMBER,    TOKEN_LITERAL_CHAR, diff --git a/asm/parser.c b/asm/parser.c index 4843429..196c09c 100644 --- a/asm/parser.c +++ b/asm/parser.c @@ -35,6 +35,8 @@ const char *perr_as_cstr(perr_t perr)      return "EXPECTED_UTYPE";    case PERR_EXPECTED_SYMBOL:      return "EXPECTED_SYMBOL"; +  case PERR_EXPECTED_LABEL: +    return "EXPECTED_LABEL";    case PERR_EXPECTED_OPERAND:      return "EXPECTED_OPERAND";    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;      ++stream->used;      return parse_sword(TOKEN_STREAM_AT(stream->data, stream->used), -                       &res->relative_address); +                       &res->address);    }    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_CHAR:      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:      *ret = (presult_t){.instruction = INST_NOOP, .type = PRES_COMPLETE_RESULT};      break; @@ -448,12 +462,19 @@ perr_t parse_next(token_stream_t *stream, presult_t *ret)    return perr;  } -struct LabelPair +label_t search_labels(label_t *labels, size_t n, char *name)  { -  char *label; -  size_t label_size; -  word addr; -}; +  size_t name_size = strlen(name); +  for (size_t i = 0; i < n; ++i) +  { +    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,                          inst_t **instructions, size_t *inst_count) @@ -474,10 +495,13 @@ perr_t process_presults(presult_t *results, size_t res_count,        printf("\n");        break;      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);        printf("\n");        break; +    case PRES_GLOBAL_LABEL: +      printf("\tSET_GLOBAL_START: name=%s\n", pres.label); +      break;      case PRES_COMPLETE_RESULT:        printf("\tCOMPLETE: inst=");        inst_print(pres.instruction, stdout); @@ -486,8 +510,11 @@ perr_t process_presults(presult_t *results, size_t res_count,      }    }  #endif -  darr_t label_pairs = {0}; -  darr_init(&label_pairs, sizeof(struct LabelPair)); +  bool global_start_defined = false; +  char *start_label         = NULL; + +  darr_t label_registry = {0}; +  darr_init(&label_registry, sizeof(label_t));    *inst_count = 0;    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)      {      case PRES_LABEL: { -      struct LabelPair pair = {0}; -      pair.label            = res.label; -      pair.addr             = (*inst_count); -      pair.label_size       = strlen(res.label); -      darr_append_bytes(&label_pairs, (byte *)&pair, sizeof(pair)); +      label_t label = {.name      = res.label, +                       .name_size = strlen(res.label), +                       .addr      = (*inst_count) + 1}; +      darr_append_bytes(&label_registry, (byte *)&label, sizeof(label));        break;      }      case PRES_RELATIVE_ADDRESS: { -      s_word offset = res.relative_address; +      s_word offset = res.address;        if (offset < 0 && ((word)(-offset)) > *inst_count)        { -        free(label_pairs.data); +        free(label_registry.data);          return PERR_INVALID_RELATIVE_ADDRESS;        }        results[i].instruction.operand.as_word = ((s_word)*inst_count) + offset;        (*inst_count)++;        break;      } +    case PRES_GLOBAL_LABEL: { +      global_start_defined = true; +      start_label          = res.label; +      break; +    }      case PRES_LABEL_ADDRESS:      case PRES_COMPLETE_RESULT: -    default: { +    default:        (*inst_count)++;        break;      } -    }    }    darr_t instr_darr = {0};    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)    {      presult_t res = results[i]; @@ -531,36 +578,34 @@ perr_t process_presults(presult_t *results, size_t res_count,      {      case PRES_LABEL_ADDRESS: {        inst_t inst = {0}; -      for (size_t j = 0; j < (label_pairs.used / sizeof(struct LabelPair)); ++j) -      { -        struct LabelPair pair = ((struct LabelPair *)label_pairs.data)[j]; -        if (pair.label_size == strlen(res.label) && -            strncmp(pair.label, res.label, pair.label_size) == 0) -        { -          inst         = res.instruction; -          inst.operand = DWORD(pair.addr); -        } -      } +      label_t label = +          search_labels((label_t *)label_registry.data, +                        label_registry.used / sizeof(label_t), res.label); -      if (inst.opcode == OP_NOOP) +      if (!label.name)        {          free(instr_darr.data); -        free(label_pairs.data); +        free(label_registry.data);          return PERR_UNKNOWN_LABEL;        } + +      inst.opcode  = res.instruction.opcode; +      inst.operand = DWORD(label.addr);        darr_append_bytes(&instr_darr, (byte *)&inst, sizeof(inst));        break;      }      case PRES_RELATIVE_ADDRESS: -    case PRES_COMPLETE_RESULT: +    case PRES_COMPLETE_RESULT: {        darr_append_bytes(&instr_darr, (byte *)&res.instruction,                          sizeof(res.instruction)); +    } +    case PRES_GLOBAL_LABEL:      case PRES_LABEL:        break;      }    } -  free(label_pairs.data); +  free(label_registry.data);    *instructions = (inst_t *)instr_darr.data;    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)        {          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(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)    {      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(presults.data); diff --git a/asm/parser.h b/asm/parser.h index 0a65310..b0091d2 100644 --- a/asm/parser.h +++ b/asm/parser.h @@ -25,9 +25,10 @@ typedef enum    PERR_EXPECTED_UTYPE,    PERR_EXPECTED_TYPE,    PERR_EXPECTED_SYMBOL, +  PERR_EXPECTED_LABEL,    PERR_EXPECTED_OPERAND, -  PERR_UNKNOWN_OPERATOR,    PERR_INVALID_RELATIVE_ADDRESS, +  PERR_UNKNOWN_OPERATOR,    PERR_UNKNOWN_LABEL,  } perr_t; @@ -37,16 +38,26 @@ typedef struct  {    inst_t instruction;    char *label; -  s_word relative_address; +  s_word address;    enum PResult_Type    {      PRES_LABEL = 0,      PRES_LABEL_ADDRESS, +    PRES_GLOBAL_LABEL,      PRES_RELATIVE_ADDRESS,      PRES_COMPLETE_RESULT,    } type;  } 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 process_presults(presult_t *, size_t, inst_t **, size_t *);  perr_t parse_stream(token_stream_t *, inst_t **, size_t *); | 
