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