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

1.1     ! 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 :-(( */
        !            23: #define LONG_LATENCY
        !            24: 
        !            25: #if !defined(USE_TOS) && !defined(USE_NO_TOS)
        !            26: #define USE_TOS
        !            27: #endif
        !            28: 
        !            29: #ifndef INDIRECT_THREADED
        !            30: #ifndef DIRECT_THREADED
        !            31: #define DIRECT_THREADED
        !            32: #endif
        !            33: #endif
        !            34: 
        !            35: #define FLUSH_ICACHE(addr,size)                asm("call_pal 0x86") /* imb (instruction-memory barrier) */
        !            36: 
        !            37: #include "../../engine/32bit.h"
        !            38: 
        !            39: #ifdef DIRECT_THREADED
        !            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: */
        !            45: #endif
        !            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: 
        !            57: #warning Direct threading for Alpha may not work with all gcc versions
        !            58: #warning ;CODE does not work on the Alpha with direct threading
        !            59: /* ;CODE puts a jump to the code after ;CODE into the defined
        !            60:    word. The code generated for the jump can only jump to targets near
        !            61:    docol (near means: within 32KB). Because the code is far from
        !            62:    docol, this does not work.
        !            63: 
        !            64:    Solution: let the code be: x=cfa[1]; goto *x;
        !            65:    */
        !            66: 
        !            67: typedef int Int32;
        !            68: typedef short Int16;
        !            69: 
        !            70: /* PFA gives the parameter field address corresponding to a cfa */
        !            71: #define PFA(cfa)       (((Cell *)cfa)+2)
        !            72: /* PFA1 is a special version for use just after a NEXT1 */
        !            73: /* the improvement here is that we may destroy cfa before using PFA1 */
        !            74: #define PFA1(cfa)       PFA(cfa)
        !            75: 
        !            76: /*
        !            77:    On the Alpha, code (in the text segment) typically cannot be
        !            78:    reached from the dictionary (in the data segment) with a normal
        !            79:    branch. It also usually takes too long (and too much space on
        !            80:    32-bit systems) to load the address as literal and jump indirectly.
        !            81:    
        !            82:    So, what we do is this: a pointer into our code (at docol, to be
        !            83:    exact) is kept in a register: _alpha_docol. When the inner
        !            84:    interpreter jumps to the word address of a variable etc., the
        !            85:    destination address is computed from that with a lda instruction
        !            86:    and stored in another register: _alpha_ca. Then an indirect jump
        !            87:    through _alpha_ca is performed. For docol, we need not compute
        !            88:    _alpha_ca first.
        !            89: 
        !            90:    How do we tell gcc all this? We declare the registers as variables:
        !            91:    _alpha_docol as explicit variable, to avoid spilling; _alpha_ca is
        !            92:    so short-lived, so it hopefully won't be spilled. A
        !            93:    pseudo-primitive cpu_dep is created with code that lets gcc's data
        !            94:    flow analysis know that _alpha_docol is used and that _alpha_ca may
        !            95:    be defined and used after any NEXT and before any primitive.  We
        !            96:    let gcc choose the register for _alpha_ca and simply change the
        !            97:    code gcc produces for the cpu_dep routine.
        !            98: */
        !            99: 
        !           100: #define CPU_DEP2       register Label _alpha_docol asm("$9")=&&docol; \
        !           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 */
        !           109: #define CODE_ADDRESS(wa)       ({Int32 *_wa=(Int32 *)(wa); \
        !           110:                                    (_wa[0]&0xfc000000)==0x68000000 ? /*JMP?*/\
        !           111:                                    &&docol : \
        !           112:                                    &&docol+((Int16 *)_wa)[0]; })
        !           113: 
        !           114: #define _CPU_DEP_LABEL (symbols[DOESJUMP])
        !           115: #define _DOCOL_LABEL   (symbols[DOCOL])
        !           116: 
        !           117: /* MAKE_CF creates an appropriate code field at the wa; ca is the code
        !           118:    address. For the Alpha, this is a lda followed by a jmp (or just a
        !           119:    jmp, if ca==&&docol).  We patch the jmp with a good hint (on the
        !           120:    21064A this saves 5 cycles!) */
        !           121: #define MAKE_CF(wa,ca) ({ \
        !           122:                             Int32 *_wa=(Int32 *)(wa); \
        !           123:                             Label _ca=(Label)(ca); \
        !           124:                             if (_ca==_DOCOL_LABEL)  \
        !           125:                               _wa[0]=(((0x1a<<26)|(31<<21)|(9<<16))| \
        !           126:                                       (((((Cell)_ca)-((Cell)_wa)-4) & 0xffff)>>2)); \
        !           127:                             else { \
        !           128:                               _wa[0]=((((Int32 *)_CPU_DEP_LABEL)[0] & 0xffff0000)| \
        !           129:                                       ((((Cell)_ca)-((Cell)_DOCOL_LABEL)) & 0xffff)); \
        !           130:                               _wa[1]=((((Int32 *)_CPU_DEP_LABEL)[1] & 0xffffc000)| \
        !           131:                                       (((((Cell)_ca)-((Cell)_wa)-8) & 0xffff)>>2));  \
        !           132:                             } \
        !           133:                        })
        !           134: 
        !           135: /* this is the point where the does code for the word with the xt cfa
        !           136:    starts. Because the jump to the code field takes only one cell on
        !           137:    64-bit systems we can use the second cell of the cfa for storing
        !           138:    the does address */
        !           139: #define DOES_CODE(cfa) \
        !           140:      ({ Int32 *_wa=(cfa); \
        !           141:        (_wa[0] == ((((Int32 *)_CPU_DEP_LABEL)[0] & 0xffff0000)| \
        !           142:                    ((((Cell)&&dodoes)-((Cell)&&docol)) & 0xffff)) && \
        !           143:         (_wa[1]&0xffffc000) == (((Int32 *)_CPU_DEP_LABEL)[1] & 0xffffc000)) \
        !           144:        ? DOES_CODE1(_wa) : 0; })
        !           145: 
        !           146: /* this is a special version of DOES_CODE for use in dodoes */
        !           147: #define DOES_CODE1(cfa)        ((Xt *)(((Cell *)(cfa))[1]))
        !           148: 
        !           149: /* the does handler resides between DOES> and the following Forth
        !           150:    code. Since the code-field jumps directly to dodoes, the
        !           151:    does-handler is not needed for the Alpha architecture */
        !           152: #define MAKE_DOES_HANDLER(addr)   0
        !           153: 
        !           154: /* This makes a code field for a does-defined word. doesp is the
        !           155:    address of the does-code. On the Alpha, the code field consists of
        !           156:    a jump to dodoes and the address of the does code */
        !           157: #define MAKE_DOES_CF(cfa,doesp) ({Xt *_cfa = (Xt *)(cfa); \
        !           158:                                    MAKE_CF(_cfa, symbols[DODOES]); \
        !           159:                                    _cfa[1] = (doesp); })
        !           160: #endif
        !           161: 

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