Browse Source

Implement an insane(LY AWESOME) system for instruction parsing.

master
Ben Kurtovic 9 years ago
parent
commit
a13c3bb93d
5 changed files with 79 additions and 21 deletions
  1. +7
    -4
      src/assembler/errors.c
  2. +6
    -4
      src/assembler/errors.h
  3. +57
    -4
      src/assembler/instructions.c
  4. +3
    -2
      src/assembler/instructions.h
  5. +6
    -7
      src/assembler/tokenizer.c

+ 7
- 4
src/assembler/errors.c View File

@@ -43,10 +43,13 @@ static const char *error_descs[] = {
[ED_SYM_DUPE_LABELS] = "duplicate definitions for label", [ED_SYM_DUPE_LABELS] = "duplicate definitions for label",
[ED_SYM_NO_LABEL] = "undefined reference to label", [ED_SYM_NO_LABEL] = "undefined reference to label",


[ED_PARSE_OP_LONG] = "opcode mnemonic is too long (2-4 characters)",
[ED_PARSE_OP_SHORT] = "opcode mnemonic is too short (2-4 characters)",
[ED_PARSE_OP_CHARS] = "invalid characters in opcode mnemonic",
[ED_PARSE_OP_UNKNOWN] = "unknown opcode mnemonic"
[ED_PS_OP_TOO_LONG] = "opcode mnemonic is too long (2-4 characters)",
[ED_PS_OP_TOO_SHORT] = "opcode mnemonic is too short (2-4 characters)",
[ED_PS_OP_INVALID] = "invalid characters in opcode mnemonic",
[ED_PS_OP_UNKNOWN] = "unknown opcode mnemonic",
[ED_PS_TOO_FEW_ARGS] = "too few arguments for opcode",
[ED_PS_TOO_MANY_ARGS] = "too many arguments for opcode",
// [ED_PS_ARG1_TYPE] = "invalid type for first argument",
}; };


/* Internal structs */ /* Internal structs */


+ 6
- 4
src/assembler/errors.h View File

@@ -42,10 +42,12 @@ typedef enum {
ED_SYM_DUPE_LABELS, ED_SYM_DUPE_LABELS,
ED_SYM_NO_LABEL, ED_SYM_NO_LABEL,


ED_PARSE_OP_LONG,
ED_PARSE_OP_SHORT,
ED_PARSE_OP_CHARS,
ED_PARSE_OP_UNKNOWN
ED_PS_OP_TOO_LONG,
ED_PS_OP_TOO_SHORT,
ED_PS_OP_INVALID,
ED_PS_OP_UNKNOWN,
ED_PS_TOO_FEW_ARGS,
ED_PS_TOO_MANY_ARGS
} ASMErrorDesc; } ASMErrorDesc;


/* Structs */ /* Structs */


+ 57
- 4
src/assembler/instructions.c View File

@@ -24,13 +24,66 @@
page0 := $0 | $8 | $10 | $18 | $20 | $28 | $30 | $38 page0 := $0 | $8 | $10 | $18 | $20 | $28 | $30 | $38
*/ */


/* Helper macros for get_inst_parser() */

#define JOIN_(a, b, c, d) ((uint32_t) ((a << 24) + (b << 16) + (c << 8) + d))

#define DISPATCH_(s, z) ( \
z == 2 ? JOIN_(s[0], s[1], 0x00, 0x00) : \
z == 3 ? JOIN_(s[0], s[1], s[2], 0x00) : \
JOIN_(s[0], s[1], s[2], s[3])) \

#define MAKE_CMP_(s) DISPATCH_(s, (sizeof(s) / sizeof(char) - 1))

#define HANDLE(m) if (key == MAKE_CMP_(#m)) return parse_inst_##m;

/* Instruction parser functions */

#define INST_FUNC(mnemonic) \
static ASMErrorDesc parse_inst_##mnemonic( \
uint8_t **bytes, size_t *length, char **symbol, const char *arg, size_t size)

INST_FUNC(nop)
{
DEBUG("dispatched to -> NOP")
return ED_PS_TOO_FEW_ARGS;
}

INST_FUNC(inc)
{
DEBUG("dispatched to -> INC")
return ED_PS_TOO_FEW_ARGS;
}

INST_FUNC(add)
{
DEBUG("dispatched to -> ADD")
return ED_PS_TOO_FEW_ARGS;
}

INST_FUNC(adc)
{
DEBUG("dispatched to -> ADC")
return ED_PS_TOO_FEW_ARGS;
}

