File:
[gforth] /
gforth /
arch /
alpha /
machine.h
Revision
1.2:
download - view:
text,
annotated -
select for diffs
Mon Sep 1 23:08:19 1997 UTC (25 years, 6 months ago) by
jwilke
Branches:
MAIN
CVS tags:
HEAD
Dos Changes:
!!Moved:
engine/32bit.h moved to arch/generic/machine.h
cache.c moved to arch/hppa/
cleanalign.c moved to engine/
!!New Files:
envos.* *.bsh
Instead of linking arch/xy/machine.h an custom include path is used
engine.a engine.o main.o makes with engine/Makefile now
history.fs and startup.fs works for dos and unix now
environment variable osclass is set in envos.fs, wich is os-specific
any comments?
supressed some warnings in main.c
/* preliminary machine file for DEC Alpha
Copyright (C) 1995 Free Software Foundation, Inc.
This file is part of Gforth.
Gforth is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Be careful: long long on Alpha are 64 bit :-(( */
#define LONG_LATENCY
#if !defined(USE_TOS) && !defined(USE_NO_TOS)
#define USE_TOS
#endif
#ifndef INDIRECT_THREADED
#ifndef DIRECT_THREADED
#define DIRECT_THREADED
#endif
#endif
#define FLUSH_ICACHE(addr,size) asm("call_pal 0x86") /* imb (instruction-memory barrier) */
#include "../generic/machine.h"
#ifdef DIRECT_THREADED
#ifdef WORDS_BIGENDIAN
#error Direct threading only supported for little-endian Alphas.
/* big-endian Alphas still store instructions in little-endian format,
so you would have to reverse the instruction accesses in the following
*/
#endif
#if SIZEOF_CHAR_P != 8
#error Direct threading only supported for Alphas with 64-bit Cells.
/* some of the stuff below assumes that the first cell in a code field
can contain 2 instructions
A simple way around this problem would be to have _alpha_docol
contain &&dodoes. This would slow down colon defs, however.
Another way is to use a special DOES_HANDLER, like most other CPUs */
#endif
#warning Direct threading for Alpha may not work with all gcc versions
#warning ;CODE does not work on the Alpha with direct threading
/* ;CODE puts a jump to the code after ;CODE into the defined
word. The code generated for the jump can only jump to targets near
docol (near means: within 32KB). Because the code is far from
docol, this does not work.
Solution: let the code be: x=cfa[1]; goto *x;
*/
typedef int Int32;
typedef short Int16;
/* PFA gives the parameter field address corresponding to a cfa */
#define PFA(cfa) (((Cell *)cfa)+2)
/* PFA1 is a special version for use just after a NEXT1 */
/* the improvement here is that we may destroy cfa before using PFA1 */
#define PFA1(cfa) PFA(cfa)
/*
On the Alpha, code (in the text segment) typically cannot be
reached from the dictionary (in the data segment) with a normal
branch. It also usually takes too long (and too much space on
32-bit systems) to load the address as literal and jump indirectly.
So, what we do is this: a pointer into our code (at docol, to be
exact) is kept in a register: _alpha_docol. When the inner
interpreter jumps to the word address of a variable etc., the
destination address is computed from that with a lda instruction
and stored in another register: _alpha_ca. Then an indirect jump
through _alpha_ca is performed. For docol, we need not compute
_alpha_ca first.
How do we tell gcc all this? We declare the registers as variables:
_alpha_docol as explicit variable, to avoid spilling; _alpha_ca is
so short-lived, so it hopefully won't be spilled. A
pseudo-primitive cpu_dep is created with code that lets gcc's data
flow analysis know that _alpha_docol is used and that _alpha_ca may
be defined and used after any NEXT and before any primitive. We
let gcc choose the register for _alpha_ca and simply change the
code gcc produces for the cpu_dep routine.
*/
#define CPU_DEP2 register Label _alpha_docol asm("$9")=&&docol; \
register Label _alpha_ca;
#define CPU_DEP3 cpu_dep: asm("lda %0, 500(%1)":"=r"(_alpha_ca):"r"(_alpha_docol)); goto *_alpha_ca;
#define CPU_DEP1 (&&cpu_dep)
/* CODE_ADDRESS is the address of the code jumped to through the code field */
#define CODE_ADDRESS(wa) ({Int32 *_wa=(Int32 *)(wa); \
(_wa[0]&0xfc000000)==0x68000000 ? /*JMP?*/\
&&docol : \
&&docol+((Int16 *)_wa)[0]; })
#define _CPU_DEP_LABEL (symbols[DOESJUMP])
#define _DOCOL_LABEL (symbols[DOCOL])
/* MAKE_CF creates an appropriate code field at the wa; ca is the code
address. For the Alpha, this is a lda followed by a jmp (or just a
jmp, if ca==&&docol). We patch the jmp with a good hint (on the
21064A this saves 5 cycles!) */
#define MAKE_CF(wa,ca) ({ \
Int32 *_wa=(Int32 *)(wa); \
Label _ca=(Label)(ca); \
if (_ca==_DOCOL_LABEL) \
_wa[0]=(((0x1a<<26)|(31<<21)|(9<<16))| \
(((((Cell)_ca)-((Cell)_wa)-4) & 0xffff)>>2)); \
else { \
_wa[0]=((((Int32 *)_CPU_DEP_LABEL)[0] & 0xffff0000)| \
((((Cell)_ca)-((Cell)_DOCOL_LABEL)) & 0xffff)); \
_wa[1]=((((Int32 *)_CPU_DEP_LABEL)[1] & 0xffffc000)| \
(((((Cell)_ca)-((Cell)_wa)-8) & 0xffff)>>2)); \
} \
})
/* this is the point where the does code for the word with the xt cfa
starts. Because the jump to the code field takes only one cell on
64-bit systems we can use the second cell of the cfa for storing
the does address */
#define DOES_CODE(cfa) \
({ Int32 *_wa=(cfa); \
(_wa[0] == ((((Int32 *)_CPU_DEP_LABEL)[0] & 0xffff0000)| \
((((Cell)&&dodoes)-((Cell)&&docol)) & 0xffff)) && \
(_wa[1]&0xffffc000) == (((Int32 *)_CPU_DEP_LABEL)[1] & 0xffffc000)) \
? DOES_CODE1(_wa) : 0; })
/* this is a special version of DOES_CODE for use in dodoes */
#define DOES_CODE1(cfa) ((Xt *)(((Cell *)(cfa))[1]))
/* the does handler resides between DOES> and the following Forth
code. Since the code-field jumps directly to dodoes, the
does-handler is not needed for the Alpha architecture */
#define MAKE_DOES_HANDLER(addr) 0
/* This makes a code field for a does-defined word. doesp is the
address of the does-code. On the Alpha, the code field consists of
a jump to dodoes and the address of the does code */
#define MAKE_DOES_CF(cfa,doesp) ({Xt *_cfa = (Xt *)(cfa); \
MAKE_CF(_cfa, symbols[DODOES]); \
_cfa[1] = (doesp); })
#endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>