* src/vm/jit/md.h (md_get_method_patch_address): Removed.
[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/types.h"
42
43 #include "vm/jit/alpha/codegen.h"
44 #include "vm/jit/alpha/md-abi.h"
45
46 #include "vm/exceptions.h"
47
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/codegen-common.h"
50 #include "vm/jit/jit.h"
51 #include "vm/jit/md.h"
52
53
54 /* global variables ***********************************************************/
55
56 bool has_ext_instr_set = false;             /* has instruction set extensions */
57
58
59 /* md_init *********************************************************************
60
61    Do some machine dependent initialization.
62
63 *******************************************************************************/
64
65 void md_init(void)
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         ieee_set_fp_control(ieee_get_fp_control()
80                                                 & ~IEEE_TRAP_ENABLE_INV
81                                                 & ~IEEE_TRAP_ENABLE_DZE
82 /*                                              & ~IEEE_TRAP_ENABLE_UNF   we dont want underflow */
83                                                 & ~IEEE_TRAP_ENABLE_OVF);
84 #endif
85 }
86
87
88 /* md_stacktrace_get_returnaddress *********************************************
89
90    Returns the return address of the current stackframe, specified by
91    the passed stack pointer and the stack frame size.
92
93 *******************************************************************************/
94
95 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
96 {
97         u1 *ra;
98
99         /* on Alpha the return address is located on the top of the stackframe */
100
101         ra = *((u1 **) (sp + framesize - SIZEOF_VOID_P));
102
103         return ra;
104 }
105
106
107 /* md_jit_method_patch_address *************************************************
108
109    Gets the patch address of the currently compiled method. The offset
110    is extracted from the load instruction(s) before the jump and added
111    to the right base address (PV or REG_METHODPTR).
112
113    INVOKESTATIC/SPECIAL:
114
115    a77bffb8    ldq     pv,-72(pv)
116    6b5b4000    jsr     (pv)
117
118    INVOKEVIRTUAL:
119
120    a7900000    ldq     at,0(a0)
121    a77c0000    ldq     pv,0(at)
122    6b5b4000    jsr     (pv)
123
124    INVOKEINTERFACE:
125
126    a7900000    ldq     at,0(a0)
127    a79cff98    ldq     at,-104(at)
128    a77c0018    ldq     pv,24(at)
129    6b5b4000    jsr     (pv)
130
131 *******************************************************************************/
132
133 void *md_jit_method_patch_address(void *pv, void *ra, void *mptr)
134 {
135         uint32_t *pc;
136         uint32_t  mcode;
137         int       opcode;
138         int       base;
139         int32_t   disp;
140         void     *pa;                       /* patch address                      */
141
142         /* Go back to the load instruction (2 instructions). */
143
144         pc = ((uint32_t *) ra) - 2;
145
146         /* Get first instruction word. */
147
148         mcode = pc[0];
149
150         /* Get opcode, base register and displacement. */
151
152         opcode = M_MEM_GET_Opcode(mcode);
153         base   = M_MEM_GET_Rb(mcode);
154         disp   = M_MEM_GET_Memory_disp(mcode);
155
156         /* Check for short or long load (2 instructions). */
157
158         switch (opcode) {
159         case 0x29: /* LDQ: TODO use define */
160                 switch (base) {
161                 case REG_PV:
162                         /* Calculate the data segment address. */
163
164                         pa = ((uint8_t *) pv) + disp;
165                         break;
166
167                 case REG_METHODPTR:
168                         /* Return NULL if no mptr was specified (used for
169                            replacement). */
170
171                         if (mptr == NULL)
172                                 return NULL;
173
174                         /* Calculate the address in the vftbl. */
175
176                         pa = ((uint8_t *) mptr) + disp;
177                         break;
178
179                 default:
180                         vm_abort_disassemble(pc, 2, "md_jit_method_patch_address: unknown instruction %x", mcode);
181                         return NULL;
182                 }
183                 break;
184
185         case 0x09: /* LDAH: TODO use define */
186                 /* XXX write a regression for this */
187
188                 vm_abort("md_jit_method_patch_address: IMPLEMENT ME!");
189
190                 pa = NULL;
191                 break;
192
193         default:
194                 vm_abort_disassemble(pc, 2, "md_jit_method_patch_address: unknown instruction %x", mcode);
195                 return NULL;
196         }
197
198         return pa;
199 }
200
201
202 /* md_codegen_get_pv_from_pc ***************************************************
203
204    Machine code:
205
206    6b5b4000    jsr     (pv)
207    277afffe    ldah    pv,-2(ra)
208    237ba61c    lda     pv,-23012(pv)
209
210 *******************************************************************************/
211
212 u1 *md_codegen_get_pv_from_pc(u1 *ra)
213 {
214         u1 *pv;
215         u4  mcode;
216         s4  offset;
217
218         pv = ra;
219
220         /* get first instruction word after jump */
221
222         mcode = *((u4 *) ra);
223
224         /* check if we have 2 instructions (ldah, lda) */
225
226         if ((mcode >> 16) == 0x277a) {
227                 /* get displacement of first instruction (ldah) */
228
229                 offset = (s4) (mcode << 16);
230                 pv += offset;
231
232                 /* get displacement of second instruction (lda) */
233
234                 mcode = *((u4 *) (ra + 1 * 4));
235
236                 assert((mcode >> 16) == 0x237b);
237
238                 offset = (s2) (mcode & 0x0000ffff);
239                 pv += offset;
240         }
241         else {
242                 /* get displacement of first instruction (lda) */
243
244                 assert((mcode >> 16) == 0x237a);
245
246                 offset = (s2) (mcode & 0x0000ffff);
247                 pv += offset;
248         }
249
250         return pv;
251 }
252
253
254 /* md_cacheflush ***************************************************************
255
256    Calls the system's function to flush the instruction and data
257    cache.
258
259 *******************************************************************************/
260
261 void md_cacheflush(u1 *addr, s4 nbytes)
262 {
263         asm_cacheflush(addr, nbytes);
264 }
265
266
267 /* md_icacheflush **************************************************************
268
269    Calls the system's function to flush the instruction cache.
270
271 *******************************************************************************/
272
273 void md_icacheflush(u1 *addr, s4 nbytes)
274 {
275         asm_cacheflush(addr, nbytes);
276 }
277
278
279 /* md_dcacheflush **************************************************************
280
281    Calls the system's function to flush the data cache.
282
283 *******************************************************************************/
284
285 void md_dcacheflush(u1 *addr, s4 nbytes)
286 {
287         /* do nothing */
288 }
289
290
291 /* md_patch_replacement_point **************************************************
292
293    Patch the given replacement point.
294
295 *******************************************************************************/
296
297 #if defined(ENABLE_REPLACEMENT)
298 void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
299 {
300         u4 mcode;
301
302         if (revert) {
303                 /* restore the patched-over instruction */
304                 *(u4*)(pc) = *(u4*)(savedmcode);
305         }
306         else {
307                 /* save the current machine code */
308                 *(u4*)(savedmcode) = *(u4*)(pc);
309
310                 /* build the machine code for the patch */
311                 mcode = (0xa41f0000 | (EXCEPTION_HARDWARE_PATCHER));
312
313                 /* write the new machine code */
314                 *(u4*)(pc) = mcode;
315         }
316         
317         /* flush instruction cache */
318     md_icacheflush(pc,4);
319 }
320 #endif /* defined(ENABLE_REPLACEMENT) */
321
322
323 /*
324  * These are local overrides for various environment variables in Emacs.
325  * Please do not remove this and leave it at the end of the file, where
326  * Emacs will automagically detect them.
327  * ---------------------------------------------------------------------
328  * Local variables:
329  * mode: c
330  * indent-tabs-mode: t
331  * c-basic-offset: 4
332  * tab-width: 4
333  * End:
334  * vim:noexpandtab:sw=4:ts=4:
335  */