Annotation of gforth/asm/numref.fs, revision 1.4
1.1 pazsan 1: \ refs.fs
2:
1.3 anton 3: \ Copyright (C) 1998 Free Software Foundation, Inc.
4:
5: \ This file is part of Gforth.
6:
7: \ Gforth is free software; you can redistribute it and/or
8: \ modify it under the terms of the GNU General Public License
9: \ as published by the Free Software Foundation; either version 2
10: \ of the License, or (at your option) any later version.
11:
12: \ This program is distributed in the hope that it will be useful,
13: \ but WITHOUT ANY WARRANTY; without even the implied warranty of
14: \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: \ GNU General Public License for more details.
16:
17: \ You should have received a copy of the GNU General Public License
18: \ along with this program; if not, write to the Free Software
1.4 ! anton 19: \ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
1.3 anton 20:
1.1 pazsan 21: 0 [IF]
22:
23: This is a generic solution for doing labels (forward and backward
24: references) in an assembler program.
25:
26: - Who to use local labels:
27:
28: Example:
29:
30: Label 10pause
31: 10 # ldy,
32: 1 $: dey,
33: 1 $ bne,
34: rts,
35: End-Label
36:
37: "n $:" defines an address reference. "n $" returns the address of the
38: reference defined with "n $:".
39:
40: - How to embed local labels in your assembler:
41:
42: At the moment all references are forward references, meaning,
43: all references are resolved at the end of the definition.
44:
45: The Simple Resolver
46:
47: The only special thing is how a label is resolved. Numref executes
48: therefor a resolver-word, example for a two byte opcode with the second
49: byte as branch-offset:
50:
51: : doresovle ( iaddr -- )
52: dup ref-addr @ - swap 1+ X c! ;
53:
54: iaddr is the address of the instruction with the reference that must
55: be resolved. The destination address of the reference is stored at ref-addr.
56:
57: The resolver must be registered bye "' doresolve TO std-resolve". This is
58: not a defered word!
59:
60: Complex Resolving
61:
62: To support different cpu-instruction with different operand formats it is
63: possible to find out the type of opcode bye accessing the targets' memory
64: in doresolve. This works for very simple processors, e.g. for 6502 it is
65: very easy to find out whether we have a 2-byte absolute address or a 1-byte
66: relative address.
67:
68: If this method is to difficult, it is possible to store additional
69: information in the resolve structure.
70:
71: When assembling an opcode you should find out whether the address is a
72: reference and then store the xt of a special
73: resolver word in the resolve structure by "ref-resolver !", or store some
74: additional data in the resolve structure by "ref-data !", if one data field
75: is not enough allocate memory and use ref-data as pointer to it.
76:
77: - Internal strucutre:
78:
79: There is a heap buffer to store the references.
80: The structure of one entry is:
81:
82: 1 cell ref-link
83: 1 cell ref-flag \ mixture of tag-number
84: \ and tag type
85: 1 cell ref-resolver \ xt of resolver
86: 1 cell ref-addr \ pointer to destination or on reference
87: \ instruction
88: \ (start of the instruction)
89: 1 cell ref-data \ additional information for resolver
90:
91:
92: [THEN]
93:
1.2 pazsan 94: require ./basic.fs
1.1 pazsan 95:
96: also assembler definitions
97:
98: hex
99:
100: 0 value ref-marker \ tells us that address is an reference
101:
102: 0 value ref-now \ points to the reference we are working on
103:
104: : ref-link ref-now ;
105: : ref-flag ref-now cell+ ;
106: : ref-resolver ref-now 2 cells + ;
107: : ref-adr ref-now 3 cells + ;
108: : ref-addr ref-now 3 cells + ;
109: : ref-data ref-now 4 cells + ;
110: : ref-tag-len 5 cells ;
111:
112: : ref-resolve ref-resolver @ execute ;
113:
114: : ref? ( -- )
115: ref-marker
116: false TO ref-marker ;
117:
118: : forward? ( target-addr -- target-addr false | true )
119: dup there = ref? and dup
120: IF nip THEN ;
121:
122: :noname false TO ref-marker ; propper8 chained
123:
124: variable ref-heap 0 ref-heap !
125:
126: ' drop value std-resolver
127:
128: : ref! ( flags/nr -- )
129: \G stores a reference tag
130: \ get mem for tag
131: ref-tag-len allocate throw to ref-now
132: \ build link
133: ref-heap @ ref-link ! ref-link ref-heap !
134: there ref-adr !
135: std-resolver ref-resolver !
136: ref-flag ! ;
137:
138: : $ ( num -- address )
139: \G makes a reference source with the next instruction
140: 01ff and 0200 or ref! there ;
141:
142: : $: ( num -- )
143: \G makes a reference target
144: 01ff and 0a00 or ref! ;
145:
146: : g$: ( num -- )
147: \G makes a reference target for a global label
148: 01ff and 0e00 or ref! ;
149:
150: : g$ ( num -- addr )
151: \G searches a global label and gets its address
152: 01ff and 0e00 or
153: ref-heap BEGIN dup >r @ dup WHILE 2dup cell+ @ =
154: IF nip to ref-now
155: ref-link @ r> !
156: ref-adr @
157: ref-now free throw EXIT THEN
158: r> drop
159: REPEAT 2drop -1 ABORT" could not resolve G label!" ;
160:
161: : kill$: ( -- )
162: \G deallocs the complete reference heap
163: ref-heap @ BEGIN dup WHILE dup @ swap free throw REPEAT drop
164: 0 ref-heap ! ;
165:
166: : find$: ( adr nr -- )
167: 0800 or
168: ref-heap
169: BEGIN dup >r @ dup WHILE 2dup cell+ @ =
170: IF nip to ref-now
171: r> drop
172: ref-resolve EXIT
173: THEN
174: r> drop
175: REPEAT 2drop -1 ABORT" could not resolve label!" ;
176:
177: : solve$
178: ref-heap dup >r @
179: BEGIN dup WHILE dup cell+ @ 0E00 and 0200 =
180: IF to ref-now
181: ref-link @ r@ !
182: ref-now >r
183: ref-adr @ ref-flag @ ( 01ff and ) find$:
184: r> to ref-now
185: ref-link ( dup >r ) @
186: ref-now free throw
187: ELSE
188: r> drop
189: dup >r @
190: THEN
191: REPEAT r> drop drop kill$: ;
192:
193: ' solve$ end-code8 chained
194:
195: previous definitions
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>