Implementing figFORTH on SH3 assembler
Revisão | 98b1462b18e381bd047560e77e0c5cb9df01a094 (tree) |
---|---|
Hora | 2014-03-07 13:52:52 |
Autor | Joel Matthew Rees <reiisi@user...> |
Commiter | Joel Matthew Rees |
up to around (FIND)
@@ -63,6 +63,20 @@ ALL_BITS: .equ H'FFFFFFFF | ||
63 | 63 | ; ----------------------------- |
64 | 64 | |
65 | 65 | |
66 | +; r0 must be used for many intermediate values. | |
67 | +; r0 -- r7 are bank-switched on interrupt. | |
68 | +; r8 -- r15 are not bank-switched on interrupt. | |
69 | +; All registers have to be explicitly saved during a full task-switch, | |
70 | +; but the supervisor monitor code can keep a lot of context in the bank-switched part. | |
71 | + | |
72 | +; Registers that should be in r8 -- r15 are (as much as possible) | |
73 | +; * temporaries that we agree to explicitly save; | |
74 | +; * true globals (global contant tables, global library pointers, etc.); | |
75 | +; * and per-task globals that have no parallel in the supervisor, if there are any. | |
76 | +; * And the flow-of-control stack pointer, maybe. | |
77 | + | |
78 | +; For system calls, accessing the switched bank is not too hard. | |
79 | + | |
66 | 80 | ; FORTH tracks the call/return sequence in a separate stack from the parameters. |
67 | 81 | fRP: .reg r15 ; control/Return stack Pointer |
68 | 82 | fSP: .reg r7 ; parameter Stack Pointer |
@@ -114,3 +128,18 @@ _p\characteristic .equ $ | ||
114 | 128 | .endm |
115 | 129 | |
116 | 130 | |
131 | +; More as an example than to be actually used: | |
132 | + .macro fSAFECALL cfa | |
133 | + sts.l pr, @-fRP | |
134 | + mov.l imm\@, fW | |
135 | + jsr @fW | |
136 | + nop | |
137 | + bra exit\@ | |
138 | + nop | |
139 | +imm\@: | |
140 | + .data.l \cfa | |
141 | +exit\@: | |
142 | + lds.l @fRP+ | |
143 | + .endm | |
144 | + | |
145 | + |
@@ -3,13 +3,21 @@ | ||
3 | 3 | ; Expression evaluator definitions for fig-FORTH for SH-3 |
4 | 4 | ; Joel Matthew Rees, Hyougo Polytec Center |
5 | 5 | ; 2014.03.01 |
6 | + | |
6 | 7 | |
7 | - .include "context.inc" | |
8 | +; Monolithic, not separate assembly: | |
9 | +; context.inc must be included before this file. | |
10 | +; .include "context.inc" | |
11 | +; | |
12 | +; .section evaluator, code | |
8 | 13 | |
9 | - .section evaluator, code, locate=h'8c000000 | |
10 | 14 | |
11 | - | |
12 | -; I -- It's tempting to put it in a dedicated register, but don't optimize too early. | |
15 | +; It's tempting to put I in a dedicated register, | |
16 | +; but we don't want to optimize too early. | |
17 | +; | |
18 | +; I ( --- index ) ( limit index *** limit index ) | |
19 | +; Copy the loop index from the return stack. Synonym for R, here. | |
20 | +; | |
13 | 21 | HEADER I, xI |
14 | 22 | mov.l @fRP, r0 ; I (loop counter) |
15 | 23 | rts |
@@ -19,4 +27,3 @@ | ||
19 | 27 | |
20 | 28 | |
21 | 29 | |
22 | - .end |
@@ -0,0 +1,17 @@ | ||
1 | + .list ON, EXP | |
2 | + | |
3 | +; Initializations for fig-FORTH for SH-3 | |
4 | +; Joel Matthew Rees, Hyougo Polytec Center | |
5 | +; 2014.02.28 | |
6 | + | |
7 | + | |
8 | +; Monolithic, not separate assembly: | |
9 | +; context.inc must be included before this file. | |
10 | +; .include "context.inc" | |
11 | +; | |
12 | +; .section initialize, code | |
13 | + | |
14 | + | |
15 | + | |
16 | + | |
17 | + |
@@ -0,0 +1,27 @@ | ||
1 | + .list ON, EXP | |
2 | + | |
3 | +; Primitive (kernel) definitions for fig-FORTH for SH-3 | |
4 | +; Joel Matthew Rees, Hyougo Polytec Center | |
5 | +; 2014.02.28 | |
6 | + | |
7 | + .include "context.inc" | |
8 | + | |
9 | + .section initialize, code, locate=h'8c000000 | |
10 | +; For various reasons, including the above "locate" declaration, | |
11 | +; this will be assembled monolithically, rather than separately. | |
12 | +; Thus: | |
13 | +; | |
14 | + .include "initialize.inc" | |
15 | + .include "primitive.inc" | |
16 | + .include "parser.inc" | |
17 | + .include "evaluator.inc" | |
18 | + .include "symbol.inc" | |
19 | + | |
20 | + | |
21 | + | |
22 | + | |
23 | + | |
24 | + | |
25 | + | |
26 | + | |
27 | + .end | |
\ No newline at end of file |
@@ -3,25 +3,49 @@ | ||
3 | 3 | ; Parser definitions for fig-FORTH for SH-3 |
4 | 4 | ; Joel Matthew Rees, Hyougo Polytec Center |
5 | 5 | ; 2014.03.01 |
6 | + | |
6 | 7 | |
7 | - .include "context.inc" | |
8 | - | |
9 | - .section parser, code, locate=h'8c000000 | |
10 | - | |
11 | - | |
8 | +; Monolithic, not separate assembly: | |
9 | +; context.inc must be included before this file. | |
10 | +; .include "context.inc" | |
11 | +; | |
12 | +; .section parser, code | |
12 | 13 | |
13 | 14 | |
15 | +; DIGIT ( c base --- ff ) | |
16 | +; ( c base --- n tf ) | |
17 | +; Translate C in base, yielding a translation valid flag. If the | |
18 | +; translation is not valid in the specified base, only the false | |
19 | +; flag is returned. | |
20 | +; | |
14 | 21 | HEADER DIGIT, xDIGIT |
15 | - mov.l @fSP, r0 | |
16 | - add.l #-'0', r0 | |
22 | + mov.l @(NATURAL_SIZE,fSP), r0 ; 7ビット文字 | |
17 | 23 | mov.b #"0", r1 |
18 | - cmp/lt r1, r0 ; r0 < r1 | |
19 | - bt xDIGITno | |
20 | - sub.l r1, r0 | |
21 | -; mov.b #"9", | |
22 | - | |
24 | + cmp/ge r1, r0 ; character (r0) >= "0" | |
25 | + bf xDIGITno | |
26 | + add.l #-"0", r0 | |
27 | + mov.b #9, r1 | |
28 | + cmp/gt r1, r0 ; digit (r0) > 9 | |
29 | + bf xDIGITbase | |
30 | + mov.b #"A"-"0", r1 | |
31 | + cmp/ge r1, r0 ; was it between "9" and "A"? | |
32 | + bf xDIGITno | |
33 | + add.l #"9"-"A"+1, r0 | |
34 | +xDIGITbase: | |
35 | + mov.l @fSP, r1 | |
36 | + cmp/ge r1, r0 ; digit (r0) >= base | |
37 | + bt xDIGITno | |
38 | + mov.l r0, @(NATURAL_SIZE,fSP) | |
39 | + mov.b #-1, r0 ; store the converted digit | |
40 | + rts | |
41 | + mov.l r0, @fSP ; set the flag on our way out | |
42 | +; | |
43 | +xDIGITno: | |
44 | + mov.b #0, r0 | |
45 | + add.l #NATURAL_SIZE, fSP | |
46 | + rts | |
47 | + mov.l r0, @fSP ; set the flag on our way out | |
23 | 48 | |
24 | 49 | |
25 | 50 | |
26 | 51 | |
27 | - .end |
@@ -0,0 +1,168 @@ | ||
1 | + .list ON, EXP | |
2 | + | |
3 | +; Primitive (kernel) definitions for fig-FORTH for SH-3 | |
4 | +; Joel Matthew Rees, Hyougo Polytec Center | |
5 | +; 2014.02.28 | |
6 | + | |
7 | + | |
8 | +; Monolithic, not separate assembly: | |
9 | +; context.inc must be included before this file. | |
10 | +; .include "context.inc" | |
11 | +; | |
12 | +; .section primitives, code, align=4 | |
13 | + | |
14 | + | |
15 | +; ***** Need to load the return register with something safe. | |
16 | +; Probably the call to next from warm? | |
17 | +; | |
18 | +; Anyway, this is the inner interpreter. | |
19 | +; | |
20 | +next: | |
21 | + mov.l @fIP+, fW ; get the pointer to the next definition to execute | |
22 | + mov.l @fW, r0 ; get the defitinition characteristic | |
23 | + jsr @r0 | |
24 | +; 3 cycles to get back to the top of the loop. | |
25 | + nop | |
26 | + bra next | |
27 | + nop | |
28 | +; Note that, since jumps to absolute addresses have limits on constant-width instruction sets, | |
29 | +; using the subroutine call mode for the virtual machine is not as much a penalty as it might seem. | |
30 | +; It also has the advantage of being more compatible with more conventional code. | |
31 | +; Ways to make an absolute jump work might include | |
32 | +; * the address of next in a table of constants (and reserving a register for the table base), or | |
33 | +; * reserving a register for the address of next. | |
34 | + | |
35 | + | |
36 | +; LIT ( --- n ) C | |
37 | +; Push the following word from the instruction stream as a | |
38 | +; literal, or immediate value. | |
39 | +; | |
40 | + HEADER LIT, LIT | |
41 | + mov.l @fIP+, r0 | |
42 | + mov.l r0, @-fSP | |
43 | + rts | |
44 | + nop | |
45 | + | |
46 | + | |
47 | +; "character" (byte or word) literal doesn't work on SH3 | |
48 | +; It'll cause alignment problems. | |
49 | + | |
50 | + | |
51 | +; EXECUTE ( adr --- ) C | |
52 | +; Jump to address on stack. Used by the "outer" interpreter to | |
53 | +; interactively invoke routines. (Not compile-only in fig.) | |
54 | +; | |
55 | + HEADER EXECUTE, EXECUTE | |
56 | + mov.l @fSP+, fW | |
57 | + mov.l @fW, r0 | |
58 | + jmp @r0 ; borrow the return there | |
59 | + nop | |
60 | + | |
61 | + | |
62 | +; BRANCH ( --- ) C | |
63 | +; Add the following word from the instruction stream to the | |
64 | +; instruction pointer (Y++). Causes a program branch. | |
65 | +; | |
66 | + HEADER BRANCH, BRANCH | |
67 | + mov.l @fIP+, r0 | |
68 | +BRANCHgo: | |
69 | + add.l r0, fIP | |
70 | + rts | |
71 | + nop | |
72 | + | |
73 | + | |
74 | +; 0BRANCH ( f --- ) C | |
75 | +; BRANCH if flag is zero. | |
76 | +; | |
77 | + HEADER 0BRANCH, ZBRANCH | |
78 | + mov.l @fSP+, r0 | |
79 | + cmp/eq #0, r0 | |
80 | + bt/s BRANCHgo | |
81 | + mov.l @fIP+, r0 | |
82 | + rts | |
83 | + nop | |
84 | + | |
85 | + | |
86 | +; fig-FORTH puts temporaries on the control stack. I prefer a third stack. | |
87 | +; But if we put I in registers, (DO) is affected. | |
88 | +; One might put I and the loop limit in, say, r8 and r9, | |
89 | +; but then they must be saved and restored, | |
90 | +; and interrupts have to avoid r8 and r9 or save them. | |
91 | +; | |
92 | +; Note: fig-FORTH +LOOP has an un-signed loop counter, but a signed increment. | |
93 | +; (JMR: but the increment is signed!) | |
94 | + | |
95 | + | |
96 | +; (LOOP) ( --- ) ( limit index *** limit index+1) C | |
97 | +; ( limit index *** ) | |
98 | +; Counting loop primitive. The counter and limit are the top two | |
99 | +; words on the return stack. If the updated index/counter does | |
100 | +; not exceed the limit, a branch occurs. If it does, the branch | |
101 | +; does not occur, and the index and limit are dropped from the | |
102 | +; return stack. | |
103 | +; | |
104 | + HEADER (LOOP), xLOOP | |
105 | + mov.l @fRP, r0 ; I (loop counter) | |
106 | + add.l #1, r0 | |
107 | + mov.l r0, @fRP ; update I | |
108 | + mov.l @(NATURAL_SIZE,fRP), r1 ; limit | |
109 | + cmp/ge r1, r0 ; r0 >= r1 ? | |
110 | + bf/s BRANCHgo ; not yet | |
111 | + mov.l @fIP+, r0 | |
112 | + rts | |
113 | + add.l #2*NATURAL_SIZE, fRP | |
114 | + | |
115 | + | |
116 | +; (+LOOP) ( n --- ) ( limit index *** limit index+n ) C | |
117 | +; ( limit index *** ) | |
118 | +; Loop with a variable increment. Terminates when the index | |
119 | +; crosses the boundary from one below the limit to the limit. A | |
120 | +; positive n will cause termination if the result index equals the | |
121 | +; limit. A negative n must cause the index to become less than | |
122 | +; the limit to cause loop termination. | |
123 | +; | |
124 | + HEADER (+LOOP), xPLOOP | |
125 | + mov.l @fSP+, r1 ; increment | |
126 | + mov.l @fRP, r0 ; I (loop counter) | |
127 | + add.l r1, r0 | |
128 | + mov.l r0, @fRP ; update I | |
129 | + shal r1 ; increment negative or positive? | |
130 | + bt/s xPLOOPminus | |
131 | + mov.l @(NATURAL_SIZE,fRP), r1 ; limit | |
132 | +; | |
133 | +; Stealing too much code would cost more than it would save. | |
134 | +xPLOOPplus: | |
135 | + cmp/ge r0, r1 ; limit (r1) >= counter (I=r0) ? | |
136 | + bf/s BRANCHgo ; not yet | |
137 | + mov.l @fIP+, r0 ; grab offset and bump fIP before we go | |
138 | + rts | |
139 | + add.l #2*NATURAL_SIZE, fRP ; drop I and limit before we return | |
140 | +; | |
141 | +xPLOOPminus: | |
142 | + cmp/ge r0, r1 ; limit (r1) >= counter (I=r0) ? | |
143 | + bt/s BRANCHgo ; not yet | |
144 | + mov.l @fIP+, r0 ; grab offset and bump fIP before we go | |
145 | + rts | |
146 | + add.l #2*NATURAL_SIZE, fRP ; drop I and limit before we return | |
147 | + | |
148 | + | |
149 | +; Putting I and limit in registers would require (DO) to save the registers first | |
150 | +; and it would require LOOP and +LOOP to restore the registers on exit. | |
151 | +; That would cost more than it would save. | |
152 | +; | |
153 | +; (DO) ( limit index --- ) ( *** limit index ) | |
154 | +; Move the loop parameters to the return stack. Synonym for D>R, here. | |
155 | +; | |
156 | + HEADER (DO), xDO | |
157 | + mov.l @fSP+, r0 | |
158 | + mov.l @fSP+, r1 | |
159 | + add.l #-2*NATURAL_SIZE, fRP | |
160 | + mov.l r1, @(NATURAL_SIZE,fRP) | |
161 | + mov.l r0, @fRP | |
162 | + rts | |
163 | + | |
164 | + | |
165 | + | |
166 | + | |
167 | + | |
168 | + |
@@ -4,22 +4,39 @@ | ||
4 | 4 | ; Joel Matthew Rees, Hyougo Polytec Center |
5 | 5 | ; 2014.02.28 |
6 | 6 | |
7 | - .include "context.inc" | |
8 | 7 | |
9 | - .section kernel, code, locate=h'8c000000 | |
8 | +; Monolithic, not separate assembly: | |
9 | +; context.inc must be included before this file. | |
10 | +; .include "context.inc" | |
11 | +; | |
12 | +; .section primitives, code, align=4 | |
13 | + | |
10 | 14 | |
11 | 15 | ; ***** Need to load the return register with something safe. |
12 | 16 | ; Probably the call to next from warm? |
13 | - | |
17 | +; | |
18 | +; Anyway, this is the inner interpreter. | |
19 | +; | |
14 | 20 | next: |
15 | 21 | mov.l @fIP+, fW ; get the pointer to the next definition to execute |
16 | 22 | mov.l @fW, r0 ; get the defitinition characteristic |
17 | 23 | jsr @r0 |
18 | - nop | |
24 | +; 3 cycles to get back to the top of the loop. | |
25 | + nop | |
19 | 26 | bra next |
20 | 27 | nop |
28 | +; Note that, since jumps to absolute addresses have limits on constant-width instruction sets, | |
29 | +; using the subroutine call mode for the virtual machine is not as much a penalty as it might seem. | |
30 | +; It also has the advantage of being more compatible with more conventional code. | |
31 | +; Ways to make an absolute jump work might include | |
32 | +; * the address of next in a table of constants (and reserving a register for the table base), or | |
33 | +; * reserving a register for the address of next. | |
21 | 34 | |
22 | 35 | |
36 | +; LIT ( --- n ) C | |
37 | +; Push the following word from the instruction stream as a | |
38 | +; literal, or immediate value. | |
39 | +; | |
23 | 40 | HEADER LIT, LIT |
24 | 41 | mov.l @fIP+, r0 |
25 | 42 | mov.l r0, @-fSP |
@@ -31,6 +48,10 @@ next: | ||
31 | 48 | ; It'll cause alignment problems. |
32 | 49 | |
33 | 50 | |
51 | +; EXECUTE ( adr --- ) C | |
52 | +; Jump to address on stack. Used by the "outer" interpreter to | |
53 | +; interactively invoke routines. (Not compile-only in fig.) | |
54 | +; | |
34 | 55 | HEADER EXECUTE, EXECUTE |
35 | 56 | mov.l @fSP+, fW |
36 | 57 | mov.l @fW, r0 |
@@ -38,6 +59,10 @@ next: | ||
38 | 59 | nop |
39 | 60 | |
40 | 61 | |
62 | +; BRANCH ( --- ) C | |
63 | +; Add the following word from the instruction stream to the | |
64 | +; instruction pointer (Y++). Causes a program branch. | |
65 | +; | |
41 | 66 | HEADER BRANCH, BRANCH |
42 | 67 | mov.l @fIP+, r0 |
43 | 68 | BRANCHgo: |
@@ -46,6 +71,9 @@ BRANCHgo: | ||
46 | 71 | nop |
47 | 72 | |
48 | 73 | |
74 | +; 0BRANCH ( f --- ) C | |
75 | +; BRANCH if flag is zero. | |
76 | +; | |
49 | 77 | HEADER 0BRANCH, ZBRANCH |
50 | 78 | mov.l @fSP+, r0 |
51 | 79 | cmp/eq #0, r0 |
@@ -55,6 +83,24 @@ BRANCHgo: | ||
55 | 83 | nop |
56 | 84 | |
57 | 85 | |
86 | +; fig-FORTH puts temporaries on the control stack. I prefer a third stack. | |
87 | +; But if we put I in registers, (DO) is affected. | |
88 | +; One might put I and the loop limit in, say, r8 and r9, | |
89 | +; but then they must be saved and restored, | |
90 | +; and interrupts have to avoid r8 and r9 or save them. | |
91 | +; | |
92 | +; Note: fig-FORTH +LOOP has an un-signed loop counter, but a signed increment. | |
93 | +; (JMR: but the increment is signed!) | |
94 | + | |
95 | + | |
96 | +; (LOOP) ( --- ) ( limit index *** limit index+1) C | |
97 | +; ( limit index *** ) | |
98 | +; Counting loop primitive. The counter and limit are the top two | |
99 | +; words on the return stack. If the updated index/counter does | |
100 | +; not exceed the limit, a branch occurs. If it does, the branch | |
101 | +; does not occur, and the index and limit are dropped from the | |
102 | +; return stack. | |
103 | +; | |
58 | 104 | HEADER (LOOP), xLOOP |
59 | 105 | mov.l @fRP, r0 ; I (loop counter) |
60 | 106 | add.l #1, r0 |
@@ -67,44 +113,47 @@ BRANCHgo: | ||
67 | 113 | add.l #2*NATURAL_SIZE, fRP |
68 | 114 | |
69 | 115 | |
70 | -; fig-FORTH puts temporaries on the control stack. I prefer a third stack. | |
71 | -; But if we put I in registers, (DO) is affected. | |
72 | -; One might put I and the loop limit in, say, r8 and r9, | |
73 | -; but then they must be saved and restored, | |
74 | -; and interrupts have to avoid r8 and r9 or save them. | |
116 | +; (+LOOP) ( n --- ) ( limit index *** limit index+n ) C | |
117 | +; ( limit index *** ) | |
118 | +; Loop with a variable increment. Terminates when the index | |
119 | +; crosses the boundary from one below the limit to the limit. A | |
120 | +; positive n will cause termination if the result index equals the | |
121 | +; limit. A negative n must cause the index to become less than | |
122 | +; the limit to cause loop termination. | |
75 | 123 | ; |
76 | -; Note: fig-FORTH +LOOP has an un-signed loop counter. | |
77 | -; (JMR: but the increment is signed!) | |
78 | 124 | HEADER (+LOOP), xPLOOP |
79 | 125 | mov.l @fSP+, r1 ; increment |
80 | 126 | mov.l @fRP, r0 ; I (loop counter) |
81 | 127 | add.l r1, r0 |
82 | 128 | mov.l r0, @fRP ; update I |
83 | - shl r1, r0 ; increment negative or positive? | |
129 | + shal r1 ; increment negative or positive? | |
84 | 130 | bt/s xPLOOPminus |
85 | - mov.l @(NATURAL_SIZE,fRP), r0 ; limit | |
131 | + mov.l @(NATURAL_SIZE,fRP), r1 ; limit | |
86 | 132 | ; |
133 | +; Stealing too much code would cost more than it would save. | |
87 | 134 | xPLOOPplus: |
88 | - cmp/ge r1, r0 ; r0 >= r1 ? | |
135 | + cmp/ge r0, r1 ; limit (r1) >= counter (I=r0) ? | |
89 | 136 | bf/s BRANCHgo ; not yet |
90 | - mov.l @fIP+, r0 | |
137 | + mov.l @fIP+, r0 ; grab offset and bump fIP before we go | |
91 | 138 | rts |
92 | - add.l #2*NATURAL_SIZE, fRP | |
139 | + add.l #2*NATURAL_SIZE, fRP ; drop I and limit before we return | |
93 | 140 | ; |
94 | 141 | xPLOOPminus: |
95 | - cmp/lt r1, r0 ; r0 < r1 ? | |
96 | -; Stealing code from xPLOOPplus would cost 2 cycles for 4 bytes saved. | |
97 | - bf/s BRANCHgo ; not yet | |
98 | - mov.l @fIP+, r0 | |
142 | + cmp/ge r0, r1 ; limit (r1) >= counter (I=r0) ? | |
143 | + bt/s BRANCHgo ; not yet | |
144 | + mov.l @fIP+, r0 ; grab offset and bump fIP before we go | |
99 | 145 | rts |
100 | - add.l #2*NATURAL_SIZE, fRP | |
146 | + add.l #2*NATURAL_SIZE, fRP ; drop I and limit before we return | |
101 | 147 | |
102 | 148 | |
103 | -; As it is, (DO) is an alias for D>R, | |
104 | -; but if we put I and the limit in registers, | |
105 | -; (DO) ceases to be so. | |
149 | +; Putting I and limit in registers would require (DO) to save the registers first | |
150 | +; and it would require LOOP and +LOOP to restore the registers on exit. | |
151 | +; That would cost more than it would save. | |
106 | 152 | ; |
107 | - HEADER (DO), xDO | |
153 | +; (DO) ( limit index --- ) ( *** limit index ) | |
154 | +; Move the loop parameters to the return stack. Synonym for D>R, here. | |
155 | +; | |
156 | + HEADER (DO), xPDO | |
108 | 157 | mov.l @fSP+, r0 |
109 | 158 | mov.l @fSP+, r1 |
110 | 159 | add.l #-2*NATURAL_SIZE, fRP |
@@ -116,4 +165,4 @@ xPLOOPminus: | ||
116 | 165 | |
117 | 166 | |
118 | 167 | |
119 | - .end | |
168 | + |
@@ -0,0 +1,30 @@ | ||
1 | + .list ON, EXP | |
2 | + | |
3 | +; Symbol table definitions for fig-FORTH for SH-3 | |
4 | +; Joel Matthew Rees, Hyougo Polytec Center | |
5 | +; 2014.03.01 | |
6 | + | |
7 | +; Monolithic, not separate assembly: | |
8 | +; context.inc must be included before this file. | |
9 | +; .include "context.inc" | |
10 | +; | |
11 | +; .section evaluator, code | |
12 | + | |
13 | + | |
14 | +; (FIND) ( name vocptr --- locptr f ) | |
15 | +; Search vocabulary for a symbol called name. Name is a pointer | |
16 | +; to a NUL terminated string of characters without count, vocptr | |
17 | +; is a pointer to a pointer to a definition (the length byte of a | |
18 | +; symbol table entry). Locptr is also a pointer to a pointer to a | |
19 | +; definition, such that, if the flag is false, a symbol with the | |
20 | +; name searched for may be inserted in proper order at that point. | |
21 | +; Vocptr and locptr may point to either the right or left entry of | |
22 | +; the order-parent entry in the symbol table, or to pointer to the | |
23 | +; root of a vocabulary. HIDDEN (smudged) definitions are | |
24 | +; lexically less than their name strings. Searches only the local | |
25 | +; vocabulary, from the order-parent node passed. Uses (REFIND). | |
26 | +; | |
27 | +; vocptr is a pointer to the parameter field of a vocabulary | |
28 | +; header. | |
29 | +; | |
30 | + HEADER (FIND), xPFIND |