Annotation of gforth/asm/numref.fs, revision 1.5

1.5     ! crook       1: \ numref.fs
1.1       pazsan      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: 
1.5     ! crook      26: How to use local labels
        !            27: =======================
1.1       pazsan     28: 
                     29: Example:
                     30: 
                     31: Label 10pause
                     32:                10 # ldy,
                     33:        1 $:    dey,
                     34:                1 $ bne,
                     35:                rts,
                     36: End-Label
                     37: 
                     38: "n $:" defines an address reference. "n $" returns the address of the
                     39: reference defined with "n $:".
                     40: 
                     41: 
1.5     ! crook      42: How to embed local labels in your assembler
        !            43: ===========================================
        !            44: 
        !            45: At the moment all references are forward references, meaning all
        !            46: references are resolved at the end of the definition.
1.1       pazsan     47: 
                     48: The Simple Resolver
1.5     ! crook      49: -------------------
1.1       pazsan     50: 
1.5     ! crook      51: The only special thing is how a label is resolved. Numref does this by
        !            52: executing a resolver-word. For example, consider a two byte opcode
        !            53: with the second byte as branch-offset. The resolver-word would look
        !            54: like this:
1.1       pazsan     55: 
1.5     ! crook      56: : doresolve ( iaddr -- )
1.1       pazsan     57:   dup ref-addr @ - swap 1+ X c! ;
                     58: 
                     59: iaddr is the address of the instruction with the reference that must
                     60: be resolved. The destination address of the reference is stored at ref-addr.
                     61: 
1.5     ! crook      62: The resolver-word must be registered like this:
        !            63: 
        !            64:  "' doresolve TO std-resolver"
        !            65: 
        !            66: This is not a deferred word!
1.1       pazsan     67: 
                     68: Complex Resolving
1.5     ! crook      69: -----------------
1.1       pazsan     70: 
1.5     ! crook      71: To support different cpu-instruction with different operand formats it
        !            72: is possible to find out the type of opcode by accessing the target's
        !            73: memory in doresolve. This works for very simple processors, e.g. for
        !            74: 6502 it is very easy to find out whether we have a 2-byte absolute
        !            75: address or a 1-byte relative address.
1.1       pazsan     76: 
1.5     ! crook      77: If this method is too difficult, it is possible to store additional
1.1       pazsan     78: information in the resolve structure.
                     79: 
                     80: When assembling an opcode you should find out whether the address is a
1.5     ! crook      81: reference and then store the xt of a special resolver word in the
        !            82: resolve structure by "ref-resolver !", or store some additional data
        !            83: in the resolve structure by "ref-data !", if one data field is not
        !            84: enough, allocate memory and use ref-data as pointer to it.
1.1       pazsan     85: 
1.5     ! crook      86: Internal structure
        !            87: ==================
1.1       pazsan     88: 
1.5     ! crook      89: There is a heap buffer to store the references.  The structure of one
        !            90: entry is:
1.1       pazsan     91: 
                     92:  1 cell                ref-link
                     93:  1 cell                ref-flag        \ mixture of tag-number
                     94:                                \ and tag type
                     95:  1 cell                ref-resolver    \ xt of resolver
                     96:  1 cell                ref-addr        \ pointer to destination or on reference
                     97:                                \ instruction
                     98:                                \ (start of the instruction)
                     99:  1 cell                ref-data        \ additional information for resolver
                    100: 
                    101: [THEN]
                    102: 
1.2       pazsan    103: require ./basic.fs
1.1       pazsan    104: 
                    105: also assembler definitions
                    106: 
                    107: hex
                    108: 
                    109: 0 value ref-marker \ tells us that address is an reference
                    110: 
                    111: 0 value ref-now        \ points to the reference we are working on
                    112: 
                    113: : ref-link ref-now ;
                    114: : ref-flag ref-now cell+ ;
                    115: : ref-resolver ref-now 2 cells + ;
                    116: : ref-adr ref-now 3 cells + ;
                    117: : ref-addr ref-now 3 cells + ;
                    118: : ref-data ref-now 4 cells + ;
                    119: : ref-tag-len 5 cells ;
                    120: 
                    121: : ref-resolve ref-resolver @ execute ;
                    122: 
                    123: : ref?         ( -- )
                    124:        ref-marker
                    125:        false TO ref-marker ;
                    126: 
                    127: : forward? ( target-addr -- target-addr false | true )
                    128:        dup there = ref? and dup
                    129:        IF nip THEN ;
                    130: 
                    131: :noname false TO ref-marker ; propper8 chained
                    132: 
                    133: variable ref-heap 0 ref-heap !
                    134: 
                    135: ' drop value std-resolver
                    136: 
                    137: : ref! ( flags/nr -- )
                    138: \G stores a reference tag
                    139:   \ get mem for tag
                    140:   ref-tag-len allocate throw to ref-now 
                    141:   \ build link
                    142:   ref-heap @ ref-link !  ref-link ref-heap !
                    143:   there ref-adr !
                    144:   std-resolver ref-resolver ! 
                    145:   ref-flag ! ;
                    146: 
                    147: : $ ( num -- address )
                    148: \G makes a reference source with the next instruction
                    149:   01ff and 0200 or ref! there  ;
                    150: 
                    151: : $: ( num -- )
                    152: \G makes a reference target
                    153:   01ff and 0a00 or ref! ;
                    154: 
                    155: : g$: ( num -- )
                    156: \G makes a reference target for a global label
                    157:   01ff and 0e00 or ref! ;
                    158:   
                    159: : g$ ( num -- addr )
                    160: \G searches a global label and gets its address
                    161:   01ff and 0e00 or
                    162:   ref-heap BEGIN dup >r @ dup WHILE 2dup cell+ @ = 
                    163:   IF nip to ref-now
                    164:      ref-link @ r> !
                    165:      ref-adr @ 
                    166:      ref-now free throw EXIT THEN
                    167:      r> drop
                    168:   REPEAT 2drop -1 ABORT" could not resolve G label!" ;
                    169: 
                    170: : kill$: ( -- )
                    171: \G deallocs the complete reference heap
                    172:   ref-heap @ BEGIN dup WHILE dup @ swap free throw REPEAT drop 
                    173:   0 ref-heap ! ;
                    174: 
                    175: : find$: ( adr nr -- )
                    176:   0800 or
                    177:   ref-heap 
                    178:   BEGIN dup >r @ dup WHILE 2dup cell+ @ =
                    179:        IF nip to ref-now
                    180:           r> drop
                    181:            ref-resolve EXIT
                    182:        THEN
                    183:      r> drop
                    184:   REPEAT 2drop -1 ABORT" could not resolve label!" ;
                    185: 
                    186: : solve$
                    187:   ref-heap dup >r @ 
                    188:   BEGIN dup WHILE dup cell+ @ 0E00 and 0200 =
                    189:    IF to ref-now
                    190:       ref-link @ r@ !
                    191:       ref-now >r
                    192:       ref-adr @ ref-flag @ ( 01ff and ) find$:
                    193:       r> to ref-now
                    194:       ref-link ( dup >r ) @
                    195:       ref-now free throw
                    196:    ELSE 
                    197:       r> drop
                    198:       dup >r @
                    199:    THEN
                    200:   REPEAT r> drop drop kill$: ;
                    201: 
                    202: ' solve$ end-code8 chained
                    203: 
                    204: previous definitions

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>