/* /*
...
Return the relevant ASMInstParser function for a given mnemonic.

NULL is returned if the mnemonic is not known.
*/ */
ASMInstParser get_inst_parser(char mnemonic[MAX_MNEMONIC_SIZE + 1])
ASMInstParser get_inst_parser(char mstr[MAX_MNEMONIC_SIZE])
{ {
// TODO
DEBUG("get_inst_parser(): -->%s<--", mnemonic)
// Exploit the fact that we can store the entire mnemonic string as a
// single 32-bit value to do fast lookups:
uint32_t key = (mstr[0] << 24) + (mstr[1] << 16) + (mstr[2] << 8) + mstr[3];

DEBUG("get_inst_parser(): -->%.*s<-- 0x%08X", MAX_MNEMONIC_SIZE, mstr, key)

HANDLE(nop)
HANDLE(inc)
HANDLE(add)
HANDLE(adc)


return NULL; return NULL;
} }

+ 3
- 2
src/assembler/instructions.h View File

@@ -12,8 +12,9 @@


/* Typedefs */ /* Typedefs */


typedef ASMErrorDesc (*ASMInstParser)(uint8_t**, size_t*, char**, const char*, size_t);
typedef ASMErrorDesc (*ASMInstParser)(
uint8_t**, size_t*, char**, const char*, size_t);


/* Functions */ /* Functions */


ASMInstParser get_inst_parser(char[MAX_MNEMONIC_SIZE + 1]);
ASMInstParser get_inst_parser(char[MAX_MNEMONIC_SIZE]);

+ 6
- 7
src/assembler/tokenizer.c View File

@@ -231,33 +231,32 @@ static ErrorInfo* parse_data(
static ErrorInfo* parse_instruction( static ErrorInfo* parse_instruction(
const ASMLine *line, ASMInstruction **inst_ptr, size_t offset) const ASMLine *line, ASMInstruction **inst_ptr, size_t offset)
{ {
char mnemonic[MAX_MNEMONIC_SIZE + 1];
char mnemonic[MAX_MNEMONIC_SIZE] = {0};
size_t i = 0; size_t i = 0;
while (i < line->length) { while (i < line->length) {
char c = line->data[i]; char c = line->data[i];
if (c == ' ') if (c == ' ')
break; break;
if (i >= MAX_MNEMONIC_SIZE) if (i >= MAX_MNEMONIC_SIZE)
return error_info_create(line, ET_PARSER, ED_PARSE_OP_LONG);
return error_info_create(line, ET_PARSER, ED_PS_OP_TOO_LONG);
if ((c < 'a' || c > 'z') && (c < '0' || c > '9')) if ((c < 'a' || c > 'z') && (c < '0' || c > '9'))
return error_info_create(line, ET_PARSER, ED_PARSE_OP_CHARS);
return error_info_create(line, ET_PARSER, ED_PS_OP_INVALID);
mnemonic[i++] = c; mnemonic[i++] = c;
} }


if (i < MIN_MNEMONIC_SIZE) if (i < MIN_MNEMONIC_SIZE)
return error_info_create(line, ET_PARSER, ED_PARSE_OP_SHORT);
return error_info_create(line, ET_PARSER, ED_PS_OP_TOO_SHORT);


uint8_t *bytes; uint8_t *bytes;
size_t arglen = line->length - i, length; size_t arglen = line->length - i, length;
char *argstart = arglen > 0 ? line->data + i : NULL, *symbol; char *argstart = arglen > 0 ? line->data + i : NULL, *symbol;


mnemonic[i] = '\0';
ASMInstParser parser = get_inst_parser(mnemonic); ASMInstParser parser = get_inst_parser(mnemonic);
if (!parser) if (!parser)
return error_info_create(line, ET_PARSER, ED_PARSE_OP_UNKNOWN);
return error_info_create(line, ET_PARSER, ED_PS_OP_UNKNOWN);


ASMErrorDesc edesc = parser(&bytes, &length, &symbol, argstart, arglen); ASMErrorDesc edesc = parser(&bytes, &length, &symbol, argstart, arglen);
if (edesc)
if (edesc != ED_NONE)
return error_info_create(line, ET_PARSER, edesc); return error_info_create(line, ET_PARSER, edesc);


ASMInstruction *inst = malloc(sizeof(ASMInstruction)); ASMInstruction *inst = malloc(sizeof(ASMInstruction));


Loading…
Cancel
Save