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