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