add evaluate_operand, fix operator tokenising

This commit is contained in:
andromeda
2026-03-18 20:26:30 +01:00
parent ec88bd7381
commit 2e222c304a
3 changed files with 123 additions and 28 deletions

BIN
twasm/.bootle/disk Normal file

Binary file not shown.

View File

@@ -578,8 +578,8 @@ tokenise:
pop rsi
push rax
mov dword [.pending_operator], 0 ; zero pending operator
xor eax, eax ; eax = number of bytes in operator
xor eax, eax ; eax = number of bytes in operator
mov [.pending_operator], eax ; zero pending operator
.operator_loop:
; TODO give this its own error
@@ -606,35 +606,19 @@ tokenise:
jmp .operator_loop ; and loop
.operator_break:
pop rax
; rax already pushed from .operator
push rdi
push rcx
mov rcx, tokens.operators ; rcx -> entry in lookup table
mov edi, [.pending_operator] ; edi = operator to be searched
call identify_operator
; ax = operator's token ID
mov cx, ax ; cx = operator's token ID for safe keeping
.operator_id_loop:
cmp rcx, tokens.operators_end ; check if index still in range
; TODO give own error
jg .unexpected_operator ; if not, error
pop rdi ; rdi = byte counter
pop rax ; rax = tokens processed
; TODO use something other than r8 and r9
mov r8d, [rcx]
mov r9d, [.pending_operator]
cmp r8d, r9d
je .found_id
add rcx, 6 ; next entry
jmp .operator_id_loop
.found_id:
push rdx
mov dx, [rcx + 4] ; dx = token id
mov [TOKEN_TABLE_ADDR + rax * TOKEN_TABLE_ENTRY_SIZE], dx ; write to token
inc rax ; table
pop rdx
pop rcx
mov [TOKEN_TABLE_ADDR + rax * TOKEN_TABLE_ENTRY_SIZE], cx
inc rax ; plus 1 token processed
mov byte [.expecting], E_COMMENT | E_NEWLINE | E_WHITESPACE | E_OPERAND
jmp .loop
@@ -650,6 +634,7 @@ tokenise:
test byte [.expecting], E_OPERAND ; make sure an operand was expected
jz .unexpected_operand ; if not, error
.operand_loop:
mov dl, [rdi]
@@ -720,6 +705,67 @@ tokenise:
.msg_operand db "operand.", 0x0A, 0x00
.pending_operator dd 0 ; the operator token that is pending processing
; ------------------------------------------------------------------------------
; evaluate_operand
;
; description:
; takes the location and length of an operand and evaluates it into binary data
; and a return code to interpret the binary data.
;
; | code | rsi contents | notes |
; |------|----------------------|-------|
; | 0x00 | token ID of register | |
; | 0xFF | - | error |
;
; parameters:
; rdi -> first byte of operand
; rsi = size of operand in bytes
;
; returned:
; rax = binary data corresponding to the operand
; dl = return code
; ------------------------------------------------------------------------------
evaluate_operand:
cmp rsi, 4
jg .unrecognised
.register:
push rdi
mov edi, [rdi] ; edi = register to be searched
; TODO figure out how to mask elegantly :/
; mask edi for lower rsi bits
cmp rsi, 4
je .register4
cmp rsi, 3
je .register3
cmp rsi, 2
je .register2
cmp rsi, 1
je .register1
.register1:
and edi, 0xFF
.register2:
and edi, 0xFFFF
.register3:
and edi, 0xFFFFFF
.register4:
call identify_register
; ax = register's token ID or UNRECOGNISED_TOKEN_ID
pop rdi
cmp ax, UNRECOGNISED_TOKEN_ID
je .unrecognised
mov dl, 0x00
ret
.unrecognised:
mov dl, 0xFF
ret
; ------------------------------------------------------------------------------
; evaluate_constant
;

View File

@@ -40,6 +40,9 @@ run_tests:
call clear_test_arena
call test_identify_operator
call clear_test_arena
call test_evaluate_operand
ret
.msg db "running test suite...", 0x0A, 0x00
@@ -499,6 +502,52 @@ test_identify_operator:
ret
.msg db "test_identify_operator...", 0x00
; ------------------------------------------------------------------------------
; test_evaluate_operand
;
; description:
; tests evaluate_operand described funtionality
; ------------------------------------------------------------------------------
test_evaluate_operand:
mov rsi, .msg
call print.test
mov rdi, .case0
mov rsi, 3
call evaluate_operand
cmp dl, 0x00
jne .fail
cmp ax, 0x0000
jne .fail
mov rdi, .case1
mov rsi, 0
call evaluate_operand
cmp dl, 0xFF
jne .fail
mov rdi, .case2
mov rsi, 3
call evaluate_operand
cmp dl, 0x00
jne .fail
cmp ax, 0x0003
jne .fail
.pass:
mov rsi, msg_pass
call print
ret
.fail:
mov rsi, msg_fail
call print
ret
.case0 db "rax"
.case1: ; intentionally blank
.case2 db "rdx"
.msg db "test_evaluate_operand...", 0x00
msg_pass:
db 0x0A
times (TEST_LINE_LENGTH + .start - .end) db " ", ; right align