File:  [gforth] / gforth / asm / numref.fs
Revision 1.9: download - view: text, annotated - select for diffs
Mon Dec 31 19:02:25 2007 UTC (16 years, 3 months ago) by anton
Branches: MAIN
CVS tags: v0-7-0, HEAD
updated copyright year after changing license notice

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

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