summaryrefslogtreecommitdiff
path: root/nqasm.c
diff options
context:
space:
mode:
authorBobby Bingham <koorogi@koorogi.info>2017-01-18 18:55:22 -0600
committerBobby Bingham <koorogi@koorogi.info>2017-01-18 18:55:22 -0600
commit619c5cc4ab4bd94f9b270a9868bb5f08ffd76acb (patch)
tree5d58bf4f4cc66621f5327edb30ba593c72b4c5da /nqasm.c
parent17d11b2e0af9cbbe9e2c02c4d1a3d2cb4509701e (diff)
nqasm: allow specifying labels for operands
Diffstat (limited to 'nqasm.c')
-rw-r--r--nqasm.c60
1 files changed, 57 insertions, 3 deletions
diff --git a/nqasm.c b/nqasm.c
index 738f815..0b0bbd8 100644
--- a/nqasm.c
+++ b/nqasm.c
@@ -1,3 +1,4 @@
+#include <assert.h>
#include <stdint.h>
#include <stdio.h>
@@ -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;