summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--04/in0329
-rw-r--r--05/constants.b2
-rw-r--r--05/main.c2
-rw-r--r--05/parse.b44
-rw-r--r--05/util.b75
-rw-r--r--README.md1
6 files changed, 127 insertions, 26 deletions
diff --git a/04/in03 b/04/in03
index 99b3c6e..a0cee4f 100644
--- a/04/in03
+++ b/04/in03
@@ -1005,7 +1005,7 @@ align
I=:line
call :set_rax_to_rvalue
call :set_rbx_to_rdi
- call :emit_zero_rdx_idiv_rbx
+ call :emit_cqo_idiv_rbx
I=:line
call :set_lvalue_to_rax
!:read_line
@@ -1014,7 +1014,7 @@ align
I=:line
call :set_rax_to_rvalue
call :set_rbx_to_rdi
- call :emit_zero_rdx_idiv_rbx
+ call :emit_cqo_idiv_rbx
call :set_rax_to_rdx
I=:line
call :set_lvalue_to_rax
@@ -1475,11 +1475,11 @@ align
:rvalue_div
call :set_rbx_to_rsi
- !:emit_zero_rdx_idiv_rbx
+ !:emit_cqo_idiv_rbx
:rvalue_rem
call :set_rbx_to_rsi
- call :emit_zero_rdx_idiv_rbx
+ call :emit_cqo_idiv_rbx
call :set_rax_to_rdx
return
@@ -1745,16 +1745,6 @@ align
x31
xc0
-:zero_rdx
- J=d4
- I=:xor_edx_edx
- D=d2
- syscall x1
- return
-:xor_edx_edx
- x31
- xd2
-
:set_rbx_to_rax
J=d4
I=:mov_rbx_rax
@@ -2014,14 +2004,15 @@ align
xf7
xeb
-:emit_zero_rdx_idiv_rbx
- call :zero_rdx
+:emit_cqo_idiv_rbx
J=d4
- I=:idiv_rbx
- D=d3
+ I=:cqo_idiv_rbx
+ D=d5
syscall x1
return
-:idiv_rbx
+:cqo_idiv_rbx
+ x48
+ x99
x48
xf7
xfb
diff --git a/05/constants.b b/05/constants.b
index 85aff7a..fa2d0f4 100644
--- a/05/constants.b
+++ b/05/constants.b
@@ -126,7 +126,7 @@
; uchar kind (one of the constants below)
; uchar info
; ushort (padding)
-; uint type (0 if expression hasn't been typed yet)
+; uint type
; immediately following the header in memory are the arguments of the expression
; - for constant ints, the 64-bit integral value
; - for constant floats, the 64-bit double value (even if expression has type float)
diff --git a/05/main.c b/05/main.c
index 357feff..ed86f51 100644
--- a/05/main.c
+++ b/05/main.c
@@ -3,4 +3,4 @@
long double d;
} (*x)(void);
*/
-typedef long int unsigned Foo[3 * 3];
+typedef long int unsigned Foo[19 + (-3) % 187 - 28 + 5 * 6];
diff --git a/05/parse.b b/05/parse.b
index bff260b..1764f82 100644
--- a/05/parse.b
+++ b/05/parse.b
@@ -943,6 +943,7 @@ function evaluate_constant_expression
argument p_value
local a
local b
+ local p
if *1expr == EXPRESSION_CONSTANT_INT goto eval_constant_int
if *1expr == EXPRESSION_IDENTIFIER goto eval_constant_identifier
@@ -951,8 +952,11 @@ function evaluate_constant_expression
if *1expr == EXPRESSION_BITWISE_NOT goto eval_bitwise_not
if *1expr == EXPRESSION_LOGICAL_NOT goto eval_logical_not
if *1expr == EXPRESSION_CAST goto eval_todo ; @TODO
- if *1expr == EXPRESSION_LOGICAL_NOT goto eval_logical_not
+ if *1expr == EXPRESSION_ADD goto eval_add
+ if *1expr == EXPRESSION_SUB goto eval_sub
if *1expr == EXPRESSION_MUL goto eval_mul
+ if *1expr == EXPRESSION_DIV goto eval_div
+ if *1expr == EXPRESSION_REMAINDER goto eval_remainder
byte 0xcc
:eval_todo
@@ -998,13 +1002,49 @@ function evaluate_constant_expression
:eval_logical_not0
*8p_value = 1
return expr
+ :eval_add
+ expr += 8
+ expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(expr, &b)
+ *8p_value = a + b
+ return expr
+ :eval_sub
+ expr += 8
+ expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(expr, &b)
+ *8p_value = a - b
+ return expr
:eval_mul
expr += 8
expr = evaluate_constant_expression(expr, &a)
expr = evaluate_constant_expression(expr, &b)
*8p_value = a * b
return expr
-
+ :eval_div
+ p = expr + 4 ; pointer to type
+ expr += 8
+ expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(expr, &b)
+ if *1p == TYPE_UNSIGNED_LONG goto eval_div_unsigned
+ ; division is signed or uses a small type, so we can use 64-bit signed division
+ *8p_value = a / b
+ return expr
+ :eval_div_unsigned
+ ; must use unsigned division
+ divmod_unsigned(a, b, p_value, &a)
+ return expr
+ :eval_remainder
+ p = expr + 4 ; pointer to type
+ expr += 8
+ expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(expr, &b)
+ if *1p == TYPE_UNSIGNED_LONG goto eval_rem_unsigned
+ *8p_value = a % b
+ return expr
+ :eval_rem_unsigned
+ divmod_unsigned(a, b, &a, p_value)
+ return expr
+
; the "usual conversions" for binary operators, as the C standard calls it
function expr_binary_type_usual_conversions
argument token ; for errors
diff --git a/05/util.b b/05/util.b
index c8c3e97..4a32af2 100644
--- a/05/util.b
+++ b/05/util.b
@@ -25,6 +25,75 @@ function full_multiply_signed
*8p_upper = upper
return
+
+function divmod_unsigned
+ argument a
+ argument b
+ argument p_quotient
+ argument p_remainder
+ local q
+ local r
+
+ ; mov rax, [rbp-16]
+ byte 0x48
+ byte 0x8b
+ byte 0x85
+ byte 0xf0
+ byte 0xff
+ byte 0xff
+ byte 0xff
+
+ ; mov rbx, rax
+ byte 0x48
+ byte 0x89
+ byte 0xc3
+
+ ; mov rax, [rbp-8]
+ byte 0x48
+ byte 0x8b
+ byte 0x85
+ byte 0xf8
+ byte 0xff
+ byte 0xff
+ byte 0xff
+
+ ; xor edx, edx
+ byte 0x31
+ byte 0xd2
+
+ ; div rbx
+ byte 0x48
+ byte 0xf7
+ byte 0xf3
+
+ ; mov [rbp-40], rax
+ byte 0x48
+ byte 0x89
+ byte 0x85
+ byte 0xd8
+ byte 0xff
+ byte 0xff
+ byte 0xff
+
+ ; mov rax, rdx
+ byte 0x48
+ byte 0x89
+ byte 0xd0
+
+ ; mov [rbp-48], rax
+ byte 0x48
+ byte 0x89
+ byte 0x85
+ byte 0xd0
+ byte 0xff
+ byte 0xff
+ byte 0xff
+
+ *8p_quotient = q
+ *8p_remainder = r
+
+ return
+
; allows for negative shifts
function right_shift
argument x
@@ -93,7 +162,8 @@ function free
syscall(11, psize, size)
return
-; returns a pointer to a null-terminated string containing the number given
+; returns a pointer to a null-terminated string containing the
+; (unsigned) number given
function itos
global 32 itos_string
argument x
@@ -102,10 +172,9 @@ function itos
p = &itos_string
p += 30
:itos_loop
- c = x % 10
+ divmod_unsigned(x, 10, &x, &c)
c += '0
*1p = c
- x /= 10
if x == 0 goto itos_loop_end
p -= 1
goto itos_loop
diff --git a/README.md b/README.md
index f000ad1..f379be1 100644
--- a/README.md
+++ b/README.md
@@ -137,6 +137,7 @@ In the table below, `IMM64` means a 64-bit *immediate* (a constant number).
│ add rax, rbx │ 48 01 d8 │ add rbx to rax │
│ sub rax, rbx │ 48 29 d8 │ subtract rbx from rax │
│ imul rbx │ 48 f7 eb │ set rdx:rax to rax * rbx (signed) │
+│ cqo │ 48 99 │ sign-extend rax to rdx:rax |
│ idiv rbx │ 48 f7 fb │ divide rdx:rax by rbx (signed); put │
│ │ │ quotient in rax, remainder in rbx │
│ mul rbx │ 48 f7 e3 │ like imul, but unsigned │