Annotation of gforth/alpha.h, revision 1.7

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

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