commit dcdf77176b840cf4bea9974a51614bfdaf888a87
parent 55c2f96d993d3f08226d66b284fa6cc92b0130ec
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Tue, 23 Nov 2021 18:36:22 -0600
subtraction
Diffstat:
5 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/main.c b/main.c
@@ -75,6 +75,10 @@ lex(struct slice start)
cur->type = TOK_PLUS;
start.ptr++;
start.len--;
+ } else if (*start.ptr == '-') {
+ cur->type = TOK_MINUS;
+ start.ptr++;
+ start.len--;
} else if (*start.ptr == '=') {
cur->type = TOK_EQUAL;
start.ptr++;
@@ -184,6 +188,9 @@ dumpbinop(enum binop op)
case OP_PLUS:
fprintf(stderr, "OP_PLUS");
break;
+ case OP_MINUS:
+ fprintf(stderr, "OP_MINUS");
+ break;
default:
error("invalid binop");
}
@@ -238,6 +245,13 @@ parseexpr(struct token **tok)
expr.left = parseexpr(tok);
expr.right = parseexpr(tok);
break;
+ case TOK_MINUS:
+ expr.kind = EXPR_BINARY;
+ expr.d.op = OP_MINUS;
+ *tok = (*tok)->next;
+ expr.left = parseexpr(tok);
+ expr.right = parseexpr(tok);
+ break;
case TOK_STRING:
expr.kind = EXPR_LIT;
expr.d.v.type = P_STR;
@@ -330,6 +344,15 @@ genexpr(char *buf, size_t idx, enum reg reg)
freereg(rreg);
break;
}
+ case OP_MINUS: {
+ len += genexpr(ptr ? ptr + len : ptr, expr->left, reg);
+ enum reg rreg = getreg();
+ len += genexpr(ptr ? ptr + len : ptr, expr->right, rreg);
+
+ len += sub_r64_r64(ptr ? ptr + len : ptr, reg, rreg);
+ freereg(rreg);
+ break;
+ }
default:
error("genexpr: unknown binary op!");
}
diff --git a/nooc.h b/nooc.h
@@ -8,6 +8,7 @@ enum tokentype {
TOK_RPAREN,
TOK_PLUS,
+ TOK_MINUS,
TOK_COMMA,
TOK_EQUAL,
@@ -80,6 +81,7 @@ enum primitive {
enum binop {
OP_PLUS,
+ OP_MINUS,
};
struct value {
diff --git a/prog.nc b/prog.nc
@@ -3,6 +3,6 @@ stdout = 0
exit = 60
len1 = 11
len2 = 6
-syscall(write, + + 0 1 + 0 1, "hello world", + 1 + 2 + 3 + 4 1)
+syscall(write, - 2 1, "hello world", + 1 + 2 + 3 + 4 1)
syscall(write, stdout, " world", len2)
syscall(exit, 0)
diff --git a/x64.c b/x64.c
@@ -103,3 +103,17 @@ add_r64_r64(char *buf, enum reg reg1, enum reg reg2)
return 3;
}
+
+size_t
+sub_r64_r64(char *buf, enum reg reg1, enum reg reg2)
+{
+ uint8_t mov[] = {0x48, 0x29};
+ uint8_t op = (MOD_DIRECT << 6) | (reg1 << 3) | reg2;
+ if (buf) {
+ memcpy(buf, mov, 2);
+ buf += 2;
+ *(buf++) = op;
+ }
+
+ return 3;
+}
diff --git a/x64.h b/x64.h
@@ -35,3 +35,4 @@ size_t add_r_imm(char *buf, enum reg reg, uint64_t imm);
size_t mov_r_imm(char *buf, enum reg reg, uint64_t imm);
size_t mov_r64_m64(char *buf, enum reg reg, uint64_t addr);
size_t add_r64_r64(char *buf, enum reg reg1, enum reg reg2);
+size_t sub_r64_r64(char *buf, enum reg reg1, enum reg reg2);