safety commit
This commit is contained in:
parent
d144537c3b
commit
9509931bc2
|
|
@ -25,6 +25,10 @@ section .rdata
|
||||||
PROLOGUE_LEN equ $ - PROLOGUE
|
PROLOGUE_LEN equ $ - PROLOGUE
|
||||||
EPILOGUE db "mov rsp, rbp", 10, "pop rbp", 10, "ret", 10
|
EPILOGUE db "mov rsp, rbp", 10, "pop rbp", 10, "ret", 10
|
||||||
EPILOGUE_LEN equ $ - EPILOGUE
|
EPILOGUE_LEN equ $ - EPILOGUE
|
||||||
|
MOV_RAX db "mov rax, "
|
||||||
|
MOV_RAX_LEN equ $ - MOV_RAX
|
||||||
|
JMP_EPILOGUE db 10, "jmp .epilogue", 10
|
||||||
|
JMP_EPILOGUE_LEN equ $ - JMP_EPILOGUE
|
||||||
|
|
||||||
REGISTER_NAMES db "abcdsidibpspr8r9r10r11r12r13r14r15"
|
REGISTER_NAMES db "abcdsidibpspr8r9r10r11r12r13r14r15"
|
||||||
WIDTHS db "erxliwdbp"
|
WIDTHS db "erxliwdbp"
|
||||||
|
|
@ -179,8 +183,73 @@ stackvar_cmp:
|
||||||
;; ast: *const Ast,
|
;; ast: *const Ast,
|
||||||
;; text: Vec<u8>,
|
;; text: Vec<u8>,
|
||||||
;; }
|
;; }
|
||||||
|
;; struct FunctionCtx {
|
||||||
|
;; current_stack_size: u64,
|
||||||
|
;; stack_vars: Vec<(u64, u64)>,
|
||||||
|
;; register_bitset: u128,
|
||||||
|
;; dirtied_register_bitset: u128,
|
||||||
|
;; }
|
||||||
;; end-structs
|
;; end-structs
|
||||||
|
|
||||||
|
;; rdi: *FunctionCtx
|
||||||
|
;; define-fn: fn codegen_allocate_register(ctx: *mut FunctionCtx) -> u8
|
||||||
|
codegen_allocate_register:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
push rbx
|
||||||
|
|
||||||
|
; scan register_bitset for free register
|
||||||
|
; example: (rax, rbp and rsp are always reserved)
|
||||||
|
; register_bitset = 0b10000011_00000000
|
||||||
|
; to do this, we first invert the bitset
|
||||||
|
; register_bitset = 0b01111100_11111111
|
||||||
|
; then we find the first set bit
|
||||||
|
; first_bit = 2
|
||||||
|
; we now set the bit in the original bitset and mark the register as dirtied
|
||||||
|
; dirtied registers are those that have been used in the function and need
|
||||||
|
; to be saved/restored in the prologue/epilogue
|
||||||
|
|
||||||
|
mov rax, [rdi + 48] ; register_bitset
|
||||||
|
xor rcx, rcx
|
||||||
|
; flip bits
|
||||||
|
not rax
|
||||||
|
; find first set bit
|
||||||
|
bsf rcx, rax
|
||||||
|
test rcx, rcx
|
||||||
|
jnz .found
|
||||||
|
mov rax, [rdi + 56] ; higher 64 bits
|
||||||
|
not rax
|
||||||
|
bsf rcx, rax
|
||||||
|
test rcx, rcx
|
||||||
|
jz .panic
|
||||||
|
add rcx, 8
|
||||||
|
|
||||||
|
.found:
|
||||||
|
mov rbx, rcx
|
||||||
|
cmp rcx, 8
|
||||||
|
jl .set_low
|
||||||
|
sub rcx, 8
|
||||||
|
bts rax, rcx
|
||||||
|
mov [rdi + 56], rax ; update register_bitset
|
||||||
|
mov rax, [rdi + 72] ; dirtied_register_bitset
|
||||||
|
bts rax, rcx
|
||||||
|
mov [rdi + 72], rax ; update dirtied_register_bitset
|
||||||
|
jmp .done
|
||||||
|
.set_low:
|
||||||
|
bts rax, rcx
|
||||||
|
mov [rdi + 48], rax ; update register_bitset
|
||||||
|
mov rax, [rdi + 64] ; dirtied_register_bitset
|
||||||
|
bts rax, rcx
|
||||||
|
mov [rdi + 64], rax ; update dirtied_register_bitset
|
||||||
|
|
||||||
|
.done:
|
||||||
|
pop rax
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
.panic:
|
||||||
|
; no free registers!
|
||||||
|
call panic
|
||||||
|
|
||||||
;; rdi: *Ctx
|
;; rdi: *Ctx
|
||||||
;; rsi: function index
|
;; rsi: function index
|
||||||
;; define-fn: fn codegen_function(ast: *const CodegenCtx, func_idx: u64) -> ()
|
;; define-fn: fn codegen_function(ast: *const CodegenCtx, func_idx: u64) -> ()
|
||||||
|
|
@ -191,14 +260,15 @@ codegen_function:
|
||||||
push r15
|
push r15
|
||||||
push r14
|
push r14
|
||||||
|
|
||||||
; scratch [88..104]
|
; scratch [104..120]
|
||||||
|
; dirtied-register-bitset [88..104] [a,b,c,d,si,di,bp,sp,8,9,10,11,12,13,14,15]
|
||||||
; register-bitset [72..88] [a,b,c,d,si,di,bp,sp,8,9,10,11,12,13,14,15]
|
; register-bitset [72..88] [a,b,c,d,si,di,bp,sp,8,9,10,11,12,13,14,15]
|
||||||
; stack-vars: Vec<(index, offset)> [32..72]
|
; stack-vars: Vec<(index, offset)> [32..72]
|
||||||
; current_stack_size: [24..32]
|
; current_stack_size: [24..32]
|
||||||
; func_idx [16..24]
|
; func_idx [16..24]
|
||||||
; ast [8..16]
|
; ast [8..16]
|
||||||
; ctx [0..8]
|
; ctx [0..8]
|
||||||
sub rsp, 104
|
sub rsp, 120
|
||||||
mov [rsp], rdi ; ctx
|
mov [rsp], rdi ; ctx
|
||||||
mov rax, [rdi]
|
mov rax, [rdi]
|
||||||
mov [rsp + 8], rax ; ast
|
mov [rsp + 8], rax ; ast
|
||||||
|
|
@ -279,13 +349,13 @@ codegen_function:
|
||||||
lea rsi, [rax + r14 * 8] ;
|
lea rsi, [rax + r14 * 8] ;
|
||||||
mov rsi, [rsi] ; AstFunction.args[i]
|
mov rsi, [rsi] ; AstFunction.args[i]
|
||||||
|
|
||||||
mov [rsp + 88], rsi
|
mov [rsp + 104], rsi ; scratch
|
||||||
mov rax, [rsp + 24] ; current_stack_size
|
mov rax, [rsp + 24] ; current_stack_size
|
||||||
mov [rsp + 96], rax
|
mov [rsp + 112], rax
|
||||||
add rax, 8 ; size_of::<u64>
|
add rax, 8 ; size_of::<u64>
|
||||||
mov [rsp + 24], rax ; current_stack_size += size_of::<u64>
|
mov [rsp + 24], rax ; current_stack_size += size_of::<u64>
|
||||||
lea rdi, [rsp + 32] ; stack-vars
|
lea rdi, [rsp + 32] ; stack-vars
|
||||||
lea rsi, [rsp + 88] ; &(index, offset)
|
lea rsi, [rsp + 104] ; &scratch: &(index, offset)
|
||||||
mov rdx, stackvar_cmp
|
mov rdx, stackvar_cmp
|
||||||
mov rcx, 0
|
mov rcx, 0
|
||||||
call vec_insert_sorted
|
call vec_insert_sorted
|
||||||
|
|
@ -308,7 +378,7 @@ codegen_function:
|
||||||
mov rdx, RET_NL_LEN
|
mov rdx, RET_NL_LEN
|
||||||
call vec_extend
|
call vec_extend
|
||||||
|
|
||||||
add rsp, 104
|
add rsp, 120
|
||||||
pop r15
|
pop r15
|
||||||
pop r14
|
pop r14
|
||||||
pop rbx
|
pop rbx
|
||||||
|
|
@ -322,4 +392,409 @@ codegen_function:
|
||||||
;; rsi: &function_ctx
|
;; rsi: &function_ctx
|
||||||
;; rdx: block index
|
;; rdx: block index
|
||||||
codegen_block:
|
codegen_block:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
push r15
|
||||||
|
push r14
|
||||||
|
push rbx
|
||||||
|
|
||||||
|
sub rsp, 16
|
||||||
|
mov [rsp], rdi ; ctx
|
||||||
|
mov [rsp + 8], rsi ; &function_ctx
|
||||||
|
|
||||||
|
mov rdi, [rdi] ; ast
|
||||||
|
mov rsi, rdx ; block index
|
||||||
|
call vec_get
|
||||||
|
mov 15, [rax + 8] ; AstNode.extra
|
||||||
|
mov rbx, [rax + 0] ; AstNode.data
|
||||||
|
|
||||||
|
xor r14, r14 ; statement index
|
||||||
|
.stmt_loop:
|
||||||
|
cmp r14, r15
|
||||||
|
jge .stmt_loop_done
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea mov, [rsp + 8] ; &function_ctx
|
||||||
|
mov rdx, [rbx + r14 * 8] ; statements[i]
|
||||||
|
call codegen_statement
|
||||||
|
inc r14
|
||||||
|
jmp .stmt_loop
|
||||||
|
|
||||||
|
.stmt_loop_done:
|
||||||
|
add rsp, 16
|
||||||
|
pop rbx
|
||||||
|
pop r14
|
||||||
|
pop r15
|
||||||
|
pop rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;; rdi: ctx
|
||||||
|
;; rsi: &function_ctx
|
||||||
|
;; rdx: expr index
|
||||||
|
;; returns: register index in rax if rdx=0, else stack-offset in rax
|
||||||
|
;; define-fn: fn codegen_expr(ctx: *const CodegenCtx, function_ctx: &FunctionCtx, expr_idx: u64) -> (u64, bool)
|
||||||
|
codegen_expr:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
push rbx
|
||||||
|
|
||||||
|
; scratch [16..32]
|
||||||
|
; function_ctx: [8..16]
|
||||||
|
; ctx [0..8]
|
||||||
|
sub rsp, 32
|
||||||
|
mov [rsp], rdi ; ctx
|
||||||
|
mov [rsp + 8], rsi ; &function_ctx
|
||||||
|
|
||||||
|
mov rdi, [rdi] ; ast
|
||||||
|
mov rsi, rdx ; statement index
|
||||||
|
call vec_get
|
||||||
|
; rax: *AstNode
|
||||||
|
|
||||||
|
|
||||||
|
mov rbx, [rax] ; AstNode.kind
|
||||||
|
cmp bl, AST_RETURN_STATEMENT
|
||||||
|
je .return
|
||||||
|
cmp bl, AST_BLOCK
|
||||||
|
je .block
|
||||||
|
cmp bl, AST_VAR_DECL
|
||||||
|
je .var_decl
|
||||||
|
cmp bl, AST_VAR_REF
|
||||||
|
je .var_ref
|
||||||
|
cmp bl, AST_NUMBER
|
||||||
|
je .number
|
||||||
|
cmp bl, AST_BINARY_OP
|
||||||
|
je .binary_op
|
||||||
|
cmp bl, AST_ASSIGNMENT
|
||||||
|
je .assignment
|
||||||
|
cmp bl, AST_PLACE_TO_VALUE
|
||||||
|
je .place_to_value
|
||||||
|
cmp bl, AST_VALUE_TO_PLACE
|
||||||
|
je .value_to_place
|
||||||
|
cmp bl, AST_DEREF
|
||||||
|
je .deref
|
||||||
|
cmp bl, AST_ADDRESS_OF
|
||||||
|
je .address_of
|
||||||
|
jmp .panic
|
||||||
|
|
||||||
|
.return:
|
||||||
|
; codegen inner expr
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
mov rsi, [rsp + 8] ; &function_ctx
|
||||||
|
mov rdx, [rax + 8] ; AstNode.data
|
||||||
|
call codegen_expr
|
||||||
|
mov rbx, rax
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
mov rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel MOV_RAX]
|
||||||
|
mov rdx, MOV_RAX_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov rdi, rbx
|
||||||
|
mov rsi, 8
|
||||||
|
lea rdx, [rsp + 16] ; scratch
|
||||||
|
call get_register_name
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
mov rdi, [rdi + 8] ; &ctx.text
|
||||||
|
mov rsi, rax
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
mov rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel JMP_EPILOGUE]
|
||||||
|
mov rdx, JMP_EPILOGUE_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov rax, 0
|
||||||
|
jmp .done
|
||||||
|
|
||||||
|
.number:
|
||||||
|
; rax = *AstNode
|
||||||
|
mov [rsp + 16], rax ; scratch = *AstNode
|
||||||
|
mov rdi, [rsp + 8] ; &function_ctx
|
||||||
|
call codegen_allocate_register
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; TODO
|
||||||
|
|
||||||
|
.done:
|
||||||
|
add rsp, 32
|
||||||
|
pop rbx
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
.panic:
|
||||||
|
call panic
|
||||||
|
|
||||||
|
|
||||||
|
;; start-structs
|
||||||
|
;; struct Operand {
|
||||||
|
;; kind: u8
|
||||||
|
;; register_and_width: u8,
|
||||||
|
;; len: u16,
|
||||||
|
;; value: u64,
|
||||||
|
;; }
|
||||||
|
;; end-structs
|
||||||
|
;; or: register: u4, width: u4
|
||||||
|
section .rdata
|
||||||
|
;; start-consts
|
||||||
|
OPERAND_REGISTER db 1 ; e.g. rax, rbx
|
||||||
|
OPERAND_RBP_OFFSET db 2 ; e.g. [rbp - 8]
|
||||||
|
OPERAND_RSP_OFFSET db 3 ; e.g. [rsp + 16]
|
||||||
|
OPERAND_ADDRESS db 4 ; e.g. [rel OPERAND_ADDRESS]
|
||||||
|
OPERAND_IMMEDIATE db 5 ; e.g. 0x10
|
||||||
|
OPERAND_CONSTANT db 6 ; e.g. OPERAND_CONSTANT
|
||||||
|
OPERAND_LABEL db 7 ; e.g. label_1234
|
||||||
|
;; end-consts
|
||||||
|
WIDTH_BYTE db 'byte '
|
||||||
|
WIDTH_WORD db 'word '
|
||||||
|
WIDTH_DWORD db 'dword '
|
||||||
|
WIDTH_QWORD db 'qword '
|
||||||
|
|
||||||
|
;; rdi: *text
|
||||||
|
;; rsi: op: *Operand
|
||||||
|
codegen_write_operand:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
push rbx
|
||||||
|
|
||||||
|
; scratch [16..40]
|
||||||
|
; *operand [8..16]
|
||||||
|
; *text [0..8]
|
||||||
|
sub rsp, 40
|
||||||
|
mov [rsp], rdi ; *text
|
||||||
|
mov [rsp + 8], rsi ; op
|
||||||
|
|
||||||
|
mov bl, byte [rsi + 0] ; op.kind
|
||||||
|
cmp bl, OPERAND_REGISTER
|
||||||
|
je .register
|
||||||
|
cmp bl, OPERAND_RBP_OFFSET
|
||||||
|
je .rbp_offset
|
||||||
|
cmp bl, OPERAND_RSP_OFFSET
|
||||||
|
je .rsp_offset
|
||||||
|
cmp bl, OPERAND_ADDRESS
|
||||||
|
je .address
|
||||||
|
cmp bl, OPERAND_IMMEDIATE
|
||||||
|
je .immediate
|
||||||
|
cmp bl, OPERAND_CONSTANT
|
||||||
|
je .constant
|
||||||
|
cmp bl, OPERAND_LABEL
|
||||||
|
je .label
|
||||||
|
jmp .panic
|
||||||
|
|
||||||
|
.register:
|
||||||
|
mov rbx, rsi
|
||||||
|
mov rdi, [rbx + 1] ; register_and_width
|
||||||
|
mov rsi, rdi
|
||||||
|
mov dil, dil ; low 4 bits = register
|
||||||
|
shr rsi, 4 ; high 4 bits = width
|
||||||
|
lea rdx, [rsp + 16] ; buffer
|
||||||
|
call get_register_name
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
mov rsi, rax ; buffer
|
||||||
|
call vec_extend
|
||||||
|
jmp .epilogue
|
||||||
|
|
||||||
|
.rbp_offset:
|
||||||
|
.rsp_offset:
|
||||||
|
; {width} [rbp {+/-} offset]
|
||||||
|
mov rsi, [rsp + 8] ; op
|
||||||
|
mov sil, byte [rsi + 1] ; register_and_width
|
||||||
|
shr sil, 4 ; width
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
call codegen_write_width
|
||||||
|
mov rbx, rax
|
||||||
|
|
||||||
|
mov byte [rsp + 16], '['
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rsp + 16]
|
||||||
|
call vec_push
|
||||||
|
|
||||||
|
; if op.kind == OPERAND_RBP_OFFSET
|
||||||
|
mov rax, [rsp + 8] ; op
|
||||||
|
mov al, byte [rax + 0] ; op.kind
|
||||||
|
cmp al, OPERAND_RBP_OFFSET
|
||||||
|
jne .rsp_offset_write
|
||||||
|
mov qword [rsp + 16], ' pbr'
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rsp + 16]
|
||||||
|
mov rdx, 4
|
||||||
|
call vec_extend
|
||||||
|
jmp .check_sign
|
||||||
|
|
||||||
|
.rsp_offset_write:
|
||||||
|
mov qword [rsp + 16], ' psr'
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rsp + 16]
|
||||||
|
mov rdx, 4
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
.check_sign:
|
||||||
|
; if value >= 0
|
||||||
|
mov rax, [rsp + 8] ; op
|
||||||
|
mov rdi, [rax + 8] ; op.value
|
||||||
|
cmp rdi, 0
|
||||||
|
jl .skip_plus
|
||||||
|
mov qword [rsp + 16], ' + '
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rsp + 16]
|
||||||
|
mov rdx, 3
|
||||||
|
call vec_extend
|
||||||
|
.skip_plus:
|
||||||
|
|
||||||
|
; write offset
|
||||||
|
mov rax, [rsp + 8] ; op
|
||||||
|
mov rdi, [rax + 8] ; op.value
|
||||||
|
lea rsi, [rsp + 16]
|
||||||
|
mov rdx, 24 ; max length
|
||||||
|
mov rcx, 10 ; radix
|
||||||
|
call int_to_str2
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
mov rsi, rax ; buffer
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov byte [rsp + 16], ']'
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rsp + 16]
|
||||||
|
call vec_push
|
||||||
|
jmp .epilogue
|
||||||
|
|
||||||
|
.address:
|
||||||
|
mov byte [rsp + 16], '['
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rsp + 16]
|
||||||
|
call vec_push
|
||||||
|
|
||||||
|
mov qword [rsp + 16], ' ler'
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rsp + 16]
|
||||||
|
mov rdx, 4
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
; write address name
|
||||||
|
mov rax, [rsp + 8] ; op
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
mov rsi, [rax + 8] ; op.value
|
||||||
|
mov rdx, [rax + 4] ; op.len
|
||||||
|
mov dx, dx ; low 16 bits
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov byte [rsp + 16], ']'
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rsp + 16]
|
||||||
|
call vec_push
|
||||||
|
jmp .epilogue
|
||||||
|
|
||||||
|
.immediate:
|
||||||
|
; write immediate value
|
||||||
|
mov rax, [rsp + 8] ; op
|
||||||
|
mov rdi, [rax + 8] ; op.value
|
||||||
|
lea rsi, [rsp + 16]
|
||||||
|
mov rdx, 24 ; max length
|
||||||
|
mov rcx, 10 ; radix
|
||||||
|
call int_to_str2
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
mov rsi, rax ; buffer
|
||||||
|
call vec_extend
|
||||||
|
jmp .epilogue
|
||||||
|
|
||||||
|
.constant:
|
||||||
|
; write constant name
|
||||||
|
mov rax, [rsp + 8] ; op
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
mov rsi, [rax + 8] ; op.value
|
||||||
|
mov rdx, [rax + 4] ; op.len
|
||||||
|
mov dx, dx ; low 16 bits
|
||||||
|
call vec_extend
|
||||||
|
jmp .epilogue
|
||||||
|
|
||||||
|
.epilogue:
|
||||||
|
add rsp, 40
|
||||||
|
pop rbx
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
.panic:
|
||||||
|
call panic
|
||||||
|
|
||||||
|
;; rdi: *text
|
||||||
|
;; rsi: width: u8
|
||||||
|
codegen_write_width:
|
||||||
|
cmp sil, 8
|
||||||
|
lea rdx, [rel WIDTH_QWORD]
|
||||||
|
mov rcx, 6
|
||||||
|
je .write
|
||||||
|
cmp sil, 4
|
||||||
|
lea rdx, [rel WIDTH_DWORD]
|
||||||
|
je .write
|
||||||
|
cmp sil, 2
|
||||||
|
lea rdx, [rel WIDTH_WORD]
|
||||||
|
mov rcx, 5
|
||||||
|
je .write
|
||||||
|
cmp sil, 1
|
||||||
|
lea rdx, [rel WIDTH_BYTE]
|
||||||
|
je .write
|
||||||
|
jmp .panic
|
||||||
|
.write:
|
||||||
|
mov rsi, rdx
|
||||||
|
mov rdx, rcx
|
||||||
|
push rdx
|
||||||
|
call vec_extend
|
||||||
|
pop rax ; length written
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;; rdi: *text
|
||||||
|
;; rsi: dst: *Operand
|
||||||
|
;; rdx: src: *Operand
|
||||||
|
codegen_move_dst_src:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
push rbx
|
||||||
|
|
||||||
|
sub rsp, 24
|
||||||
|
mov [rsp], rdi ; *text
|
||||||
|
mov [rsp + 8], rsi ; dst
|
||||||
|
mov [rsp + 16], rdx ; src
|
||||||
|
|
||||||
|
cmp byte [rsi + 0], OPERAND_ADDRESS
|
||||||
|
jg .panic ; unsupported dst kind
|
||||||
|
|
||||||
|
; if dst.width != src.width
|
||||||
|
mov cl, byte [rsi + 2] ; dst.register_and_width
|
||||||
|
mov bl, byte [rdx + 2] ; src.register_and_width
|
||||||
|
shr cl, 4
|
||||||
|
shr bl, 4
|
||||||
|
cmp cl, bl
|
||||||
|
jne .panic ; mismatched widths
|
||||||
|
|
||||||
|
; if dst.width == 8 && src.kind == OPERAND_ADDRESS
|
||||||
|
xor rbx, rbx
|
||||||
|
cmp cl, 8
|
||||||
|
cmovne rbx, [rdx + 0]
|
||||||
|
cmp bl, OPERAND_ADDRESS
|
||||||
|
je .panic ; address can only be moved to full-sized destinations
|
||||||
|
|
||||||
|
cmp byte [rsi + 0], OPERAND_REGISTER
|
||||||
|
je .do_move
|
||||||
|
cmp byte [rdx + 0], OPERAND_REGISTER
|
||||||
|
jne .xchg_rax ; if dst != register and src != register, xchg via rax
|
||||||
|
jmp .do_move
|
||||||
|
|
||||||
|
.xchg_rax:
|
||||||
|
; xchg rax, [src]
|
||||||
|
; mov [dst], rax
|
||||||
|
; xchg rax, [src]
|
||||||
|
.do_move:
|
||||||
|
|
||||||
|
.epilogue:
|
||||||
|
add rsp, 24
|
||||||
|
pop rbx
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.panic:
|
||||||
|
call panic
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue