• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Implementing figFORTH on SH3 assembler


Commit MetaInfo

Revisão98b1462b18e381bd047560e77e0c5cb9df01a094 (tree)
Hora2014-03-07 13:52:52
AutorJoel Matthew Rees <reiisi@user...>
CommiterJoel Matthew Rees

Mensagem de Log

up to around (FIND)

Mudança Sumário

Diff

--- a/context.inc
+++ b/context.inc
@@ -63,6 +63,20 @@ ALL_BITS: .equ H'FFFFFFFF
6363 ; -----------------------------
6464
6565
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+
6680 ; FORTH tracks the call/return sequence in a separate stack from the parameters.
6781 fRP: .reg r15 ; control/Return stack Pointer
6882 fSP: .reg r7 ; parameter Stack Pointer
@@ -114,3 +128,18 @@ _p\characteristic .equ $
114128 .endm
115129
116130
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+
--- a/evaluator.inc
+++ b/evaluator.inc
@@ -3,13 +3,21 @@
33 ; Expression evaluator definitions for fig-FORTH for SH-3
44 ; Joel Matthew Rees, Hyougo Polytec Center
55 ; 2014.03.01
6+
67
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
813
9- .section evaluator, code, locate=h'8c000000
1014
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+;
1321 HEADER I, xI
1422 mov.l @fRP, r0 ; I (loop counter)
1523 rts
@@ -19,4 +27,3 @@
1927
2028
2129
22- .end
--- /dev/null
+++ b/initialize.inc
@@ -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+
--- /dev/null
+++ b/main.src
@@ -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
--- a/parser.inc
+++ b/parser.inc
@@ -3,25 +3,49 @@
33 ; Parser definitions for fig-FORTH for SH-3
44 ; Joel Matthew Rees, Hyougo Polytec Center
55 ; 2014.03.01
6+
67
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
1213
1314
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+;
1421 HEADER DIGIT, xDIGIT
15- mov.l @fSP, r0
16- add.l #-'0', r0
22+ mov.l @(NATURAL_SIZE,fSP), r0 ; 7ビット文字
1723 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
2348
2449
2550
2651
27- .end
--- /dev/null
+++ b/primitive.inc
@@ -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+
--- a/primitive.src
+++ b/primitive.src
@@ -4,22 +4,39 @@
44 ; Joel Matthew Rees, Hyougo Polytec Center
55 ; 2014.02.28
66
7- .include "context.inc"
87
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+
1014
1115 ; ***** Need to load the return register with something safe.
1216 ; Probably the call to next from warm?
13-
17+;
18+; Anyway, this is the inner interpreter.
19+;
1420 next:
1521 mov.l @fIP+, fW ; get the pointer to the next definition to execute
1622 mov.l @fW, r0 ; get the defitinition characteristic
1723 jsr @r0
18- nop
24+; 3 cycles to get back to the top of the loop.
25+ nop
1926 bra next
2027 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.
2134
2235
36+; LIT ( --- n ) C
37+; Push the following word from the instruction stream as a
38+; literal, or immediate value.
39+;
2340 HEADER LIT, LIT
2441 mov.l @fIP+, r0
2542 mov.l r0, @-fSP
@@ -31,6 +48,10 @@ next:
3148 ; It'll cause alignment problems.
3249
3350
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+;
3455 HEADER EXECUTE, EXECUTE
3556 mov.l @fSP+, fW
3657 mov.l @fW, r0
@@ -38,6 +59,10 @@ next:
3859 nop
3960
4061
62+; BRANCH ( --- ) C
63+; Add the following word from the instruction stream to the
64+; instruction pointer (Y++). Causes a program branch.
65+;
4166 HEADER BRANCH, BRANCH
4267 mov.l @fIP+, r0
4368 BRANCHgo:
@@ -46,6 +71,9 @@ BRANCHgo:
4671 nop
4772
4873
74+; 0BRANCH ( f --- ) C
75+; BRANCH if flag is zero.
76+;
4977 HEADER 0BRANCH, ZBRANCH
5078 mov.l @fSP+, r0
5179 cmp/eq #0, r0
@@ -55,6 +83,24 @@ BRANCHgo:
5583 nop
5684
5785
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+;
58104 HEADER (LOOP), xLOOP
59105 mov.l @fRP, r0 ; I (loop counter)
60106 add.l #1, r0
@@ -67,44 +113,47 @@ BRANCHgo:
67113 add.l #2*NATURAL_SIZE, fRP
68114
69115
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.
75123 ;
76-; Note: fig-FORTH +LOOP has an un-signed loop counter.
77-; (JMR: but the increment is signed!)
78124 HEADER (+LOOP), xPLOOP
79125 mov.l @fSP+, r1 ; increment
80126 mov.l @fRP, r0 ; I (loop counter)
81127 add.l r1, r0
82128 mov.l r0, @fRP ; update I
83- shl r1, r0 ; increment negative or positive?
129+ shal r1 ; increment negative or positive?
84130 bt/s xPLOOPminus
85- mov.l @(NATURAL_SIZE,fRP), r0 ; limit
131+ mov.l @(NATURAL_SIZE,fRP), r1 ; limit
86132 ;
133+; Stealing too much code would cost more than it would save.
87134 xPLOOPplus:
88- cmp/ge r1, r0 ; r0 >= r1 ?
135+ cmp/ge r0, r1 ; limit (r1) >= counter (I=r0) ?
89136 bf/s BRANCHgo ; not yet
90- mov.l @fIP+, r0
137+ mov.l @fIP+, r0 ; grab offset and bump fIP before we go
91138 rts
92- add.l #2*NATURAL_SIZE, fRP
139+ add.l #2*NATURAL_SIZE, fRP ; drop I and limit before we return
93140 ;
94141 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
99145 rts
100- add.l #2*NATURAL_SIZE, fRP
146+ add.l #2*NATURAL_SIZE, fRP ; drop I and limit before we return
101147
102148
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.
106152 ;
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
108157 mov.l @fSP+, r0
109158 mov.l @fSP+, r1
110159 add.l #-2*NATURAL_SIZE, fRP
@@ -116,4 +165,4 @@ xPLOOPminus:
116165
117166
118167
119- .end
168+
--- /dev/null
+++ b/symbol.inc
@@ -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