From 6c6b91f9a6bc5ae203e99ac7abb3a70215488a6f Mon Sep 17 00:00:00 2001 From: Bobby Bingham Date: Wed, 18 Jan 2017 19:40:18 -0600 Subject: nqasm: support unary operators in immediate expressions --- lexer.l | 6 +++++- nqasm.c | 19 +++++++++++++++++-- nqasm.h | 16 +++++++++++++--- parser.y | 10 ++++++++++ 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/lexer.l b/lexer.l index 053ac4e..324c3da 100644 --- a/lexer.l +++ b/lexer.l @@ -76,7 +76,11 @@ HEX [0-9a-f] \. { return T_DOT; } @ { return T_DEREF; } -[-+]?{DEC}+ { return intlit(yytext, 10, &yylval.lval); } +\+ { return T_OPERATOR_ADD; } +- { return T_OPERATOR_SUB; } +! { return T_OPERATOR_NOT; } +~ { return T_OPERATOR_INV; } +{DEC}+ { return intlit(yytext, 10, &yylval.lval); } 0x{HEX}+ { return intlit(yytext+2, 16, &yylval.lval); } {SP}*,{SP}* { return T_COMMA; } diff --git a/nqasm.c b/nqasm.c index ee3010a..49b4ec6 100644 --- a/nqasm.c +++ b/nqasm.c @@ -56,12 +56,27 @@ void add_instruction(const struct instruction *inst) addr += 2; } +struct argument *argdup(const struct argument *arg) +{ + struct argument *ret = malloc(sizeof *ret); + if (!ret) { + fprintf(stderr, "unable to allocate argument\n"); + exit(1); + } + *ret = *arg; + return ret; +} + static long eval_argument(const struct argument *arg, uint16_t pc) { struct label *l; switch (arg->type) { - case ARG_INTEGER: return arg->value; - case ARG_PC: return pc; + case ARG_INTEGER: return arg->value; + case ARG_PC: return pc; + case ARG_UNARY_ADD: return eval_argument(arg->children[0], pc); + case ARG_UNARY_SUB: return -eval_argument(arg->children[0], pc); + case ARG_UNARY_NOT: return !eval_argument(arg->children[0], pc); + case ARG_UNARY_INV: return ~eval_argument(arg->children[0], pc); case ARG_LABEL: l = vector_search(&labels->v, &(struct label) { .name = arg->label }, cmp_label); diff --git a/nqasm.h b/nqasm.h index 0bc51f7..e5a7452 100644 --- a/nqasm.h +++ b/nqasm.h @@ -1,15 +1,23 @@ #ifndef NQ_NQASM_H #define NQ_NQASM_H -#define ARG_INTEGER 0 -#define ARG_LABEL 1 -#define ARG_PC 2 +enum { + ARG_INTEGER, + ARG_LABEL, + ARG_PC, + + ARG_UNARY_ADD, + ARG_UNARY_SUB, + ARG_UNARY_NOT, + ARG_UNARY_INV, +}; struct argument { int type; union { long value; char *label; + const struct argument *children[1]; }; }; @@ -25,5 +33,7 @@ struct instruction { void add_instruction(const struct instruction *); void add_label(const char *); +struct argument *argdup(const struct argument *); + #endif diff --git a/parser.y b/parser.y index 2ec2264..cb1343f 100644 --- a/parser.y +++ b/parser.y @@ -16,6 +16,7 @@ void yyerror(const char *msg) #define MKARGVALUE(v) (struct argument) { .type = ARG_INTEGER, .value = (v) } #define MKARGLABEL(l) (struct argument) { .type = ARG_LABEL, .label = (l) } #define MKARGTYPE(t) (struct argument) { .type = (t) } +#define MKARGEXPR(op,c) (struct argument) { .type = (op), .children = c } %} @@ -84,6 +85,11 @@ void yyerror(const char *msg) %token T_DOT "." %token T_DEREF "@" +%token T_OPERATOR_ADD "+" +%token T_OPERATOR_SUB "-" +%token T_OPERATOR_NOT "!" +%token T_OPERATOR_INV "~" + %type inst %type reg %type regp @@ -181,6 +187,10 @@ expr: intlit { $$ = MKARGVALUE($1); } | T_LABEL { $$ = MKARGLABEL($1); } | "." { $$ = MKARGTYPE(ARG_PC); } + | "+" expr { $$ = MKARGEXPR(ARG_UNARY_ADD, { argdup(&$2) }); } + | "-" expr { $$ = MKARGEXPR(ARG_UNARY_SUB, { argdup(&$2) }); } + | "!" expr { $$ = MKARGEXPR(ARG_UNARY_NOT, { argdup(&$2) }); } + | "~" expr { $$ = MKARGEXPR(ARG_UNARY_INV, { argdup(&$2) }); } ; intlit: T_INT -- cgit v1.2.3