From 619c5cc4ab4bd94f9b270a9868bb5f08ffd76acb Mon Sep 17 00:00:00 2001 From: Bobby Bingham Date: Wed, 18 Jan 2017 18:55:22 -0600 Subject: nqasm: allow specifying labels for operands --- lexer.l | 1 + nqasm.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- nqasm.h | 7 ++++++- parser.y | 64 ++++++++++++++++++++++++---------------------------------------- vector.c | 10 ++++++++++ vector.h | 2 ++ 6 files changed, 100 insertions(+), 44 deletions(-) diff --git a/lexer.l b/lexer.l index 28aa7fe..7d44adf 100644 --- a/lexer.l +++ b/lexer.l @@ -79,6 +79,7 @@ HEX [0-9a-f] [-+]?{DEC}+ { return intlit(yytext, 10, &yylval.lval); } 0x{HEX}+ { return intlit(yytext+2, 16, &yylval.lval); } {SP}*,{SP}* { return T_COMMA; } +{LABEL} { SETSTR(yytext); return T_LABEL; } {SP}*{COMMENT}?\n { BEGIN(INITIAL); return T_EOL; } {SP}*{COMMENT} { BEGIN(INITIAL); return T_EOL; } diff --git a/nqasm.c b/nqasm.c index 738f815..0b0bbd8 100644 --- a/nqasm.c +++ b/nqasm.c @@ -1,3 +1,4 @@ +#include #include #include @@ -15,6 +16,12 @@ struct label { uint16_t addr; +static int cmp_label(const void *a, const void *b) +{ + const struct label *la = a, *lb = b; + return strcmp(la->name, lb->name); +} + #define DEFINE_VECTOR(name, arraytype, arrayname, initsize) \ static struct name { \ struct vector v; \ @@ -49,7 +56,25 @@ void add_instruction(const struct instruction *inst) addr += 2; } -static void assemble_instruction(const struct instruction *inst) +static long eval_argument(const struct argument *arg) +{ + struct label *l; + switch (arg->type) { + case ARG_INTEGER: + return arg->value; + + case ARG_LABEL: + l = vector_search(&labels->v, &(struct label) { .name = arg->label }, cmp_label); + if (l) return l->addr; + fprintf(stderr, "unknown label '%s'\n", arg->label); + exit(1); + + default: + assert(0); + } +} + +static void assemble_instruction(const struct instruction *inst, uint16_t pc) { const struct mnemonic *mnem = &mnemonics[inst->mnem]; uint16_t bits = mnem->bits; @@ -57,7 +82,34 @@ static void assemble_instruction(const struct instruction *inst) const struct operand *ops = mnem->operands; const struct argument *args = inst->args.args; for (int i = 0; i < 3 && ops[i].type; i++) { - bits |= args[i].value << ops[i].shift; + long value = eval_argument(args + i); + + switch (ops[i].type) { + case REG: + case REGPTR: + if (0 > value || value >= 8) { + fprintf(stderr, "invalid register\n"); + exit(1); + } + break; + case IMM: + if (-0x80 > value || value > 0xff) { + fprintf(stderr, "immediate operand out of range\n"); + exit(1); + } + break; + case PCOFF: + value -= pc; + if (-0x80 > value || value > 0x7f) { + fprintf(stderr, "pc offset operand out of range\n"); + exit(1); + } + break; + default: + assert(0); + } + + bits |= (value & 255) << ops[i].shift; } printf("%04x\n", bits); @@ -84,8 +136,10 @@ int main(int argc, char **argv) yyparse(); + vector_sort(&labels->v, cmp_label); + for (size_t i = 0; i < instrs->v.count; i++) { - assemble_instruction(instrs->i + i); + assemble_instruction(instrs->i + i, 2 * i); } return 0; diff --git a/nqasm.h b/nqasm.h index 232c41b..f2e036d 100644 --- a/nqasm.h +++ b/nqasm.h @@ -1,9 +1,14 @@ #ifndef NQ_NQASM_H #define NQ_NQASM_H +#define ARG_INTEGER 0 +#define ARG_LABEL 1 + struct argument { + int type; union { - int value; + long value; + char *label; }; }; diff --git a/parser.y b/parser.y index 1f4f5bd..e6cb0b1 100644 --- a/parser.y +++ b/parser.y @@ -13,7 +13,8 @@ void yyerror(const char *msg) #define INSTRUCTION_ARGS(m,a) (struct instruction) { MNEM_ ## m, a } #define INSTRUCTION(m) (struct instruction) { MNEM_ ## m } #define MKARGS(...) (struct arguments) { { __VA_ARGS__ } } -#define MKARGVALUE(v) (struct argument) { .value = (v) } +#define MKARGVALUE(v) (struct argument) { .type = ARG_INTEGER, .value = (v) } +#define MKARGLABEL(l) (struct argument) { .type = ARG_LABEL, .label = (l) } %} @@ -84,16 +85,14 @@ void yyerror(const char *msg) %token T_COLON ":" %type inst -%type imm -%type pcoff +%type expr %type a_reg2 %type a_reg3 %type a_regp %type a_regp_reg %type a_reg_regp -%type a_reg_imm -%type a_reg_pcoff -%type a_pcoff +%type a_reg_expr +%type a_expr %type intlit %% @@ -136,17 +135,17 @@ inst: | T_LD_BL a_reg_regp { $$ = INSTRUCTION_ARGS(LD_BL, $2); } | T_LD_BH a_reg_regp { $$ = INSTRUCTION_ARGS(LD_BH, $2); } | T_LD_W a_reg_regp { $$ = INSTRUCTION_ARGS(LD_W, $2); } - | T_LDI_BL a_reg_imm { $$ = INSTRUCTION_ARGS(LDI_BL, $2); } - | T_LDI_BH a_reg_imm { $$ = INSTRUCTION_ARGS(LDI_BH, $2); } - | T_BEQ a_pcoff { $$ = INSTRUCTION_ARGS(BEQ, $2); } - | T_BNE a_pcoff { $$ = INSTRUCTION_ARGS(BNE, $2); } - | T_BGT a_pcoff { $$ = INSTRUCTION_ARGS(BGT, $2); } - | T_BGE a_pcoff { $$ = INSTRUCTION_ARGS(BGE, $2); } - | T_BLT a_pcoff { $$ = INSTRUCTION_ARGS(BLT, $2); } - | T_BLE a_pcoff { $$ = INSTRUCTION_ARGS(BLE, $2); } - | T_BRA a_pcoff { $$ = INSTRUCTION_ARGS(BRA, $2); } + | T_LDI_BL a_reg_expr { $$ = INSTRUCTION_ARGS(LDI_BL, $2); } + | T_LDI_BH a_reg_expr { $$ = INSTRUCTION_ARGS(LDI_BH, $2); } + | T_BEQ a_expr { $$ = INSTRUCTION_ARGS(BEQ, $2); } + | T_BNE a_expr { $$ = INSTRUCTION_ARGS(BNE, $2); } + | T_BGT a_expr { $$ = INSTRUCTION_ARGS(BGT, $2); } + | T_BGE a_expr { $$ = INSTRUCTION_ARGS(BGE, $2); } + | T_BLT a_expr { $$ = INSTRUCTION_ARGS(BLT, $2); } + | T_BLE a_expr { $$ = INSTRUCTION_ARGS(BLE, $2); } + | T_BRA a_expr { $$ = INSTRUCTION_ARGS(BRA, $2); } | T_JMP a_regp { $$ = INSTRUCTION_ARGS(JMP, $2); } - | T_ADDPC a_reg_pcoff { $$ = INSTRUCTION_ARGS(ADDPC, $2); } + | T_ADDPC a_reg_expr { $$ = INSTRUCTION_ARGS(ADDPC, $2); } | T_NOP { $$ = INSTRUCTION(NOP); } ; @@ -160,30 +159,15 @@ a_regp_reg: T_SPACE T_REGPTR "," T_REG { $$ = MKARGS($2, $4); } a_reg_regp: T_SPACE T_REG "," T_REGPTR { $$ = MKARGS($2, $4); } -a_reg_imm: - T_SPACE T_REG "," imm { $$ = MKARGS($2, $4); } -a_reg_pcoff: - T_SPACE T_REG "," pcoff { $$ = MKARGS($2, $4); } -a_pcoff: - T_SPACE pcoff { $$ = MKARGS($2); } - -pcoff: intlit { - if (-0x80 > $1 || $1 > 0x7f) { - yyerror("pc offset operand out of range"); - YYERROR; - } else { - $$ = MKARGVALUE((uint8_t) $1); - } - } - -imm: intlit { - if (-0x80 > $1 || $1 > 0xff) { - yyerror("immediate operand out of range"); - YYERROR; - } else { - $$ = MKARGVALUE((uint8_t) $1); - } - } +a_reg_expr: + T_SPACE T_REG "," expr { $$ = MKARGS($2, $4); } +a_expr: + T_SPACE expr { $$ = MKARGS($2); } + +expr: + intlit { $$ = MKARGVALUE($1); } + | T_LABEL { $$ = MKARGLABEL($1); } + ; intlit: T_INT | T_BADINT { diff --git a/vector.c b/vector.c index 57f62d7..8ff637c 100644 --- a/vector.c +++ b/vector.c @@ -35,3 +35,13 @@ void *vector_append(struct vector **vp) return (char*)v + v->arrayoff + v->count++ * v->elemsize; } +void vector_sort(struct vector *v, int (*cmp)(const void *, const void *)) +{ + qsort((char*)v + v->arrayoff, v->count, v->elemsize, cmp); +} + +void *vector_search(struct vector *v, const void *key, int (*cmp)(const void *, const void *)) +{ + return bsearch(key, (char*)v + v->arrayoff, v->count, v->elemsize, cmp); +} + diff --git a/vector.h b/vector.h index fb32da7..6fba081 100644 --- a/vector.h +++ b/vector.h @@ -9,5 +9,7 @@ struct vector { void *vector_init(size_t alloc, size_t elemsize, size_t arrayoff); void *vector_append(struct vector **vp); +void vector_sort(struct vector *v, int (*cmp)(const void *, const void *)); +void *vector_search(struct vector *v, const void *key, int (*cmp)(const void *, const void *)); #endif -- cgit v1.2.3