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