;; s2 calculator interpreter ;; 9 feb 2007 ;; register convention ;; r31 stack pointer (system) ;; r30 display ;; r29 link register ;; r28 return value ;; r27 evaluation stack (calculator) .symbol tkNum 1 tkAdd 2 tkSub 3 tkMul 4 tkDiv 5 tkF0 6 tkF1 7 tkF2 8 tkF3 9 tkF4 10 tkF5 11 tkF6 12 tkF7 13 tkF8 14 tkF9 15 tkEq 16 tkLd 17 tkEOL 18 ;; end of line token VALUE 901 ;; let r1 = t, r2 = test, trap 3 return value in r28 .code 0 :loop ;; loop until end of line trap 3 ;; read() eq r2 r28 #tkEOL jt r2 exit mv r1 r28 jal r29 eval jmp loop :exit trap 0 ;; let r1 be input, r2 = test, r3 = temp :eval push r31 r29 eq r2 r1 #tkNum jt r2 xNum eq r2 r1 #tkAdd jt r2 xAdd eq r2 r1 #tkSub jt r2 xSub eq r2 r1 #tkMul jt r2 xMul eq r2 r1 #tkDiv jt r2 xDiv eq r2 r1 #tkF0 jt r2 xF0 eq r2 r1 #tkF1 jt r2 xF1 eq r2 r1 #tkF2 jt r2 xF2 eq r2 r1 #tkF3 jt r2 xF3 eq r2 r1 #tkF4 jt r2 xF4 eq r2 r1 #tkF5 jt r2 xF5 eq r2 r1 #tkF6 jt r2 xF6 eq r2 r1 #tkF7 jt r2 xF7 eq r2 r1 #tkF8 jt r2 xF8 eq r2 r1 #tkF9 jt r2 xF9 eq r2 r1 #tkEq jt r2 xEq eq r2 r1 #tkLd jt r2 xLd :return pop r31 r29 ret r29 :evalnxt ;; read and eval next token push r31 r29 trap 3 mv r1 r28 jal r29 eval pop r31 r29 ret r29 :evaln ;; read, eval var arg push r31 r29 mv r3 #0 trap 3 mv r1 r28 :while eq r2 r1 #tkEq ;; until found = jt r2 skip jal r29 eval trap 3 mv r1 r28 add r3 r3 #1 jmp while :skip push r27 r3 ;; push n pop r31 r29 ret r29 :xNum ;; push value ld r3 VALUE push r27 r3 jmp return :xAdd ;; get another arg then add jal r29 evalnxt jal r29 fAdd push r27 r28 ;; push result jmp return :xSub jal r29 evalnxt jal r29 fSub push r27 r28 jmp return :xMul jal r29 evalnxt jal r29 fMul push r27 r28 jmp return :xDiv jal r29 evalnxt jal r29 fDiv push r27 r28 jmp return :xEq pop r27 r30 ;; pop eval stack trap 1 ;; print to screen jmp return :xLd trap 4 jmp return :xF0 jal r29 jF0 ;; zero arg jmp return :xF1 jal r29 evalnxt ;; one arg jal r29 jF1 push r27 r28 jmp return :xF2 jal r29 evalnxt jal r29 jF2 push r27 r28 jmp return :xF3 jal r29 evalnxt jal r29 jF3 push r27 r28 jmp return :xF4 jal r29 evalnxt ;; two arg jal r29 evalnxt jal r29 jF4 push r27 r28 jmp return :xF5 jal r29 evalnxt jal r29 evalnxt jal r29 jF5 push r27 r28 jmp return :xF6 jal r29 evalnxt jal r29 evalnxt jal r29 jF6 push r27 r28 jmp return :xF7 jal r29 evalnxt jal r29 evalnxt jal r29 jF7 push r27 r28 jmp return :xF8 jal r29 evaln ;; var arg jal r29 jF8 pop r27 r30 trap 1 ;; and display jmp return :xF9 jal r29 evaln jal r29 jF9 pop r27 r30 trap 1 jmp return ;; jump table to link dynamic load object :jF0 jmp return :jF1 jmp return :jF2 jmp return :jF3 jmp return :jF4 jmp return :jF5 jmp return :jF6 jmp return :jF7 jmp return :jF8 jmp return :jF9 jmp return ;; subroutine to do basic functions ;; use r1 r2, return result in r28 :fAdd push r31 r1 push r31 r2 pop r27 r2 pop r27 r1 add r28 r1 r2 pop r31 r2 pop r31 r1 ret r29 :fSub push r31 r1 push r31 r2 pop r27 r2 pop r27 r1 sub r28 r1 r2 pop r31 r2 pop r31 r1 ret r29 :fMul push r31 r1 push r31 r2 pop r27 r2 pop r27 r1 mul r28 r1 r2 pop r31 r2 pop r31 r1 ret r29 :fDiv push r31 r1 push r31 r2 pop r27 r2 pop r27 r1 div r28 r1 r2 pop r31 r2 pop r31 r1 ret r29 ;; subroutines to do special functions ;; f0..f9 .end