Annotation of gforth/arch/alpha/machine.h, revision 1.11

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

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