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