1 /* src/vm/jit/powerpc64/patcher.c - PowerPC64 code patching functions
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
8 This file is part of CACAO.
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.
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.
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
35 #include "vm/jit/powerpc64/md.h"
37 #include "mm/memory.h"
39 #include "native/native.h"
41 #include "vm/builtin.h"
42 #include "vm/exceptions.h"
43 #include "vm/initialize.h"
45 #include "vm/jit/asmpart.h"
46 #include "vm/jit/methodheader.h"
47 #include "vm/jit/patcher-common.h"
48 #include "vm/jit/stacktrace.h"
50 #include "vmcore/class.h"
51 #include "vmcore/field.h"
52 #include "vmcore/options.h"
53 #include "vmcore/references.h"
54 #include "vm/resolve.h"
57 /* patcher_patch_code **********************************************************
59 Just patches back the original machine code.
61 *******************************************************************************/
63 void patcher_patch_code(patchref_t *pr)
65 /* patch back original code */
67 *((u4 *) pr->mpc) = pr->mcode;
69 /* synchronize instruction cache */
71 md_icacheflush(pr->mpc, 4);
75 /* patcher_get_putstatic *******************************************************
79 <patched call position>
80 816dffc8 lwz r11,-56(r13)
81 80ab0000 lwz r5,0(r11)
83 *******************************************************************************/
85 bool patcher_get_putstatic(patchref_t *pr)
93 /* get stuff from the stack */
97 uf = (unresolved_field *) pr->ref;
98 datap = (u1 *) pr->datap;
100 /* get the fieldinfo */
102 if (!(fi = resolve_field_eager(uf)))
105 /* check if the field's class is initialized */
107 if (!(fi->class->state & CLASS_INITIALIZED))
108 if (!initialize_class(fi->class))
111 /* patch back original code */
113 *((u4 *) ra) = mcode;
115 /* synchronize instruction cache */
117 md_icacheflush(ra, 4);
119 /* patch the field value's address */
121 *((intptr_t *) datap) = (intptr_t) fi->value;
123 /* synchronize data cache */
125 md_dcacheflush(datap, SIZEOF_VOID_P);
131 /* patcher_get_putfield ********************************************************
135 <patched call position>
136 811f0014 lwz r8,20(r31)
138 *******************************************************************************/
140 bool patcher_get_putfield(patchref_t *pr)
144 unresolved_field *uf;
149 uf = (unresolved_field *) pr->ref;
151 /* get the fieldinfo */
153 if (!(fi = resolve_field_eager(uf)))
156 /* patch back original code */
158 *((u4 *) ra) = mcode;
160 /* synchronize instruction cache */
162 md_icacheflush(ra, 4);
164 /* if we show disassembly, we have to skip the nop */
169 /* patch the field's offset */
171 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
173 /* synchronize instruction cache */
175 md_icacheflush(ra, 8);
181 /* patcher_invokestatic_special ************************************************
185 <patched call position>
186 81adffd8 lwz r13,-40(r13)
190 ******************************************************************************/
192 bool patcher_invokestatic_special(patchref_t *pr)
196 unresolved_method *um;
200 /* get stuff from the stack */
204 um = (unresolved_method *) pr->ref;
205 datap = (u1 *) pr->datap;
207 /* get the fieldinfo */
209 if (!(m = resolve_method_eager(um)))
212 /* patch back original code */
214 *((u4 *) ra) = mcode;
216 /* synchronize instruction cache */
218 md_icacheflush(ra, 4);
220 /* patch stubroutine */
222 *((ptrint *) datap) = (ptrint) m->stubroutine;
224 /* synchronize data cache */
226 md_dcacheflush(datap, SIZEOF_VOID_P);
232 /* patcher_invokevirtual *******************************************************
236 <patched call position>
237 81830000 lwz r12,0(r3)
238 81ac0088 lwz r13,136(r12)
242 *******************************************************************************/
244 bool patcher_invokevirtual(patchref_t *pr)
248 unresolved_method *um;
252 /* get stuff from the stack */
256 um = (unresolved_method *) pr->ref;
258 /* get the fieldinfo */
260 if (!(m = resolve_method_eager(um)))
263 /* patch back original code */
265 *((u4 *) ra) = mcode;
267 /* synchronize instruction cache */
269 md_icacheflush(ra, 4);
271 /* if we show disassembly, we have to skip the nop */
276 /* patch vftbl index */
278 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
280 *((s4 *) (ra + 4)) |= (disp & 0x0000ffff);
282 /* synchronize instruction cache */
284 md_icacheflush(ra, 2 * 4);
290 /* patcher_invokeinterface *****************************************************
294 <patched call position>
295 81830000 lwz r12,0(r3)
296 818cffd0 lwz r12,-48(r12)
297 81ac000c lwz r13,12(r12)
301 *******************************************************************************/
303 bool patcher_invokeinterface(patchref_t *pr)
307 unresolved_method *um;
311 /* get stuff from the stack */
315 um = (unresolved_method *) pr->ref;
317 /* get the fieldinfo */
319 if (!(m = resolve_method_eager(um)))
322 /* patch back original code */
324 *((u4 *) ra) = mcode;
326 /* synchronize instruction cache */
328 md_icacheflush(ra, 4);
330 /* if we show disassembly, we have to skip the nop */
335 /* patch interfacetable index */
337 disp = OFFSET(vftbl_t, interfacetable[0]) -
338 sizeof(methodptr*) * m->class->index;
340 /* XXX TWISTI: check displacement */
342 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
344 /* patch method offset */
346 disp = sizeof(methodptr) * (m - m->class->methods);
348 /* XXX TWISTI: check displacement */
350 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
352 /* synchronize instruction cache */
354 md_icacheflush(ra, 3 * 4);
360 /* patcher_checkcast_interface **************************************
364 <patched call position>
365 81870000 lwz r12,0(r7)
366 800c0010 lwz r0,16(r12)
367 34000000 addic. r0,r0,0
368 408101fc bgt- 0x3002e518 FIXME
369 83c00003 lwz r30,3(0) FIXME
370 800c0000 lwz r0,0(r12)
372 *******************************************************************************/
374 bool patcher_checkcast_interface(patchref_t *pr)
377 constant_classref *cr;
382 /* get stuff from stack */
385 cr = (constant_classref *) pr->ref;
387 /* get the fieldinfo */
388 if (!(c = resolve_classref_eager(cr))) {
392 /* patch back original code */
393 *((u4 *) ra) = mcode;
395 /* synchronize instruction cache */
397 md_icacheflush(ra, 4);
399 /* if we show NOPs, we have to skip them */
403 /* patch super class index */
406 *((s4*)(ra + 2*4)) |= (disp & 0x0000ffff);
408 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
410 *((s4 *)(ra + 5*4)) |= (disp & 0x0000ffff);
412 /* sync instruction cache */
413 md_icacheflush(ra, 6*4);
419 /* patcher_instanceof_interface **************************************
423 <patched call position>
424 81870000 lwz r12,0(r7)
425 800c0010 lwz r0,16(r12)
426 34000000 addic. r0,r0,0
427 408101fc ble- 0x3002e518
428 800c0000 lwz r0,0(r12)
430 *******************************************************************************/
432 bool patcher_instanceof_interface(patchref_t *pr)
436 constant_classref *cr;
440 /* get stuff from the stack */
444 cr = (constant_classref *) pr->ref;
446 /* get the fieldinfo */
448 if (!(c = resolve_classref_eager(cr)))
451 /* patch back original code */
453 *((u4 *) ra) = mcode;
455 /* synchronize instruction cache */
457 md_icacheflush(ra, 4);
459 /* if we show disassembly, we have to skip the nop */
464 /* patch super class index */
468 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
470 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
472 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
474 /* synchronize instruction cache */
476 md_icacheflush(ra, 5 * 4);
482 /* patcher_resolve_classref_to_classinfo ***************************************
486 <patched call postition>
487 806dffc4 lwz r3,-60(r13)
488 81adffc0 lwz r13,-64(r13)
495 <patched call position>
496 808dffc0 lwz r4,-64(r13)
497 38a10038 addi r5,r1,56
498 81adffbc lwz r13,-68(r13)
505 <patched call position>
506 808dffd8 lwz r4,-40(r13)
507 81adffd4 lwz r13,-44(r13)
511 *******************************************************************************/
513 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
515 constant_classref *cr;
520 /* get stuff from the stack */
524 cr = (constant_classref *) pr->ref;
525 datap = (u1 *) pr->datap;
527 /* get the classinfo */
529 if (!(c = resolve_classref_eager(cr)))
532 /* patch back original code */
534 *((u4 *) ra) = mcode;
536 /* synchronize instruction cache */
538 md_icacheflush(ra, 4);
540 /* patch the classinfo pointer */
542 *((ptrint *) datap) = (ptrint) c;
544 /* synchronize data cache */
546 md_dcacheflush(datap, SIZEOF_VOID_P);
552 /* patcher_resolve_classref_to_vftbl *******************************************
556 <patched call position>
557 81870000 lwz r12,0(r7)
558 800c0014 lwz r0,20(r12)
559 818dff78 lwz r12,-136(r13)
564 <patched call position>
565 817d0000 lwz r11,0(r29)
566 818dff8c lwz r12,-116(r13)
568 *******************************************************************************/
570 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
572 constant_classref *cr;
577 /* get stuff from the stack */
581 cr = (constant_classref *) pr->ref;
582 datap = (u1 *) pr->datap;
584 /* get the fieldinfo */
586 if (!(c = resolve_classref_eager(cr)))
589 /* patch back original code */
591 *((u4 *) ra) = mcode;
593 /* synchronize instruction cache */
595 md_icacheflush(ra, 4);
597 /* patch super class' vftbl */
599 *((ptrint *) datap) = (ptrint) c->vftbl;
601 /* synchronize data cache */
603 md_dcacheflush(datap, SIZEOF_VOID_P);
608 /* patcher_resolve_classref_to_flags *******************************************
610 CHECKCAST/INSTANCEOF:
612 <patched call position>
613 818dff7c lwz r12,-132(r13)
615 *******************************************************************************/
617 bool patcher_resolve_classref_to_flags(patchref_t *pr)
619 constant_classref *cr;
624 /* get stuff from the stack */
628 cr = (constant_classref *) pr->ref;
629 datap = (u1 *) pr->datap;
631 /* get the fieldinfo */
633 if (!(c = resolve_classref_eager(cr)))
636 /* patch back original code */
638 *((u4 *) ra) = mcode;
640 /* synchronize instruction cache */
642 md_icacheflush(ra, 4);
644 /* patch class flags */
646 *((s4 *) datap) = (s4) c->flags;
648 /* synchronize data cache */
650 md_dcacheflush(datap, SIZEOF_VOID_P);
657 * These are local overrides for various environment variables in Emacs.
658 * Please do not remove this and leave it at the end of the file, where
659 * Emacs will automagically detect them.
660 * ---------------------------------------------------------------------
663 * indent-tabs-mode: t
667 * vim:noexpandtab:sw=4:ts=4: