diff --git a/boot.c b/boot.c index 3b29c97..ba8b11e 100644 --- a/boot.c +++ b/boot.c @@ -682,9 +682,9 @@ int step_of(int type) { return 1; } -void asm_slli_t0(int type) { +void asm_shift_t0(const char* op, int type) { if (type == TYPE_INT_PTR) { - printf(" slli t0, t0, 2\n"); + printf(" %s t0, t0, 2\n", op); } } @@ -704,7 +704,7 @@ int asm_add(int lhs, int rhs) { int ptr_type = local_type[ptr]; load(0, idx); load(1, ptr); - asm_slli_t0(ptr_type); + asm_shift_t0("slli", ptr_type); printf(" add t0, t0, t1\n"); return materialize_t0(ptr_type); } @@ -715,6 +715,28 @@ int asm_add(int lhs, int rhs) { return asm_rr("add", lhs, rhs); } +int asm_sub(int lhs, int rhs) { + int type1 = local_type[lhs] & TYPE_PTR_MASK; + int type2 = local_type[rhs] & TYPE_PTR_MASK; + if (type1 && type2) { + load(0, lhs); + load(1, rhs); + int ptr_type = local_type[lhs]; + printf(" sub t0, t0, t1\n"); + asm_shift_t0("srli", ptr_type); + return materialize_t0(TYPE_INT); + } + if (type1) { + int neg = asm_r("neg", rhs); + return asm_add(lhs, neg); + } + if (type2) { + eprintf("a number cannot be subtracted by a pointer\n"); + exit(1); + } + return asm_rr("sub", lhs, rhs); +} + // parser int parse_expr(); @@ -870,7 +892,7 @@ int parse_add_expr() { lhs = asm_add(lhs, rhs); } else if (token_type == TOKEN_MINUS) { int rhs = parse_mul_expr(); - lhs = asm_rr("sub", lhs, rhs); + lhs = asm_sub(lhs, rhs); } else { unget_token(); break;