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