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