File:  [gforth] / gforth / arch / alpha / machine.h
Revision 1.9: download - view: text, annotated - select for diffs
Sat Sep 23 15:47:02 2000 UTC (23 years, 7 months ago) by anton
Branches: MAIN
CVS tags: v0-5-0, HEAD
changed FSF address in copyright messages

    1: /* DEC Alpha
    2: 
    3:   Copyright (C) 1995,1996,1997,1998,2000 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
   19:   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
   20: */
   21: 
   22: /* Be careful: long long on Alpha are 64 bit :-(( */
   23: 
   24: #ifndef THREADING_SCHEME
   25: #define THREADING_SCHEME 5
   26: #endif
   27: 
   28: #if !defined(USE_TOS) && !defined(USE_NO_TOS)
   29: #define USE_TOS
   30: #endif
   31: 
   32: #ifndef INDIRECT_THREADED
   33: #ifndef DIRECT_THREADED
   34: #define DIRECT_THREADED
   35: #endif
   36: #endif
   37: 
   38: #define FLUSH_ICACHE(addr,size)		asm("call_pal 0x86") /* imb (instruction-memory barrier) */
   39: 
   40: #include "../generic/machine.h"
   41: 
   42: #ifdef DIRECT_THREADED
   43: #ifdef WORDS_BIGENDIAN
   44: #error Direct threading only supported for little-endian Alphas.
   45: /* big-endian Alphas still store instructions in little-endian format,
   46:    so you would have to reverse the instruction accesses in the following
   47: */
   48: #endif
   49: #if SIZEOF_CHAR_P != 8
   50: #error Direct threading only supported for Alphas with 64-bit Cells.
   51: /* some of the stuff below assumes that the first cell in a code field
   52:    can contain 2 instructions
   53: 
   54:    A simple way around this problem would be to have _alpha_docol
   55:    contain &&dodoes. This would slow down colon defs, however.
   56: 
   57:    Another way is to use a special DOES_HANDLER, like most other CPUs */
   58: #endif
   59: 
   60: #warning Direct threading for Alpha may not work with all gcc versions
   61: #warning ;CODE does not work on the Alpha with direct threading
   62: /* ;CODE puts a jump to the code after ;CODE into the defined
   63:    word. The code generated for the jump can only jump to targets near
   64:    docol (near means: within 32KB). Because the code is far from
   65:    docol, this does not work.
   66: 
   67:    Solution: let the code be: x=cfa[1]; goto *x;
   68:    */
   69: 
   70: typedef int Int32;
   71: typedef short Int16;
   72: 
   73: /* PFA gives the parameter field address corresponding to a cfa */
   74: #define PFA(cfa)	(((Cell *)cfa)+2)
   75: /* PFA1 is a special version for use just after a NEXT1 */
   76: /* the improvement here is that we may destroy cfa before using PFA1 */
   77: #define PFA1(cfa)       PFA(cfa)
   78: 
   79: /*
   80:    On the Alpha, code (in the text segment) typically cannot be
   81:    reached from the dictionary (in the data segment) with a normal
   82:    branch. It also usually takes too long (and too much space on
   83:    32-bit systems) to load the address as literal and jump indirectly.
   84:    
   85:    So, what we do is this: a pointer into our code (at docol, to be
   86:    exact) is kept in a register: _alpha_docol. When the inner
   87:    interpreter jumps to the word address of a variable etc., the
   88:    destination address is computed from that with a lda instruction
   89:    and stored in another register: _alpha_ca. Then an indirect jump
   90:    through _alpha_ca is performed. For docol, we need not compute
   91:    _alpha_ca first.
   92: 
   93:    How do we tell gcc all this? We declare the registers as variables:
   94:    _alpha_docol as explicit variable, to avoid spilling; _alpha_ca is
   95:    so short-lived, so it hopefully won't be spilled. A
   96:    pseudo-primitive cpu_dep is created with code that lets gcc's data
   97:    flow analysis know that _alpha_docol is used and that _alpha_ca may
   98:    be defined and used after any NEXT and before any primitive.  We
   99:    let gcc choose the register for _alpha_ca and simply change the
  100:    code gcc produces for the cpu_dep routine.
  101: */
  102: 
  103: /* if you change this, also change _DOCOL_LABEL below */
  104: #define DO_BASE		(&&docol)
  105: 
  106: #define CPU_DEP2	register Label _alpha_docol asm("$9")=DO_BASE; \
  107: 			register Label _alpha_ca;
  108: 
  109: #define CPU_DEP3	cpu_dep: asm("lda %0, 500(%1)":"=r"(_alpha_ca):"r"(_alpha_docol)); goto *_alpha_ca;
  110: 
  111: #define CPU_DEP1	(&&cpu_dep)
  112: 
  113: 
  114: /* CODE_ADDRESS is the address of the code jumped to through the code field */
  115: #define CODE_ADDRESS(wa) ({ \
  116: 	Int32 *_wa=(Int32 *)(wa); \
  117: 	(_wa[0]&0xfc000000)==0x68000000 ? /*JMP?*/\
  118: 	 DO_BASE : \
  119: 	 ((((_wa[0]^((Int32 *)_CPU_DEP_LABEL)[0]) & 0xffff0000)==0 && \
  120: 	   ((_wa[1]^((Int32 *)_CPU_DEP_LABEL)[1]) & 0xffffc000)==0 ) ? \
  121: 	  (DO_BASE+((Int16 *)_wa)[0]) : \
  122: 	  (Label)_wa); })
  123: 
  124: #define _CPU_DEP_LABEL	(symbols[DOESJUMP])
  125: #define _DOCOL_LABEL	(symbols[DOCOL])
  126: 
  127: /* MAKE_CF creates an appropriate code field at the wa; ca is the code
  128:    address. For the Alpha, this is a lda followed by a jmp (or just a
  129:    jmp, if ca==DO_BASE).  We patch the jmp with a good hint (on the
  130:    21064A this saves 5 cycles!) */
  131: #define MAKE_CF(wa,ca)	({ \
  132: 	Int32 *_wa=(Int32 *)(wa); \
  133: 	Label _ca=(Label)(ca); \
  134: 	if (_ca==_DOCOL_LABEL)  \
  135: 	    _wa[0]=(((0x1a<<26)|(31<<21)|(9<<16))| \
  136: 	            (((((Cell)_ca)-((Cell)_wa)-4) & 0xffff)>>2)); \
  137: 	else { \
  138: 	    _wa[0]=((((Int32 *)_CPU_DEP_LABEL)[0] & 0xffff0000)| \
  139: 		    ((((Cell)_ca)-((Cell)_DOCOL_LABEL)) & 0xffff)); \
  140: 	    _wa[1]=((((Int32 *)_CPU_DEP_LABEL)[1] & 0xffffc000)| \
  141: 		    (((((Cell)_ca)-((Cell)_wa)-8) & 0xffff)>>2));  \
  142: 	} \
  143:     })
  144: 
  145: /* this is the point where the does code for the word with the xt cfa
  146:    starts. Because the jump to the code field takes only one cell on
  147:    64-bit systems we can use the second cell of the cfa for storing
  148:    the does address */
  149: #define DOES_CODE(cfa) \
  150:      ({ Int32 *_wa=(cfa); \
  151: 	(_wa[0] == ((((Int32 *)_CPU_DEP_LABEL)[0] & 0xffff0000)| \
  152: 		    ((((Cell)&&dodoes)-((Cell)DO_BASE)) & 0xffff)) && \
  153: 	 (_wa[1]&0xffffc000) == (((Int32 *)_CPU_DEP_LABEL)[1] & 0xffffc000)) \
  154: 	? DOES_CODE1(_wa) : 0; })
  155: 
  156: /* this is a special version of DOES_CODE for use in dodoes */
  157: #define DOES_CODE1(cfa)	((Xt *)(((Cell *)(cfa))[1]))
  158: 
  159: /* the does handler resides between DOES> and the following Forth
  160:    code. Since the code-field jumps directly to dodoes, the
  161:    does-handler is not needed for the Alpha architecture */
  162: #define MAKE_DOES_HANDLER(addr)   ((void)0)
  163: 
  164: /* This makes a code field for a does-defined word. doesp is the
  165:    address of the does-code. On the Alpha, the code field consists of
  166:    a jump to dodoes and the address of the does code */
  167: #define MAKE_DOES_CF(cfa,doesp) ({Xt *_cfa = (Xt *)(cfa); \
  168: 				    MAKE_CF(_cfa, symbols[DODOES]); \
  169: 				    _cfa[1] = (doesp); })
  170: #endif
  171: 
  172: #ifdef FORCE_REG
  173: /* $9-$14 are callee-saved, $1-$8 and $22-$25 are caller-saved */
  174: #define IPREG asm("$10")
  175: #define SPREG asm("$11")
  176: #define RPREG asm("$12")
  177: #define LPREG asm("$13")
  178: #define TOSREG asm("$14")
  179: /* #define CFAREG asm("$22") egcs-1.0.3 crashes with any caller-saved
  180:    register decl */
  181: #endif /* FORCE_REG */

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