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