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

version 1.9, 2000/09/23 15:47:02 version 1.13, 2003/01/19 23:35:31
Line 1 Line 1
 /* DEC Alpha  /* DEC Alpha
   
   Copyright (C) 1995,1996,1997,1998,2000 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 29 Line 29
 #define USE_TOS  #define USE_TOS
 #endif  #endif
   
 #ifndef INDIRECT_THREADED  
 #ifndef DIRECT_THREADED  
 #define DIRECT_THREADED  
 #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 WORDS_BIGENDIAN  
 #error Direct threading only supported for little-endian Alphas.  
 /* big-endian Alphas still store instructions in little-endian format,  
    so you would have to reverse the instruction accesses in the following  
 */  
 #endif  
 #if SIZEOF_CHAR_P != 8  
 #error Direct threading only supported for Alphas with 64-bit Cells.  
 /* some of the stuff below assumes that the first cell in a code field  
    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.  
 */  
   
 /* if you change this, also change _DOCOL_LABEL below */  
 #define DO_BASE         (&&docol)  
   
 #define CPU_DEP2        register Label _alpha_docol asm("$9")=DO_BASE; \  
                         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?*/\  
          DO_BASE : \  
          ((((_wa[0]^((Int32 *)_CPU_DEP_LABEL)[0]) & 0xffff0000)==0 && \  
            ((_wa[1]^((Int32 *)_CPU_DEP_LABEL)[1]) & 0xffffc000)==0 ) ? \  
           (DO_BASE+((Int16 *)_wa)[0]) : \  
           (Label)_wa); })  
   
 #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==DO_BASE).  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)DO_BASE)) & 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)   ((void)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  
   
 #ifdef FORCE_REG  #ifdef FORCE_REG
 /* $9-$14 are callee-saved, $1-$8 and $22-$25 are caller-saved */  /* $9-$14 are callee-saved, $1-$8 and $22-$25 are caller-saved */
 #define IPREG asm("$10")  #define IPREG asm("$10")

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


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