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