* src/vm/jit/powerpc/emit.c (emit_patcher_traps): Formerly known
[cacao.git] / src / vm / jit / powerpc / patcher.c
1 /* src/vm/jit/powerpc/patcher.c - PowerPC 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    $Id: patcher.c 8216 2007-07-19 13:51:21Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "mm/memory.h"
37 #include "native/native.h"
38
39 #include "vm/builtin.h"
40 #include "vm/exceptions.h"
41 #include "vm/initialize.h"
42
43 #include "vm/jit/asmpart.h"
44 #include "vm/jit/md.h"
45 #include "vm/jit/methodheader.h"
46 #include "vm/jit/patcher-common.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 "vm/resolve.h"
53 #include "vmcore/references.h"
54
55
56 #define PATCH_BACK_ORIGINAL_MCODE \
57         *((u4 *) pr->mpc) = (u4) pr->mcode; \
58         md_icacheflush((u1 *) pr->mpc, 4);
59
60
61 /* patcher_initialize_class ****************************************************
62
63    Initalizes a given classinfo pointer.  This function does not patch
64    any data.
65
66 *******************************************************************************/
67
68 bool patcher_initialize_class(patchref_t *pr)
69 {
70         classinfo *c;
71
72         /* get stuff from the stack */
73
74         c = (classinfo *) pr->ref;
75
76         /* check if the class is initialized */
77
78         if (!(c->state & CLASS_INITIALIZED))
79                 if (!initialize_class(c))
80                         return false;
81
82         PATCH_BACK_ORIGINAL_MCODE;
83
84         return true;
85 }
86
87
88 /* patcher_resolve_class *******************************************************
89
90    Resolves a given unresolved_class pointer.  This function does not
91    patch any data.
92
93 *******************************************************************************/
94
95 #ifdef ENABLE_VERIFIER
96 bool patcher_resolve_class(patchref_t *pr)
97 {
98         unresolved_class *uc;
99
100         /* get stuff from the stack */
101
102         uc = (unresolved_class *) pr->ref;
103
104         /* resolve the class and check subtype constraints */
105
106         if (!resolve_class_eager_no_access_check(uc))
107                 return false;
108
109         PATCH_BACK_ORIGINAL_MCODE;
110
111         return true;
112 }
113 #endif /* ENABLE_VERIFIER */
114
115
116 /* patcher_resolve_classref_to_classinfo ***************************************
117
118    ACONST:
119
120    <patched call postition>
121    806dffc4    lwz   r3,-60(r13)
122    81adffc0    lwz   r13,-64(r13)
123    7da903a6    mtctr r13
124    4e800421    bctrl
125
126
127    MULTIANEWARRAY:
128
129    <patched call position>
130    808dffc0    lwz   r4,-64(r13)
131    38a10038    addi  r5,r1,56
132    81adffbc    lwz   r13,-68(r13)
133    7da903a6    mtctr r13
134    4e800421    bctrl
135
136
137    ARRAYCHECKCAST:
138
139    <patched call position>
140    808dffd8    lwz   r4,-40(r13)
141    81adffd4    lwz   r13,-44(r13)
142    7da903a6    mtctr r13
143    4e800421    bctrl
144
145 *******************************************************************************/
146
147 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
148 {
149         constant_classref *cr;
150         u1                *datap;
151         classinfo         *c;
152
153         /* get stuff from the stack */
154
155         cr    = (constant_classref *) pr->ref;
156         datap = (u1 *)                pr->datap;
157
158         /* get the classinfo */
159
160         if (!(c = resolve_classref_eager(cr)))
161                 return false;
162
163         PATCH_BACK_ORIGINAL_MCODE;
164
165         /* patch the classinfo pointer */
166
167         *((ptrint *) datap) = (ptrint) c;
168
169         /* synchronize data cache */
170
171         md_dcacheflush(datap, SIZEOF_VOID_P);
172
173         return true;
174 }
175
176
177 /* patcher_resolve_classref_to_vftbl *******************************************
178
179    CHECKCAST (class):
180
181    <patched call position>
182    81870000    lwz   r12,0(r7)
183    800c0014    lwz   r0,20(r12)
184    818dff78    lwz   r12,-136(r13)
185
186
187    INSTANCEOF (class):
188
189    <patched call position>
190    817d0000    lwz   r11,0(r29)
191    818dff8c    lwz   r12,-116(r13)
192
193 *******************************************************************************/
194
195 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
196 {
197         constant_classref *cr;
198         u1                *datap;
199         classinfo         *c;
200
201         /* get stuff from the stack */
202
203         cr    = (constant_classref *) pr->ref;
204         datap = (u1 *)                pr->datap;
205
206         /* get the fieldinfo */
207
208         if (!(c = resolve_classref_eager(cr)))
209                 return false;
210
211         PATCH_BACK_ORIGINAL_MCODE;
212
213         /* patch super class' vftbl */
214
215         *((ptrint *) datap) = (ptrint) c->vftbl;
216
217         /* synchronize data cache */
218
219         md_dcacheflush(datap, SIZEOF_VOID_P);
220
221         return true;
222 }
223
224
225 /* patcher_resolve_classref_to_flags *******************************************
226
227    CHECKCAST/INSTANCEOF:
228
229    <patched call position>
230    818dff7c    lwz   r12,-132(r13)
231
232 *******************************************************************************/
233
234 bool patcher_resolve_classref_to_flags(patchref_t *pr)
235 {
236         constant_classref *cr;
237         u1                *datap;
238         classinfo         *c;
239
240         /* get stuff from the stack */
241
242         cr    = (constant_classref *) pr->ref;
243         datap = (u1 *)                pr->datap;
244
245         /* get the fieldinfo */
246
247         if (!(c = resolve_classref_eager(cr)))
248                 return false;
249
250         PATCH_BACK_ORIGINAL_MCODE;
251
252         /* patch class flags */
253
254         *((s4 *) datap) = (s4) c->flags;
255
256         /* synchronize data cache */
257
258         md_dcacheflush(datap, SIZEOF_VOID_P);
259
260         return true;
261 }
262
263
264 /* patcher_resolve_native_function *********************************************
265
266    XXX
267
268 *******************************************************************************/
269
270 #if !defined(WITH_STATIC_CLASSPATH)
271 bool patcher_resolve_native_function(patchref_t *pr)
272 {
273         methodinfo  *m;
274         u1          *datap;
275         functionptr  f;
276
277         /* get stuff from the stack */
278
279         m     = (methodinfo *) pr->ref;
280         datap = (u1 *)         pr->datap;
281
282         /* resolve native function */
283
284         if (!(f = native_resolve_function(m)))
285                 return false;
286
287         PATCH_BACK_ORIGINAL_MCODE;
288
289         /* patch native function pointer */
290
291         *((ptrint *) datap) = (ptrint) f;
292
293         /* synchronize data cache */
294
295         md_dcacheflush(datap, SIZEOF_VOID_P);
296
297         return true;
298 }
299 #endif /* !defined(WITH_STATIC_CLASSPATH) */
300
301
302 /* patcher_get_putstatic *******************************************************
303
304    Machine code:
305
306    <patched call position>
307    816dffc8    lwz   r11,-56(r13)
308    80ab0000    lwz   r5,0(r11)
309
310 *******************************************************************************/
311
312 bool patcher_get_putstatic(patchref_t *pr)
313 {
314         u1               *ra;
315         unresolved_field *uf;
316         u1               *datap;
317         fieldinfo        *fi;
318
319         /* get stuff from the stack */
320
321         ra    = (u1 *)                pr->mpc;
322         uf    = (unresolved_field *)  pr->ref;
323         datap = (u1 *)                pr->datap;
324
325         /* get the fieldinfo */
326
327         if (!(fi = resolve_field_eager(uf)))
328                 return false;
329
330         /* check if the field's class is initialized */
331
332         if (!(fi->class->state & CLASS_INITIALIZED))
333                 if (!initialize_class(fi->class))
334                         return false;
335
336         PATCH_BACK_ORIGINAL_MCODE;
337
338         /* patch the field value's address */
339
340         *((ptrint *) datap) = (ptrint) &(fi->value);
341
342         /* synchronize data cache */
343
344         md_dcacheflush(datap, SIZEOF_VOID_P);
345
346         return true;
347 }
348
349
350 /* patcher_get_putfield ********************************************************
351
352    Machine code:
353
354    <patched call position>
355    811f0014    lwz   r8,20(r31)
356
357 *******************************************************************************/
358
359 bool patcher_get_putfield(patchref_t *pr)
360 {
361         u1               *ra;
362         unresolved_field *uf;
363         fieldinfo        *fi;
364         s2                disp;
365
366         ra = (u1 *)               pr->mpc;
367         uf = (unresolved_field *) pr->ref;
368
369         /* get the fieldinfo */
370
371         if (!(fi = resolve_field_eager(uf)))
372                 return false;
373
374         PATCH_BACK_ORIGINAL_MCODE;
375
376         /* if we show NOPs, we have to skip them */
377
378         if (opt_shownops)
379                 ra = ra + 1 * 4;
380
381         /* patch the field's offset */
382
383         if (IS_LNG_TYPE(fi->type)) {
384                 /* If the field has type long, we have to patch two
385                    instructions.  But we have to check which instruction
386                    is first.  We do that with the offset of the first
387                    instruction. */
388
389                 disp = *((u4 *) (ra + 0 * 4));
390
391                 if (disp == 4) {
392                         *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
393                         *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
394                 }
395                 else {
396                         *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
397                         *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
398                 }
399         }
400         else
401                 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
402
403         /* synchronize instruction cache */
404
405         md_icacheflush(ra + 0 * 4, 2 * 4);
406
407         return true;
408 }
409
410
411 /* patcher_invokestatic_special ************************************************
412
413    Machine code:
414
415    <patched call position>
416    81adffd8    lwz   r13,-40(r13)
417    7da903a6    mtctr r13
418    4e800421    bctrl
419
420 ******************************************************************************/
421
422 bool patcher_invokestatic_special(patchref_t *pr)
423 {
424         unresolved_method *um;
425         u1                *datap;
426         methodinfo        *m;
427
428         /* get stuff from the stack */
429
430         um    = (unresolved_method *) pr->ref;
431         datap = (u1 *)                pr->datap;
432
433         /* get the fieldinfo */
434
435         if (!(m = resolve_method_eager(um)))
436                 return false;
437
438         PATCH_BACK_ORIGINAL_MCODE;
439
440         /* patch stubroutine */
441
442         *((ptrint *) datap) = (ptrint) m->stubroutine;
443
444         /* synchronize data cache */
445
446         md_dcacheflush(datap, SIZEOF_VOID_P);
447
448         return true;
449 }
450
451
452 /* patcher_invokevirtual *******************************************************
453
454    Machine code:
455
456    <patched call position>
457    81830000    lwz   r12,0(r3)
458    81ac0088    lwz   r13,136(r12)
459    7da903a6    mtctr r13
460    4e800421    bctrl
461
462 *******************************************************************************/
463
464 bool patcher_invokevirtual(patchref_t *pr)
465 {
466         u1                *ra;
467         unresolved_method *um;
468         methodinfo        *m;
469         s4                 disp;
470
471         /* get stuff from the stack */
472
473         ra = (u1 *)                pr->mpc;
474         um = (unresolved_method *) pr->ref;
475
476         /* get the fieldinfo */
477
478         if (!(m = resolve_method_eager(um)))
479                 return false;
480
481         PATCH_BACK_ORIGINAL_MCODE;
482
483         /* if we show NOPs, we have to skip them */
484
485         if (opt_shownops)
486                 ra = ra + 1 * 4;
487
488         /* patch vftbl index */
489
490         disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
491
492         *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
493
494         /* synchronize instruction cache */
495
496         md_icacheflush(ra + 1 * 4, 1 * 4);
497
498         return true;
499 }
500
501
502 /* patcher_invokeinterface *****************************************************
503
504    Machine code:
505
506    <patched call position>
507    81830000    lwz   r12,0(r3)
508    818cffd0    lwz   r12,-48(r12)
509    81ac000c    lwz   r13,12(r12)
510    7da903a6    mtctr r13
511    4e800421    bctrl
512
513 *******************************************************************************/
514
515 bool patcher_invokeinterface(patchref_t *pr)
516 {
517         u1                *ra;
518         unresolved_method *um;
519         methodinfo        *m;
520         s4                 disp;
521
522         /* get stuff from the stack */
523
524         ra = (u1 *)                pr->mpc;
525         um = (unresolved_method *) pr->ref;
526
527         /* get the fieldinfo */
528
529         if (!(m = resolve_method_eager(um)))
530                 return false;
531
532         PATCH_BACK_ORIGINAL_MCODE;
533
534         /* if we show NOPs, we have to skip them */
535
536         if (opt_shownops)
537                 ra = ra + 1 * 4;
538
539         /* patch interfacetable index */
540
541         disp = OFFSET(vftbl_t, interfacetable[0]) -
542                 sizeof(methodptr*) * m->class->index;
543
544         /* XXX TWISTI: check displacement */
545
546         *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
547
548         /* patch method offset */
549
550         disp = sizeof(methodptr) * (m - m->class->methods);
551
552         /* XXX TWISTI: check displacement */
553
554         *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
555
556         /* synchronize instruction cache */
557
558         md_icacheflush(ra + 1 * 4, 2 * 4);
559
560         return true;
561 }
562
563
564 /* patcher_checkcast_interface *************************************************
565
566    Machine code:
567
568    <patched call position>
569    81870000    lwz     r12,0(r7)
570    800c0010    lwz     r0,16(r12)
571    34000000    addic.  r0,r0,0
572    41810008    bgt-    0x014135d8
573    83c00003    lwz     r30,3(0)
574    800c0000    lwz     r0,0(r12)
575
576 *******************************************************************************/
577
578 bool patcher_checkcast_interface(patchref_t *pr)
579 {
580         u1                *ra;
581         constant_classref *cr;
582         classinfo         *c;
583         s4                 disp;
584
585         /* get stuff from the stack */
586
587         ra = (u1 *)                pr->mpc;
588         cr = (constant_classref *) pr->ref;
589
590         /* get the fieldinfo */
591
592         if (!(c = resolve_classref_eager(cr)))
593                 return false;
594
595         PATCH_BACK_ORIGINAL_MCODE;
596
597         /* if we show NOPs, we have to skip them */
598
599         if (opt_shownops)
600                 ra = ra + 1 * 4;
601
602         /* patch super class index */
603
604         disp = -(c->index);
605
606         *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
607
608         disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
609
610         *((s4 *) (ra + 5 * 4)) |= (disp & 0x0000ffff);
611
612         /* synchronize instruction cache */
613
614         md_icacheflush(ra + 2 * 4, 4 * 4);
615
616         return true;
617 }
618
619
620 /* patcher_instanceof_interface ************************************************
621
622    Machine code:
623
624    <patched call position>
625    81870000    lwz     r12,0(r7)
626    800c0010    lwz     r0,16(r12)
627    34000000    addic.  r0,r0,0
628    41810008    bgt-    0x014135d8
629    83c00003    lwz     r30,3(0)
630    800c0000    lwz     r0,0(r12)
631
632 *******************************************************************************/
633
634 bool patcher_instanceof_interface(patchref_t *pr)
635 {
636         u1                *ra;
637         constant_classref *cr;
638         classinfo         *c;
639         s4                 disp;
640
641         /* get stuff from the stack */
642
643         ra = (u1 *)                pr->mpc;
644         cr = (constant_classref *) pr->ref;
645
646         /* get the fieldinfo */
647
648         if (!(c = resolve_classref_eager(cr)))
649                 return false;
650
651         PATCH_BACK_ORIGINAL_MCODE;
652
653         /* if we show NOPs, we have to skip them */
654
655         if (opt_shownops)
656                 ra = ra + 1 * 4;
657
658         /* patch super class index */
659
660         disp = -(c->index);
661
662         *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
663
664         disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
665
666         *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
667
668         /* synchronize instruction cache */
669
670         md_icacheflush(ra + 2 * 4, 3 * 4);
671
672         return true;
673 }
674
675
676 /*
677  * These are local overrides for various environment variables in Emacs.
678  * Please do not remove this and leave it at the end of the file, where
679  * Emacs will automagically detect them.
680  * ---------------------------------------------------------------------
681  * Local variables:
682  * mode: c
683  * indent-tabs-mode: t
684  * c-basic-offset: 4
685  * tab-width: 4
686  * End:
687  * vim:noexpandtab:sw=4:ts=4:
688  */