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