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