Diff for /gforth/arch/alpha/machine.h between versions 1.2 and 1.13

version 1.2, 1997/09/01 23:08:19 version 1.13, 2003/01/19 23:35:31
Line 1 Line 1
 /* preliminary machine file for DEC Alpha  /* DEC Alpha
   
   Copyright (C) 1995 Free Software Foundation, Inc.    Copyright (C) 1995-2003 Free Software Foundation, Inc.
   
   This file is part of Gforth.    This file is part of Gforth.
   
Line 16 Line 16
   
   You should have received a copy of the GNU General Public License    You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software    along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 */  */
   
 /* Be careful: long long on Alpha are 64 bit :-(( */  /* Be careful: long long on Alpha are 64 bit :-(( */
 #define LONG_LATENCY  
   
 #if !defined(USE_TOS) && !defined(USE_NO_TOS)  #ifndef THREADING_SCHEME
 #define USE_TOS  #define THREADING_SCHEME 5
 #endif  #endif
   
 #ifndef INDIRECT_THREADED  #if !defined(USE_TOS) && !defined(USE_NO_TOS)
 #ifndef DIRECT_THREADED  #define USE_TOS
 #define DIRECT_THREADED  
 #endif  
 #endif  #endif
   
 #define FLUSH_ICACHE(addr,size)         asm("call_pal 0x86") /* imb (instruction-memory barrier) */  #define FLUSH_ICACHE(addr,size)         asm("call_pal 0x86") /* imb (instruction-memory barrier) */
   
 #include "../generic/machine.h"  #include "../generic/machine.h"
   
 #ifdef DIRECT_THREADED  #ifdef FORCE_REG
 #ifdef WORDS_BIGENDIAN  /* $9-$14 are callee-saved, $1-$8 and $22-$25 are caller-saved */
 #error Direct threading only supported for little-endian Alphas.  #define IPREG asm("$10")
 /* big-endian Alphas still store instructions in little-endian format,  #define SPREG asm("$11")
    so you would have to reverse the instruction accesses in the following  #define RPREG asm("$12")
 */  #define LPREG asm("$13")
 #endif  #define TOSREG asm("$14")
 #if SIZEOF_CHAR_P != 8  /* #define CFAREG asm("$22") egcs-1.0.3 crashes with any caller-saved
 #error Direct threading only supported for Alphas with 64-bit Cells.     register decl */
 /* some of the stuff below assumes that the first cell in a code field  #endif /* FORCE_REG */
    can contain 2 instructions  
   
    A simple way around this problem would be to have _alpha_docol  
    contain &&dodoes. This would slow down colon defs, however.  
   
    Another way is to use a special DOES_HANDLER, like most other CPUs */  
 #endif  
   
 #warning Direct threading for Alpha may not work with all gcc versions  
 #warning ;CODE does not work on the Alpha with direct threading  
 /* ;CODE puts a jump to the code after ;CODE into the defined  
    word. The code generated for the jump can only jump to targets near  
    docol (near means: within 32KB). Because the code is far from  
    docol, this does not work.  
   
    Solution: let the code be: x=cfa[1]; goto *x;  
    */  
   
 typedef int Int32;  
 typedef short Int16;  
   
 /* PFA gives the parameter field address corresponding to a cfa */  
 #define PFA(cfa)        (((Cell *)cfa)+2)  
 /* PFA1 is a special version for use just after a NEXT1 */  
 /* the improvement here is that we may destroy cfa before using PFA1 */  
 #define PFA1(cfa)       PFA(cfa)  
   
 /*  
    On the Alpha, code (in the text segment) typically cannot be  
    reached from the dictionary (in the data segment) with a normal  
    branch. It also usually takes too long (and too much space on  
    32-bit systems) to load the address as literal and jump indirectly.  
      
    So, what we do is this: a pointer into our code (at docol, to be  
    exact) is kept in a register: _alpha_docol. When the inner  
    interpreter jumps to the word address of a variable etc., the  
    destination address is computed from that with a lda instruction  
    and stored in another register: _alpha_ca. Then an indirect jump  
    through _alpha_ca is performed. For docol, we need not compute  
    _alpha_ca first.  
   
    How do we tell gcc all this? We declare the registers as variables:  
    _alpha_docol as explicit variable, to avoid spilling; _alpha_ca is  
    so short-lived, so it hopefully won't be spilled. A  
    pseudo-primitive cpu_dep is created with code that lets gcc's data  
    flow analysis know that _alpha_docol is used and that _alpha_ca may  
    be defined and used after any NEXT and before any primitive.  We  
    let gcc choose the register for _alpha_ca and simply change the  
    code gcc produces for the cpu_dep routine.  
 */  
   
 #define CPU_DEP2        register Label _alpha_docol asm("$9")=&&docol; \  
                         register Label _alpha_ca;  
   
 #define CPU_DEP3        cpu_dep: asm("lda %0, 500(%1)":"=r"(_alpha_ca):"r"(_alpha_docol)); goto *_alpha_ca;  
   
 #define CPU_DEP1        (&&cpu_dep)  
   
   
 /* CODE_ADDRESS is the address of the code jumped to through the code field */  
 #define CODE_ADDRESS(wa)        ({Int32 *_wa=(Int32 *)(wa); \  
                                     (_wa[0]&0xfc000000)==0x68000000 ? /*JMP?*/\  
                                     &&docol : \  
                                     &&docol+((Int16 *)_wa)[0]; })  
   
 #define _CPU_DEP_LABEL  (symbols[DOESJUMP])  
 #define _DOCOL_LABEL    (symbols[DOCOL])  
   
 /* MAKE_CF creates an appropriate code field at the wa; ca is the code  
    address. For the Alpha, this is a lda followed by a jmp (or just a  
    jmp, if ca==&&docol).  We patch the jmp with a good hint (on the  
    21064A this saves 5 cycles!) */  
 #define MAKE_CF(wa,ca)  ({ \  
                              Int32 *_wa=(Int32 *)(wa); \  
                              Label _ca=(Label)(ca); \  
                              if (_ca==_DOCOL_LABEL)  \  
                                _wa[0]=(((0x1a<<26)|(31<<21)|(9<<16))| \  
                                        (((((Cell)_ca)-((Cell)_wa)-4) & 0xffff)>>2)); \  
                              else { \  
                                _wa[0]=((((Int32 *)_CPU_DEP_LABEL)[0] & 0xffff0000)| \  
                                        ((((Cell)_ca)-((Cell)_DOCOL_LABEL)) & 0xffff)); \  
                                _wa[1]=((((Int32 *)_CPU_DEP_LABEL)[1] & 0xffffc000)| \  
                                        (((((Cell)_ca)-((Cell)_wa)-8) & 0xffff)>>2));  \  
                              } \  
                         })  
   
 /* this is the point where the does code for the word with the xt cfa  
    starts. Because the jump to the code field takes only one cell on  
    64-bit systems we can use the second cell of the cfa for storing  
    the does address */  
 #define DOES_CODE(cfa) \  
      ({ Int32 *_wa=(cfa); \  
         (_wa[0] == ((((Int32 *)_CPU_DEP_LABEL)[0] & 0xffff0000)| \  
                     ((((Cell)&&dodoes)-((Cell)&&docol)) & 0xffff)) && \  
          (_wa[1]&0xffffc000) == (((Int32 *)_CPU_DEP_LABEL)[1] & 0xffffc000)) \  
         ? DOES_CODE1(_wa) : 0; })  
   
 /* this is a special version of DOES_CODE for use in dodoes */  
 #define DOES_CODE1(cfa) ((Xt *)(((Cell *)(cfa))[1]))  
   
 /* the does handler resides between DOES> and the following Forth  
    code. Since the code-field jumps directly to dodoes, the  
    does-handler is not needed for the Alpha architecture */  
 #define MAKE_DOES_HANDLER(addr)   0  
   
 /* This makes a code field for a does-defined word. doesp is the  
    address of the does-code. On the Alpha, the code field consists of  
    a jump to dodoes and the address of the does code */  
 #define MAKE_DOES_CF(cfa,doesp) ({Xt *_cfa = (Xt *)(cfa); \  
                                     MAKE_CF(_cfa, symbols[DODOES]); \  
                                     _cfa[1] = (doesp); })  
 #endif  
   

Removed from v.1.2  
changed lines
  Added in v.1.13


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