📄 interpreter.inc
字号:
and.w bitpos(r14), r12 ; mask off uninteresting bits
jz x_false ; bit is zero
jmp x_true ; bit is one
bitpos:
dw 1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7
dw 1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15
; Binary + operator
x_plus:
add.w r12, r14 ; add NOS to TOS
addc.w r13, r15
ret
; Binary - operator
x_minus:
sub.w r14, r12 ; subtract NOS from TOS
subc.w r15, r13
mov.w r12, r14
mov.w r13, r15
ret
; Binary * operator
x_star:
#ifdef HARDWARE_MULTIPLY
; Save status register so we can restore IE on exit.
push.w sr
; Disable interrupts and really wait for them to be disabled.
dint
nop
; Form low product (low1 * low2).
mov.w r12, &MPY
mov.w r14, &OP2
mov.w r14, &MAC ; prepare for high1*low2 + carry-over
mov.w &RESLO, r14
; Carry over high part of 32-bit product to when we calculate
; the high order product.
mov.w &RESHI, &RESLO
mov.w r13, &OP2
mov.w r12, &MAC ; low1*high2 + high1*low2 + carry over
mov.w r15, &OP2
mov.w &RESLO, r15
; Restore SR and return. Isn't the multiplier cute?
reti
#else
; Multiplication by clockwork. Save working registers.
push.w r10
push.w r11
; Clear product
clr.w r10
clr.w r11
; Single bit multiplication step
L$0 clrc
rrc.w r15
rrc.w r14
jnc L$1
; One bit shifted out, update product
add.w r12, r10
addc.w r13, r11
; Update shift register
L$1 add.w r12, r12
addc.w r13, r13
; Continue until all bits shifted out of multiplicand.
cmp.w #0, r14
jne L$0
cmp.w #0, r15
jne L$0
; Move product to result registers.
mov.w r10, r14
mov.w r11, r15
; Restore working registers
pop.w r11
pop.w r10
ret
#endif
; Binary / operator
x_slash:
; Exchange registers.
xor.w r12, r14
xor.w r14, r12
xor.w r12, r14
xor.w r13, r15
xor.w r15, r13
xor.w r13, r15
; Check for division by zero.
x_slash_10:
cmp.w #0, r13
jnz x_slash_20
cmp.w #0, r12
jz divide_by_zero_error
; Save working registers.
x_slash_20:
push.w r9
push.w r10
push.w r11
; Quotient is negative if the dividend and divisor signs differ.
mov.w r15, r9
xor.w r13, r9
; Compute magnitude of divisor.
tst.w r13
jge Positive$Divisor
xor.w #-1, r12
xor.w #-1, r13
add.w #1, r12
addc.w #0, r13
; Compute magnitude of dividend.
Positive$Divisor
tst.w r15
jge Positive$Dividend
xor.w #-1, r14
xor.w #-1, r15
add.w #1, r14
addc.w #0, r15
; Perform division, r15:r14 = quotient, r11:r10 = remainder
Positive$Dividend
call #___uint32_divmod
; If the dividend and divisor signs differ, negate quotient.
tst.w r9
jge Positive$Quotient
xor.w #-1, r14
xor.w #-1, r15
add.w #1, r14
addc.w #0, r15
; Restore working registers.
Positive$Quotient
pop.w r11
pop.w r10
pop.w r9
ret
; Binary MOD operator
x_mod:
; Exchange arguments
xor.w r12, r14
xor.w r14, r12
xor.w r12, r14
xor.w r13, r15
xor.w r15, r13
xor.w r13, r15
; Check for division by zero.
cmp.w #0, r13
jnz x_mod_10
cmp.w #0, r12
jz divide_by_zero_error
; Save working registers.
x_mod_10:
push.w r11
push.w r10
push.w r9
; Sign of remainder takes sign of dividend.
mov.w r15, r9
; Compute magnitude of divisor.
tst.w r12
jge x_mod_20
xor.w #-1, r12
xor.w #-1, r13
add.w #1, r12
addc.w #0, r13
; Compute magnitude of dividend.
x_mod_20:
tst.w r15
jge x_mod_30
xor.w #-1, r14
xor.w #-1, r15
add.w #1, r14
addc.w #0, r15
; Perform division, r15:r14 = quotient, r11:r10 = remainder
x_mod_30:
call #___uint32_divmod
; Move remainder to result registers.
mov.w r10, r14
mov.w r11, r15
; Apply sign of dividend to remainder.
tst.w r9
jge x_mod_40
call #negate
; Restore working registers.
x_mod_40:
pop.w r9
pop.w r10
pop.w r11
ret
___uint32_divmod:
; Save working registers
push.w r8
push.w r9
; Zero remainder.
clr.w r11
clr.w r10
; Prime division step count.
mov.w #32+1, r9
jmp NextStep$
; Trial subtract.
DivideStep$
sub.w r12, r10
subc.w r13, r11
jc NextStep$
; Trial subtraction underflowed, so restore.
add.w r12, r10
addc.w r13, r11
clrc
; Carry contains whether subtraction was made or not (inverted).
NextStep$
rlc.w r14
rlc.w r15
rlc.w r10
rlc.w r11
; Save carry out as remainder overshoots by one bit in the last step.
rrc.w r8
; Iterate for 32 bits.
dec.w r9
jnz DivideStep$
; Restore bit shifted out of remainder.
rlc.w r8
rrc.w r11
rrc.w r10
; Restore working registers.
pop.w r9
pop.w r8
; Resturn with quotient in r12:r13 and remainder in r14:r15.
ret
; AND operator
x_and:
and.w r12, r14
and.w r13, r15
ret
; BIC operator
x_bic:
bic.w r14, r12
bic.w r15, r13
mov.w r12, r14
mov.w r13, r15
ret
; IMP operator - a IMP b == NOT a OR b
x_imp:
xor.w #-1, r12
xor.w #-1, r13 ; Fall through to OR
; OR operator
x_or:
bis.w r12, r14
bis.w r13, r15
ret
; XOR operator
x_xor:
xor.w r12, r14
xor.w r13, r15
ret
; EQV operator - a EQV b == NOT (a XOR b)
x_eqv:
xor.w r12, r14
xor.w r13, r15
jmp x_not_10
; NOT operator
x_not:
call #eval_unary ; evaluate argument
x_not_10:
xor.w #-1, r14
xor.w #-1, r15
ret
; Unary - operator
x_negate:
call #get_eval_unary ; evaluate argument
negate:
xor.w #-1, r14 ; negate by forming one's complement
xor.w #-1, r15
add.w #1, r14 ; and adding one to form two's complement
addc.w #0, r15
x_negate_return:
ret
; VARPTR addr
x_varptr:
call #varptr ; get address
mov.w #0, r15 ; overwrite size designation
ret
; Parse a variable and return its address in R14 and zero in R15.
; The variable can be simple or an array
varptr:
mov.w #0, r14 ; set the array base as zero for ?
cmp.b #'?', r4 ; byte indirection operator?
jz varptr_25 ; ...yes, do byte indirection
cmp.b #'@', r4 ; word indirection operator?
jnz varptr_05
mov.b @tp+, r4 ; skip '@'
call #eval_unary ; get address
bic.w #1, r14 ; word align
mov.w #2, r15 ; indicate 16-bit data
ret
varptr_05:
cmp.b #'!', r4 ; word indirection operator?
jnz varptr_07 ; ...no, must start with a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -