fix function prologue/epilogue, 2nd pass
This commit is contained in:
parent
4b9596e892
commit
d03916a3f8
2 changed files with 210 additions and 25 deletions
213
04b/in03
213
04b/in03
|
@ -34,6 +34,7 @@ A=d3
|
||||||
J=A
|
J=A
|
||||||
?J<0:output_file_error
|
?J<0:output_file_error
|
||||||
|
|
||||||
|
:second_pass_starting_point
|
||||||
; write ELF header
|
; write ELF header
|
||||||
J=d4
|
J=d4
|
||||||
I=:ELF_header
|
I=:ELF_header
|
||||||
|
@ -150,6 +151,24 @@ D=A
|
||||||
!:read_line
|
!:read_line
|
||||||
|
|
||||||
:eof
|
:eof
|
||||||
|
C=:second_pass
|
||||||
|
D=1C
|
||||||
|
?D!0:exit_success
|
||||||
|
; set 2nd pass to 1
|
||||||
|
1C=d1
|
||||||
|
; seek both files back to start
|
||||||
|
J=d3
|
||||||
|
I=d0
|
||||||
|
D=d0
|
||||||
|
syscall x8
|
||||||
|
J=d4
|
||||||
|
I=d0
|
||||||
|
D=d0
|
||||||
|
syscall x8
|
||||||
|
|
||||||
|
!:second_pass_starting_point
|
||||||
|
|
||||||
|
:exit_success
|
||||||
J=d0
|
J=d0
|
||||||
syscall x3c
|
syscall x3c
|
||||||
|
|
||||||
|
@ -177,7 +196,7 @@ align
|
||||||
C=:local_start
|
C=:local_start
|
||||||
8C=I
|
8C=I
|
||||||
J=:local_variables
|
J=:local_variables
|
||||||
D=d9
|
D=d5
|
||||||
call :ident_lookup
|
call :ident_lookup
|
||||||
C=A
|
C=A
|
||||||
?C!0:local_redeclaration
|
?C!0:local_redeclaration
|
||||||
|
@ -192,9 +211,9 @@ align
|
||||||
J+=d1
|
J+=d1
|
||||||
; store address
|
; store address
|
||||||
D=:stack_end
|
D=:stack_end
|
||||||
D=8D
|
D=4D
|
||||||
8J=D
|
4J=D
|
||||||
J+=d8
|
J+=d4
|
||||||
; store null terminator
|
; store null terminator
|
||||||
1J=0
|
1J=0
|
||||||
; update :stack_end
|
; update :stack_end
|
||||||
|
@ -222,6 +241,11 @@ align
|
||||||
reserve d8
|
reserve d8
|
||||||
|
|
||||||
:handle_global
|
:handle_global
|
||||||
|
; ignore if this is the second pass
|
||||||
|
C=:second_pass
|
||||||
|
C=1C
|
||||||
|
?C!0:read_line
|
||||||
|
|
||||||
; skip ' '
|
; skip ' '
|
||||||
I+=d1
|
I+=d1
|
||||||
call :read_type
|
call :read_type
|
||||||
|
@ -234,7 +258,7 @@ align
|
||||||
C=:global_start
|
C=:global_start
|
||||||
8C=I
|
8C=I
|
||||||
J=:global_variables
|
J=:global_variables
|
||||||
D=d9
|
D=d5
|
||||||
call :ident_lookup
|
call :ident_lookup
|
||||||
C=A
|
C=A
|
||||||
?C!0:global_redeclaration
|
?C!0:global_redeclaration
|
||||||
|
@ -250,9 +274,9 @@ align
|
||||||
J+=d1
|
J+=d1
|
||||||
; store address
|
; store address
|
||||||
D=:static_memory_end
|
D=:static_memory_end
|
||||||
D=8D
|
D=4D
|
||||||
8J=D
|
4J=D
|
||||||
J+=d8
|
J+=d4
|
||||||
; store null terminator
|
; store null terminator
|
||||||
1J=0
|
1J=0
|
||||||
; update :static_memory_end
|
; update :static_memory_end
|
||||||
|
@ -267,10 +291,10 @@ align
|
||||||
!:read_line
|
!:read_line
|
||||||
|
|
||||||
:handle_function
|
:handle_function
|
||||||
; emit "mov rbp, rsp"
|
; emit prologue
|
||||||
J=d4
|
J=d4
|
||||||
I=:mov_rbp_rsp
|
I=:function_prologue
|
||||||
D=d3
|
D=d14
|
||||||
syscall x1
|
syscall x1
|
||||||
|
|
||||||
; reset local variable table
|
; reset local variable table
|
||||||
|
@ -282,10 +306,50 @@ align
|
||||||
; go read the next line
|
; go read the next line
|
||||||
!:read_line
|
!:read_line
|
||||||
|
|
||||||
:mov_rbp_rsp
|
:function_prologue
|
||||||
|
; sub rsp, 8
|
||||||
|
x48
|
||||||
|
x81
|
||||||
|
xec
|
||||||
|
x08
|
||||||
|
x00
|
||||||
|
x00
|
||||||
|
x00
|
||||||
|
; mov [rsp], rbp
|
||||||
|
x48
|
||||||
|
x89
|
||||||
|
x2c
|
||||||
|
x24
|
||||||
|
; mov rbp, rsp
|
||||||
R=S
|
R=S
|
||||||
|
; total length: 7 + 4 + 3 = 14 bytes
|
||||||
|
|
||||||
|
:function_epilogue
|
||||||
|
; mov rsp, rbp
|
||||||
|
S=R
|
||||||
|
; mov rbp, [rsp]
|
||||||
|
x48
|
||||||
|
x8b
|
||||||
|
x2c
|
||||||
|
x24
|
||||||
|
; add rsp, 8
|
||||||
|
x48
|
||||||
|
x81
|
||||||
|
xc4
|
||||||
|
x08
|
||||||
|
x00
|
||||||
|
x00
|
||||||
|
x00
|
||||||
|
; ret
|
||||||
|
return
|
||||||
|
; total length = 15 bytes
|
||||||
|
|
||||||
:handle_label_definition
|
:handle_label_definition
|
||||||
|
; ignore if this is the second pass
|
||||||
|
C=:second_pass
|
||||||
|
C=1C
|
||||||
|
?C!0:read_line
|
||||||
|
|
||||||
; make sure label only has identifier characters
|
; make sure label only has identifier characters
|
||||||
I=:line
|
I=:line
|
||||||
I+=d1
|
I+=d1
|
||||||
|
@ -338,16 +402,9 @@ align
|
||||||
; @TODO: handle argument
|
; @TODO: handle argument
|
||||||
|
|
||||||
|
|
||||||
; emit "mov rsp, rbp"
|
|
||||||
J=d4
|
J=d4
|
||||||
I=:mov_rsp_rbp
|
I=:function_epilogue
|
||||||
D=d3
|
D=d15
|
||||||
syscall x1
|
|
||||||
|
|
||||||
; emit "ret"
|
|
||||||
J=d4
|
|
||||||
I=:ret
|
|
||||||
D=d1
|
|
||||||
syscall x1
|
syscall x1
|
||||||
|
|
||||||
; go read the next lines
|
; go read the next lines
|
||||||
|
@ -391,6 +448,11 @@ align
|
||||||
; look up identifier rsi in list rdi with separation rdx between entries
|
; look up identifier rsi in list rdi with separation rdx between entries
|
||||||
; returns address of whatever's right after the identifier in the list, or 0 if not found
|
; returns address of whatever's right after the identifier in the list, or 0 if not found
|
||||||
:ident_lookup
|
:ident_lookup
|
||||||
|
C=:second_pass
|
||||||
|
C=1C
|
||||||
|
; use default of 0 on first pass
|
||||||
|
?C!0:return_0
|
||||||
|
|
||||||
C=:ident_lookup_sep
|
C=:ident_lookup_sep
|
||||||
8C=D
|
8C=D
|
||||||
C=:ident_lookup_i
|
C=:ident_lookup_i
|
||||||
|
@ -432,6 +494,104 @@ align
|
||||||
?B=A:return_1
|
?B=A:return_1
|
||||||
!:return_0
|
!:return_0
|
||||||
|
|
||||||
|
; set rax to the term in rsi
|
||||||
|
:set_rax_to_term
|
||||||
|
R=I
|
||||||
|
|
||||||
|
C=1I
|
||||||
|
D=''
|
||||||
|
?C=D:term_char
|
||||||
|
|
||||||
|
C=1I
|
||||||
|
D=d58
|
||||||
|
?C<D:term_number
|
||||||
|
|
||||||
|
; variable
|
||||||
|
J=:local_variables
|
||||||
|
D=d5
|
||||||
|
call :ident_lookup
|
||||||
|
C=A
|
||||||
|
?C=0:rax2term_try_global
|
||||||
|
; it's a local variable
|
||||||
|
; skip over its type
|
||||||
|
C+=d1
|
||||||
|
; read the offset from rbp
|
||||||
|
D=4C
|
||||||
|
; put negated offset in rcx
|
||||||
|
C=d0
|
||||||
|
C-=D
|
||||||
|
; store negated offset in :rax2term_addr
|
||||||
|
D=:rax2term_addr
|
||||||
|
4D=C
|
||||||
|
|
||||||
|
J=d4
|
||||||
|
I=:load_rbp_offset_prefix
|
||||||
|
D=d3
|
||||||
|
syscall x1
|
||||||
|
J=d4
|
||||||
|
I=:rax2term_addr
|
||||||
|
D=d4
|
||||||
|
syscall x1
|
||||||
|
|
||||||
|
|
||||||
|
:rax2term_try_global
|
||||||
|
J=:global_variables
|
||||||
|
D=d5
|
||||||
|
call :ident_lookup
|
||||||
|
C=A
|
||||||
|
?C=0:bad_term
|
||||||
|
; it's a global variable
|
||||||
|
; skip over its type
|
||||||
|
C+=d1
|
||||||
|
C=4C
|
||||||
|
D=:rax2term_addr
|
||||||
|
4D=C
|
||||||
|
|
||||||
|
; put address in rbx
|
||||||
|
J=d4
|
||||||
|
I=:mov_ebx_imm32_prefix
|
||||||
|
D=d1
|
||||||
|
syscall x1
|
||||||
|
J=d4
|
||||||
|
I=:rax2term_addr
|
||||||
|
D=d4
|
||||||
|
syscall x1
|
||||||
|
|
||||||
|
; now load [rbx] into rax
|
||||||
|
J=d4
|
||||||
|
I=:mov_rax_[rbx]
|
||||||
|
D=d3
|
||||||
|
syscall x1
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
:term_char
|
||||||
|
; @TODO
|
||||||
|
xcc
|
||||||
|
|
||||||
|
:term_number
|
||||||
|
; @TODO
|
||||||
|
xcc
|
||||||
|
|
||||||
|
align
|
||||||
|
:rax2term_addr
|
||||||
|
reserve d4
|
||||||
|
|
||||||
|
:mov_ebx_imm32_prefix
|
||||||
|
xbb
|
||||||
|
|
||||||
|
:mov_rax_[rbx]
|
||||||
|
x48
|
||||||
|
x8b
|
||||||
|
x03
|
||||||
|
|
||||||
|
; prefix for mov rax, [rbp+IMM32]
|
||||||
|
:load_rbp_offset_prefix
|
||||||
|
x48
|
||||||
|
x8b
|
||||||
|
x85
|
||||||
|
|
||||||
|
|
||||||
; read the space-terminated type from rsi, advance rsi, and set rax to the corresponding type number:
|
; read the space-terminated type from rsi, advance rsi, and set rax to the corresponding type number:
|
||||||
; 0 for non-pointer types
|
; 0 for non-pointer types
|
||||||
; 1 for pointer to char
|
; 1 for pointer to char
|
||||||
|
@ -532,6 +692,15 @@ align
|
||||||
xa
|
xa
|
||||||
x0
|
x0
|
||||||
|
|
||||||
|
:bad_term
|
||||||
|
B=:bad_term_error_message
|
||||||
|
!:program_error
|
||||||
|
|
||||||
|
:bad_term_error_message
|
||||||
|
str Bad term.
|
||||||
|
xa
|
||||||
|
x0
|
||||||
|
|
||||||
:label_redefinition
|
:label_redefinition
|
||||||
B=:label_redefinition_error_message
|
B=:label_redefinition_error_message
|
||||||
!:program_error
|
!:program_error
|
||||||
|
@ -796,6 +965,8 @@ align
|
||||||
reserve d20000
|
reserve d20000
|
||||||
:labels
|
:labels
|
||||||
reserve d200000
|
reserve d200000
|
||||||
|
:second_pass
|
||||||
|
reserve d1
|
||||||
|
|
||||||
:ELF_header
|
:ELF_header
|
||||||
x7f
|
x7f
|
||||||
|
|
|
@ -37,10 +37,16 @@ mov byte [rbx], al
|
||||||
>88 03
|
>88 03
|
||||||
mov al, byte [rbx]
|
mov al, byte [rbx]
|
||||||
>8a 03
|
>8a 03
|
||||||
mov qword [rsp], rax
|
mov rax, qword [rbp+imm32]
|
||||||
>48 89 04 24
|
>48 8b 85 IMM32 (note: imm may be negative)
|
||||||
mov rax, qword [rsp]
|
mov qword [rbp+imm32], rax
|
||||||
>48 8b 04 24
|
>48 89 85 IMM32 (note: imm may be negative)
|
||||||
|
mov qword [rsp], rbp
|
||||||
|
>48 89 2c 24
|
||||||
|
mov rbp, qword [rsp]
|
||||||
|
>48 8b 2c 24
|
||||||
|
mov ebx, imm32
|
||||||
|
>bb IMM32
|
||||||
neg rax
|
neg rax
|
||||||
>48 f7 d8
|
>48 f7 d8
|
||||||
add rax, rbx
|
add rax, rbx
|
||||||
|
@ -75,6 +81,8 @@ sar rax, imm8
|
||||||
>48 c1 f8 IMM8
|
>48 c1 f8 IMM8
|
||||||
sub rsp, imm32
|
sub rsp, imm32
|
||||||
>48 81 ec IMM32
|
>48 81 ec IMM32
|
||||||
|
add rsp, imm32
|
||||||
|
>48 81 c4 IMM32
|
||||||
cmp rax, rbx
|
cmp rax, rbx
|
||||||
>48 39 d8
|
>48 39 d8
|
||||||
test rax, rax
|
test rax, rax
|
||||||
|
@ -102,3 +110,9 @@ syscall
|
||||||
nop
|
nop
|
||||||
>90
|
>90
|
||||||
(more will be added as needed)
|
(more will be added as needed)
|
||||||
|
|
||||||
|
to be removed:
|
||||||
|
mov qword [rsp], rax
|
||||||
|
>48 89 04 24
|
||||||
|
mov rax, qword [rsp]
|
||||||
|
>48 8b 04 24
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue