* src/vm/jit/patcher-common.c: Moved to .cpp.
[cacao.git] / src / vm / jit / alpha / patcher.c
1 /* src/vm/jit/alpha/patcher.c - Alpha code patching functions
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29
30 #include "vm/types.h"
31
32 #include "vm/jit/alpha/md.h"
33
34 #include "mm/memory.h"
35
36 #include "native/native.h"
37
38 #include "vm/jit/builtin.hpp"
39 #include "vm/class.h"
40 #include "vm/field.hpp"
41 #include "vm/initialize.h"
42 #include "vm/options.h"
43 #include "vm/references.h"
44 #include "vm/resolve.h"
45
46 #include "vm/jit/asmpart.h"
47 #include "vm/jit/patcher-common.hpp"
48 #include "vm/jit/methodheader.h"
49
50
51 #define PATCH_BACK_ORIGINAL_MCODE \
52         *((u4 *) pr->mpc) = (u4) pr->mcode; \
53     md_icacheflush(NULL, 0);
54
55
56 /* patcher_patch_code **********************************************************
57
58    Just patches back the original machine code.
59
60 *******************************************************************************/
61
62 void patcher_patch_code(patchref_t *pr)
63 {
64         PATCH_BACK_ORIGINAL_MCODE;
65 }
66
67
68 /* patcher_resolve_classref_to_classinfo ***************************************
69
70    ACONST:
71
72    <patched call postition>
73    a61bff80    ldq     a0,-128(pv)
74
75    MULTIANEWARRAY:
76
77    <patched call position>
78    a63bff80    ldq     a1,-128(pv)
79    47de0412    mov     sp,a2
80    a77bff78    ldq     pv,-136(pv)
81    6b5b4000    jsr     (pv)
82
83    ARRAYCHECKCAST:
84
85    <patched call position>
86    a63bfe60    ldq     a1,-416(pv)
87    a77bfe58    ldq     pv,-424(pv)
88    6b5b4000    jsr     (pv)
89
90 *******************************************************************************/
91
92 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
93 {
94         constant_classref *cr;
95         u1                *datap;
96         classinfo         *c;
97
98         /* get stuff from the stack */
99
100         cr    = (constant_classref *) pr->ref;
101         datap = (u1 *)                pr->datap;
102
103         /* get the classinfo */
104
105         if (!(c = resolve_classref_eager(cr)))
106                 return false;
107
108         PATCH_BACK_ORIGINAL_MCODE;
109
110         /* patch the classinfo pointer */
111
112         *((ptrint *) datap) = (ptrint) c;
113
114         return true;
115 }
116
117
118 /* patcher_resolve_classref_to_vftbl *******************************************
119
120    CHECKCAST (class):
121    INSTANCEOF (class):
122
123    <patched call position>
124    a7940000    ldq     at,0(a4)
125    a7bbff28    ldq     gp,-216(pv)
126
127 *******************************************************************************/
128
129 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
130 {
131         constant_classref *cr;
132         u1                *datap;
133         classinfo         *c;
134
135         /* get stuff from the stack */
136
137         cr    = (constant_classref *) pr->ref;
138         datap = (u1 *)                pr->datap;
139
140         /* get the fieldinfo */
141
142         if (!(c = resolve_classref_eager(cr)))
143                 return false;
144
145         PATCH_BACK_ORIGINAL_MCODE;
146
147         /* patch super class' vftbl */
148
149         *((ptrint *) datap) = (ptrint) c->vftbl;
150
151         return true;
152 }
153
154
155 /* patcher_resolve_classref_to_flags *******************************************
156
157    CHECKCAST/INSTANCEOF:
158
159    <patched call position>
160
161 *******************************************************************************/
162
163 bool patcher_resolve_classref_to_flags(patchref_t *pr)
164 {
165         constant_classref *cr;
166         u1                *datap;
167         classinfo         *c;
168
169         /* get stuff from the stack */
170
171         cr    = (constant_classref *) pr->ref;
172         datap = (u1 *)                pr->datap;
173
174         /* get the fieldinfo */
175
176         if (!(c = resolve_classref_eager(cr)))
177                 return false;
178
179         PATCH_BACK_ORIGINAL_MCODE;
180
181         /* patch class flags */
182
183         *((s4 *) datap) = (s4) c->flags;
184
185         return true;
186 }
187
188
189 /* patcher_get_putstatic *******************************************************
190
191    Machine code:
192
193    <patched call position>
194    a73bff98    ldq     t11,-104(pv)
195    a2590000    ldl     a2,0(t11)
196
197 *******************************************************************************/
198
199 bool patcher_get_putstatic(patchref_t *pr)
200 {
201         unresolved_field *uf;
202         u1               *datap;
203         fieldinfo        *fi;
204
205         /* get stuff from the stack */
206
207         uf    = (unresolved_field *) pr->ref;
208         datap = (u1 *)               pr->datap;
209
210         /* get the fieldinfo */
211
212         if (!(fi = resolve_field_eager(uf)))
213                 return false;
214
215         /* check if the field's class is initialized */
216
217         if (!(fi->clazz->state & CLASS_INITIALIZED))
218                 if (!initialize_class(fi->clazz))
219                         return false;
220
221         PATCH_BACK_ORIGINAL_MCODE;
222
223         /* patch the field value's address */
224
225         *((intptr_t *) datap) = (intptr_t) fi->value;
226
227         return true;
228 }
229
230
231 /* patcher_get_putfield ********************************************************
232
233    Machine code:
234
235    <patched call position>
236    a2af0020    ldl     a5,32(s6)
237
238 *******************************************************************************/
239
240 bool patcher_get_putfield(patchref_t *pr)
241 {
242         u1               *ra;
243         unresolved_field *uf;
244         fieldinfo        *fi;
245
246         ra    = (u1 *)               pr->mpc;
247         uf    = (unresolved_field *) pr->ref;
248
249         /* get the fieldinfo */
250
251         if (!(fi = resolve_field_eager(uf)))
252                 return false;
253
254         PATCH_BACK_ORIGINAL_MCODE;
255
256         /* patch the field's offset into the instruction */
257
258         *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
259
260         md_icacheflush(NULL, 0);
261
262         return true;
263 }
264
265
266 /* patcher_invokestatic_special ************************************************
267
268    Machine code:
269
270    <patched call position>
271    a77bffa8    ldq     pv,-88(pv)
272    6b5b4000    jsr     (pv)
273
274 ******************************************************************************/
275
276 bool patcher_invokestatic_special(patchref_t *pr)
277 {
278         unresolved_method *um;
279         u1                *datap;
280         methodinfo        *m;
281
282         /* get stuff from the stack */
283
284         um    = (unresolved_method *) pr->ref;
285         datap = (u1 *)                pr->datap;
286
287         /* get the fieldinfo */
288
289         if (!(m = resolve_method_eager(um)))
290                 return false;
291
292         PATCH_BACK_ORIGINAL_MCODE;
293
294         /* patch stubroutine */
295
296         *((ptrint *) datap) = (ptrint) m->stubroutine;
297
298         return true;
299 }
300
301
302 /* patcher_invokevirtual *******************************************************
303
304    Machine code:
305
306    <patched call position>
307    a7900000    ldq     at,0(a0)
308    a77c0100    ldq     pv,256(at)
309    6b5b4000    jsr     (pv)
310
311 *******************************************************************************/
312
313 bool patcher_invokevirtual(patchref_t *pr)
314 {
315         u1                *ra;
316         unresolved_method *um;
317         methodinfo        *m;
318
319         /* get stuff from the stack */
320
321         ra    = (u1 *)                pr->mpc;
322         um    = (unresolved_method *) pr->ref;
323
324         /* get the fieldinfo */
325
326         if (!(m = resolve_method_eager(um)))
327                 return false;
328
329         PATCH_BACK_ORIGINAL_MCODE;
330
331         /* patch vftbl index */
332
333         *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
334                                                                  sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
335
336         md_icacheflush(NULL, 0);
337
338         return true;
339 }
340
341
342 /* patcher_invokeinterface *****************************************************
343
344    Machine code:
345
346    <patched call position>
347    a7900000    ldq     at,0(a0)
348    a79cffa0    ldq     at,-96(at)
349    a77c0018    ldq     pv,24(at)
350    6b5b4000    jsr     (pv)
351
352 *******************************************************************************/
353
354 bool patcher_invokeinterface(patchref_t *pr)
355 {
356         u1                *ra;
357         unresolved_method *um;
358         methodinfo        *m;
359
360         /* get stuff from the stack */
361
362         ra    = (u1 *)                pr->mpc;
363         um    = (unresolved_method *) pr->ref;
364
365         /* get the fieldinfo */
366
367         if (!(m = resolve_method_eager(um)))
368                 return false;
369
370         PATCH_BACK_ORIGINAL_MCODE;
371
372         /* patch interfacetable index */
373
374         *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
375                                                                  sizeof(methodptr*) * m->clazz->index) & 0x0000ffff);
376
377         /* patch method offset */
378
379         *((s4 *) (ra + 4 + 4)) |=
380                 (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x0000ffff);
381
382         md_icacheflush(NULL, 0);
383
384         return true;
385 }
386
387
388 /* patcher_checkcast_interface *************************************************
389
390    Machine code:
391
392    <patched call position>
393    a78e0000    ldq     at,0(s5)
394    a3bc001c    ldl     gp,28(at)
395    23bdfffd    lda     gp,-3(gp)
396    efa0002e    ble     gp,0x00000200002bf6b0
397    a7bcffe8    ldq     gp,-24(at)
398
399 *******************************************************************************/
400
401 bool patcher_checkcast_interface(patchref_t *pr)
402 {
403         u1                *ra;
404         constant_classref *cr;
405         classinfo         *c;
406
407         /* get stuff from the stack */
408
409         ra    = (u1 *)                pr->mpc;
410         cr    = (constant_classref *) pr->ref;
411
412         /* get the fieldinfo */
413
414         if (!(c = resolve_classref_eager(cr)))
415                 return false;
416
417         PATCH_BACK_ORIGINAL_MCODE;
418
419         /* patch super class index */
420
421         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
422
423         *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
424                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
425
426         md_icacheflush(NULL, 0);
427
428         return true;
429 }
430
431
432 /* patcher_instanceof_interface ************************************************
433
434    Machine code:
435
436    <patched call position>
437    a78e0000    ldq     at,0(s5)
438    a3bc001c    ldl     gp,28(at)
439    23bdfffd    lda     gp,-3(gp)
440    efa0002e    ble     gp,0x00000200002bf6b0
441    a7bcffe8    ldq     gp,-24(at)
442
443 *******************************************************************************/
444
445 bool patcher_instanceof_interface(patchref_t *pr)
446 {
447         u1                *ra;
448         constant_classref *cr;
449         classinfo         *c;
450
451         /* get stuff from the stack */
452
453         ra    = (u1 *)                pr->mpc;
454         cr    = (constant_classref *) pr->ref;
455
456         /* get the fieldinfo */
457
458         if (!(c = resolve_classref_eager(cr)))
459                 return false;
460
461         PATCH_BACK_ORIGINAL_MCODE;
462
463         /* patch super class index */
464
465         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
466
467         *((s4 *) (ra + 4 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
468                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
469
470         md_icacheflush(NULL, 0);
471
472         return true;
473 }
474
475
476 /*
477  * These are local overrides for various environment variables in Emacs.
478  * Please do not remove this and leave it at the end of the file, where
479  * Emacs will automagically detect them.
480  * ---------------------------------------------------------------------
481  * Local variables:
482  * mode: c
483  * indent-tabs-mode: t
484  * c-basic-offset: 4
485  * tab-width: 4
486  * End:
487  * vim:noexpandtab:sw=4:ts=4:
488  */