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>