125ff089211127a14b9eeb2db0d541ecc0e209fd
[cacao.git] / src / vm / jit / alpha / md.c
1 /* src/vm/jit/alpha/md.c - machine dependent Alpha functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25 */
26
27
28 #include "config.h"
29
30 #include <assert.h>
31 #include <stdint.h>
32 #include <ucontext.h>
33
34 #if defined(__LINUX__)
35 # include <asm/fpu.h>
36
37 extern unsigned long ieee_get_fp_control();
38 extern void ieee_set_fp_control(unsigned long fp_control);
39 #endif
40
41 #include "vm/jit/alpha/codegen.h"
42 #include "vm/jit/alpha/md.h"
43
44 #include "vm/exceptions.h"
45
46 #include "vm/jit/asmpart.h"
47 #include "vm/jit/jit.h"
48
49
50 /* global variables ***********************************************************/
51
52 bool has_ext_instr_set = false;             /* has instruction set extensions */
53
54
55 /* md_init *********************************************************************
56
57    Do some machine dependent initialization.
58
59 *******************************************************************************/
60
61 void md_init(void)
62 {
63 #if defined(__LINUX__)
64         unsigned long int fpcw;
65 #endif
66
67         /* check for extended instruction set */
68
69         has_ext_instr_set = !asm_md_init();
70
71 #if defined(__LINUX__)
72         /* Linux on Digital Alpha needs an initialisation of the ieee
73            floating point control for IEEE compliant arithmetic (option
74            -mieee of GCC). Under Digital Unix this is done
75            automatically. */
76
77         /* initialize floating point control */
78
79         fpcw = ieee_get_fp_control();
80
81         fpcw = fpcw
82                 & ~IEEE_TRAP_ENABLE_INV
83                 & ~IEEE_TRAP_ENABLE_DZE
84                 /* We dont want underflow. */
85 /*              & ~IEEE_TRAP_ENABLE_UNF */
86                 & ~IEEE_TRAP_ENABLE_OVF;
87
88 /*      fpcw = fpcw */
89 /*              | IEEE_TRAP_ENABLE_INV */
90 /*              | IEEE_TRAP_ENABLE_DZE */
91 /*              | IEEE_TRAP_ENABLE_OVF */
92 /*              | IEEE_TRAP_ENABLE_UNF */
93 /*              | IEEE_TRAP_ENABLE_INE */
94 /*              | IEEE_TRAP_ENABLE_DNO; */
95
96         ieee_set_fp_control(fpcw);
97 #endif
98 }
99
100
101 /* md_jit_method_patch_address *************************************************
102
103    Gets the patch address of the currently compiled method. The offset
104    is extracted from the load instruction(s) before the jump and added
105    to the right base address (PV or REG_METHODPTR).
106
107    INVOKESTATIC/SPECIAL:
108
109    a77bffb8    ldq     pv,-72(pv)
110    6b5b4000    jsr     (pv)
111
112    INVOKEVIRTUAL:
113
114    a7900000    ldq     at,0(a0)
115    a77c0000    ldq     pv,0(at)
116    6b5b4000    jsr     (pv)
117
118    INVOKEINTERFACE:
119
120    a7900000    ldq     at,0(a0)
121    a79cff98    ldq     at,-104(at)
122    a77c0018    ldq     pv,24(at)
123    6b5b4000    jsr     (pv)
124
125 *******************************************************************************/
126
127 void *md_jit_method_patch_address(void *pv, void *ra, void *mptr)
128 {
129         uint32_t *pc;
130         uint32_t  mcode;
131         int       opcode;
132         int       base;
133         int32_t   disp;
134         void     *pa;                       /* patch address                      */
135
136         /* Go back to the load instruction (2 instructions). */
137
138         pc = ((uint32_t *) ra) - 2;
139
140         /* Get first instruction word. */
141
142         mcode = pc[0];
143
144         /* Get opcode, base register and displacement. */
145
146         opcode = M_MEM_GET_Opcode(mcode);
147         base   = M_MEM_GET_Rb(mcode);
148         disp   = M_MEM_GET_Memory_disp(mcode);
149
150         /* Check for short or long load (2 instructions). */
151
152         switch (opcode) {
153         case 0x29: /* LDQ: TODO use define */
154                 switch (base) {
155                 case REG_PV:
156                         /* Calculate the data segment address. */
157
158                         pa = ((uint8_t *) pv) + disp;
159                         break;
160
161                 case REG_METHODPTR:
162                         /* Return NULL if no mptr was specified (used for
163                            replacement). */
164
165                         if (mptr == NULL)
166                                 return NULL;
167
168                         /* Calculate the address in the vftbl. */
169
170                         pa = ((uint8_t *) mptr) + disp;
171                         break;
172
173                 default:
174                         vm_abort_disassemble(pc, 2, "md_jit_method_patch_address: unknown instruction %x", mcode);
175                         return NULL;
176                 }
177                 break;
178
179         case 0x09: /* LDAH: TODO use define */
180                 /* XXX write a regression for this */
181
182                 vm_abort("md_jit_method_patch_address: IMPLEMENT ME!");
183
184                 pa = NULL;
185                 break;
186
187         default:
188                 vm_abort_disassemble(pc, 2, "md_jit_method_patch_address: unknown instruction %x", mcode);
189                 return NULL;
190         }
191
192         return pa;
193 }
194
195
196 /* md_patch_replacement_point **************************************************
197
198    Patch the given replacement point.
199
200 *******************************************************************************/
201
202 #if defined(ENABLE_REPLACEMENT)
203 void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
204 {
205         u4 mcode;
206
207         if (revert) {
208                 /* restore the patched-over instruction */
209                 *(u4*)(pc) = *(u4*)(savedmcode);
210         }
211         else {
212                 /* save the current machine code */
213                 *(u4*)(savedmcode) = *(u4*)(pc);
214
215                 /* build the machine code for the patch */
216                 mcode = (0xa41f0000 | (EXCEPTION_HARDWARE_PATCHER));
217
218                 /* write the new machine code */
219                 *(u4*)(pc) = mcode;
220         }
221         
222         /* flush instruction cache */
223     md_icacheflush(pc,4);
224 }
225 #endif /* defined(ENABLE_REPLACEMENT) */
226
227
228 /*
229  * These are local overrides for various environment variables in Emacs.
230  * Please do not remove this and leave it at the end of the file, where
231  * Emacs will automagically detect them.
232  * ---------------------------------------------------------------------
233  * Local variables:
234  * mode: c
235  * indent-tabs-mode: t
236  * c-basic-offset: 4
237  * tab-width: 4
238  * End:
239  * vim:noexpandtab:sw=4:ts=4:
240  */