summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--05/codegen.b118
-rw-r--r--05/main.c2
-rw-r--r--05/util.b5
-rw-r--r--README.md5
4 files changed, 124 insertions, 6 deletions
diff --git a/05/codegen.b b/05/codegen.b
index 304b612..1f0d077 100644
--- a/05/codegen.b
+++ b/05/codegen.b
@@ -150,12 +150,41 @@ function emit_call_rax
code_output += 2
return
+function emit_push_rax
+ ; 50
+ *1code_output = 0x50
+ code_output += 1
+ return
+
function emit_syscall
; 0f 05
*2code_output = 0x050f
code_output += 2
return
+function emit_lea_rax_rbp_plus_imm32
+ ; 48 8d 85 IMM32
+ argument imm32
+ *2code_output = 0x8d48
+ code_output += 2
+ *1code_output = 0x85
+ code_output += 1
+ *4code_output = imm32
+ code_output += 4
+ return
+
+function emit_rep_movsb
+ ; f3 a4
+ *2code_output = 0xa4f3
+ code_output += 2
+ return
+
+function emit_movsq
+ ; 48 a5
+ *2code_output = 0xa548
+ code_output += 2
+ return
+
; make sure you put the return value in the proper place before calling this
function generate_return
emit_mov_reg(REG_RSP, REG_RBP)
@@ -164,11 +193,92 @@ function generate_return
emit_ret()
return
+; returns pointer to end of expression
+function generate_push_expression
+ argument expr
+ local c
+ c = *1expr
+ if c == EXPRESSION_CONSTANT_INT goto generate_push_int
+
+ die(.str_genpushexprNI)
+ :str_genpushexprNI
+ string generate_push_expression not implemented.
+ byte 0
+ :generate_push_int
+ expr += 8
+ emit_mov_rax_imm64(*8expr)
+ emit_push_rax()
+ expr += 8
+ return expr
+
+; copy sizeof(type) bytes, rounded up to the nearest 8, from rsi to rdi
+function generate_copy_rsi_to_rdi_qwords
+ argument type
+ local n
+ n = type_sizeof(type)
+ n = round_up_to_8(n)
+ if n == 8 goto rsi2rdi_qwords_simple
+ ; this is a struct or something, use rep movsb
+ emit_mov_rax_imm64(n)
+ emit_mov_reg(REG_RCX, REG_RAX)
+ emit_rep_movsb()
+ return
+
+ :rsi2rdi_qwords_simple
+ ; copy 8 bytes from rsi to rdi
+ ; this is a little "optimization" over rep movsb with rcx = 8, mainly it just makes debugging easier (otherwise you'd need 8 `stepi`s in gdb to skip over the instruction)
+ emit_movsq()
+ return
+
function generate_statement
argument statement
+ local dat1
+ local dat2
+ local dat3
+ local dat4
+ local n
+ local p
+ local c
+
+ dat1 = statement + 8
+ dat1 = *8dat1
+ dat2 = statement + 16
+ dat2 = *8dat2
+ dat3 = statement + 24
+ dat3 = *8dat3
+ dat4 = statement + 32
+ dat4 = *8dat4
+
+ c = *1statement
+
+ if c == STATEMENT_BLOCK goto gen_block
+ if c == STATEMENT_RETURN goto gen_return
; @TODO
- return
-
+ die(.str_genstmtNI)
+ :str_genstmtNI
+ string generate_statement not implemented.
+ byte 0
+ :gen_block
+ :gen_block_loop
+ if *1dat1 == 0 goto gen_block_loop_end
+ generate_statement(dat1)
+ dat1 += 40
+ goto gen_block_loop
+ :gen_block_loop_end
+ return
+ :gen_return
+ if dat1 == 0 goto gen_return_noexpr
+ generate_push_expression(dat1)
+ ; copy sizeof(return expression) rounded up to 8 bytes from [rsp] to [rbp+16]
+ emit_mov_reg(REG_RSI, REG_RSP)
+ emit_lea_rax_rbp_plus_imm32(16)
+ emit_mov_reg(REG_RDI, REG_RAX)
+ p = dat1 + 4
+ generate_copy_rsi_to_rdi_qwords(*4p)
+
+ :gen_return_noexpr
+ generate_return()
+ return
function generate_function
argument function_name
argument function_statement
@@ -185,7 +295,7 @@ function generate_function
; prologue
emit_sub_rsp_imm32(8)
emit_mov_qword_rsp_rbp()
- emit_mov_reg(REG_RBP, REG_RSP)
+ emit_mov_reg(REG_RBP, REG_RSP)
generate_statement(function_statement)
@@ -216,7 +326,7 @@ function generate_functions
:genfs_cont
p = memchr(function_name, 0)
p += 1
- generate_function(function_name, p)
+ generate_function(function_name, *8p)
function_name = p + 8
goto genfunctions_loop
:genfunctions_loop_end
diff --git a/05/main.c b/05/main.c
index 98cfb19..5cbffbf 100644
--- a/05/main.c
+++ b/05/main.c
@@ -14,5 +14,5 @@ struct B { struct A *blah; }
*/
int main(int argc, char **argv) {
- argv+argc;
+ return 42;
}
diff --git a/05/util.b b/05/util.b
index 5f7c5e6..25ce686 100644
--- a/05/util.b
+++ b/05/util.b
@@ -5,6 +5,11 @@ function sign_extend_32_to_64
n |= c * 0xffffffff00000000
return n
+; round up to nearest multiple of 8
+function round_up_to_8
+ argument n
+ n += 7
+ return n & 0xfffffffffffffff8
; multiply two 64-bit signed numbers to a 128-bit number
function full_multiply_signed
diff --git a/README.md b/README.md
index 3430546..12faae7 100644
--- a/README.md
+++ b/README.md
@@ -127,7 +127,7 @@ ax bx cx dx sp bp si di
│ mov [rbx], ax │ 66 89 03 │ store ax as 2 bytes at address rbx │
│ mov ax, [rbx] │ 66 8b 03 │ load 2 bytes from address rbx into eax │
│ mov [rbx], al │ 88 03 │ store al as 1 byte at address rbx │
-│ mov al, [rbx] │ 8a 03 │ load 1 byte from addrress rbx into al │
+│ mov al, [rbx] │ 8a 03 │ load 1 byte from address rbx into al │
│ mov rax, [rbp+IMM32] │ 48 8b 85 IMM32 │ load 8 bytes from address rbp+IMM32 │
│ │ │ into rax (note: IMM32 may be negative) │
│ mov rax, [rsp+IMM32] │ 48 8b 84 24 IMM32 │ load 8 bytes from address rsp+IMM32 │
@@ -138,6 +138,9 @@ ax bx cx dx sp bp si di
│ mov rbp, [rsp] │ 48 8b 2c 24 │ load 8 bytes from rsp into rbp │
│ lea rax, [rbp+IMM32] │ 48 8d 85 IMM32 │ set rax to rbp+IMM32 │
│ lea rsp, [rbp+IMM32] │ 48 8d a5 IMM32 │ set rsp to rbp+IMM32 │
+| movsq | 48 a5 | copy 8 bytes from rsi to rdi |
+| rep movsb | f3 a4 | copy rcx bytes from rsi to rdi |
+│ push rax │ 50 │ push rax onto the stack │
│ neg rax │ 48 f7 d8 │ set rax to -rax │
│ add rax, rbx │ 48 01 d8 │ add rbx to rax │
│ sub rax, rbx │ 48 29 d8 │ subtract rbx from rax │