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