Initial commit of files related to NED architecture.
[ned1] / software / 4func_calculator / calc.asm
CommitLineData
bc5b63cf
AT
1# (c) 2018 Aaron Taylor <ataylor at subgeniuskitty dot com>
2# See LICENSE.txt file for copyright and license details.
3
4# Simple 4-function calculator in NED assembly.
5# 20181128 - Aaron Taylor
6
7calc
8 JSR>calcinit
9
10 calcloop
11 # Refresh the display.
12 JSR>printtopstackentry
13
14 # Get a character/command.
15 JSR>getchar
16
17 # Check for 'zero stack entry' command.
18 LDSP+0
19 JSR>evalzerostackentry
20
21 # Check for 'negate stack entry' command.
22 LDSP+0
23 JSR>evalnegatestackentry
24
25 # Check for stack navigation commands.
26 LDSP+0
27 JSR>evalstacknavigation
28
29 # Check for ASCII digit (append to stack entry) command.
30 LDSP+0
31 JSR>evalasciidigit
32
33 # Check for ASCII 'addition' command.
34 LDSP+0
35 JSR>evalmathaddition
36
37 # Check for ASCII 'subtraction' command.
38 LDSP+0
39 JSR>evalmathsubtraction
40
41 # Check for ASCII 'multiplication' command.
42 LDSP+0
43 JSR>evalmathmultiplication
44
45 # Check for ASCII 'division' command.
46 LDSP+0
47 JSR>evalmathdivision
48
49 # Dump existing character and get the next character.
50 TEST
51 JMP>calcloop
52
53# Should be unreachable.
54HALT
55
56##########################################################################################
57calcinit
58##########################################################################################
59# Description:
60# Initializes stack for calc subroutine.
61# Zeros the Data Stack in RAM.
62# Call Stack:
63# Return PC <-- TOS
64# Return Stack:
65# Data Stack Base Address (=0x40000000)
66# Data Stack Offset (=0) <-- TOS
67##########################################################################################
68 # Setup program stack.
69 WORD_1073741824
70 SWAP
71 IM_0
72 SWAP
73
74 # Prepare to generate Data Stack pointers.
75 LDSP+2 # Data Stack Base Address
76 LDSP+2 # Data Stack Offset
77
78 # Zero the Data Stack.
79 calcinitzeroloop
80
81 # Increment Data Stack Offset, store 0 at location.
82 JSR>incrementstackindex
83 IM_0
84 LDSP+2
85 LDSP+2
86 ADD
87 STORE
88
89 # Check for loop termination
90 LDSP+0
91 TEST
92 BRZ>calcinitzeroloopend
93 JMP>calcinitzeroloop
94
95 calcinitzeroloopend
96
97 # Clean up stack and return.
98 TEST
99 TEST
100 RTS
101
102##########################################################################################
103incrementstackindex
104##########################################################################################
105# Description:
106# Increment the Data Stack Offset, wrapping if approriate.
107# Call Stack:
108# Data Stack Offset
109# Return PC <-- TOS
110# Return Stack:
111# Data Stack Offset
112##########################################################################################
113 # Increment the Data Stack Offset
114 SWAP
115 IM_4 # Four bytes per word
116 ADD
117
118 # See if the new Data Stack Offset should wrap. If so, set it to zero.
119 LDSP+0
120 IM_12 # Total of four stack entries (offsets: 0, 4, 8, 12).
121 JSR>subtract
122 TEST
123 IM_12 # Address of PSW register.
124 LOAD
125 IM_2 # Negative bit in PSW
126 AND
127 TEST
128 BRZ>incrementstackindexreturn
129 # Negative bit was set, so wrap to start of stack.
130 TEST
131 IM_0
132 incrementstackindexreturn
133 SWAP
134 RTS
135
136##########################################################################################
137decrementstackindex
138##########################################################################################
139# Description:
140# Decrement the Data Stack Offset, wrapping if approriate.
141# Call Stack:
142# Data Stack Offset
143# Return PC <-- TOS
144# Return Stack:
145# Data Stack Offset
146##########################################################################################
147 # Decrement the Data Stack Offset
148 SWAP
149 IM_4
150 SWAP
151 JSR>subtract
152
153 # See if new Data Stack Offset should wrap, indicated by value < 0.
154 # If so, set it to 12 (offsets: 0, 4, 8, 12).
155 LDSP+0
156 TEST
157 IM_12 # Address of PSW register.
158 LOAD
159 IM_2 # Negative bit in PSW register.
160 AND
161 TEST
162 BRZ>decrementstackindexreturn
163 # Negative bit was set, so wrap to end of stack.
164 TEST
165 IM_12
166 decrementstackindexreturn
167 SWAP
168 RTS
169
170##########################################################################################
171printstackindex
172##########################################################################################
173# Description:
174# Prints the data stack index in user readable form.
175# Call Stack:
176# Data Stack Offset
177# Return PC <-- TOS
178# Return Stack:
179# <empty>
180##########################################################################################
181 # Put Return PC on bottom of stack.
182 SWAP
183
184 # Put post-number portion of the string on the stack (colon, space, NUL).
185 IM_0 # ASCII NUL
186 SWAP
187 WORD_32 # ASCII ' '
188 SWAP
189 WORD_58 # ASCII ':'
190 SWAP
191
192 # Stack now looks like:
193 # Return PC
194 # ASCII NUL
195 # ASCII ' '
196 # ASCII ':'
197 # Data Stack Offset
198
199 # Divide Data Stack Offset by 4 to generate index since there are 4 bytes per word.
200 IM_4
201 JSR>divide
202 TEST # DROP Remainder
203
204 # Convert index to ASCII and print the string.
205 JSR>itoa
206 JSR>printstring
207 RTS
208
209##########################################################################################
210printbinaryinteger
211##########################################################################################
212# Description:
213# Prints a binary integer to ASCII terminal.
214# Call Stack:
215# Integer
216# Return PC <-- TOS
217# Return Stack:
218# <empty>
219##########################################################################################
220 # Put Return PC on bottom of stack.
221 SWAP
222
223 # Put ASCII NUL on stack as end of string.
224 IM_0
225 SWAP
226
227 # Separate Integer into sign and magnitude.
228 LDSP+0
229 IM_4
230 LOAD
231 AND
232 SWAP
233 JSR>absolutevalue
234
235 # Stack now looks like:
236 # Return PC
237 # ASCII NUL
238 # Sign flag (nonzero for negative result, 0 for positive result)
239 # ABS(Integer)
240
241 # First check if the number is zero and print a single zero if true.
242 LDSP+0
243 TEST
244 BRZ>printbinaryintegerloopend
245
246 # Repeatedly divide by ten and push each digit onto the stack in ASCII.
247 printbinaryintegerloop
248
249 # Verify Integer still has digits to print (i.e. Integer != 0)
250 LDSP+0
251 TEST
252 BRZ>printbinaryintegerloopend
253
254 # Extract the least significant digit.
255 IM_10
256 JSR>divide
257
258 # Convert to ASCII and add to string on stack.
259 JSR>itoa
260 LDSP+2 # Sign flag
261 SWAP
262 STSP+2
263 SWAP
264
265 # Loop
266 JMP>printbinaryintegerloop
267
268 printbinaryintegerloopend
269 TEST # DROP ABS(Integer)
270
271 # Push a leading ASCII zero onto stack.
272 IM_0
273 JSR>itoa
274 SWAP
275
276 # Stack now looks like:
277 # Return PC
278 # ASCII NUL
279 # ASCII digit
280 # ...
281 # ASCII digit
282 # Sign flag (nonzero for negative result, 0 for positive result)
283
284 # Push sign onto stack as ASCII character.
285 TEST
286 BRZ>printbinaryintegerpositive
287
288 # Add ASCII '-' sign to stack
289 WORD_44
290 IM_1
291 ADD
292 JMP>printbinaryintegerend
293
294 printbinaryintegerpositive
295
296 # Add ASCII '+' sign to stack
297 WORD_42
298 IM_1
299 ADD
300
301 printbinaryintegerend
302
303 # Print the string and return
304 JSR>printstring
305 RTS
306
307##########################################################################################
308printtopstackentry
309##########################################################################################
310# Description:
311# Prints the current TOS entry.
312# Call Stack:
313# Data Stack Base Address
314# Data Stack Offset
315# Return PC <-- TOS
316# Return Stack:
317# Data Stack Base Address
318# Data Stack Offset <-- TOS
319##########################################################################################
320 # Prepare the screen and cursor.
321 JSR>ansiescapeclearscreen
322 JSR>ansiescapesetcursorcolumnone
323
324 # Print the data stack index
325 LDSP+1
326 JSR>printstackindex
327
328 # Print the TOS entry from the data stack in human readable form.
329 LDSP+2
330 LDSP+2
331 ADD
332 LOAD
333 JSR>printbinaryinteger
334 RTS
335
336##########################################################################################
337evalzerostackentry
338##########################################################################################
339# Description:
340# If character on TOS is ASCII "'", zero the current data stack entry.
341# Call Stack:
342# Data Stack Base Address
343# Data Stack Offset
344# ASCII character
345# ASCII character
346# Return PC <-- TOS
347# Return Stack:
348# Data Stack Base Address
349# Data Stack Offset
350# ASCII character
351##########################################################################################
352 SWAP
353
354 # Test for ASCII "'".
355 WORD_38 # ASCII "'"
356 IM_1
357 ADD
358 JSR>subtract
359 TEST
360 BRZ>evalzerostackentrymatch
361
362 # No match, return from subroutine
363 RTS
364
365 evalzerostackentrymatch
366
367 # Matched, zero the stack entry and return.
368
369 # Stack now looks like:
370 # Data Stack Base Address
371 # Data Stack Offset
372 # ASCII character
373 # Return PC <-- TOS
374
375 IM_0
376 LDSP+4 # Data Stack Base Address
377 LDSP+4 # Data Stack Offset
378 ADD
379 STORE
380 RTS
381
382##########################################################################################
383evalstacknavigation
384##########################################################################################
385# Description:
386# If character on TOS is ASCII '.' or ',', inc/dec Data Stack Offset to next entry.
387# Call Stack:
388# Data Stack Base Address
389# Data Stack Offset
390# ASCII character
391# ASCII character
392# Return PC <-- TOS
393# Return Stack:
394# Data Stack Base Address
395# Data Stack Offset
396# ASCII character
397##########################################################################################
398 SWAP
399 LDSP+0
400
401 # Test for ASCII ','
402 WORD_44 # ASCII ','
403 JSR>subtract
404 TEST
405 BRZ>evalstacknavigationprevmatch
406
407 # No match.
408 JMP>evalstacknavigationnexttest
409
410 evalstacknavigationprevmatch
411
412 # Matched, decrement Data Stack Offset.
413
414 # Stack now looks like:
415 # Data Stack Base Address
416 # Data Stack Offset
417 # ASCII character
418 # Return PC <-- TOS
419 # ASCII character
420
421 # Decrement the Data Stack Offset
422 LDSP+3 # Data Stack Offset
423 JSR>decrementstackindex
424 STSP+3
425
426 # Clean up stack and return.
427 TEST
428 RTS
429
430 evalstacknavigationnexttest
431 # Test for ASCII '.'
432 WORD_46 # ASCII '.'
433 JSR>subtract
434 TEST
435 BRZ>evalstacknavigationnextmatch
436
437 # No match.
438 RTS
439
440 evalstacknavigationnextmatch
441
442 # Matched, increment Data Stack Offset
443
444 # Increment and return.
445 LDSP+2 # Data Stack Offset
446 JSR>incrementstackindex
447 STSP+2
448 RTS
449
450##########################################################################################
451evalnegatestackentry
452##########################################################################################
453# Description:
454# If character on TOS is ASCII ';', negate the current data stack entry.
455# Call Stack:
456# Data Stack Base Address
457# Data Stack Offset
458# ASCII character
459# ASCII character
460# Return PC <-- TOS
461# Return Stack:
462# Data Stack Base Address
463# Data Stack Offset
464# ASCII character
465##########################################################################################
466 SWAP
467
468 # Test for ASCII ';'
469 WORD_58 # ASCII ';'
470 IM_1
471 ADD
472 JSR>subtract
473 TEST
474 BRZ>evalnegatestackentrymatch
475
476 # No match, return from subroutine
477 RTS
478
479 evalnegatestackentrymatch
480
481 # Matched, negate the stack entry and return.
482
483 # Stack now looks like:
484 # Data Stack Base Address
485 # Data Stack Offset
486 # ASCII character
487 # Return PC <-- TOS
488
489 LDSP+3 # Data Stack Base Address
490 LDSP+3 # Data Stack Offset
491 ADD
492 LDSP+0
493 LOAD
494 JSR>negate
495 SWAP
496 STORE
497 RTS
498
499##########################################################################################
500evalmathaddition
501##########################################################################################
502# Description:
503# If character on TOS is ASCII '+', perform addition on TOS and NOS.
504# Call Stack:
505# Data Stack Base Address
506# Data Stack Offset
507# ASCII character
508# ASCII character
509# Return PC <-- TOS
510# Return Stack:
511# Data Stack Base Address
512# Data Stack Offset
513# ASCII character
514##########################################################################################
515 SWAP
516
517 # Test for ASCII '+' (43).
518 IM_30
519 IM_13
520 ADD
521 JSR>subtract
522 TEST
523 BRZ>evalmathadditionmatch
524
525 # No match, return from subroutine
526 RTS
527
528 evalmathadditionmatch
529
530 # Matched. Perform addition.
531
532 # Stack now looks like:
533 # Data Stack Base Address
534 # Data Stack Offset
535 # ASCII character
536 # Return PC <-- TOS
537
538 # Fetch the first operand.
539 LDSP+3 # Data Stack Base Address
540 LDSP+3 # Data Stack Offset
541 ADD
542 LOAD
543
544 # Decrement Data Stack Offset.
545 LDSP+3 # Data Stack Offset
546 JSR>decrementstackindex
547 STSP+3
548
549 # Fetch the second operand.
550 LDSP+4 # Data Stack Base Address
551 LDSP+4 # Data Stack Offset
552 ADD
553 LOAD
554
555 # Perform the addition.
556 ADD
557
558 # Store the result.
559 LDSP+4 # Data Stack Base Address
560 LDSP+4 # Data Stack Offset
561 ADD
562 STORE
563
564 # Return
565 RTS
566
567##########################################################################################
568evalmathsubtraction
569##########################################################################################
570# Description:
571# If character on TOS is ASCII '-', perform subtraction NOS-TOS.
572# Call Stack:
573# Data Stack Base Address
574# Data Stack Offset
575# ASCII character
576# ASCII character
577# Return PC <-- TOS
578# Return Stack:
579# Data Stack Base Address
580# Data Stack Offset
581# ASCII character
582##########################################################################################
583 SWAP
584
585 # Test for ASCII '-' (45).
586 IM_30
587 IM_15
588 ADD
589 JSR>subtract
590 TEST
591 BRZ>evalmathsubtractionmatch
592
593 # No match, return from subroutine
594 RTS
595
596 evalmathsubtractionmatch
597
598 # Matched. Perform subtraction.
599
600 # Stack now looks like:
601 # Data Stack Base Address
602 # Data Stack Offset
603 # ASCII character
604 # Return PC <-- TOS
605
606 # Fetch the first operand.
607 LDSP+3 # Data Stack Base Address
608 LDSP+3 # Data Stack Offset
609 ADD
610 LOAD
611
612 # Decrement Data Stack Offset.
613 LDSP+3 # Data Stack Offset
614 JSR>decrementstackindex
615 STSP+3
616
617 # Fetch the second operand.
618 LDSP+4 # Data Stack Base Address
619 LDSP+4 # Data Stack Offset
620 ADD
621 LOAD
622
623 # Perform the subtraction.
624 JSR>subtract
625
626 # Store the result.
627 LDSP+4 # Data Stack Base Address
628 LDSP+4 # Data Stack Offset
629 ADD
630 STORE
631
632 # Return
633 RTS
634
635##########################################################################################
636evalmathmultiplication
637##########################################################################################
638# Description:
639# If character on TOS is ASCII '*', perform multiplication on TOS and NOS.
640# Call Stack:
641# Data Stack Base Address
642# Data Stack Offset
643# ASCII character
644# ASCII character
645# Return PC <-- TOS
646# Return Stack:
647# Data Stack Base Address
648# Data Stack Offset
649# ASCII character
650##########################################################################################
651 SWAP
652
653 # Test for ASCII '*' (42).
654 IM_30
655 IM_12
656 ADD
657 JSR>subtract
658 TEST
659 BRZ>evalmathmultiplicationmatch
660
661 # No match, return from subroutine
662 RTS
663
664 evalmathmultiplicationmatch
665
666 # Matched. Perform multiplication.
667
668 # Stack now looks like:
669 # Data Stack Base Address
670 # Data Stack Offset
671 # ASCII character
672 # Return PC <-- TOS
673
674 # Fetch the first operand.
675 LDSP+3 # Data Stack Base Address
676 LDSP+3 # Data Stack Offset
677 ADD
678 LOAD
679
680 # Decrement Data Stack Offset.
681 LDSP+3 # Data Stack Offset
682 JSR>decrementstackindex
683 STSP+3
684
685 # Fetch the second operand.
686 LDSP+4 # Data Stack Base Address
687 LDSP+4 # Data Stack Offset
688 ADD
689 LOAD
690
691 # Perform the multiplication.
692 JSR>multiply
693
694 # Store the result.
695 LDSP+4 # Data Stack Base Address
696 LDSP+4 # Data Stack Offset
697 ADD
698 STORE
699
700 # Return
701 RTS
702
703##########################################################################################
704evalmathdivision
705##########################################################################################
706# Description:
707# If character on TOS is ASCII '/', perform division NOS/TOS.
708# Returns quotient on TOS and remainder on NOS.
709# Call Stack:
710# Data Stack Base Address
711# Data Stack Offset
712# ASCII character
713# ASCII character
714# Return PC <-- TOS
715# Return Stack:
716# Data Stack Base Address
717# Data Stack Offset
718# ASCII character
719##########################################################################################
720 SWAP
721
722 # Test for ASCII '/' (47).
723 IM_30
724 IM_17
725 ADD
726 JSR>subtract
727 TEST
728 BRZ>evalmathdivisionmatch
729
730 # No match, return from subroutine
731 RTS
732
733 evalmathdivisionmatch
734
735 # Matched. Perform division.
736
737 # Stack now looks like:
738 # Data Stack Base Address
739 # Data Stack Offset
740 # ASCII character
741 # Return PC <-- TOS
742
743 # Fetch the first operand.
744 LDSP+3 # Data Stack Base Address
745 LDSP+3 # Data Stack Offset
746 ADD
747 LOAD
748
749 # Decrement Data Stack Offset.
750 LDSP+3 # Data Stack Offset
751 JSR>decrementstackindex
752 STSP+3
753
754 # Fetch the second operand.
755 LDSP+4 # Data Stack Base Address
756 LDSP+4 # Data Stack Offset
757 ADD
758 LOAD
759
760 # Perform the division.
761 SWAP
762 JSR>divide
763
764 # Store the remainder.
765 LDSP+5 # Data Stack Base Address
766 LDSP+5 # Data Stack Offset
767 ADD
768 STORE
769
770 # Increment the Data Stack Offset
771 LDSP+3 # Data Stack Offset
772 JSR>incrementstackindex
773 STSP+3
774
775 # Store the quotient.
776 LDSP+4 # Data Stack Base Address
777 LDSP+4 # Data Stack Offset
778 ADD
779 STORE
780
781 # Return
782 RTS
783
784##########################################################################################
785evalasciidigit
786##########################################################################################
787# Description:
788# If character on TOS is ASCII digit, append it to current stack entry.
789# Call Stack:
790# Data Stack Base Address
791# Data Stack Offset
792# ASCII character
793# ASCII character
794# Return PC <-- TOS
795# Return Stack:
796# Data Stack Base Address
797# Data Stack Offset
798# ASCII character
799##########################################################################################
800 SWAP
801
802 # Test for ASCII digit.
803 JSR>isasciidigit
804 TEST
805 BRZ>evalasciidigitmatch
806
807 # No match, return from subroutine
808 RTS
809
810 evalasciidigitmatch
811
812 # Matched, append result to current stack entry and return.
813
814 # Stack now looks like:
815 # Data Stack Base Address
816 # Data Stack Offset
817 # ASCII digit
818 # Return PC <-- TOS
819
820 # Load the existing entry from top of data stack.
821 LDSP+3 # Data Stack Base Address
822 LDSP+3 # Data Stack Offset
823 ADD
824 LDSP+0
825 LOAD
826
827 # Multiply existing entry by ten and add new digit to least-significant location.
828 IM_10
829 JSR>multiply
830 LDSP+3 # ASCII digit
831 JSR>atoi
832 ADD
833
834 # Put new entry back on top of data stack and return.
835 SWAP
836 STORE
837 RTS
838
839##########################################################################################
840isasciidigit
841##########################################################################################
842# Description:
843# Tests if character is ASCII digit (0..9). Returns 0 if true, 1 if false.
844# Call Stack:
845# ASCII character
846# Return PC <-- TOS
847# Return Stack:
848# <boolean, 0=true, 1=false>
849##########################################################################################
850 # Subtract ASCII '0' value, translating ASCII digit to integer.
851 SWAP
852 WORD_48
853 SWAP
854 JSR>subtract
855 # Copy and test negative result. This would indicate an ASCII character below '0'.
856 LDSP+0
857 TEST
858 IM_12 # Address of PSW register
859 LOAD
860 IM_2
861 AND
862 TEST
863 BRZ>isasciidigitcontinued
864 # The result was negative, so clean up stack and return false.
865 IM_1
866 STSP+0
867 SWAP
868 RTS
869 isasciidigitcontinued
870 # Subtract another 10 and check for positive result. This indicates ASCII char > '9'.
871 IM_10
872 SWAP
873 JSR>subtract
874 TEST
875 IM_12
876 LOAD
877 IM_2
878 AND
879 TEST
880 BRZ>isasciidigitfalse
881 # The result was true, so clean up stack and return true.
882 IM_0
883 SWAP
884 RTS
885 isasciidigitfalse
886 # The result was false, so clean up stack and return false.
887 IM_1
888 SWAP
889 RTS
890
891##########################################################################################
892generatesignflag
893##########################################################################################
894# Description:
895# Given a pair of twos-complement signed integers X and Y, generates a sign flag.
896# Flag is non-zero if the product of X and Y would be negative, otherwise flag is zero.
897# Call Stack:
898# Y Operand
899# X Operand
900# Return PC <-- TOS
901# Return Stack:
902# Sign Flag <-- TOS
903##########################################################################################
904 # Place Return PC at bottom of stack.
905 LDSP+2
906 LDSP+1
907 STSP+3
908 STSP+0
909
910 # Stack now looks like:
911 # Return PC
912 # X Operand
913 # Y Operand <-- TOS
914
915 IM_4
916 LOAD
917 AND
918 SWAP
919 IM_4
920 LOAD
921 AND
922 XOR
923 SWAP
924 RTS
925
926##########################################################################################
927negate
928##########################################################################################
929# Description:
930# Returns the additive inverse of a twos-complement operand.
931# Call Stack:
932# Operand
933# Return PC <-- TOS
934# Return Stack:
935# Result <-- TOS
936##########################################################################################
937 SWAP
938 NOT
939 IM_1
940 ADD
941 SWAP
942 RTS
943
944##########################################################################################
945absolutevalue
946##########################################################################################
947# Description:
948# Returns the absolute value of a twos-complement operand.
949# Call Stack:
950# Operand
951# Return PC <-- TOS
952# Return Stack:
953# Result <-- TOS
954##########################################################################################
955 SWAP
956 LDSP+0
957 IM_4
958 LOAD
959 AND
960 TEST
961 BRZ>absolutevaluereturn
962 JSR>negate
963
964 absolutevaluereturn
965 SWAP
966 RTS
967
968##########################################################################################
969multiply
970##########################################################################################
971# Description:
972# Performs X*Y and returns result on TOS.
973# Call Stack:
974# Y Operand
975# X Operand
976# Return PC <-- TOS
977# Return Stack:
978# Result <-- TOS
979##########################################################################################
980 # Place Return PC at bottom of stack.
981 LDSP+2
982 LDSP+1
983 STSP+3
984 STSP+0
985
986 # Stack now looks like:
987 # Return PC
988 # X Operand
989 # Y Operand <-- TOS
990
991 # Generate a sign flag and store it behind the operands.
992 LDSP+1
993 LDSP+1
994 JSR>generatesignflag
995 LDSP+2
996 SWAP
997 STSP+2
998
999 # Stack now looks like:
1000 # Return PC
1001 # Sign flag (nonzero for negative result, 0 for positive result)
1002 # Y Operand
1003 # X Operand <-- TOS
1004
1005 # Convert both X and Y Operands to absolute value.
1006 JSR>absolutevalue
1007 SWAP
1008 JSR>absolutevalue
1009
1010 # Stack now looks like:
1011 # Return PC
1012 # Sign flag (nonzero for negative result, 0 for positive result)
1013 # ABS(X Operand)
1014 # ABS(Y Operand) <-- TOS
1015
1016 # Prepare the stack for multiplication algorithm
1017 IM_0 # For magnitude of left/right shifts.
1018 LDSP+0 # Sets up stack location to build/store result.
1019
1020 # Check Nth bit of second operand.
1021 testbit
1022 LDSP+2 # Y Operand
1023 LDSP+2 # Shift magnitude
1024 SHIFT
1025 IM_1
1026 AND
1027 TEST
1028 BRZ>skipadd
1029 # If indicated by a 1 bit, shift and add first operand to result.
1030 LDSP+3 # X Operand
1031 IM_4 # 0x80000000
1032 LOAD
1033 LDSP+3 # Shift magnitude
1034 OR
1035 SHIFT
1036 ADD
1037 skipadd
1038
1039 # Increment shift magnitude counter.
1040 LDSP+1 # Shift magnitude
1041 IM_1
1042 ADD
1043 STSP+1
1044
1045 # Test for completion of multiplication algorithm (31 shifts).
1046 LDSP+1 # Shift magnitude
1047 IM_30
1048 JSR>subtract
1049 TEST
1050 BRZ>multiplycleanup
1051 JMP>testbit
1052
1053 # Clean up the the stack after performing multiplication.
1054 multiplycleanup
1055 STSP+0
1056 STSP+0
1057 STSP+0
1058
1059 # Stack now looks like:
1060 # Return PC
1061 # Sign flag (nonzero for negative result, 0 for positive result)
1062 # ABS(X*Y) <-- TOS
1063
1064 # Set the sign of the product.
1065 applysign
1066 SWAP
1067 TEST
1068 BRZ>multiplyreturn
1069 JSR>negate
1070
1071 # Clean up and return.
1072 multiplyreturn
1073 SWAP
1074 RTS
1075
1076##########################################################################################
1077divide
1078##########################################################################################
1079# Description:
1080# Division with remainder.
1081# Halts on zero divisor.
1082# Call Stack:
1083# Dividend
1084# Divisor
1085# Return PC <-- TOS
1086# Return Stack:
1087# Quotient
1088# Remainder <-- TOS
1089##########################################################################################
1090 # Move Return PC to bottom of stack.
1091 LDSP+2
1092 SWAP
1093 STSP+2
1094 SWAP
1095
1096 # Stack now looks like:
1097 # Return PC
1098 # Dividend
1099 # Divisor <-- TOS
1100
1101 # Check for zero divisor
1102 LDSP+0
1103 TEST
1104 BRZ>divideexception
1105
1106 # Generate a sign flag and store it behind the operands.
1107 LDSP+1
1108 LDSP+1
1109 JSR>generatesignflag
1110 LDSP+2
1111 SWAP
1112 STSP+2
1113
1114 # Stack now looks like:
1115 # Return PC
1116 # Sign flag (nonzero for negative result, 0 for positive result)
1117 # Divisor
1118 # Dividend <-- TOS
1119
1120 # Convert both Dividend and Divisor to absolute value.
1121 JSR>absolutevalue
1122 SWAP
1123 JSR>absolutevalue
1124
1125 # Stack now looks like:
1126 # Return PC
1127 # Sign flag (nonzero for negative result, 0 for positive result)
1128 # ABS(Dividend)
1129 # ABS(Divisor) <-- TOS
1130
1131 # Prepare stack for division algorithm.
1132 IM_31 # Cycle Counter - Loop from n-1 -> 0 where n = 32 bits.
1133 IM_0 # Quotient
1134 IM_0 # Remainder
1135
1136 # Binary long division
1137 divisionloop
1138 # Check Cycle Counter for end-of-loop condition (CC = -1).
1139 LDSP+2 # Cycle Counter
1140 IM_1
1141 ADD
1142 TEST
1143 BRZ>divisionloopend
1144
1145 # While Cycle Counter >= 0
1146
1147 # Left-shift Remainder by 1 bit.
1148 IM_1
1149 IM_4 # Address of 0x80000000 register
1150 LOAD
1151 OR
1152 SHIFT
1153
1154 # Set LSB of Remainder equal to bit (Cycle Counter) of Dividend.
1155 LDSP+4 # Dividend
1156 LDSP+3 # Cycle Counter
1157 SHIFT
1158 IM_1
1159 AND
1160 OR
1161
1162 # Check if Remainder >= Divisor
1163 LDSP+3 # Divisor
1164 LDSP+1 # Remainder
1165 JSR>subtract
1166 TEST
1167 IM_12 # Address of PSW register
1168 LOAD
1169 IM_2 # Bit for Negative Flag in PSW
1170 AND
1171 IM_2
1172 XOR
1173 TEST
1174 BRZ>divisionsubloopend
1175
1176 # If Remainder >= Divisor
1177
1178 # Set Remainder = Remainder - Divisor
1179 LDSP+3 # Divisor
1180 SWAP
1181 JSR>subtract
1182
1183 # Set bit (Cycle Counter) of Quotient equal to 1.
1184 SWAP
1185 IM_1
1186 LDSP+3 # Cycle Counter
1187 IM_4
1188 LOAD
1189 OR
1190 SHIFT
1191 OR
1192 SWAP
1193
1194 divisionsubloopend
1195
1196 # Decrement Cycle Counter
1197 IM_1
1198 LDSP+3 # Cycle Counter
1199 JSR>subtract
1200 STSP+2
1201
1202 # Loop over next division cycle
1203 JMP>divisionloop
1204
1205 divisionloopend
1206
1207 # Stack cleanup
1208 STSP+1
1209 STSP+1
1210 STSP+1
1211
1212 # Stack now looks like:
1213 # Return PC
1214 # Sign flag (nonzero for negative result, 0 for positive result)
1215 # Remainder
1216 # Quotient <-- TOS
1217
1218 # Set sign of results.
1219 LDSP+2 # Sign flag
1220 TEST
1221 BRZ>divisioncleanup
1222 JSR>negate
1223 SWAP
1224 JSR>negate
1225 SWAP
1226
1227 divisioncleanup
1228
1229 # Clean up and return
1230 SWAP
1231 LDSP+3 # Return PC
1232 SWAP
1233 STSP+2
1234 SWAP
1235 STSP+2
1236 RTS
1237
1238 # For now we can only HALT on errors and let the PC inform our debugging.
1239 divideexception
1240 HALT
1241
1242##########################################################################################
1243subtract
1244##########################################################################################
1245# Description:
1246# Performs X-Y and returns result on TOS.
1247# Call Stack:
1248# Y Operand
1249# X Operand
1250# Return PC <-- TOS
1251# Return Stack:
1252# Result <-- TOS
1253##########################################################################################
1254 # Place Return PC at bottom of stack.
1255 LDSP+2
1256 LDSP+1
1257 STSP+3
1258 STSP+0
1259 # Stack now looks like:
1260 # Return PC
1261 # X Operand
1262 # Y Operand <-- TOS
1263
1264 JSR>negate
1265 ADD
1266 SWAP
1267 RTS
1268
1269##########################################################################################
1270atoi
1271##########################################################################################
1272# Description:
1273# Converts an ASCII decimal into the corresponding integer value.
1274# No bounds checks; assumed to already be performed in isasciidigit().
1275# Call Stack:
1276# Operand
1277# Return PC <-- TOS
1278# Return Stack:
1279# Result <-- TOS
1280##########################################################################################
1281 SWAP
1282 WORD_48
1283 SWAP
1284 JSR>subtract
1285 SWAP
1286 RTS
1287
1288##########################################################################################
1289itoa
1290##########################################################################################
1291# Description:
1292# Converts an integer (0..9) into the corresponding ASCII character.
1293# Call Stack:
1294# Operand
1295# Return PC <-- TOS
1296# Return Stack:
1297# Result <-- TOS
1298##########################################################################################
1299 # Copy operand to TOS
1300 LDSP+1
1301 # Verify that operand < 10
1302 IM_10
1303 LDSP+1
1304 JSR>subtract
1305 TEST # Set PSW according to difference.
1306 # Branch if non-negative:
1307 IM_12 # Address of PSW
1308 LOAD
1309 IM_2
1310 AND
1311 TEST
1312 BRZ>itoahalt
1313 # Verify that operand > -1
1314 LDSP+0
1315 TEST # Set PSW according to operand.
1316 # Branch if negative:
1317 IM_12
1318 LOAD
1319 IM_2
1320 AND
1321 IM_2
1322 XOR
1323 TEST
1324 BRZ>itoahalt # Branch if operand was negative.
1325 # Convert the integer to its ASCII representation and return to caller.
1326 WORD_48
1327 ADD
1328 STSP+1
1329 RTS
1330 # Halt on error
1331 itoahalt
1332 HALT
1333
1334##########################################################################################
1335putchar
1336##########################################################################################
1337# Description:
1338# Writes one character to the terminal.
1339# Call Stack:
1340# Character to write
1341# Return PC <-- TOS
1342# Return Stack:
1343# <empty>
1344##########################################################################################
1345 WORD_134217728 # XBUF
1346 WORD_134217732 # XCSR
1347 LDSP+3
1348 SWAP
1349 putcharloop
1350 LDSP+0
1351 LOAD
1352 TEST
1353 BRZ>putcharloop
1354 TEST # Drop XCSR from stack
1355 SWAP
1356 STORE
1357 # Wrote the character. Clean up stack and return.
1358 STSP+0
1359 RTS
1360
1361##########################################################################################
1362getchar
1363##########################################################################################
1364# Description:
1365# Reads one character from the terminal.
1366# Call Stack:
1367# Return PC <-- TOS
1368# Return Stack:
1369# Character <-- TOS
1370##########################################################################################
1371 WORD_134217736 # RBUF
1372 WORD_134217740 # RCSR
1373 getcharloop
1374 LDSP+0
1375 LOAD
1376 TEST
1377 BRZ>getcharloop
1378 LDSP+1
1379 LOAD
1380 # Found a character. Clean up stack and return.
1381 STSP+0
1382 STSP+0
1383 SWAP
1384 RTS
1385
1386##########################################################################################
1387printstring
1388##########################################################################################
1389# Description:
1390# Prints a null-terminated string located on the stack.
1391# Call Stack:
1392# ASCII NUL
1393# ASCII character
1394# ...
1395# ASCII character
1396# Return PC <-- TOS
1397##########################################################################################
1398 SWAP
1399 BRZ>printstringreturn
1400 JSR>putchar
1401 JMP>printstring
1402
1403 printstringreturn
1404 TEST
1405 RTS
1406
1407##########################################################################################
1408ansiescapeclearscreen
1409##########################################################################################
1410# Description:
1411# Clears the entire screen.
1412# Call Stack:
1413# Return PC <-- TOS
1414# Return Stack:
1415# <empty>
1416##########################################################################################
1417 # ASCII NUL
1418 WORD_0
1419 # ASCII 'J'
1420 WORD_74
1421 # ASCII '2'
1422 WORD_50
1423 # ASCII '['
1424 WORD_90
1425 IM_1
1426 ADD
1427 # ASCII ESC
1428 WORD_26
1429 IM_1
1430 ADD
1431 # Print string and return
1432 JSR>printstring
1433 RTS
1434
1435##########################################################################################
1436ansiescapesetcursorcolumnone
1437##########################################################################################
1438# Description:
1439# Reset cursor to column 1 of screen.
1440# Call Stack:
1441# Return PC <-- TOS
1442# Return Stack:
1443# <empty>
1444##########################################################################################
1445 # ASCII NUL
1446 WORD_0
1447 # ASCII 'G'
1448 WORD_70
1449 IM_1
1450 ADD
1451 # ASCII '1'
1452 WORD_48
1453 IM_1
1454 ADD
1455 # ASCII '['
1456 WORD_90
1457 IM_1
1458 ADD
1459 # ASCII ESC
1460 WORD_26
1461 IM_1
1462 ADD
1463 # Print string and return
1464 JSR>printstring
1465 RTS