📄 interpreter.inc
字号:
x_print_20:
cmp.b #T_HEX, r4 ; print value in hexadecimal?
jnz x_print_23 ; ...no, continue to decode it
call #get_eval_expr ; evaluate expression to print
call #print_hex ; print it in hex
jmp x_print_35 ; deal with termimators
x_print_23:
cmp.b #T_BIN, r4 ; print value in binary?
jnz x_print_25 ; ...no, continue to decode it
call #get_eval_expr ; evaluate expression to print
call #print_bin ; print it in binary
jmp x_print_35 ; deal with termimators
x_print_25:
cmp.b #T_CLEAR, r4 ; CLEAR?
jnz x_print_30 ; ...no, continue to decode it
mov.w #0x0c, r15 ; prepare to print form feed
call #print_char ; send it to the channel
jmp x_print_40 ; deal with separators
x_print_30:
call #end_of_statement ; end of line which terminates printing?
jz x_print_end ; ...yes, wrap up
call #eval_expr ; nothing matches, so parse it as an expression
call #print_integer ; print it in decimal
x_print_35:
sub.w #1, tp ; back up token pointer for code ahead
x_print_40:
mov.w #1, r11 ; prepare to hold CRLF
mov.b @tp+, r4 ; prime R4 with next character
x_print_50:
cmp.b #';', r4 ; expression separator?
jz x_print_01 ; ...yes, continue with hold flag set
cmp.b #',', r4 ; expression separator?
jz x_print_00 ; ...yes, continue with hold flag set
cmp.w #0, r4 ; end of line?
jz x_print_end_10 ; yes, terminate with a new line
cmp.w #':', r4 ; end if statement?
jz x_print_end_10 ; yes, terminate with a new line
jmp syntax_error ; bad termination is reported as a syntax error
x_print_end:
cmp.w #0, r11 ; hold CRLF?
jnz term ; ...yes, forget new line and continue with execution
x_print_end_10:
mov.w #'\n', r15 ; print a new line
call #print_char
jmp term ; continue with processing
; Print the string delimited by a quotation mark.
; Shared between INPUT and PRINT.
print_quoted_string:
mov.b @tp+, r4 ; get character in string
cmp.b #'"', r4 ; terminated?
jz print_quoted_string_return ; ...yes, deal with terminators
cmp.b #0, r4 ; end of string?
jz mismatched_quote_error ; ...yes, report error
mov.w r4, r15 ; prepare character to print
call #print_char ; print it
jmp print_quoted_string ; and get the next one
print_quoted_string_return:
mov.b @tp+, r4 ; fetch token after final quotation mark
ret
; BPUT [#channel, ] expr, expr, ...
x_bput:
mov.w #1, r15 ; default to channel 1 if no channel number given
call #select_channel
cmp.w #'#', r4 ; channel number being specified?
jnz x_bput_10 ; ...no, so just use default
call #get_eval_expr ; evaluate the channel number
mov.w r14, r15 ; only use the low 16 bits of the channel number
call #select_channel ; select the channel, error if it's bad
x_bput_00:
call #check_comma ; a comma must come next
x_bput_10:
call #eval_expr ; get the byte to put to the channel
mov.w r14, r15 ; the byte is delivered in R14, so move to R15
call #print_char ; put the byte
call #end_of_statement ; finished statement?
jnz x_bput_00 ; ...no, need a comma and another expression
jmp term ; finish off statement
; BGET #channel
x_bget:
cmp.b #'#', r4 ; require a channel number
jnz syntax_error ; ...but didn't get one
mov.b @tp+, r4 ; skip '#'
call #eval_unary ; get the channel number
mov.w r14, r15 ; only use the low 16 bits of the channel number
call #select_channel ; select the channel
call #get_char ; read the character into R15
mov.w r15, r14 ; zero-extend TOS
mov.w #0, r15
ret
; RESET
x_reset:
mov.w #0, &WDTCTL ; bad password generates reset
jmp term ; ...but simulator doesn't
; MEMORY
x_memory:
call #memory
jmp term
memory:
mov.w sp, r14
sub.w &ramtop, r14
mov.w #0, r15
call #print_integer
mov.w #ram_message, r15
call #print_message
mov.w #0xfc00, r14
sub.w &flashtop, r14
call #print_integer
mov.w #flash_message, r15
call #print_message
ret
; BREAK [ ON | OFF | expr ]
x_break:
call #eval_expr_on_off ; Evaluate ON to -1, OFF to 0, and
bic.w #BREAK, &flags ; Prepare for BREAK OFF
bis.w r14, r15
cmp.w #0, r15 ; zero value means BREAK OFF
jz x_break_return
bis.w #BREAK, &flags ; non-zero value turns on BREAK flag
x_break_return:
jmp term
; RESUME
x_resume:
pop.w r4 ; get opened structure
cmp.w #T_RESUME, r4 ; RESUME expected from ON ... processing?
jnz cant_resume_error ; ...no, can't RESUME
pop.w lp ; restore resume point
pop.w tp
sub.w #1, tp
pop.w sr ; restore interrupt enable status
jmp chrget ; continue with mainline code
; INTERRUPT ON
; INTERRUPT OFF
x_interrupt:
cmp.b #T_ON, r4
jnz x_interrupt_10
eint
mov.b @tp+, r4
jmp term
x_interrupt_10:
cmp.b #T_OFF, r4
jnz syntax_error
dint
mov.b @tp+, r4
jmp term
; Evaluate an expression with ON evaluating to -1 and OFF evaluating to 0
eval_expr_on_off:
cmp.w #T_ON, r4 ; ON?
jz eval_expr_on_off_10 ; ...yes, return TRUE
cmp.w #T_OFF, r4 ; OFF?
jnz eval_expr ; ...no, parse as an expression
mov.b @tp+, r4 ; skip OFF token
jmp x_false ; return FALSE
eval_expr_on_off_10:
mov.b @tp+, r4 ; skip ON token
jmp x_true ; return TRUE
; Get next token and evaluate expression
get_eval_expr:
mov.b @tp+, r4 ; get next token
; Evaluate expression and return an integer in R15:R14
eval_expr:
push.w #T_PLUS-1 ; least binding operator, lower precedence than any other
eval_expr_10:
call #eval_unary ; evaluate a unary expression
; Operator?
eval_expr_cont:
cmp.w #FIRST_BINARY_TOKEN, r4 ; if this isn't a binary operator, reduce whole stack and wrap up
jnc eval_expr_60
cmp.w #LAST_BINARY_TOKEN+1, r4
jc eval_expr_60
mov.w @sp, r13 ; get stacked operator and compare precendence of this operator
cmp.b operator_precedence-FIRST_BINARY_TOKEN+1(r4), operator_precedence-FIRST_BINARY_TOKEN+1(r13)
jc eval_expr_60 ; same or lower precedence, so reduce and keep parsing
push.w r15 ; save TOS value on stack
push.w r14
push.w r4 ; save current operator on stack
mov.b @tp+, r4 ; get next character from the token stream
jmp eval_expr_10 ; and it must start a unary expression
eval_expr_60:
pop.w r10 ; get stacked operator
cmp.w #FIRST_BINARY_TOKEN-1, r10 ; if it's the lowest precedence (cf eval_expr), we're done.
jz eval_expr_return
pop.w r12 ; pop saved TOS into NOS
pop.w r13
add.w r10, r10 ; compute index into operator table
; invoke operator routine
call binarytab-FIRST_BINARY_TOKEN*2(r10)
jmp eval_expr_cont ; continue with parsing expression
eval_expr_return:
ret
get_eval_unary:
mov.b @tp+, r4 ; get next token
eval_unary:
tst.b r4
jge eval_expr_20
; Token is negative, so it's an operator or function
cmp.w #T_BIT, r4 ; BIT used as unary operator?
jz x_unary_bit ; ...yes, handle it specially
cmp.w #T_MINUS, r4 ; - used as unary operator?
jz x_negate ; ...yes, handle it specially
cmp.w #T_PLUS, r4 ; + used as unary operator?
jz get_eval_unary ; ...yes, handle it specially
cmp.w #FIRST_UNARY_TOKEN, r4
jnc syntax_error
cmp.w #LAST_UNARY_TOKEN+1, r4
jc syntax_error
add.w r4, r4
mov.w r4, r13
mov.b @tp+, r4
br unarytab-FIRST_UNARY_TOKEN*2(r13)
eval_expr_20:
cmp.b #'(', r4
jne eval_expr_30
call #get_eval_expr
cmp.b #')', r4
jne mismatched_parenthesis_error
mov.b @tp+, r4
ret
eval_expr_30:
call #is_digit
jc read_int
eval_expr_50:
call #varptr ; parse variable and get address into R14
cmp.w #4, r15 ; address of a 32-bit value?
jz eval_expr_70 ; ...yes, read 32-bit value
cmp.w #2, r15 ; address of a 16-bit value?
jz eval_expr_80 ; ...yes, read 16-bit value
mov.b @r14, r14 ; ...no, read byte
mov.w #0, r15 ; zero extend
ret
eval_expr_70:
mov.w 2(r14), r15 ; fetch 32 bits
mov.w @r14, r14
ret
eval_expr_80:
mov.w @r14, r14 ; fetch 16 bits
mov.w #0, r15 ; zero extend
ret
; Read integer value into R15:R14 from the token stream.
read_int:
mov.w #0, r15
mov.w #0, r14
read_int_10:
sub.w #'0', r4
call #mul_10
add.w r4, r14
addc.w #0, r15
mov.b @tp+, r4
call #is_digit
jc read_int_10
ret
; >
x_gt:
sub.w r12, r14
subc.w r13, r15
jl x_true
jmp x_false
; <
x_lt:
sub.w r14, r12 ; compare operands, less?
subc.w r15, r13
jl x_true ; ...yes, return true else fall through
; FALSE
x_false:
mov.w #0, r15 ; FALSE is zero
mov.w #0, r14
ret
; =
x_eq:
cmp.w r14, r12 ; same low parts?
jnz x_false ; ...no, must be different
cmp.w r15, r13 ; same high parts?
jnz x_false ; ...no, return false else fall through
; TRUE
x_true:
mov.w #-1, r15 ; true value is all bits set
mov.w #-1, r14
ret
; <>
x_ne:
cmp.w r14, r12 ; same low parts?
jnz x_true ; ...no, must be true
cmp.w r15, r13 ; same high parts?
jnz x_true ; ...no, must be true
jmp x_false ; both parts are the same, so result is false
; a <= b = !(b > a)
x_le:
sub.w r12, r14
subc.w r13, r15
jl x_false
jmp x_true
; a >= b = !(b < a)
x_ge:
sub.w r14, r12
subc.w r15, r13
jl x_false
jmp x_true
; x BIT y
; If bit is not in 0..31, return 0.
x_bit:
cmp.w #0, r15
jnz x_false
cmp.w #0x20, r14
jc x_false
; If bit is within the high word, shift and adjust bit number.
cmp.w #16, r14
jnc x_bit_10
mov.w r13, r12
; Test bit and return value
x_bit_10:
and.w #0xf, r14 ; now testing bits 0 through 15
add.w r14, r14
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -