swapforth
1# r0 TOS
2# r1..r15 scratch
3# r20 GPIO shadow
4# r21 GPIO shadow
5# r22 GPIO shadow
6# r24
7# r25 constant 0
8# r26 FSP
9# r27 DSP
10# r28 do/loop counter
11# r29 do/loop offset
12# r30 cc
13# r31 RSP
14
15.if SIMULATOR
16.equ __RAMSIZE,65536
17.endif
18
19.equ PM_UNLOCK, 0x1fc80
20.equ PM_ADDR, 0x1fc84
21.equ PM_DATA, 0x1fc88
22
23.section .text
24.equ FSTACK_TOP, 0xf8fc
25.equ DSTACK_TOP, 0xfcfc
26.global _start
27_start:
28.if SIMULATOR
29jmp codestart
30.else
31jmp __PMSIZE-4
32.endif
33jmp 0 /* ft900_watchdog */
34jmp interrupt_0
35jmp interrupt_1
36jmp interrupt_2
37jmp interrupt_3
38jmp interrupt_4
39jmp interrupt_5
40jmp interrupt_6
41jmp interrupt_7
42jmp interrupt_8
43jmp interrupt_9
44jmp interrupt_10
45jmp interrupt_11
46jmp interrupt_12
47jmp interrupt_13
48jmp interrupt_14
49jmp interrupt_15
50jmp interrupt_16
51jmp interrupt_17
52jmp interrupt_18
53jmp interrupt_19
54jmp interrupt_20
55jmp interrupt_21
56jmp interrupt_22
57jmp interrupt_23
58jmp interrupt_24
59jmp interrupt_25
60jmp interrupt_26
61jmp interrupt_27
62jmp interrupt_28
63jmp interrupt_29
64jmp interrupt_30
65jmp interrupt_31
66jmp 0x3fff8
67
68jmp codestart
69
70/*
71Macro to construct the interrupt stub code.
72it just saves r0, loads r0 with the int vector
73and branches to interrupt_common.
74*/
75
76.macro inth i=0
77interrupt_\i:
78push $r0
79ldk $r0,noop
80jmp interrupt_common
81.endm
82
83inth 0
84inth 1
85inth 2
86inth 3
87inth 4
88inth 5
89inth 6
90inth 7
91inth 8
92inth 9
93inth 10
94inth 11
95inth 12
96inth 13
97inth 14
98inth 15
99inth 16
100inth 17
101inth 18
102inth 19
103inth 20
104inth 21
105inth 22
106inth 23
107inth 24
108inth 25
109inth 26
110inth 27
111inth 28
112inth 29
113inth 30
114inth 31
115inth 32
116
117/* On entry: r0, already saved, holds the handler function */
118interrupt_common:
119push $r1 /* { */
120push $r2 /* { */
121push $r3 /* { */
122push $r4 /* { */
123push $r5 /* { */
124push $r6 /* { */
125push $r7 /* { */
126push $r8 /* { */
127push $r9 /* { */
128push $r10 /* { */
129push $r11 /* { */
130push $r12 /* { */
131push $r13 /* { */
132push $r14 /* { */
133push $r15 /* { */
134
135push $r27 /* { */
136push $cc /* { */
137
138calli $r0
139
140pop $cc /* } */
141pop $r27 /* } */
142
143pop $r15 /* } */
144pop $r14 /* } */
145pop $r13 /* } */
146pop $r12 /* } */
147pop $r11 /* } */
148pop $r10 /* } */
149pop $r9 /* } */
150pop $r8 /* } */
151pop $r7 /* } */
152pop $r6 /* } */
153pop $r5 /* } */
154pop $r4 /* } */
155pop $r3 /* } */
156pop $r2 /* } */
157pop $r1 /* } */
158pop $r0 /* } matching push in interrupt_0-31 above */
159reti
160
161/* Null function for unassigned interrupt to point at */
162nullvector:
163return
164
165.equ sys_regclkcfg , 0x10008
166.equ sys_regmsc0cfg_b2, 0x1001a
167.equ sys_regmsc0cfg_b3, 0x1001b
168
169.equ sys_regpad48 , 0x1004c
170.equ sys_regpad49 , 0x1004d
171.equ sys_regpad50 , 0x1004e
172.equ sys_regpad51 , 0x1004f
173.equ sys_regpad52 , 0x10050
174.equ sys_regpad53 , 0x10051
175.equ sys_regpad54 , 0x10052
176.equ sys_regpad55 , 0x10053
177
178.equ uart1_rhr , 0x10320
179.equ uart1_thr , 0x10320
180.equ uart1_ier , 0x10321
181.equ uart1_isr_reg , 0x10322
182.equ uart1_fcr , 0x10322
183.equ uart1_lcr , 0x10323
184.equ uart1_mcr , 0x10324
185.equ uart1_lsr , 0x10325
186.equ uart1_icr , 0x10325
187.equ uart1_msr , 0x10326
188.equ uart1_spr , 0x10327
189.equ uart1_dll , 0x10320
190.equ uart1_dlm , 0x10321
191
192.macro snap reg
193move $r0,\reg
194call dot
195stophere:
196jmp stophere
197.endm
198
199.macro lit v=0
200call dupe
201ldk $r0,\v
202.endm
203
204.macro litm v=0
205call dupe
206lpm $r0,\v
207.endm
208
209.set forth_link,0
210.set internal_link,0
211
212.macro fheader fname,immediate=0
213.section .text
214.align 2
215.long 0xe0000000 + forth_link + \immediate
216.set forth_link,.-4
217.string "\fname"
218.align 2
219.endm
220
221.macro header fname,aname,immediate=0
222fheader "\fname",\immediate
223\aname :
224.endm
225
226.macro iheader fname,aname,immediate=0
227.section .text
228.align 2
229.long 0xe0000000 + internal_link + \immediate
230.set internal_link,.-4
231.string "\fname"
232.align 2
233.endm
234
235.macro _dup
236sub $r27,$r27,4
237sti $r27,0,$r0
238.endm
239
240.macro _drop
241ldi $r0,$r27,0
242add $r27,$r27,4
243.endm
244
245.macro _2drop
246ldi $r0,$r27,4
247add $r27,$r27,8
248.endm
249
250.macro _r1_n
251ldi $r1,$r27,0
252add $r27,$r27,4
253.endm
254
255.equ source_spec_size, 16
256
257.macro push_source_spec
258lda $r1,_source_id
259push $r1
260lda $r1,sourceA
261push $r1
262lda $r1,sourceC
263push $r1
264lda $r1,_in
265push $r1
266.endm
267
268.macro pop_source_spec
269pop $r1
270sta _in,$r1
271pop $r1
272sta sourceC,$r1
273pop $r1
274sta sourceA,$r1
275pop $r1
276sta _source_id,$r1
277.endm
278
279# Lower-case the text in aname
280lower_aname:
281ldk $r1,aname
282lower_aname_0:
283ldi.b $r2,$r1,0
284cmp $r2,'A'
285jmpc b,lower_aname_1
286cmp $r2,'Z'
287jmpc a,lower_aname_1
288add $r2,$r2,'a'-'A'
289sti.b $r1,0,$r2
290lower_aname_1:
291add $r1,$r1,1
292cmp $r1,aname+32
293jmpc nz,lower_aname_0
294return
295
296mkheader: /* ( <spaces>name -- ) */
297call _parse_word
298/* XXX - should check for zero string here */
299
300call lower_aname
301lda $r4,cwl /* $r4 -> cwl */
302ldi $r1,$r4,4 /* $r1 -> previous word */
303lda $r2,cp /* $r2 -> new header */
304sti $r4,4,$r2
305
306sta PM_ADDR,$r2 /* start writing */
307lpm $r2,store-8 /* the very first header is the link mask */
308or $r1,$r1,$r2
309sta PM_DATA,$r1 /* write link */
310
311add $r3,$r3,4
312and $r3,$r3,~3
313
314ldk $r2,aname
315ldk $r1,PM_DATA
316streamout $r1,$r2,$r3 /* write name */
317
318lda $r2,cp
319add $r2,$r2,4
320add $r2,$r2,$r3
321sta cp,$r2
322sta thisxt,$r2
323return
324
325push_r1:
326_dup
327move $r0,$r1
328return
329
330####### ANS CORE #################################################
331
332header "!",store
333ldi $r1,$r27,0
334sti $r0,0,$r1
335_2drop
336return
337
338
339
340fheader "*"
341_r1_n
342mul $r0,$r0,$r1
343return
344
345
346
347header "+",plus
348_r1_n
349add $r0,$r0,$r1
350return
351
352fheader "allot"
353call __dp
354jmp plus_store
355
356header "+!",plus_store
357ldi $r1,$r27,0
358ldi $r2,$r0,0
359add $r2,$r2,$r1
360sti $r0,0,$r2
361jmp two_drop
362
363header "(+loop)",do_plus_loop
364addcc $r28,$r0
365ashr $r1,$r0,31
366xor $cc,$cc,$r1
367add $r28,$r28,$r0
368_drop
369return
370
371fheader "+loop",1
372lit do_plus_loop
373call compile_comma
374
375lshr $r0,$r0,2
376lpm $r1,_template_jnc
377or $r0,$r0,$r1
378call code_comma
379
380jmp loop_clean
381
382header ",",comma
383_dup
384lda $r0,dp
385add $r1,$r0,4
386sta dp,$r1
387jmp store
388
389header "pm,",pm_comma
390call pmhere
391add $r1,$r0,4
392sta cp,$r1
393jmp pm_store
394
395
396header "code,",code_comma
397jmp pm_comma
398
399header "sync",sync
400return
401
402header "-",minus
403_r1_n
404sub $r0,$r1,$r0
405return
406
407
408header "/",slash
409_r1_n
410div $r0,$r1,$r0
411return
412
413header "/mod",slash_mod
414ldi $r1,$r27,0
415mod $r2,$r1,$r0
416sti $r27,0,$r2
417div $r0,$r1,$r0
418return
419
420fheader "0<"
421ashr $r0,$r0,31
422return
423
424fheader "0="
425cmp $r0,0
426bexts $r0,$r30,(1<<5)|0
427return
428
429fheader "1+"
430add $r0,$r0,1
431return
432
433header "1-",one_minus
434sub $r0,$r0,1
435return
436
437header "2!",two_store
438ldi $r1,$r27,0
439sti $r0,0,$r1
440ldi $r1,$r27,4
441sti $r0,4,$r1
442ldi $r0,$r27,8
443add $r27,$r27,12
444return
445
446fheader "2*"
447ashl $r0,$r0,1
448return
449
450fheader "2/"
451ashr $r0,$r0,1
452return
453
454header "2@",two_fetch
455ldi $r1,$r0,4
456ldi $r0,$r0,0
457sub $r27,$r27,4
458sti $r27,0,$r1
459return
460
461header "2drop",two_drop
462_2drop
463return
464
465header "2dup",two_dupe
466ldi $r1,$r27,0
467sub $r27,$r27,8
468sti $r27,4,$r0
469sti $r27,0,$r1
470return
471
472fheader "2over"
473ldi $r1,$r27,8
474call push_r1
475ldi $r1,$r27,8
476jmp push_r1
477
478header "2swap",two_swap
479exi $r0,$r27,4
480ldi $r1,$r27,0
481exi $r1,$r27,8
482sti $r27,0,$r1
483return
484
485header "2lit",two_lit /* Push (r1,r2). For optimizer. */
486sub $r27,$r27,8
487sti $r27,4,$r0
488sti $r27,0,$r1
489move $r0,$r2
490return
491
492fheader ":"
493call mkheader
494lda $r1,thisxt
495sub $r1,$r1,4
496sta tosmudge,$r1
497call smudge
498jmp right_bracket
499
500header "smudge",smudge /* Flip the top bit of the first char of this name */
501lda $r1,tosmudge
502lpmi $r2,$r1,0
503xor $r2,$r2,-1
504sta PM_ADDR,$r1
505sta PM_DATA,$r2
506return
507
508header ";",semicolon,1
509call smudge
510call exit
511jmp left_bracket
512
513fheader "<"
514_r1_n
515cmp $r0,$r1
516bexts $r0,$r30,(1<<5)|5
517return
518
519
520header "=",equal
521_r1_n
522cmp $r0,$r1
523bexts $r0,$r30,(1<<5)|0
524return
525
526header "cmp_cc",cmp_cc
527ldi $r1,$r27,0
528cmp $r1,$r0 /* note order: ( a b ) is compared (a,b) */
529_2drop
530return
531
532fheader ">"
533_r1_n
534cmp $r1,$r0
535bexts $r0,$r30,(1<<5)|5
536return
537
538
539fheader ">body"
540/* "literal" compiles a dupe then "ldk". Extract the field of the "ldk" */
541lpmi $r0,$r0,4
542ldk $r1,0x3ffff
543and $r0,$r0,$r1
544return
545
546header ">number",to_number
547ldi $r1,$r27,0 /* $r1 is caddr */
548ldi $r2,$r27,4 /* $r2:$r3 is the accumulator */
549ldi $r3,$r27,8
550lda $r4,_base /* $r4 is base */
551
552to_number_0:
553cmp $r0,0
554jmpc z,to_number_2
555
556ldi.b $r6,$r1,0
557
558cmp $r6,'a'
559ldk $r7,-'a'+10
560jmpc ae,to_number_1
561
562cmp $r6,'A'
563ldk $r7,-'A'+10
564jmpc ae,to_number_1
565
566cmp $r6,'9'
567jmpc a,to_number_2
568ldk $r7,-'0'+0
569to_number_1:
570add $r6,$r6,$r7
571cmp $r6,$r4
572jmpc ae,to_number_2
573
574muluh $r5,$r3,$r4 /* $r2:$r3 *= $r4 */
575mul $r3,$r3,$r4
576mul $r2,$r2,$r4
577add $r2,$r2,$r5
578
579addcc $r3,$r6
580add $r3,$r3,$r6
581bextu $r6,$r30,(1 << 5) | 1
582add $r2,$r2,$r6
583
584add $r1,$r1,1
585sub $r0,$r0,1
586
587jmp to_number_0
588
589to_number_2:
590sti $r27,0,$r1
591sti $r27,4,$r2
592sti $r27,8,$r3
593return
594
595header ">r",to_r
596pop $r1
597push $r0
598_drop
599jmpi $r1
600
601header "?dup",question_dupe
602cmp $r0,0
603jmpc nz,dupe
604return
605
606header "@",fetch
607ldi $r0,$r0,0
608return
609
610header "ul@",u_l_fetch
611ldi $r0,$r0,0
612return
613
614
615fheader "abs"
616cmp $r0,0
617jmpc lt,negate
618return
619
620fheader "tethered"
621lit _tethered
622return
623
624.macro ifteth label
625lda $cc,_tethered
626jmpx 0,$cc,0,\label
627.endm
628
629header "accept",accept
630ifteth 1f
631lit 0x1e
632call emit
6331:
634push $r28
635ldk $r28,0
636
637accept_1:
638call key
639.if SIMULATOR == 1
640cmp $r0,'\n'
641.else
642cmp $r0,'\r'
643.endif
644jmpc z,accept_2
645
646cmp $r0,8
647jmpc z,accept_backspace
648cmp $r0,0x7f
649jmpc nz,accept_3
650accept_backspace:
651call drop
652cmp $r28,0
653jmpc z,accept_1
654lit 8
655call emit
656call space
657lit 8
658call emit
659sub $r28,$r28,1
660jmp accept_1
661accept_3:
662cmp $r0,'\n'
663jmpc nz,accept_4
664call drop
665jmp accept_1
666accept_4:
667ldi $r1,$r27,4
668add $r1,$r1,$r28
669sti.b $r1,0,$r0
670ifteth 1f
671call drop
672jmp 2f
6731: call emit
6742: add $r28,$r28,1
675jmp accept_1
676accept_2:
677call two_drop
678move $r0,$r28
679pop $r28
680
681return
682
683header "align",align
684lda $r1,dp
685add $r1,$r1,3
686and $r1,$r1,~3
687sta dp,$r1
688return
689
690fheader "aligned"
691add $r0,$r0,3
692and $r0,$r0,~3
693return
694
695fheader "and"
696_r1_n
697and $r0,$r0,$r1
698return
699
700fheader "base"
701lit _base
702return
703
704header "begin",begin,1
705call check_compiling
706call sync
707lda $r1,cp
708jmp push_r1
709
710check_compiling: /* Throw -14 if interpreting */
711lda $r1,_state
712cmp $r1,0
713ldk $r1,-14
714jmpc z,throw_r1
715return
716throw_r1:
717call push_r1
718jmp throw
719
720
721header "c!",c_store
722ldi $r1,$r27,0
723sti.b $r0,0,$r1
724_2drop
725return
726
727header "c,",c_comma
728_dup
729lda $r0,dp
730add $r1,$r0,1
731sta dp,$r1
732jmp c_store
733
734header "c@",c_fetch
735ldi.b $r0,$r0,0
736return
737
738header "uw@",uw_fetch
739ldi.s $r0,$r0,0
740return
741
742header "w@",w_fetch
743ldi.s $r0,$r0,0
744bexts $r0,$r0,0
745return
746
747header "w!",w_store
748ldi $r1,$r27,0
749sti.s $r0,0,$r1
750_2drop
751return
752
753header "w,",w_comma
754_dup
755lda $r0,dp
756add $r1,$r0,2
757sta dp,$r1
758jmp w_store
759
760fheader "cell+"
761add $r0,$r0,4
762return
763
764fheader "cells"
765ashl $r0,$r0,2
766return
767
768header "count",count
769add $r1,$r0,1
770add $r27,$r27,-4
771sti $r27,0,$r1
772ldi.b $r0,$r0,0
773return
774
775header "cr",cr
776lit '\r'
777call emit
778lit '\n'
779jmp emit
780
781fheader "create"
782call mkheader
783call align
784_dup
785lda $r0,dp
786call literal
787call sync
788lda $r1,cp
789sta recent,$r1
790jmp exit
791
792header "decimal",decimal
793ldk $r1,10
794sta _base,$r1
795return
796
797header "depth",depth
798call dupe
799ldk $r0,DSTACK_TOP-4
800sub $r0,$r0,$r27
801lshr $r0,$r0,2
802return
803
804/*
805* How DO...LOOP is implemented
806*
807* Uses two registers:
808* $r28 is the counter; it starts negative and counts up. When it reaches 0, loop exits
809* $r29 is the offset. It is set up at loop start so that I can be computed from ($r28+$r29)
810*
811* So when DO we have ( limit start ) on the stack so need to compute:
812* $r28 = start - limit
813* $r29 = limit
814*
815* E.g. for "13 3 DO"
816* $r28 = -10
817* $r29 = 13
818*
819* So the loop runs:
820* $28 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1
821* I 3 4 5 6 7 8 9 10 11 12
822*
823*/
824
825dodo:
826pop $r1
827push $r28
828push $r29
829/* $r0 is start */
830ldi $r29,$r27,0 /* $r29 is limit */
831cmp $r0,$r29 /* compare for ?DO */
832sub $r28,$r0,$r29
833_2drop
834jmpi $r1
835
836header "do0cmp",do0cmp
837cmp $r0,0
838_drop
839return
840
841fheader "do",1
842ldk $r1,0
843sta leaves,$r1
844
845lit dodo
846call compile_comma
847jmp begin
848
849header "does>",does
850lda $r1,recent
851sta PM_ADDR,$r1
852pop $r1 /* $r1 is the DOES code address */
853lshr $r1,$r1,2
854lpm $r2,_template_jmp
855or $r1,$r1,$r2
856sta PM_DATA,$r1
857return
858
859header "drop",drop
860ldi $r0,$r27,0
861add $r27,$r27,4
862return
863
864header "dup",dupe
865_dup
866return
867
868
869fheader "evaluate"
870push_source_spec
871
872call tosource
873sta _in,$r25
874ldk $r1,-1
875sta _source_id,$r1
876
877call interpret
878
879pop_source_spec
880return
881
882header "execute",execute
883move $r1,$r0
884_drop
885jmpi $r1
886
887header "exit",exit,1
888_dup
889lpm $r0,_template_return
890call code_comma
891jmp sync
892
893header "fill",fill
894ldi $r1,$r27,4
895ldi $r2,$r27,0
896or $cc,$r0,$r1
897or $cc,$cc,$r2
898jmpx 0,$cc,1,1f
899memset.s $r1,$r0,$r2
900jmp 9f
9011: memset.b $r1,$r0,$r2
9029: ldi $r0,$r27,8
903add $r27,$r27,12
904return
905
906
907header "here",here
908_dup
909lda $r0,dp
910return
911
912header "noop",noop
913nop
914return
915
916header "atomic-swap",atomic_swap
917ldi $r1,$r27,0
918exi.b $r1,$r0,0
919move $r0,$r1
920jmp nip
921
922header "dp",__dp
923_dup
924ldk $r0,dp
925return
926
927header "cp",__cp
928_dup
929ldk $r0,cp
930return
931
932
933fheader "i"
934_dup
935add $r0,$r28,$r29
936return
937
938header "(if)",paren_if_paren
939call sync
940jmp 1f
9411:
942litm call_do0cmp
943call pm_comma
944lpm $r1,_template_jz
945lshr $r0,$r0,2
946or $r0,$r0,$r1
947jmp pm_comma
948call_do0cmp: call do0cmp
949
950fheader "if",1
951call check_compiling
952call false
953call paren_if_paren
954forward: /* forward ref to the just-compiled jmp */
955call sync
956lda $r1,cp
957sub $r1,$r1,4
958jmp push_r1
959
960fheader "immediate"
961/* dict @ dup pm@ 1 or swap pm! */
962call dupe
963lda $r0,cwl
964ldi $r0,$r0,4
965call dupe
966lpmi $r0,$r0,0
967or $r0,$r0,1
968call swap
969jmp pm_store
970
971header "invert",invert
972xor $r0,$r0,-1
973return
974
975fheader "j"
976ldi $r1,$sp,4
977ldi $r2,$sp,8
978add $r1,$r1,$r2
979jmp push_r1
980
981
982header "leave",leave,1
983call sync
984lda $r1,leaves
985lda $r2,cp
986sta leaves,$r2
987
988ashr $r1,$r1,2
989lpm $r2,_template_jmp
990or $r1,$r1,$r2
991call push_r1
992call code_comma
993jmp sync
994
995header "literal",literal,1
996jmp 1f
9971: litm cdupe
998call pm_comma
999set_r0:
1000/* when r0 is outside -100000 to fffff, shift right 10, recurse, then use ldl */
1001ldk $r2,-0x80000
1002cmp $r0,$r2
1003jmpc lt,1f
1004ldk $r2,0x7ffff
1005cmp $r0,$r2
1006jmpc gt,1f
1007
1008ashl $r0,$r0,12
1009lshr $r0,$r0,12
1010lpm $r1,_template_ldk_r0
1011or $r0,$r0,$r1
1012jmp pm_comma
1013
1014cdupe:
10151: call dupe
1016ashr $r0,$r0,10
1017call set_r0
1018ldk $r2,0x3ff
1019and $r0,$r0,$r2
1020ashl $r0,$r0,4
1021lpm $r1,_template_ldl_r0
1022or $r0,$r0,$r1
1023jmp pm_comma
1024
1025fheader "loop",1
1026lpm $r1,_template_inc28
1027call push_r1
1028call code_comma
1029
1030lshr $r0,$r0,2
1031lpm $r1,_template_j28m
1032or $r0,$r0,$r1
1033call code_comma
1034
1035loop_clean:
1036call sync
1037lda $r1,leaves
1038loop_0:
1039cmp $r1,0
1040jmpc z,loop_1
1041lpmi $r2,$r1,0
1042ldk $r3,0x3ffff
1043and $r2,$r2,$r3
1044ashl $r2,$r2,2
1045push $r2
1046
1047call push_r1
1048call then
1049pop $r1
1050jmp loop_0
1051loop_1:
1052
1053lit unloop
1054jmp compile_comma
1055
1056fheader "lshift"
1057_r1_n
1058ashl $r0,$r1,$r0
1059return
1060
1061fheader "m*"
1062ldi $r1,$r27,0
1063
1064mul $r2,$r0,$r1
1065sti $r27,0,$r2
1066
1067muluh $r2,$r0,$r1
1068
1069ashr $r3,$r0,31
1070and $r3,$r3,$r1
1071sub $r2,$r2,$r3
1072
1073ashr $r3,$r1,31
1074and $r3,$r3,$r0
1075sub $r0,$r2,$r3
1076
1077return
1078
1079fheader "max"
1080ldi $r1,$r27,0
1081cmp $r1,$r0
1082jmpc gt,drop
1083jmp nip
1084
1085fheader "min"
1086ldi $r1,$r27,0
1087cmp $r1,$r0
1088jmpc lt,drop
1089jmp nip
1090
1091fheader "mod"
1092_r1_n
1093mod $r0,$r1,$r0
1094return
1095
1096fheader "umod"
1097_r1_n
1098umod $r0,$r1,$r0
1099return
1100
1101
1102header "negate",negate
1103sub $r0,$r25,$r0
1104return
1105
1106fheader "or"
1107_r1_n
1108or $r0,$r0,$r1
1109return
1110
1111header "over",over
1112_dup
1113ldi $r0,$r27,4
1114return
1115
1116header "postpone",postpone,1
1117call parse_name
1118call sfind
1119cmp $r0,1
1120_drop
1121jmpc z,_postpone_immed
1122
1123call literal
1124lit compile_comma
1125_postpone_immed:
1126jmp compile_comma
1127
1128header "r>",r_from
1129pop $r1
1130_dup
1131pop $r0
1132jmpi $r1
1133
1134header "r@",r_fetch
1135_dup
1136ldi $r0,$sp,4
1137return
1138
1139header "recurse",recurse,1
1140_dup
1141lda $r0,thisxt
1142jmp compile_comma
1143
1144
1145header "rot",rot
1146exi $r0,$r27,0
1147exi $r0,$r27,4
1148return
1149
1150fheader "rshift"
1151_r1_n
1152lshr $r0,$r1,$r0
1153return
1154
1155
1156fheader "s>d"
1157_dup
1158ashr $r0,$r0,31
1159return
1160
1161
1162header "space",space
1163lit ' '
1164jmp emit
1165
1166
1167fheader "state"
1168lit _state
1169return
1170
1171header "swap",swap
1172exi $r0,$r27,0
1173return
1174
1175header "then",then,1
1176call check_compiling
1177call sync
1178lda $r1,cp
1179lshr $r1,$r1,2
1180lpmi $r2,$r0,0
1181ldk $r3,~0xffff
1182and $r2,$r2,$r3
1183or $r1,$r1,$r2
1184sta PM_ADDR,$r0
1185sta PM_DATA,$r1
1186jmp drop
1187
1188fheader "u<"
1189_r1_n
1190cmp $r0,$r1
1191bexts $r0,$r30,(1<<5)|6
1192return
1193
1194header "um*",u_m_star
1195ldi $r1,$r27,0
1196mul $r2,$r0,$r1
1197muluh $r0,$r0,$r1
1198sti $r27,0,$r2
1199return
1200
1201header "unloop",unloop
1202pop $r1
1203pop $r29
1204pop $r28
1205jmpi $r1
1206
1207header "until",until,1
1208call check_compiling
1209jmp paren_if_paren
1210
1211fheader "xor"
1212_r1_n
1213xor $r0,$r0,$r1
1214return
1215
1216header "[",left_bracket,1
1217sta _state,$r25
1218return
1219
1220
1221header "]",right_bracket
1222ldk $r1,3
1223sta _state,$r1
1224return
1225
1226####### ANS CORE EXT #############################################
1227
1228
1229header "0<>",zero_notequal
1230cmp $r0,0
1231bexts $r0,$r30,(1<<5)|0
1232xor $r0,$r0,-1
1233return
1234
1235fheader "0>"
1236cmp $r0,0
1237bexts $r0,$r30,(1<<5)|5
1238return
1239
1240fheader "2>r"
1241pop $r2
1242ldi $r1,$r27,0
1243push $r1
1244push $r0
1245_2drop
1246jmpi $r2
1247
1248fheader "2r>"
1249pop $r3
1250pop $r2
1251pop $r1
1252push $r3
1253jmp two_lit
1254
1255fheader "2r@"
1256ldi $r1,$sp,8
1257ldi $r2,$sp,4
1258jmp two_lit
1259
1260_dummy: .long 0
1261
1262header ":noname",colon_noname
1263ldk $r1,_dummy /* So that ';' will unsmudge nothing */
1264sta tosmudge,$r1
1265lda $r1,cp
1266sta thisxt,$r1
1267call push_r1
1268jmp right_bracket
1269
1270fheader "<>"
1271_r1_n
1272cmp $r0,$r1
1273bexts $r0,$r30,(1<<5)|0
1274xor $r0,$r0,-1
1275return
1276
1277header "?do",question_do,1
1278lit dodo
1279call compile_comma
1280
1281call sync
1282lda $r1,cp
1283sta leaves,$r1
1284call false
1285call jz_comma
1286jmp begin
1287
1288header "again",again,1
1289call check_compiling
1290jmp jmp_comma
1291
1292
1293header "compile,",compile_comma
1294jmp 1f
12951: lshr $r0,$r0,2
1296lpm $r1,_template_call
1297or $r0,$r0,$r1
1298jmp pm_comma
1299
1300
1301header "false",false
1302_dup
1303ldk $r0,0
1304return
1305
1306header "nip",nip
1307add $r27,$r27,4
1308return
1309
1310header "parse",parse
1311move $r4,$r0
1312lda $r0,_in
1313lda $r1,sourceA
1314add $r0,$r0,$r1
1315_dup
1316
1317ldk $r0,-1
1318lda $r2,_in
1319lda $r3,sourceC
1320/* r0 is count */
1321/* r1 is sourceA */
1322/* r2 is >in */
1323/* r4 is char */
1324parse_0:
1325add $r0,$r0,1
1326cmp $r3,$r2
1327jmpc z,parse_1
1328add $r5,$r1,$r2
1329ldi.b $r5,$r5,0
1330add $r2,$r2,1
1331cmp $r4,$r5
1332jmpc nz,parse_0
1333parse_1:
1334sta _in,$r2
1335return
1336
1337fheader "pick"
1338ashl $r0,$r0,2
1339add $r0,$r0,$r27
1340ldi $r0,$r0,0
1341return
1342
1343fheader "query"
1344
1345header "refill",refill
1346lda $r1,_source_id /* When the input source is a string from EVALUATE, return false */
1347cmp $r1,-1
1348jmpc z,false
1349
1350lit tib
1351lit 256
1352call accept
1353sta sourceC,$r0
1354call drop
1355sta _in,$r25
1356jmp true
1357
1358
1359header "roll",roll
1360ashl $r1,$r0,2
1361_drop
1362add $r1,$r1,$r27
1363move $r2,$r27
1364jmp 2f
13651: exi $r0,$r2,0
1366add $r2,$r2,4
13672: cmp $r1,$r2
1368jmpc nz,1b
1369return
1370
1371
1372header "(source-id)",paren_source_id_paren
1373lit _source_id
1374return
1375
1376
1377header "true",true
1378_dup
1379ldk $r0,-1
1380return
1381
1382
1383fheader "u>"
1384_r1_n
1385cmp $r1,$r0
1386bexts $r0,$r30,(1<<5)|6
1387return
1388
1389fheader "unused"
1390call dupe
1391ldk $r0,DSTACK_TOP-256
1392lda $r1,dp
1393sub $r0,$r0,$r1
1394return
1395
1396####### DOUBLE AND DOUBLE EXT ####################################
1397
1398header "2literal",two_literal,1
1399call swap
1400call literal
1401jmp literal
1402
1403header "2rot",two_rote /* ( x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2 ) */
1404/* 16 12 8 4 0 16 12 8 4 0 */
1405exi $r0,$r27,4
1406exi $r0,$r27,12
1407
1408ldi $r1,$r27,0
1409exi $r1,$r27,8
1410exi $r1,$r27,16
1411sti $r27,0,$r1
1412return
1413
1414header "d+",d_plus
1415/* $r0: ud2.hi */
1416ldi $r1,$r27,0 /* $r1: ud2.lo */
1417ldi $r2,$r27,4 /* $r2: ud1.hi */
1418ldi $r3,$r27,8 /* $r3: ud1.lo */
1419addcc $r1,$r3
1420bextu $r4,$cc,(1<<5)|1
1421add $r1,$r1,$r3
1422add $r0,$r0,$r2
1423add $r0,$r0,$r4
1424add $r27,$r27,8
1425sti $r27,0,$r1
1426return
1427
1428header "d-",d_minus
1429call d_negate
1430jmp d_plus
1431
1432header "d0<",d_zero_less
1433add $r27,$r27,4
1434ashr $r0,$r0,31
1435return
1436
1437header "d0=",d_zero_equals
1438_r1_n
1439or $r0,$r0,$r1
1440cmp $r0,0
1441bexts $r0,$r30,(1<<5)|0
1442return
1443
1444header "d2*",d_two_star
1445ldi $r1,$r27,0
1446lshr $r2,$r1,31
1447ashl $r0,$r0,1
1448ashl $r1,$r1,1
1449or $r0,$r0,$r2
1450sti $r27,0,$r1
1451return
1452
1453header "d2/",d_two_slash
1454ldi $r1,$r27,0
1455ashl $r2,$r0,31
1456ashr $r0,$r0,1
1457lshr $r1,$r1,1
1458or $r1,$r1,$r2
1459sti $r27,0,$r1
1460return
1461
1462header "d<",d_less_than
1463/* $r0: ud2.hi */
1464ldi $r2,$r27,4 /* $r2: ud1.hi */
1465cmp $r0,$r2
1466jmpc nz,1f
1467ldi $r1,$r27,0 /* $r1: ud2.lo */
1468ldi $r3,$r27,8 /* $r3: ud1.lo */
1469cmp $r1,$r3
1470add $r27,$r27,12
1471bexts $r0,$cc,(1<<5)|6
1472return
14731:
1474add $r27,$r27,12
1475bexts $r0,$cc,(1<<5)|5
1476return
1477
1478header "d=",d_equals
1479ldi $r2,$r27,4 /* $r2: ud1.hi */
1480xor $r0,$r0,$r2
1481ldi $r1,$r27,0 /* $r1: ud2.lo */
1482ldi $r3,$r27,8 /* $r3: ud1.lo */
1483xor $r1,$r1,$r3
1484or $r0,$r0,$r1
1485cmp $r0,0
1486add $r27,$r27,12
1487bexts $r0,$cc,(1<<5)|0
1488return
1489
1490header "d>s",d_to_s
1491jmp drop
1492
1493header "dabs",d_abs
1494cmp $r0,0
1495jmpc lt,d_negate
1496return
1497
1498header "dnegate",d_negate
1499ldi $r1,$r27,0
1500xor $r0,$r0,-1
1501xor $r1,$r1,-1
1502add $r1,$r1,1
1503cmp $r1,0
1504jmpc nz,d_negate_1
1505add $r0,$r0,1
1506d_negate_1:
1507sti $r27,0,$r1
1508return
1509
1510header "du<",d_u_less /* ( ud1 ud2 -- flag ) */
1511/* $r0: ud2.hi */
1512ldi $r2,$r27,4 /* $r2: ud1.hi */
1513cmp $r2,$r0
1514jmpc nz,known$
1515ldi $r1,$r27,0 /* $r1: ud2.lo */
1516ldi $r3,$r27,8 /* $r3: ud1.lo */
1517cmp $r3,$r1
1518known$:
1519add $r27,$r27,12
1520bexts $r0,$cc,(1<<5)|1
1521return
1522
1523####### ANS TOOLS AND TOOLS EXT ##################################
1524
1525header "ahead",ahead,1
1526call check_compiling
1527call false
1528call jmp_comma
1529jmp forward
1530
1531####### EXCEPTION ################################################
1532
1533header "catch",catch /* ( xt -- exception# | 0 ) */
1534push_source_spec
1535push $r27
1536lda $r1,handler
1537push $r1
1538sta handler,$sp
1539call execute
1540pop $r1
1541sta handler,$r1
1542pop $r1
1543add $sp,$sp,source_spec_size
1544jmp false
1545
1546header "throw",throw
1547cmp $r0,0
1548jmpc z,drop
1549lda $sp,handler
1550pop $r1
1551sta handler,$r1
1552pop $r27
1553pop_source_spec
1554return
1555
1556header "ithrow",ithrow /* THROW from an interrupt handler */
1557ldk $r1,throw
1558push $r1
1559reti
1560
1561####### STRING ###################################################
1562
1563header "/string",slash_string
1564move $r2,$r0
1565_drop
1566sub $r0,$r0,$r2
1567ldi $r1,$r27,0
1568add $r1,$r1,$r2
1569sti $r27,0,$r1
1570return
1571
1572header "cmove",cmove
1573ldi $r1,$r27,4
1574ldi $r2,$r27,0
1575memcpy.b $r2,$r1,$r0
1576ldi $r0,$r27,8
1577add $r27,$r27,12
1578return
1579
1580header "cmove>",cmove_up
1581ldi $r1,$r27,4 /* */
1582add $r1,$r1,$r0 /* $r1: srcptr */
1583ldi $r2,$r27,0 /* $r2: dst */
1584add $r3,$r2,$r0 /* $r3: dstptr */
1585jmp cmove_up_1
1586
1587cmove_up_0:
1588sub $r1,$r1,1
1589sub $r3,$r3,1
1590ldi.b $r4,$r1,0
1591sti.b $r3,0,$r4
1592cmove_up_1:
1593cmp $r2,$r3
1594jmpc nz,cmove_up_0
1595
1596ldi $r0,$r27,8
1597add $r27,$r27,12
1598return
1599
1600header "compare",compare
1601/* ( c-addr1 u1 c-addr2 u2 -- n ) */
1602/* $r0: u2 */
1603ldi $r1,$r27,0 /* $r1: addr2 */
1604ldi $r2,$r27,4 /* $r2: u1 */
1605ldi $r3,$r27,8 /* $r3: addr1 */
1606add $r27,$r27,12
1607
1608cmp $r0,$r2
1609jmpc z,2f
1610jmpc b,1f
1611
1612/* u2 is larger */
1613add $r2,$r2,$r3
1614ldk $r0,-1
1615jmp 4f
1616
16171:
1618add $r2,$r0,$r3
1619ldk $r0,1
1620jmp 4f
1621
16222:
1623add $r2,$r0,$r3
1624ldk $r0,0
1625jmp 4f
1626
16273:
1628ldi.b $r4,$r1,0
1629ldi.b $r5,$r3,0
1630cmp $r5,$r4
1631jmpc nz,5f
1632add $r1,$r1,1
1633add $r3,$r3,1
1634
16354:
1636cmp $r2,$r3
1637jmpc nz,3b
1638return
1639
16405:
1641sub $r0,$r5,$r4
1642ashr $r0,$r0,31
1643or $r0,$r0,1
1644return
1645
1646.macro tolower r
1647cmp \r,'z'
1648jmpc gt,9f
1649cmp \r,'a'
1650jmpc lt,9f
1651add \r,\r,'A'-'a'
16529:
1653.endm
1654
1655header "icompare",icompare
1656/* ( c-addr1 u1 c-addr2 u2 -- n ) */
1657/* $r0: u2 */
1658ldi $r1,$r27,0 /* $r1: addr2 */
1659ldi $r2,$r27,4 /* $r2: u1 */
1660ldi $r3,$r27,8 /* $r3: addr1 */
1661add $r27,$r27,12
1662
1663cmp $r0,$r2
1664jmpc z,2f
1665jmpc b,1f
1666
1667/* u2 is larger */
1668add $r2,$r2,$r3
1669ldk $r0,-1
1670jmp 4f
1671
16721:
1673add $r2,$r0,$r3
1674ldk $r0,1
1675jmp 4f
1676
16772:
1678add $r2,$r0,$r3
1679ldk $r0,0
1680jmp 4f
1681
16823:
1683ldi.b $r4,$r1,0
1684ldi.b $r5,$r3,0
1685tolower $r4
1686tolower $r5
1687cmp $r5,$r4
1688jmpc nz,5f
1689add $r1,$r1,1
1690add $r3,$r3,1
1691
16924:
1693cmp $r2,$r3
1694jmpc nz,3b
1695return
1696
16975:
1698sub $r0,$r5,$r4
1699ashr $r0,$r0,31
1700or $r0,$r0,1
1701return
1702
1703####### ASSEMBLER ################################################
1704
1705_template_jmp: jmp 0
1706_template_call: call 0
1707_template_return: return
1708_template_ldk_r0: ldk $r0,0
1709_template_ldl_r0: ldl $r0,$r0,0
1710_template_jz: jmpc z,0
1711_template_inc28: add $r28,$r28,1
1712_template_j28m: jmpx 31,$r28,1,0
1713_template_jnc: jmpc nc,0
1714
1715jmp_comma:
1716lshr $r0,$r0,2
1717lpm $r1,_template_jmp
1718or $r0,$r0,$r1
1719jmp code_comma
1720
1721jz_comma:
1722lshr $r0,$r0,2
1723lpm $r1,_template_jz
1724or $r0,$r0,$r1
1725jmp code_comma
1726
1727####### UART #####################################################
1728
1729header "setpad",setpad /* ( u n -- ) Set chip pad n to function u */
1730ldk $r1,0x1001c
1731add $r0,$r0,$r1
1732ldi $r1,$r27,0
1733sti.b $r0,0,$r1
1734jmp two_drop
1735
1736orbang:
1737ldi $r1,$r27,0
1738ldi $r2,$r0,0
1739or $r1,$r1,$r2
1740sti $r0,0,$r1
1741jmp two_drop
1742
1743uart.idx:
1744lit uart1_spr
1745call c_store
1746lit uart1_icr
1747jmp c_store
1748
1749.equ CPR, 1
1750.equ TCR, 2
1751
1752uart.start:
1753lit 0x0010
1754lit sys_regclkcfg
1755call orbang
1756
1757lit 0x08
1758lit CPR
1759call uart.idx
1760lit 4
1761lit TCR
1762call uart.idx
1763
1764/* Enable pad for UART bit [7:6] */
1765lit 0xc0
1766lit 48
1767call setpad
1768
1769lit 0xc0
1770lit 49
1771call setpad
1772
1773lit 0x28
1774lit sys_regmsc0cfg_b2
1775call c_store
1776
1777lit 0x83
1778lit uart1_lcr
1779call c_store
1780
1781lit 217 / 8
1782/* lit 195 / 8 */
1783lit uart1_dll
1784call c_store
1785
1786lit 0
1787lit uart1_dlm
1788call c_store
1789
1790lit 0x03
1791lit uart1_lcr
1792call c_store
1793
1794lit 0x00
1795lit uart1_fcr
1796call c_store
1797
1798lit 0x02
1799lit uart1_mcr
1800jmp c_store
1801
1802header "uart-emit",uart_emit
1803.if SIMULATOR == 1
1804sta.b 0x10000,$r0
1805.else
1806lda.b $r1,0x10325
1807tst.b $r1,(1<<5)
1808jmpc z,uart_emit
1809sta.b 0x10320,$r0
1810.endif
1811jmp drop
1812
1813header "uart-key",uart_key
1814_dup
1815.if SIMULATOR == 1
1816lda.b $r0,0x10000
1817cmp.b $r0,255
1818jmpc nz,1f
1819ldk $r0,0
1820sta 0x1fffc,$r0
18211:
1822.else
1823key_1:
1824lda.b $r1,0x10325
1825tst.b $r1,(1<<0)
1826jmpc z,key_1
1827lda.b $r0,0x10320
1828.endif
1829return
1830
1831####### CHARACTER I/O ############################################
1832
1833default_emit:
1834jmp uart_emit
1835
1836header "emit",emit
1837jmp uart_emit
1838
1839header "key",key
1840jmp uart_key
1841
1842header ".x",hex8
1843call dupe
1844lshr $r0,$r0,16
1845call hex4
1846hex4:
1847call dupe
1848lshr $r0,$r0,8
1849call hex2
1850hex2:
1851call dupe
1852lshr $r0,$r0,4
1853call digit
1854digit:
1855and $r0,$r0,15
1856cmp $r0,10
1857ldk $r1,'0'
1858jmpc lt,hex1a
1859ldk $r1,'a'-10
1860hex1a: add $r0,$r0,$r1
1861jmp emit
1862
1863####### FT900 ####################################################
1864
1865header "digitalwrite",digitalWrite /* ( val pin -- ) */
1866ldi $r1,$r27,0
1867
1868tst $r0,0x20
1869jmpc nz,1f
1870tst $r0,0x40
1871jmpc nz,2f
1872
1873or $r0,$r0,1<<5 /* $r0 is the bitfield spec for bins */
1874
1875ldl $r1,$r1,$r0
1876bins $r20,$r20,$r1
1877sta 0x10084,$r20
1878_2drop
1879return
1880
18811: /* For GPIO32-63, $r0 is *already* bitfield spec! */
1882ldl $r1,$r1,$r0
1883bins $r21,$r21,$r1
1884sta 0x10088,$r21
1885_2drop
1886return
1887
18882: /* For GPIO64+, flip r0 bits 5+6 */
1889xor $r0,$r0,3<<5 /* $r0 is the bitfield spec for bins */
1890ldl $r1,$r1,$r0
1891bins $r22,$r22,$r1
1892sta 0x1008c,$r22
1893_2drop
1894return
1895
1896header "digitalread",digitalRead /* ( pin -- val ) */
1897tst $r0,0x60
1898jmpc nz,1f
1899
1900or $r0,$r0,1<<5 /* $r0 is the bitfield spec for bexts */
1901lda $r1,0x10084
1902bexts $r0,$r1,$r0
1903return
1904
19051: tst $r0,0x40
1906jmpc nz,2f
1907/* For GPIO32-63, $r0 is *already* bitfield spec! */
1908lda $r1,0x10088
1909bexts $r0,$r1,$r0
1910return
1911
19122: /* For GPIO64+, flip r0 bits 5+6 */
1913xor $r0,$r0,0x60 /* $r0 is the bitfield spec for bexts */
1914lda $r1,0x1008c
1915bexts $r0,$r1,$r0
1916return
1917
1918
1919fheader "streamin" # ( dst ioddr n -- )
1920ldi $r1,$r27,0
1921ldi $r2,$r27,4
1922streamin.l $r2,$r1,$r0
1923ldi $r0,$r27,8
1924add $r27,$r27,12
1925return
1926
1927fheader "streamin.b" # ( dst ioddr n -- )
1928ldi $r1,$r27,0
1929ldi $r2,$r27,4
1930streamin.b $r2,$r1,$r0
1931ldi $r0,$r27,8
1932add $r27,$r27,12
1933return
1934
1935fheader "streamout"
1936ldi $r1,$r27,0
1937ldi $r2,$r27,4
1938streamout.l $r2,$r1,$r0
1939ldi $r0,$r27,8
1940add $r27,$r27,12
1941return
1942
1943fheader "streamout.b"
1944ldi $r1,$r27,0
1945ldi $r2,$r27,4
1946streamout.b $r2,$r1,$r0
1947ldi $r0,$r27,8
1948add $r27,$r27,12
1949return
1950
1951header "flip",_flip
1952_r1_n
1953flip $r0,$r1,$r0
1954return
1955
1956####### PROGRAM MEMORY ###########################################
1957
1958pm_cold:
1959lpm $r1,magic
1960sta PM_UNLOCK,$r1
1961return
1962magic: .long 0x1337f7d1
1963
1964header "pm!", pm_store
1965ldi $r1,$r27,0
1966sta PM_ADDR,$r0
1967sta PM_DATA,$r1
1968_2drop
1969return
1970
1971header "pm@", pm_fetch
1972lpmi $r0,$r0,0
1973return
1974
1975header "pmc@", pm_c_fetch
1976lpmi.b $r0,$r0,0
1977return
1978
1979fheader "words"
1980call false
1981
1982words_a:
1983call cr
1984call dupe
1985ashl $r0,$r0,2
1986ldi $r0,$r0,searchlist
1987ldi $r0,$r0,4
1988jmp words_2
1989
1990words_0:
1991call dupe
1992lpmi $r1,$r0,0
1993add $r0,$r0,4
1994
1995# was once useful to mark immediate words with $...
1996# tst $r1,1
1997# jmpc z,emitword
1998# lit '$'
1999# call emit
2000jmp emitword
2001words_1:
2002call emit
2003add $r0,$r0,1
2004emitword:
2005call dupe
2006lpmi.b $r0,$r0,0
2007cmp $r0,0
2008jmpc nz,words_1
2009call space
2010call two_drop
2011
2012lpmi $r0,$r0,0
2013ldk $r1,0x3ffff
2014ashl $r1,$r1,2
2015and $r0,$r0,$r1
2016words_2:
2017cmp $r0,0
2018jmpc nz,words_0
2019
2020call drop
2021
2022add $r0,$r0,1
2023lda $r1,nsearch
2024cmp $r0,$r1
2025jmpc lt,words_a
2026jmp drop
2027
2028# DEFER! ( xt2 xt1 -- ) CORE-EXT
2029#
2030# Set the word xt1 to execute xt2.
2031#
2032header "defer!",defer_store
2033call swap
2034lshr $r0,$r0,2
2035lpm $r1,_template_jmp
2036or $r0,$r0,$r1
2037call swap
2038
2039jmp pm_store
2040
2041####### SEARCH ###################################################
2042
2043iheader "ctx",internal_context
2044lit context_0
2045lit context_1-context_0
2046return
2047
2048iheader "_wl",_wl
2049lit wordlists
2050return
2051
2052header "forth-wordlist",forth_wordlist
2053lit forth
2054return
2055
2056header "internal-wordlist",internal_wordlist
2057lit internal
2058return
2059
2060header "get-order",get_order
2061_dup
2062lda $r0,nsearch
2063ashl $r1,$r0,2
2064sub $r27,$r27,$r1
2065ldk $r2,searchlist
2066memcpy.l $r27,$r2,$r1
2067return
2068
2069header "set-order",set_order
2070sta nsearch,$r0
2071ashl $r1,$r0,2
2072ldk $r2,searchlist
2073memcpy $r2,$r27,$r1
2074add $r27,$r27,$r1
2075jmp drop
2076
2077header "get-current",get_current
2078_dup
2079lda $r0,cwl
2080return
2081
2082header "set-current",set_current
2083sta cwl,$r0
2084jmp drop
2085
2086header "definitions",definitions
2087lda $r1,searchlist
2088sta cwl,$r1
2089return
2090
2091header "search-wordlist",search_wordlist
2092
2093move $r9,$r0
2094_drop
2095
2096move $r3,$r0
2097ldk $r1,aname
2098add $r1,$r1,$r0
2099sti $r1,0,$r25
2100
2101ldk $r2,aname
2102ldi $r1,$r27,0
2103memcpy.b $r2,$r1,$r0
2104
2105call lower_aname
2106
2107call lookup
2108cmp $r9,0
2109jmpc nz,search_wordlist_1
2110call two_drop
2111jmp false
2112
2113search_wordlist_1:
2114and $r1,$r1,~3
2115sti $r27,0,$r1
2116lpmi $r0,$r9,0
2117and $r0,$r0,1 /* 0 -> -1, 1 -> 1 */
2118cmp $r0,1
2119jmpc z,search_wordlist_2
2120ldk $r0,-1
2121search_wordlist_2:
2122return
2123
2124header "source",source
2125_dup
2126lda $r0,sourceA
2127_dup
2128lda $r0,sourceC
2129return
2130
2131header "tosource",tosource
2132sta sourceC,$r0
2133call drop
2134sta sourceA,$r0
2135jmp drop
2136
2137fheader ">in"
2138lit _in
2139return
2140
2141fheader ">inwas"
2142lit _inwas
2143return
2144
2145####### FLOAT ####################################################
2146
2147fheader "fdup"
2148ldi $r2,$r26,0
2149fpush: # Push $r2 on the fp-stack
2150sub $r26,$r26,4
2151sti $r26,0,$r2
2152return
2153
2154fheader "fdrop"
2155add $r26,$r26,4
2156return
2157
2158fheader "fswap"
2159ldi $r1,$r26,0
2160exi $r1,$r26,4
2161sti $r26,0,$r1
2162return
2163
2164fheader "f0<"
2165_dup
2166ldi $r0,$r26,0
2167add $r26,$r26,4
2168bexts $r0,$r0,(1<<5)|31
2169return
2170
2171header "f<",f_less
2172_dup
2173ldi $r1,$r26,0
2174ldi $r0,$r26,4
2175add $r26,$r26,8
2176
2177call __cmpsf2_ # -1 0 1
2178ashr $r0,$r0,31 # 0 0 -1
2179return
2180
2181fheader "fabs"
2182ldi $r1,$r26,0
2183bins $r1,$r1,(1<<5)|31
2184sti $r26,0,$r1
2185return
2186
2187header "(fliteral)",_fliteral
2188pop $r1
2189lpmi $r2,$r1,0
2190add $r1,$r1,4
2191sub $r26,$r26,4
2192sti $r26,0,$r2
2193jmpi $r1
2194
2195header "fliteral",fliteral,1
2196lit _fliteral
2197call compile_comma
2198call sync
2199call f_from
2200call pm_comma
2201jmp sync
2202
2203fheader "fdepth"
2204call dupe
2205ldk $r0,FSTACK_TOP
2206sub $r0,$r0,$r26
2207ashr $r0,$r0,2
2208return
2209
2210header "s>f",s_to_f
2211call __floatsisf
2212_to_f:
2213sub $r26,$r26,4
2214sti $r26,0,$r0
2215jmp drop
2216
2217header "us>f",us_to_f
2218call __floatunsisf
2219jmp _to_f
2220
2221header "f>",f_from
2222call dupe
2223ldi $r0,$r26,0
2224add $r26,$r26,4
2225return
2226
2227header ">f",to_f
2228jmp _to_f
2229
2230header "fnegate",f_negate
2231ldi $r1,$r26,0
2232bins $r2,$r25,-512|(1<<5)|31 # r2 = 80000000
2233xor $r1,$r1,$r2
2234sti $r26,0,$r1
2235return
2236
2237header "f+",f_plus
2238push $r0
2239ldi $r1,$r26,0
2240ldi $r0,$r26,4
2241
2242call __addsf3
2243_f2: # handle result of 2-ary operator
2244add $r26,$r26,4
2245sti $r26,0,$r0
2246pop $r0
2247return
2248
2249header "f-",f_minus
2250push $r0
2251ldi $r1,$r26,0
2252ldi $r0,$r26,4
2253call __subsf3
2254jmp _f2
2255
2256header "f*",f_mul
2257push $r0
2258ldi $r1,$r26,0
2259ldi $r0,$r26,4
2260call __mulsf3
2261jmp _f2
2262
2263header "f/",f_div
2264push $r0
2265ldi $r1,$r26,0
2266ldi $r0,$r26,4
2267call __divsf3
2268jmp _f2
2269
2270.include "float.s"
2271
2272header "f>d",f_to_d
2273sub $r27,$r27,8
2274sti $r27,4,$r0
2275
2276ldi $cc,$r26,0
2277add $r26,$r26,4
2278
2279jmpx 31,$cc,0,0f
2280
2281call 0f
2282jmp d_negate
2283
22840:
2285ashl $r2,$cc,8 # mantissa left-justified in r2...
2286bins $r2,$r2,-512|(1 << 5)|31 # ...with implied bit set
2287bextu $r3,$cc,(8<<5)|23 # exponent in r3
2288
2289# exponent lo hi
2290# -------- -- --
2291# <127 0 0
2292# 127 m>>31 0
2293# ...
2294# 158 m>>0 0
2295# 159 m<<1 m>>31
2296# ...
2297# 189 m<<31 m>>1
2298# 190 -------- overflow --------
2299#
2300# So a little algebra gives three cases:
2301#
2302# exponent lo hi
2303# -------- -- --
2304# <127 0 0
2305# 127 .. 158 m>>(158-e) 0
2306# 159 .. 189 m<<(e-158) m>>(190-e)
2307# >=190 -------- overflow --------
2308
2309cmp $r3,127
2310jmpc gte,1f
2311ldk $r1,0 # lo
2312ldk $r0,0 # hi
2313jmp 3f
2314
23151: cmp $r3,158
2316jmpc gt,2f
2317
2318ldk $r4,158 #
2319sub $r4,$r4,$r3
2320lshr $r1,$r2,$r4 # lo
2321ldk $r0,0 # hi
2322jmp 3f
2323
23242: sub $r4,$r3,158
2325ashl $r1,$r2,$r4 # lo
2326ldk $r4,190
2327sub $r4,$r4,$r3
2328lshr $r0,$r2,$r4
23293:
2330sti $r27,0,$r1
2331return
2332
2333####### SYSTEM VARIABLES #########################################
2334
2335.section .bss
2336
2337.set ramhere,0
2338
2339.macro allot name size
2340.equ \name,ramhere
2341.set ramhere,ramhere+\size
2342.endm
2343
2344allot guardian,4 /* */
2345allot context_0,0
2346allot dp,4 /* RAM data pointer */
2347allot cp,4 /* Code pointer */
2348allot cwl,4 /* Compilation word list */
2349allot wordlists,4 /* All word lists */
2350allot nsearch,4 /* Number of word lists in searchlist */
2351allot searchlist,4*16 /* search list */
2352allot context_1,0
2353allot forth,8 /* Forth word list */
2354allot internal,8 /* Internal word list */
2355allot handler,4 /* exception handler */
2356allot aname,32 /* name buffer, used during dictionary search */
2357allot tib,256 /* terminal input buffer */
2358allot sourceA,4 /* tib+1 */
2359allot sourceC,4 #
2360allot _in,4 /* >IN */
2361allot _inwas,4 /* >IN at start of previous word */
2362allot recent,4 /* most recent CREATE */
2363allot thisxt,4 /* most recent xt */
2364allot tosmudge,4 /* smudge point, usually xt-4 */
2365allot leaves,4 /* chain of LEAVE pointers */
2366allot _source_id,4
2367allot _state,4
2368allot _base,4
2369allot _tethered,4
2370
2371__end:
2372.section .text
2373
2374####### OUTER INTERPRETER ########################################
2375
2376header "report",report /* ( u -- 0 ) describe error u */
2377jmp drop
2378
2379# QUIT implementation based on ANS A.9
2380
2381header "quit",quit
2382ldk $sp,0xfffc # XXX
2383
2384sta _source_id,$r25
2385
2386call left_bracket
2387
2388quit_0:
2389lit repl
2390call catch
2391cmp $r0,0
2392jmpc z,quit_ok
2393
2394call report
2395jmp quit
2396
2397repl:
2398lit tib
2399call dupe
2400lit 256
2401call accept
2402call tosource
2403
2404call space
2405
2406sta _in,$r25
2407jmp interpret
2408
2409quit_ok:
2410call drop
2411call space
2412lit 'o'
2413call emit
2414lit 'k'
2415call emit
2416call cr
2417jmp quit_0
2418
2419header "hook-number",hook_number
2420lit -13 /* undefined word ( ANS spec. section 9.3.5 ) */
2421call throw
2422
2423isvoid:
2424call nip
2425call do0cmp
2426jmpc z,1f
2427call two_drop
2428call hook_number
2429pop $r1
2430pop $r1
24311: return
2432
2433# consume1 ( caddr u -- caddr' u' )
2434# if string starts with $r2, bump character and return NZ
2435
2436consume1:
2437ldi $r3,$r27,0
2438ldi.b $r1,$r3,0
2439cmp.b $r2,$r1
2440jmpc z,1f
24410:
2442cmp $r0,$r0 # Set Z
2443return
24441:
2445cmp $r0,0
2446jmpc z,0b
2447sub $r0,$r0,1
2448add $r3,$r3,1
2449sti $r27,0,$r3
2450return
2451
2452doubleAlso2:
2453lit 0
2454lit 0
2455call two_swap
2456ldk $r2,'-'
2457call consume1
2458push $cc
2459call to_number
2460ldk $r2,'.'
2461call consume1
2462jmpc z,1f
2463call isvoid
2464pop $cc
2465callc nz,d_negate
2466lit two_literal
2467return
24681:
2469call isvoid
2470_drop
2471pop $cc
2472callc nz,negate
2473lit literal
2474return
2475
2476# Set BASE to $r2, call doubleAlso2, restore BASE
2477baseDoubleAlso2:
2478lda $r1,_base
2479push $r1
2480sta _base,$r2
2481lit doubleAlso2
2482call catch
2483pop $r1
2484sta _base,$r1
2485jmp throw
2486
2487doubleAlso1:
2488ldk $r2,'$'
2489call consume1
2490ldk $r2,16
2491jmpc nz,baseDoubleAlso2
2492
2493ldk $r2,'#'
2494call consume1
2495ldk $r2,10
2496jmpc nz,baseDoubleAlso2
2497
2498ldk $r2,'%'
2499call consume1
2500ldk $r2,2
2501jmpc nz,baseDoubleAlso2
2502
2503cmp $r0,3
2504jmpc nz,doubleAlso2
2505ldi $r1,$r27,0
2506ldi.b $r2,$r1,0
2507cmp $r2,'\''
2508jmpc nz,doubleAlso2
2509ldi.b $r2,$r1,2
2510cmp $r2,'\''
2511jmpc nz,doubleAlso2
2512
2513call drop
2514ldi.b $r0,$r0,1
2515lit literal
2516return
2517
2518doubleAlso:
2519call doubleAlso1
2520jmp drop
2521
2522doubleAlso_comma:
2523call doubleAlso1
2524jmp execute
2525
2526dispatch:
2527jmp execute # -1 0 non-immediate
2528jmp doubleAlso # 0 0 number
2529jmp execute # 1 0 immediate
2530
2531jmp compile_comma # -1 2 non-immediate
2532jmp doubleAlso_comma # 0 2 number
2533jmp execute # 1 2 immediate
2534
2535guardian:
2536.long 0x70617773
2537
2538header "interpret",interpret
2539lda $r1,_in
2540sta _inwas,$r1
2541call parse_name
2542cmp $r0,0
2543jmpc z,two_drop
2544
2545call sfind
2546lda $r1,_state
2547add $r0,$r0,$r1
2548ashl $r0,$r0,2
2549ldk $r1,(dispatch+4)
2550add $r0,$r0,$r1
2551call execute
2552
2553ldk $r1,DSTACK_TOP
2554cmp $r27,$r1
2555ldk $r1,-4 /* stack underflow */
2556jmpc a,throw_r1
2557jmp interpret
2558
2559lda $r1,0
2560lpm $r2,guardian
2561cmp $r1,$r2
2562ldk $r1,-9 /* memory error */
2563jmpc nz,throw_r1
2564
2565jmp interpret
2566
2567/*
2568* PARSE-NAME ( <spaces>name -- c-addr u )
2569
2570* Skip leading spaces and parse name delimited by a space. c-addr
2571* is the address within the input buffer and u is the length of the
2572* selected string. If the parse area is empty, the resulting string has
2573* a zero length.
2574*/
2575
2576header "parse-name",parse_name
2577call _skipspaces
2578_dup
2579lda $r1,_in
2580lda $r0,sourceA
2581add $r0,$r0,$r1
2582call _parse_word
2583_dup
2584move $r0,$r3
2585return
2586
2587_skipspaces:
2588lda $r1,_in
2589lda $r4,sourceC
2590_skipspaces_0:
2591cmp $r1,$r4
2592jmpc z,_skipspaces_finish
2593lda $r3,sourceA
2594add $r3,$r3,$r1
2595ldi.b $r2,$r3,0
2596cmp $r2,' '
2597jmpc a,_skipspaces_finish
2598add $r1,$r1,1
2599jmp _skipspaces_0
2600_skipspaces_finish:
2601sta _in,$r1
2602return
2603
2604_parse_word:
2605/* Scan the current input buffer for a word
2606* $r3 is length, and word copied into aname
2607* if end of buffer, $r3 is zero.
2608*/
2609
2610call _skipspaces
2611
2612ldk $r3,0 /* Current ptr into aname */
2613ldk $r2,aname
2614memset $r2,$r25,32
2615lda $r4,sourceC
2616
2617_parse_word_loop:
2618lda $r1,_in
2619cmp $r1,$r4
2620jmpc z,_parse_word_finish
2621
2622lda $r5,sourceA
2623add $r5,$r5,$r1
2624ldi.b $r2,$r5,0
2625add $r1,$r1,1
2626sta _in,$r1
2627
2628cmp $r2,' '
2629jmpc be,_parse_word_finish
2630
2631/* append non-blank to aname */
2632sti.b $r3,aname,$r2
2633add $r3,$r3,1
2634jmp _parse_word_loop
2635
2636_parse_word_finish:
2637return
2638
2639/*
2640
2641SFIND
2642( c-addr u -- c-addr u 0 | xt 1 | xt -1 )
2643
2644Find the definition named in the string at c-addr. If the
2645definition is not found, return c-addr and zero. If the definition
2646is found, return its execution token xt. If the definition is
2647immediate, also return one (1), otherwise also return minus-one
2648(-1).
2649
2650*/
2651header "sfind",sfind
2652
2653move $r3,$r0
2654ldk $r1,aname
2655add $r1,$r1,$r0
2656sti $r1,0,$r25
2657
2658ldk $r2,aname
2659ldi $r1,$r27,0
2660memcpy.b $r2,$r1,$r0
2661
2662call lower_aname
2663
2664ldk $r2,0 /* $r2 counts through search order */
2665sfind_0:
2666push $r2
2667push $r3
2668ashl $r2,$r2,2
2669ldi $r9,$r2,searchlist
2670call lookup
2671pop $r3
2672pop $r2
2673cmp $r9,0
2674jmpc nz,sfind_1
2675
2676add $r2,$r2,1 /* try next wordlist */
2677lda $r4,nsearch
2678cmp $r2,$r4
2679jmpc lt,sfind_0
2680
2681jmp false
2682sfind_1:
2683and $r1,$r1,~3
2684sti $r27,0,$r1
2685lpmi $r0,$r9,0
2686and $r0,$r0,1 /* 0 -> -1, 1 -> 1 */
2687cmp $r0,1
2688jmpc z,sfind_2
2689ldk $r0,-1
2690sfind_2:
2691return
2692
2693lookup:
2694/* On entry: */
2695/* $r9 word list to search */
2696/* a word of length $r3 at aname, 0x00 padded */
2697/* On exit: */
2698/* $r13 padded length (in bytes) */
2699/* $r9 found word's link, or zero */
2700/* $r1 found word's xt (if $r9 is nonzero) */
2701
2702add $r13,$r3,4
2703and $r13,$r13,~3
2704
2705lda $r1,aname+0
2706lda $r2,aname+4
2707lda $r3,aname+8
2708lda $r4,aname+12
2709lda $r5,aname+16
2710lda $r6,aname+20
2711lda $r7,aname+24
2712lda $r8,aname+28
2713
2714ldi $r9,$r9,4
2715ldk $r15,0x3ffff
2716ashl $r15,$r15,2
2717
2718/* $r12 is comparison code */
2719mul $r14,$r13,3 /* 3 instructions for each compare */
2720ldk $r12,compare_0
2721sub $r12,$r12,$r14
2722jmp lookup_1
2723nomatch:
2724lpmi $r9,$r9,0
2725and $r9,$r9,$r15
2726lookup_1:
2727cmp $r9,0
2728jmpic nz,$r12
2729endsearch:
2730return
2731
2732compare_8:
2733lpmi $r10,$r9,32
2734cmp $r10,$r8
2735jmpc nz,nomatch
2736compare_7:
2737lpmi $r10,$r9,28
2738cmp $r10,$r7
2739jmpc nz,nomatch
2740compare_6:
2741lpmi $r10,$r9,24
2742cmp $r10,$r6
2743jmpc nz,nomatch
2744compare_5:
2745lpmi $r10,$r9,20
2746cmp $r10,$r5
2747jmpc nz,nomatch
2748compare_4:
2749lpmi $r10,$r9,16
2750cmp $r10,$r4
2751jmpc nz,nomatch
2752compare_3:
2753lpmi $r10,$r9,12
2754cmp $r10,$r3
2755jmpc nz,nomatch
2756compare_2:
2757lpmi $r10,$r9,8
2758cmp $r10,$r2
2759jmpc nz,nomatch
2760compare_1:
2761lpmi $r10,$r9,4
2762cmp $r10,$r1
2763jmpc nz,nomatch
2764compare_0:
2765add $r1,$r9,4
2766add $r1,$r1,$r13
2767jmp endsearch
2768
2769# Save the current pointers to PM so that they will be restored at reboot.
2770# Append active RAM to the end of PM, so that it will be restored
2771# Return the end of the complete PM region
2772
2773header "commit",commit /* ( -- pmend ) */
2774call pmhere
2775lit saved_pmdp
2776call pm_store
2777
2778call dupe
2779lda $r0,dp
2780lit saved_dp
2781call pm_store
2782
2783call dupe
2784lda $r0,cp
2785sta PM_ADDR,$r0
2786
2787ldk $r0,PM_DATA
2788ldk $r1,0
2789lda $r2,dp
2790
2791streamout $r0,$r1,$r2
2792
2793lda $r0,cp
2794add $r0,$r0,$r2
2795
2796return
2797
2798header "pmhere",pmhere
2799call dupe
2800lda $r0,cp
2801return
2802
2803header "int-caller",int_caller
2804ldi $r1,$sp,20*4
2805jmp push_r1
2806
2807# From Hacker's Delight, 2nd ed. p.195-196
2808#
2809# unsigned divlu2(unsigned u1, unsigned u0, unsigned v,
2810# unsigned *r) {
2811# const unsigned b = 65536; // Number base (16 bits).
2812# unsigned un1, un0, // Norm. dividend LSD's.
2813# vn1, vn0, // Norm. divisor digits.
2814# q1, q0, // Quotient digits.
2815# un32, un21, un10,// Dividend digit pairs.
2816# rhat; // A remainder.
2817# int s; // Shift amount for norm.
2818#
2819# if (u1 >= v) { // If overflow, set rem.
2820# if (r != NULL) // to an impossible value,
2821# *r = 0xFFFFFFFF; // and return the largest
2822# return 0xFFFFFFFF;} // possible quotient.
2823#
2824# s = nlz(v); // 0 <= s <= 31.
2825# v = v << s; // Normalize divisor.
2826# vn1 = v >> 16; // Break divisor up into
2827# vn0 = v & 0xFFFF; // two 16-bit digits.
2828#
2829# un32 = (u1 << s) | (u0 >> 32 - s) & (-s >> 31);
2830# un10 = u0 << s; // Shift dividend left.
2831#
2832# un1 = un10 >> 16; // Break right half of
2833# un0 = un10 & 0xFFFF; // dividend into two digits.
2834#
2835# q1 = un32/vn1; // Compute the first
2836# rhat = un32 - q1*vn1; // quotient digit, q1.
2837# again1:
2838# if (q1 >= b || q1*vn0 > b*rhat + un1) {
2839# q1 = q1 - 1;
2840# rhat = rhat + vn1;
2841# if (rhat < b) goto again1;}
2842#
2843# un21 = un32*b + un1 - q1*v; // Multiply and subtract.
2844#
2845# q0 = un21/vn1; // Compute the second
2846# rhat = un21 - q0*vn1; // quotient digit, q0.
2847# again2:
2848# if (q0 >= b || q0*vn0 > b*rhat + un0) {
2849# q0 = q0 - 1;
2850# rhat = rhat + vn1;
2851# if (rhat < b) goto again2;}
2852#
2853# if (r != NULL) // If remainder is wanted,
2854# *r = (un21*b + un0 - q0*v) >> s; // return it.
2855# return q1*b + q0;
2856# }
2857
2858# un1 r1
2859# un0 r2 also un10
2860# vn1 r3
2861# vn0 r4
2862# q1 r5
2863# q0 r6
2864# un32 r7
2865# un21 r8
2866# r9
2867# rhat r10
2868# s r11
2869
2870header "um/mod",u_m_slash_mod
2871ldi $r1,$r27,0 # v:r0 u1:r1 r0:r2
2872ldi $r2,$r27,4
2873add $r27,$r27,4
2874
2875move $r9,$r0
2876nlz $r9,$r12 # 0 <= s <= 31.
2877ashl $r0,$r0,$r9 # Normalize divisor.
2878lshr $r3,$r0,16 # Break divisor up into
2879bins $r4,$r0,16 # two 16-bit digits.
2880
2881cmp $r9,0
2882jmpc nz,1f
2883move $r7,$r1
2884jmp 2f
28851:
2886ashl $r7,$r1,$r9
2887ldk $r12,32
2888sub $r12,$r12,$r9
2889lshr $r12,$r2,$r12
2890or $r7,$r7,$r12
2891ashl $r2,$r2,$r9
28922:
2893
2894lshr $r1,$r2,16 # Break right half of
2895bins $r2,$r2,16 # dividend into two digits.
2896
2897udiv $r5,$r7,$r3 # Compute the first
2898mul $r12,$r5,$r3
2899sub $r10,$r7,$r12 # quotient digit, q1.
2900
2901again1:
2902btst $r5,16
2903jmpc nz,1f
2904# q1*vn0 > b*rhat + un1
2905mul $cc,$r5,$r4
2906ashl $r12,$r10,16
2907add $r12,$r12,$r1
2908cmp $cc,$r12
2909jmpc be,2f
29101:
2911sub $r5,$r5,1 # q1 = q1 - 1;
2912add $r10,$r10,$r3 # rhat = rhat + vn1;
2913btst $r10,16
2914jmpc z,again1
29152:
2916
2917# un21 = un32*b + un1 - q1*v; // Multiply and subtract.
2918#
2919# q0 = un21/vn1; // Compute the second
2920# rhat = un21 - q0*vn1; // quotient digit, q0.
2921
2922ashl $r8,$r7,16 # Multiply and subtract.
2923add $r8,$r8,$r1 # un21 = un32*b + un1 - q1*v;
2924mul $r12,$r5,$r0
2925sub $r8,$r8,$r12
2926
2927udiv $r6,$r8,$r3 # Compute the second
2928mul $r12,$r6,$r3
2929sub $r10,$r8,$r12 # quotient digit, q0.
2930
2931again2:
2932btst $r6,16
2933jmpc nz,1f
2934# q1*vn0 > b*rhat + un1
2935mul $cc,$r6,$r4
2936ashl $r12,$r10,16
2937add $r12,$r12,$r2
2938cmp $cc,$r12
2939jmpc be,2f
29401:
2941sub $r6,$r6,1 # q0 = q0 - 1;
2942add $r10,$r10,$r3 # rhat = rhat + vn1;
2943btst $r10,16
2944jmpc z,again2
29452:
2946# *r = (un21*b + un0 - q0*v) >> s;
2947ashl $r8,$r8,16
2948add $r8,$r8,$r2
2949mul $r12,$r6,$r0
2950sub $r8,$r8,$r12
2951lshr $r8,$r8,$r9
2952sti $r27,0,$r8
2953
2954# return q1*b + q0; # quotient
2955ashl $r0,$r5,16
2956add $r0,$r0,$r6
2957return
2958
2959####### BOOT #####################################################
2960
2961h80000000: .long 0x80000000
2962
2963codestart:
2964ldk $sp,__RAMSIZE-4
2965ldk $r26,FSTACK_TOP
2966ldk $r27,DSTACK_TOP
2967
2968ldk $r20,0 /* GPIO shadows */
2969ldk $r21,0
2970ldk $r22,0
2971ldk $r25,0 /* constant 0 */
2972
2973.if SIMULATOR==0
2974ldk $r1,0x80
2975sta.b sys_regmsc0cfg_b3,$r1
2976
2977/* Enable the RTC as soon as possible */
2978/* Write 1 to RTC_EN in RTC_CCR */
2979ldk $r1,(1 << 2)
2980sta 0x1028c,$r1
2981
2982/* lpm $r1,h80000000 */
2983/* sta 0x10018,$r1 */
2984.endif
2985
2986lpm $r1,saved_pmdp
2987sta cp,$r1
2988lpm $r2,saved_dp
2989sta dp,$r2
2990
2991/* copy all of RAM from pm[cp to cp+dp] */
2992ldk $r0,0 /* dest */
2993ramloader:
2994lpmi $r3,$r1,0
2995sti $r0,0,$r3
2996add $r0,$r0,4
2997add $r1,$r1,4
2998cmp $r0,$r2
2999jmpc be,ramloader
3000
3001.if SIMULATOR==0
3002call uart.start
3003.endif
3004
3005sta _tethered,$r25
3006call decimal
3007call left_bracket
3008call pm_cold
3009
3010ldk $r0,emit
3011sta PM_ADDR,$r0
3012lpm $r0,default_emit
3013sta PM_DATA,$r0
3014
3015call cr
3016lit 80
3017banner:
3018lit '-'
3019call emit
3020add $r0,$r0,-1
3021cmp $r0,0
3022jmpc nz,banner
3023call drop
3024
3025lpm $r1,coldname /* find a word named 'cold' */
3026sta 0,$r1
3027
3028lit 0
3029lit 4
3030call sfind
3031
3032cmp $r0,0
3033call drop
3034jmpc z,no_cold
3035
3036call execute
3037call cr
3038
3039jmp quit
3040
3041no_cold:
3042call cr /* empty banner */
3043call two_drop
3044jmp quit
3045
3046coldname:
3047.ascii "cold"
3048
3049# RAM is initialized from PM as follows:
3050# cp is loaded from saved_pmdp
3051# dp is loaded from saved_dp
3052# Then RAM is copied from pm[cp .. cp+dp]
3053
3054saved_pmdp: .long endcode
3055saved_dp: .long ramhere
3056
3057
3058endcode:
3059.long 0x70617773 /* guardian */
3060.long ramhere /* dp */
3061.long endcode /* cp */
3062.long forth /* cwl */
3063.long forth /* word lists */
3064.long 2 /* nsearch */
3065.long forth /* searchlist */
3066.long internal
3067.long 0
3068.long 0
3069.long 0
3070.long 0
3071.long 0
3072.long 0
3073.long 0
3074.long 0
3075.long 0
3076.long 0
3077.long 0
3078.long 0
3079.long 0
3080.long 0
3081
3082.long internal /* forth word list #0 */
3083.long forth_link /* forth word list #4 */
3084.long 0 /* internal word list #0 */
3085.long internal_link /* internal word list #4 */
3086