1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
/* This is the machine-specific part for MIPS R[2346810]000 processors
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.
*/
#if !defined(USE_TOS) && !defined(USE_NO_TOS)
/* on the mips this is a mixed blessing, since defining this spills
the rp with some gcc versions. This machine has 31 regs, yet that's
not enough for gcc-2.4.5 :-( */
#define USE_TOS
#endif
/* cache flush stuff */
#ifndef INDIRECT_THREADED
#ifndef DIRECT_THREADED
#define DIRECT_THREADED
/* direct threading saves 2 cycles per primitive on an R3000, 4 on an R4000 */
#endif
#endif
#ifdef ultrix
#include <mips/cachectl.h>
#else
/* works on Irix */
#include <sys/cachectl.h>
#endif
#define FLUSH_ICACHE(addr,size) \
cacheflush((char *)(addr), (int)(size), BCACHE)
#include "32bit.h"
#ifdef DIRECT_THREADED
/* some definitions for composing opcodes */
#define JUMP_MASK 0x03ffffff
#define J_PATTERN 0x08000000
#define JAL_PATTERN 0x0c000000
/* this provides the first 4 bits of a jump address, i.e. it must be <16 */
#define SEGMENT_NUM 1
#define JUMP(addr) (J_PATTERN|((((unsigned)(addr))&JUMP_MASK)>>2))
#define CALL(addr) (JAL_PATTERN|((((unsigned)(addr))&JUMP_MASK)>>2))
/* 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 */
# define PFA1(cfa) PFA(cfa)
/* CODE_ADDRESS is the address of the code jumped to through the code field */
# define CODE_ADDRESS(cfa) ((Label)(((*(unsigned *)(cfa))^J_PATTERN^(SEGMENT_NUM<<26))<<2))
/* MAKE_CF creates an appropriate code field at the cfa; ca is the code address */
# define MAKE_CF(cfa,ca) ({long * _cfa = (long *)(cfa); \
_cfa[0] = JUMP(ca); \
_cfa[1] = 0; /* nop */})
# ifdef undefined
/* the following version uses JAL to make PFA1 faster */
# define PFA1(label) ({register Cell *pfa asm("$31"); \
pfa; })
/* CODE_ADDRESS is the address of the code jumped to through the code field */
# define CODE_ADDRESS(cfa) ((Label)(((*(unsigned *)(cfa))^JAL_PATTERN^(SEGMENT_NUM<<26))<<2))
# define MAKE_CF(cfa,ca) ({long *_cfa = (long *)(cfa); \
long _ca = (long)(ca); \
_cfa[0] = CALL(_ca); \
_cfa[1] = 0; /* *(long *)_ca; delay slot */})
# endif /* undefined */
/* this is the point where the does code starts if cfa points to a
code field of a does>-defined word */
#define DOES_CODE(cfa) \
({ Xt _cfa=(Xt)(cfa); \
Label _ca=CODE_ADDRESS(_cfa); \
((*(unsigned *)_cfa)&(~JUMP_MASK)) == J_PATTERN && \
(*(unsigned *)_ca) == JUMP(symbols[DODOES]) \
? _ca+DOES_HANDLER_SIZE : 0; })
/* this is a special version of DOES_CODE for use in dodoes */
#define DOES_CODE1(cfa) ((Xt *)(((char *)CODE_ADDRESS(cfa))+DOES_HANDLER_SIZE))
# define MAKE_DOES_CF(cfa,does_code) \
({long does_handlerp=((long)(does_code))-DOES_HANDLER_SIZE; \
long *_cfa = (long*)(cfa); \
_cfa[0] = JUMP(does_handlerp); \
_cfa[1] = 0; /* nop */})
/*
# define MAKE_DOES_CF(cfa, does_code) ({char *does_handlerp=((char *)does_code)-DOES_HANDLER_SIZE; \
MAKE_CF(cfa,does_handlerp); \
MAKE_DOES_HANDLER(does_handlerp) ;})
*/
/* this stores a jump dodoes at addr */
# define MAKE_DOES_HANDLER(addr) MAKE_CF(addr,symbols[DODOES])
#endif
#ifdef undefined
/* and here are some more efficient versions that can be tried later */
/* the first version saves one cycle by doing something useful in the
delay slot. !! check that the instruction in the delay slot is legal
*/
#define MAKE_DOESJUMP(addr) ({long * _addr = (long *)addr; \
_addr[0] = JUMP(((unsigned)symbols[DODOES])+4); \
_addr[1] = *(long *)symbols[DODOES]; /* delay */})
/* the following version uses JAL to make DOES_CODE1 faster */
/* !! does the declaration clear the register ? */
/* it's ok to use the same reg as in PFA1:
dodoes is the only potential problem and I have taken care of it */
#define DOES_CODE1(cfa) ({register Code *_does_code asm("$31"); \
_does_code; })
#define MAKE_DOESJUMP(addr) ({long * _addr = (long *)addr; \
_addr[0] = CALL(((long)symbols[DODOES])+4);
_addr[1] = *(long *)symbols[DODOES]; /* delay */})
#endif
#ifdef FORCE_REG
#define IPREG asm("$16")
#define SPREG asm("$17")
#define RPREG asm("$18")
#define LPREG asm("$19")
#define CFAREG asm("$20")
#define TOSREG asm("$21")
#endif /* FORCE_REG */
|