diff options
author | pommicket <pommicket@gmail.com> | 2022-01-06 17:37:02 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-01-06 17:37:02 -0500 |
commit | 6f1a0855861e013aed5bef49e85d988bca24cabc (patch) | |
tree | 8b3ee89a9e2908400dff645c280210620a73b7b8 | |
parent | db552a4dcacc5d82f00e595be4ca3faae75a3ddb (diff) |
if!
-rw-r--r-- | 04b/in03 | 861 | ||||
-rw-r--r-- | 04b/in04b | 35 | ||||
-rw-r--r-- | instructions.txt | 8 |
3 files changed, 806 insertions, 98 deletions
@@ -147,6 +147,20 @@ call :string= D=A ?D!0:handle_string +I=:line +J=:"goto" +C=x20 +call :string= +D=A +?D!0:handle_goto + +I=:line +J=:"if" +C=x20 +call :string= +D=A +?D!0:handle_if + ; set delimiter to newline C=xa @@ -162,6 +176,18 @@ call :string= D=A ?D!0:handle_return +; check if this is an assignment +I=:line +:assignment_check_loop + C=1I + D=xa + ?C=D:assignment_check_loop_end + D='= + ?C=D:handle_assignment + I+=d1 + !:assignment_check_loop +:assignment_check_loop_end + ; check if this is a function call (where we discard the return value) I=:line ; (check for an opening bracket not preceded by a space) @@ -458,7 +484,7 @@ align call :ident_copy R=J - ; figure out where in the file we are + ; figure out where in the file we are (using lseek) J=d4 I=d0 D=d1 @@ -477,6 +503,496 @@ align ; read the next line !:read_line +:handle_goto + J=d4 + I=:jmp_prefix + D=d1 + syscall x1 + I=:line + ; 5 = length of "goto " + I+=d5 + call :emit_label_jump_address + !:read_line +:jmp_prefix + xe9 + +:handle_if + I=:line + I+=d3 + ; skip term 1 + call :go_to_space + I+=d1 + ; skip operator + call :go_to_space + I+=d1 + ; put second operand in rsi + call :set_rax_to_term + call :set_rsi_to_rax + + + I=:line + ; length of "if " + I+=d3 + ; put first operand in rax + call :set_rax_to_term + ; put second operand in rbx + call :set_rbx_to_rsi + ; emit cmp rax, rbx + J=d4 + I=:cmp_rax_rbx + D=d3 + syscall x1 + + I=:line + I+=d3 + call :go_to_space + I+=d1 + R=I + C=x20 + + I=R + J=:"==" + call :string= + I=A + ?I!0:write_je + + I=R + J=:"!=" + call :string= + I=A + ?I!0:write_jne + + I=R + J=:">" + call :string= + I=A + ?I!0:write_jg + + I=R + J=:"<" + call :string= + I=A + ?I!0:write_jl + + I=R + J=:">=" + call :string= + I=A + ?I!0:write_jge + + I=R + J=:"<=" + call :string= + I=A + ?I!0:write_jle + + I=R + J=:"]" + call :string= + I=A + ?I!0:write_ja + + I=R + J=:"[" + call :string= + I=A + ?I!0:write_jb + + I=R + J=:"]=" + call :string= + I=A + ?I!0:write_jae + + I=R + J=:"[=" + call :string= + I=A + ?I!0:write_jbe + + !:bad_jump + + :write_je + J=d4 + I=:je_prefix + D=d2 + syscall x1 + !:if_continue + + :write_jne + J=d4 + I=:jne_prefix + D=d2 + syscall x1 + !:if_continue + + :write_jl + J=d4 + I=:jl_prefix + D=d2 + syscall x1 + !:if_continue + + :write_jg + J=d4 + I=:jg_prefix + D=d2 + syscall x1 + !:if_continue + + :write_jle + J=d4 + I=:jle_prefix + D=d2 + syscall x1 + !:if_continue + + :write_jge + J=d4 + I=:jge_prefix + D=d2 + syscall x1 + !:if_continue + + :write_jb + J=d4 + I=:jb_prefix + D=d2 + syscall x1 + !:if_continue + + :write_ja + J=d4 + I=:ja_prefix + D=d2 + syscall x1 + !:if_continue + + :write_jbe + J=d4 + I=:jbe_prefix + D=d2 + syscall x1 + !:if_continue + + :write_jae + J=d4 + I=:jae_prefix + D=d2 + syscall x1 + !:if_continue + +:if_continue + I=:line + I+=d3 + ; skip term 1 + call :go_to_space + I+=d1 + ; skip operator + call :go_to_space + I+=d1 + ; skip term 2 + call :go_to_space + I+=d1 + J=:"goto" + C=x20 + call :string= + C=A + ; make sure word after term 2 is "goto" + ?C=0:bad_jump + I+=d1 + call :emit_label_jump_address + !:read_line + +:je_prefix + x0f + x84 +:jne_prefix + x0f + x85 +:jl_prefix + x0f + x8c +:jg_prefix + x0f + x8f +:jle_prefix + x0f + x8e +:jge_prefix + x0f + x8d +:jb_prefix + x0f + x82 +:ja_prefix + x0f + x87 +:jbe_prefix + x0f + x86 +:jae_prefix + x0f + x83 + +:cmp_rax_rbx + x48 + x39 + xd8 + +align +:reladdr + reserve d4 + +; emit relative address (for jumping) of label in rsi +:emit_label_jump_address + ; address doesn't matter for first pass + C=:second_pass + C=1C + ?C=0:jump_ignore_address + ; look up label; store address in rbp + J=:labels + call :ident_lookup + C=A + ?C=0:bad_label + R=4C +:jump_ignore_address + + ; first, figure out current address + J=d4 + I=d0 + D=d1 + syscall x8 + C=A + ; add an additional 4 because the relative address is 4 bytes long + C+=x400004 + + ; compute relative address + D=d0 + D-=C + D+=R + ; store in :reladdr + C=:reladdr + 4C=D + ; output + J=d4 + I=:reladdr + D=d4 + syscall x1 + return + +align +:assignment_type + reserve d8 +:handle_assignment + I-=d1 + C=:assignment_type + 8C=I + + I+=d2 + C=1I + D=x20 + ; check for space after = + ?C!D:bad_assignment + I+=d1 + + ; set rdi to right-hand side of assignment + call :set_rax_to_rvalue + call :set_rdi_to_rax + + J=:assignment_type + J=8J + C=1J + ; put newline after lvalue to make parsing easier + D=xa + 1J=D + D=x20 + ?C=D:handle_assignment_cont + J-=d1 + D=xa + 1J=D + :handle_assignment_cont + D=x20 + ?C=D:handle_plain_assignment + D='+ + ?C=D:handle_+= + D='- + ?C=D:handle_-= + D='* + ?C=D:handle_*= + D='/ + ?C=D:handle_/= + D='% + ?C=D:handle_%= + D='& + ?C=D:handle_&= + D='| + ?C=D:handle_|= + D='^ + ?C=D:handle_^= + D='< + ?C=D:handle_<= + D='> + ?C=D:handle_>= + + !:bad_assignment + +:handle_plain_assignment + I=:line + call :set_lvalue_to_rax + !:read_line + +:handle_+= + I=:line + call :set_rax_to_rvalue + call :set_rbx_to_rdi + call :emit_add_rax_rbx + I=:line + call :set_lvalue_to_rax + !:read_line + +:handle_-= + I=:line + call :set_rax_to_rvalue + call :set_rbx_to_rdi + call :emit_sub_rax_rbx + I=:line + call :set_lvalue_to_rax + !:read_line + +:handle_*= + I=:line + call :set_rax_to_rvalue + call :set_rbx_to_rdi + call :emit_imul_rbx + I=:line + call :set_lvalue_to_rax + !:read_line + +:handle_/= + I=:line + call :set_rax_to_rvalue + call :set_rbx_to_rdi + call :emit_zero_rdx_idiv_rbx + I=:line + call :set_lvalue_to_rax + !:read_line + +:handle_%= + I=:line + call :set_rax_to_rvalue + call :set_rbx_to_rdi + call :emit_zero_rdx_idiv_rbx + call :set_rax_to_rdx + I=:line + call :set_lvalue_to_rax + !:read_line + +:handle_&= + I=:line + call :set_rax_to_rvalue + call :set_rbx_to_rdi + call :emit_and_rax_rbx + I=:line + call :set_lvalue_to_rax + !:read_line + +:handle_|= + I=:line + call :set_rax_to_rvalue + call :set_rbx_to_rdi + call :emit_or_rax_rbx + I=:line + call :set_lvalue_to_rax + !:read_line + +:handle_^= + I=:line + call :set_rax_to_rvalue + call :set_rbx_to_rdi + call :emit_xor_rax_rbx + I=:line + call :set_lvalue_to_rax + !:read_line + +:handle_<= + I=:line + call :set_rax_to_rvalue + call :set_rcx_to_rdi + call :emit_shl_rax_cl + I=:line + call :set_lvalue_to_rax + !:read_line + +:handle_>= + I=:line + call :set_rax_to_rvalue + call :set_rcx_to_rdi + call :emit_shr_rax_cl + I=:line + call :set_lvalue_to_rax + !:read_line + +align +:lvalue + reserve d8 + +; set the lvalue in rsi to <rax> +:set_lvalue_to_rax + C=:lvalue + 8C=I + + ; first, store away <rax> value in <rdi> + R=I + call :set_rdi_to_rax + I=R + + C=:lvalue + I=8C + C=1I + D='* + + ?C=D:lvalue_deref + ; not a dereference; just a variable + C=:lvalue + I=8C + call :set_rax_to_address_of_variable + call :set_rbx_to_rax + call :set_rax_to_rdi + call :set_[rbx]_to_rax + return + :lvalue_deref + C=:lvalue + I=8C + I+=d2 + call :set_rax_to_address_of_variable + call :set_rbx_to_rax + call :set_rax_to_[rbx] + call :set_rbx_to_rax + call :set_rax_to_rdi + + C=:lvalue + I=8C + I+=d1 + C=1I + + D='1 + ?C=D:lvalue_deref1 + D='2 + ?C=D:lvalue_deref2 + D='4 + ?C=D:lvalue_deref4 + D='8 + ?C=D:lvalue_deref8 + !:bad_assignment + :lvalue_deref1 + !:set_[rbx]_to_al + :lvalue_deref2 + !:set_[rbx]_to_ax + :lvalue_deref4 + !:set_[rbx]_to_eax + :lvalue_deref8 + !:set_[rbx]_to_rax :handle_return I=:line @@ -819,122 +1335,45 @@ align :rvalue_add call :set_rbx_to_rsi - J=d4 - I=:add_rax_rbx - D=d3 - syscall x1 - return -:add_rax_rbx - x48 - x01 - xd8 + !:emit_add_rax_rbx :rvalue_sub call :set_rbx_to_rsi - J=d4 - I=:sub_rax_rbx - D=d3 - syscall x1 - return -:sub_rax_rbx - x48 - x29 - xd8 + !:emit_sub_rax_rbx :rvalue_mul call :set_rbx_to_rsi - J=d4 - I=:imul_rbx - D=d3 - syscall x1 - return -:imul_rbx - x48 - xf7 - xeb + !:emit_imul_rbx :rvalue_div call :set_rbx_to_rsi - call :zero_rdx - J=d4 - I=:idiv_rbx - D=d3 - syscall x1 - return -:idiv_rbx - x48 - xf7 - xfb + !:emit_zero_rdx_idiv_rbx :rvalue_rem call :set_rbx_to_rsi - call :zero_rdx - J=d4 - I=:idiv_rbx - D=d3 - syscall x1 + call :emit_zero_rdx_idiv_rbx call :set_rax_to_rdx return :rvalue_and call :set_rbx_to_rsi - J=d4 - I=:and_rax_rbx - D=d3 - syscall x1 - return -:and_rax_rbx - x48 - x21 - xd8 + !:emit_and_rax_rbx :rvalue_or call :set_rbx_to_rsi - J=d4 - I=:or_rax_rbx - D=d3 - syscall x1 - return -:or_rax_rbx - x48 - x09 - xd8 + !:emit_or_rax_rbx :rvalue_xor call :set_rbx_to_rsi - J=d4 - I=:xor_rax_rbx - D=d3 - syscall x1 - return -:xor_rax_rbx - x48 - x31 - xd8 + !:emit_xor_rax_rbx :rvalue_shl call :set_rcx_to_rsi - J=d4 - I=:shl_rax_cl - D=d3 - syscall x1 - return -:shl_rax_cl - x48 - xd3 - xe0 + !:emit_shl_rax_cl :rvalue_shr call :set_rcx_to_rsi - J=d4 - I=:shr_rax_cl - D=d3 - syscall x1 - return -:shr_rax_cl - x48 - xd3 - xe8 + !:emit_shr_rax_cl :rvalue_addressof I+=d1 @@ -1204,6 +1643,15 @@ align :mov_rbx_rsi B=I +:set_rbx_to_rdi + J=d4 + I=:mov_rbx_rdi + D=d3 + syscall x1 + return +:mov_rbx_rdi + B=J + :set_rcx_to_rsi J=d4 I=:mov_rcx_rsi @@ -1213,6 +1661,15 @@ align :mov_rcx_rsi C=I +:set_rcx_to_rdi + J=d4 + I=:mov_rcx_rdi + D=d3 + syscall x1 + return +:mov_rcx_rdi + C=J + :set_rax_to_rdx J=d4 I=:mov_rax_rdx @@ -1222,6 +1679,15 @@ align :mov_rax_rdx A=D +:set_rax_to_rdi + J=d4 + I=:mov_rax_rdi + D=d3 + syscall x1 + return +:mov_rax_rdi + A=J + :set_rsi_to_rax J=d4 I=:mov_rsi_rax @@ -1231,6 +1697,15 @@ align :mov_rsi_rax I=A +:set_rdi_to_rax + J=d4 + I=:mov_rdi_rax + D=d3 + syscall x1 + return +:mov_rdi_rax + J=A + :set_rax_to_[rbx] J=d4 I=:mov_rax_[rbx] @@ -1272,13 +1747,156 @@ align :mov_al_[rbx] x8a x03 + + +:set_[rbx]_to_rax + J=d4 + I=:mov_[rbx]_rax + D=d3 + syscall x1 + return +:mov_[rbx]_rax + x48 + x89 + x03 +:set_[rbx]_to_eax + J=d4 + I=:mov_[rbx]_eax + D=d2 + syscall x1 + return +:mov_[rbx]_eax + x89 + x03 + +:set_[rbx]_to_ax + J=d4 + I=:mov_[rbx]_ax + D=d3 + syscall x1 + return +:mov_[rbx]_ax + x66 + x89 + x03 + +:set_[rbx]_to_al + J=d4 + I=:mov_[rbx]_al + D=d2 + syscall x1 + return +:mov_[rbx]_al + x88 + x03 + :mov_rax_imm64_prefix x48 xb8 -align +:emit_add_rax_rbx + J=d4 + I=:add_rax_rbx + D=d3 + syscall x1 + return +:add_rax_rbx + x48 + x01 + xd8 + +:emit_sub_rax_rbx + J=d4 + I=:sub_rax_rbx + D=d3 + syscall x1 + return +:sub_rax_rbx + x48 + x29 + xd8 + +:emit_and_rax_rbx + J=d4 + I=:and_rax_rbx + D=d3 + syscall x1 + return +:and_rax_rbx + x48 + x21 + xd8 + +:emit_or_rax_rbx + J=d4 + I=:or_rax_rbx + D=d3 + syscall x1 + return +:or_rax_rbx + x48 + x09 + xd8 + +:emit_xor_rax_rbx + J=d4 + I=:xor_rax_rbx + D=d3 + syscall x1 + return +:xor_rax_rbx + x48 + x31 + xd8 + +:emit_shl_rax_cl + J=d4 + I=:shl_rax_cl + D=d3 + syscall x1 + return +:shl_rax_cl + x48 + xd3 + xe0 + +:emit_shr_rax_cl + J=d4 + I=:shr_rax_cl + D=d3 + syscall x1 + return +:shr_rax_cl + x48 + xd3 + xe8 + +:emit_imul_rbx + J=d4 + I=:imul_rbx + D=d3 + syscall x1 + return +:imul_rbx + x48 + xf7 + xeb + +:emit_zero_rdx_idiv_rbx + call :zero_rdx + J=d4 + I=:idiv_rbx + D=d3 + syscall x1 + return +:idiv_rbx + x48 + xf7 + xfb + +align :imm64 reserve d8 @@ -1367,6 +1985,15 @@ align str Bad number. xa x0 + +:bad_assignment + B=:bad_assignment_error_message + !:program_error + +:bad_assignment_error_message + str Bad assignment. + xa + x0 :bad_term B=:bad_term_error_message @@ -1376,6 +2003,15 @@ align str Bad term. xa x0 + +:bad_jump + B=:bad_jump_error_message + !:program_error + +:bad_jump_error_message + str Bad jump. + xa + x0 :bad_call B=:bad_call_error_message @@ -1596,6 +2232,16 @@ align ?D!C:memccpy return +; advance rsi to the next space or newline character +:go_to_space + C=1I + D=xa + ?C=D:return_0 + D=x20 + ?C=D:return_0 + I+=d1 + !:go_to_space + :"global" str global x20 @@ -1617,9 +2263,46 @@ align :"string" str string x20 +:"goto" + str goto + x20 +:"if" + str if + x20 :"function" str function xa +:"==" + str == + x20 +:"!=" + str != + x20 +:">" + str > + x20 +:"<" + str < + x20 +:"<=" + str <= + x20 +:">=" + str >= + x20 +:"[" + str [ + x20 +:"]" + str ] + x20 +:"[=" + str [= + x20 +:"]=" + str ]= + x20 + :zero x0 @@ -3,9 +3,10 @@ ; local <name> ; argument <name> ; :<label> +; .<label> (local label) ; statement: ; <declaration> -; if <term> <==/</>/>=/<=/!=> <term> goto <label> NOTE: this uses signed comparisons +; if <term> <==/</>/>=/<=/!=/[/]/[=/]=> <term> goto <label> NOTE: this uses signed comparisons ; goto <label> ; <lvalue> = <rvalue> ; <lvalue> += <rvalue> @@ -43,8 +44,24 @@ ; <term> < <term> (left shift) ; <term> > <term> (unsigned right shift) -syscall(1, 1, .str_hw, 14) -syscall(0x3c, 42) + +if 0 > -1 goto main + +syscall(0x3c, 0) + +:main +function + global str + global strp + local offset + strp = &str + *8strp = .str_hw + offset = 2 + offset &= offset + offset %= 2 + *8strp += offset + syscall(1, 1, str, 14) + syscall(0x3c, 42) :str_hw string Hello, world! @@ -173,8 +190,8 @@ function len = 0 :strlen_loop p = s + len - c = *1 p - if c == 0 goto strlen_loop_end + c = *1p + ; if c == 0 goto strlen_loop_end len += 1 goto strlen_loop :strlen_loop_end @@ -196,7 +213,7 @@ function syscall(1, 1, s, len) return -:main +:main2 function puts(.str_hello_world) syscall(0x3c, 0) @@ -213,9 +230,9 @@ function local p v = *4x p = *8y - *4p = v - if v == 0 goto something - *1p = v + 1 + ;*4p = v + ;if v == 0 goto something + ;*1p = v + 1 v = *2p return v :something diff --git a/instructions.txt b/instructions.txt index 03b13cf..39bc1b6 100644 --- a/instructions.txt +++ b/instructions.txt @@ -105,10 +105,18 @@ jl rel32 >0f 8c REL32 jg rel32 >0f 8f REL32 +jle rel32 +>0f 8e REL32 +jge rel32 +>0f 8d REL32 jb rel32 >0f 82 REL32 ja rel32 >0f 87 REL32 +jbe rel32 +>0f 86 REL32 +jae rel32 +>0f 83 REL32 call rax >ff d0 ret |