diff options
Diffstat (limited to '04b/in03')
-rw-r--r-- | 04b/in03 | 308 |
1 files changed, 160 insertions, 148 deletions
@@ -11,23 +11,14 @@ C=:labels_end D=:labels 8C=D -I=8S -A=d3 -?I!A:usage_error ; open input file - J=S - ; argv[1] is at *(rsp+16) - J+=d16 - J=8J + J=:input_filename I=d0 syscall x2 J=A ?J<0:input_file_error ; open output file - J=S - ; argv[2] is at *(rsp+24) - J+=d24 - J=8J + J=:output_filename I=x241 D=x1ed syscall x2 @@ -126,6 +117,7 @@ C=x20 call :string= D=A ?D!0:handle_local +; arguments are treated the same as local variables I=:line J=:"argument" C=x20 @@ -140,7 +132,9 @@ call :string= D=A ?D!0:handle_return +; set delimiter to newline C=xa + I=:line J=:"function" call :string= @@ -173,7 +167,7 @@ D=A syscall x3c align -:local_start +:local_variable_name reserve d8 :handle_local @@ -188,27 +182,22 @@ align I=R ; skip ' ' I+=d1 - call :read_type - R=A - I+=d1 - ; check if already defined - C=:local_start + ; store away pointer to variable name + C=:local_variable_name 8C=I + + ; check if already defined J=:local_variables - D=d5 call :ident_lookup C=A ?C!0:local_redeclaration - C=:local_start + C=:local_variable_name I=8C J=:local_variables_end J=8J call :ident_copy - ; store type - 1J=R - J+=d1 ; increase stack_end, store it in J C=:stack_end D=4C @@ -218,11 +207,6 @@ align J+=d4 ; store null terminator 1J=0 - ; update :stack_end - D=:stack_end - C=8D - C+=d8 - 8D=C ; update :local_variables_end I=:local_variables_end 8I=J @@ -241,7 +225,8 @@ align align :global_start reserve d8 - +:global_variable_name + reserve d8 :handle_global ; ignore if this is the second pass C=:second_pass @@ -250,43 +235,33 @@ align ; skip ' ' I+=d1 - call :read_type - ; put type in R - R=A - ; skip ' ' after type - I+=d1 - ; check if already defined - C=:global_start + ; store away pointer to variable name + C=:global_variable_name 8C=I - J=:global_variables - D=d5 + ; check if already defined + J=:global_variables call :ident_lookup C=A ?C!0:global_redeclaration - C=:global_start - I=8C + C=:global_variable_name + I=8C J=:global_variables_end J=8J call :ident_copy - ; store type - 1J=R - J+=d1 ; store address D=:static_memory_end - D=4D - 4J=D + C=4D + 4J=C J+=d4 - ; store null terminator - 1J=0 - ; update :static_memory_end - D=:static_memory_end - C=8D + ; increase static_memory_end C+=d8 - 8D=C + 4D=C + ; store null terminator + 1J=0 ; update :global_variables_end I=:global_variables_end 8I=J @@ -308,7 +283,7 @@ align ; reset stack_end D=:stack_end - 8D=0 + 4D=0 ; go read the next line !:read_line @@ -374,8 +349,7 @@ align I=:line I+=d1 - J=:labels - D=d4 + J=:global_variables call :ident_lookup C=A ?C!0:label_redefinition @@ -387,6 +361,7 @@ align call :ident_copy R=J + ; figure out where in the file we are J=d4 I=d0 D=d1 @@ -394,6 +369,7 @@ align C=A C+=x400000 J=R + ; store address 4J=C J+=d4 @@ -452,14 +428,10 @@ align align :ident_lookup_i reserve d8 -:ident_lookup_sep - reserve d8 -; look up identifier rsi in list rdi with separation rdx between entries +; look up identifier rsi in list rdi ; returns address of whatever's right after the identifier in the list, or 0 if not found :ident_lookup - C=:ident_lookup_sep - 8C=D C=:ident_lookup_i 8C=I @@ -480,9 +452,8 @@ align ; check if this was it ?C!0:return_J ; nope. keep going - C=:ident_lookup_sep - C=8C - J+=C + ; skip over address: + J+=d4 !:ident_lookup_loop ; can the character in rbx appear in an identifier? @@ -520,14 +491,10 @@ align ; variable J=:local_variables - xcc - 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 @@ -546,16 +513,15 @@ align D=d4 syscall x1 + return :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 + ; get its address C=4C D=:rax2term_addr 4D=C @@ -579,13 +545,122 @@ align return :term_char - ; @TODO - xcc + I+=d1 + I=1I + !:set_rax_to_immediate + +:number_is_negative + reserve d1 :term_number - ; @TODO - xcc + C=1I + D='- + ; set rdx to 0 if number is positive, 1 if negative + ?C=D:term_number_negative + D=d0 + !:term_number_cont + :term_number_negative + D=d1 + I+=d1 + :term_number_cont + ; store away negativity + C=:number_is_negative + 1C=D + + C=1I + D='0 + ?C=D:term_hex_number + ; it's a decimal number + ; rbp will store the number + R=d0 + :decimal_number_loop + C=1I + D='9 + ?C>D:decimal_number_loop_end + D='0 + ?C<D:decimal_number_loop_end + C-=D + ; multiply by 10 + B=d10 + A=R + mul + R=A + ; add this digit + R+=C + + I+=d1 + !:decimal_number_loop + :decimal_number_loop_end + !:term_number_output + +:term_hex_number + I+=d1 + C=1I + D='x + ; 0 followed by something other than x + ?C!D:bad_term + I+=d1 + ; rbp will store the number + R=d0 + :hex_number_loop + C=1I + D='0 + ?C<D:hex_number_loop_end + D=d58 + ?C<D:hex_number_0123456789 + D='a + ?C<D:hex_number_loop_end + D='f + ?C>D:hex_number_loop_end + ; one of the digits a-f + D=xffffffffffffffa9 + !:hex_number_digit + :hex_number_0123456789 + D=xffffffffffffffd0 + :hex_number_digit + C+=D + ; shift left by 4 + R<=d4 + ; add digit + R+=C + I+=d1 + !:hex_number_loop + :hex_number_loop_end + !:term_number_output +:term_number_output + ; we now have the *unsigned* number in rbp. first, take the sign into consideration + C=:number_is_negative + D=1C + ?D=0:number_not_negative + ; R = -R + C=R + R=d0 + R-=C + :number_not_negative + I=R + !:set_rax_to_immediate + + + +; set <rax> to the immediate in rsi. +:set_rax_to_immediate + C=:imm64 + 8C=I + + ; write prefix + J=d4 + D=d2 + I=:mov_rax_imm64_prefix + syscall x1 + + ; write immediate + J=d4 + D=d8 + I=:imm64 + syscall x1 + return + align :rax2term_addr reserve d4 @@ -593,6 +668,13 @@ align :mov_ebx_imm32_prefix xbb +:mov_rax_imm64_prefix + x48 + xb8 + +align +:imm64 + reserve d8 :mov_rax_[rbx] x48 x8b @@ -602,62 +684,14 @@ align :load_rbp_offset_prefix x48 x8b - x85 - - -; read the space-terminated type from rsi, advance rsi, and set rax to the corresponding type number: -; 0 for non-pointer types -; 1 for pointer to char -; 2 for pointer to short -; 4 for pointer to int -; 8 for pointer to long -:read_type - C=1I - D='* - ?C=D:read_pointer_type - ; it's not a pointer - call :read_simple_type - A=d0 - return - :read_pointer_type - ; it's a pointer! - I+=d1 - !:read_simple_type - -; returns 1 for char, 2 for short, 4 for int, 8 for long -:read_simple_type - R=I - C=x20 - I=R - J=:"char" - call :string= - D=A - ?D!0:return_1 - I=R - J=:"short" - call :string= - D=A - ?D!0:return_2 - I=R - J=:"int" - call :string= - D=A - ?D!0:return_4 - I=R - J=:"long" - call :string= - D=A - ?D!0:return_8 - !:bad_type + x85 +:input_filename + str in04b + x0 -:usage_error - B=:usage_error_message - call :general_error - -:usage_error_message - str Please provide an input and an output file. - xa +:output_filename + str out04b x0 :input_file_error @@ -695,15 +729,6 @@ align str Bad label. xa x0 - -:bad_type - B=:bad_type_error_message - !:program_error - -:bad_type_error_message - str Bad type. - xa - x0 :bad_term B=:bad_term_error_message @@ -924,19 +949,6 @@ align ?D!C:memccpy return -:"char" - str char - x20 -:"short" - str short - x20 -:"int" - str int - x20 -:"long" - str long - x20 - :"global" str global x20 |