return, integer literals
This commit is contained in:
parent
d8bb5b8957
commit
bba56d2b51
4 changed files with 125 additions and 7 deletions
118
05/codegen.b
118
05/codegen.b
|
@ -150,12 +150,41 @@ function emit_call_rax
|
||||||
code_output += 2
|
code_output += 2
|
||||||
return
|
return
|
||||||
|
|
||||||
|
function emit_push_rax
|
||||||
|
; 50
|
||||||
|
*1code_output = 0x50
|
||||||
|
code_output += 1
|
||||||
|
return
|
||||||
|
|
||||||
function emit_syscall
|
function emit_syscall
|
||||||
; 0f 05
|
; 0f 05
|
||||||
*2code_output = 0x050f
|
*2code_output = 0x050f
|
||||||
code_output += 2
|
code_output += 2
|
||||||
return
|
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
|
; make sure you put the return value in the proper place before calling this
|
||||||
function generate_return
|
function generate_return
|
||||||
emit_mov_reg(REG_RSP, REG_RBP)
|
emit_mov_reg(REG_RSP, REG_RBP)
|
||||||
|
@ -164,11 +193,92 @@ function generate_return
|
||||||
emit_ret()
|
emit_ret()
|
||||||
return
|
return
|
||||||
|
|
||||||
function generate_statement
|
; returns pointer to end of expression
|
||||||
argument statement
|
function generate_push_expression
|
||||||
; @TODO
|
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
|
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
|
||||||
|
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
|
function generate_function
|
||||||
argument function_name
|
argument function_name
|
||||||
argument function_statement
|
argument function_statement
|
||||||
|
@ -216,7 +326,7 @@ function generate_functions
|
||||||
:genfs_cont
|
:genfs_cont
|
||||||
p = memchr(function_name, 0)
|
p = memchr(function_name, 0)
|
||||||
p += 1
|
p += 1
|
||||||
generate_function(function_name, p)
|
generate_function(function_name, *8p)
|
||||||
function_name = p + 8
|
function_name = p + 8
|
||||||
goto genfunctions_loop
|
goto genfunctions_loop
|
||||||
:genfunctions_loop_end
|
:genfunctions_loop_end
|
||||||
|
|
|
@ -14,5 +14,5 @@ struct B { struct A *blah; }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
argv+argc;
|
return 42;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,11 @@ function sign_extend_32_to_64
|
||||||
n |= c * 0xffffffff00000000
|
n |= c * 0xffffffff00000000
|
||||||
return n
|
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
|
; multiply two 64-bit signed numbers to a 128-bit number
|
||||||
function full_multiply_signed
|
function full_multiply_signed
|
||||||
|
|
|
@ -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 [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 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 [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 │
|
│ mov rax, [rbp+IMM32] │ 48 8b 85 IMM32 │ load 8 bytes from address rbp+IMM32 │
|
||||||
│ │ │ into rax (note: IMM32 may be negative) │
|
│ │ │ into rax (note: IMM32 may be negative) │
|
||||||
│ mov rax, [rsp+IMM32] │ 48 8b 84 24 IMM32 │ load 8 bytes from address rsp+IMM32 │
|
│ 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 │
|
│ 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 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 │
|
│ 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 │
|
│ neg rax │ 48 f7 d8 │ set rax to -rax │
|
||||||
│ add rax, rbx │ 48 01 d8 │ add rbx to rax │
|
│ add rax, rbx │ 48 01 d8 │ add rbx to rax │
|
||||||
│ sub rax, rbx │ 48 29 d8 │ subtract rbx from rax │
|
│ sub rax, rbx │ 48 29 d8 │ subtract rbx from rax │
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue