1 /* src/vm/jit/powerpc64/patcher.c - PowerPC64 code patching functions
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
33 #include "vm/jit/powerpc64/md.h"
35 #include "mm/memory.h"
37 #include "native/native.h"
39 #include "vm/builtin.h"
40 #include "vm/exceptions.h"
41 #include "vm/initialize.h"
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"
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"
55 /* patcher_patch_code **********************************************************
57 Just patches back the original machine code.
59 *******************************************************************************/
61 void patcher_patch_code(patchref_t *pr)
63 /* patch back original code */
65 *((u4 *) pr->mpc) = pr->mcode;
67 /* synchronize instruction cache */
69 md_icacheflush(pr->mpc, 4);
73 /* patcher_get_putstatic *******************************************************
77 <patched call position>
78 816dffc8 lwz r11,-56(r13)
79 80ab0000 lwz r5,0(r11)
81 *******************************************************************************/
83 bool patcher_get_putstatic(patchref_t *pr)
91 /* get stuff from the stack */
95 uf = (unresolved_field *) pr->ref;
96 datap = (u1 *) pr->datap;
98 /* get the fieldinfo */
100 if (!(fi = resolve_field_eager(uf)))
103 /* check if the field's class is initialized */
105 if (!(fi->clazz->state & CLASS_INITIALIZED))
106 if (!initialize_class(fi->clazz))
109 /* patch back original code */
111 *((u4 *) ra) = mcode;
113 /* synchronize instruction cache */
115 md_icacheflush(ra, 4);
117 /* patch the field value's address */
119 *((intptr_t *) datap) = (intptr_t) fi->value;
121 /* synchronize data cache */
123 md_dcacheflush(datap, SIZEOF_VOID_P);
129 /* patcher_get_putfield ********************************************************
133 <patched call position>
134 811f0014 lwz r8,20(r31)
136 *******************************************************************************/
138 bool patcher_get_putfield(patchref_t *pr)
142 unresolved_field *uf;
147 uf = (unresolved_field *) pr->ref;
149 /* get the fieldinfo */
151 if (!(fi = resolve_field_eager(uf)))
154 /* patch back original code */
156 *((u4 *) ra) = mcode;
158 /* synchronize instruction cache */
160 md_icacheflush(ra, 4);
162 /* if we show disassembly, we have to skip the nop */
167 /* patch the field's offset */
169 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
171 /* synchronize instruction cache */
173 md_icacheflush(ra, 8);
179 /* patcher_invokestatic_special ************************************************
183 <patched call position>
184 81adffd8 lwz r13,-40(r13)
188 ******************************************************************************/
190 bool patcher_invokestatic_special(patchref_t *pr)
194 unresolved_method *um;
198 /* get stuff from the stack */
202 um = (unresolved_method *) pr->ref;
203 datap = (u1 *) pr->datap;
205 /* get the fieldinfo */
207 if (!(m = resolve_method_eager(um)))
210 /* patch back original code */
212 *((u4 *) ra) = mcode;
214 /* synchronize instruction cache */
216 md_icacheflush(ra, 4);
218 /* patch stubroutine */
220 *((ptrint *) datap) = (ptrint) m->stubroutine;
222 /* synchronize data cache */
224 md_dcacheflush(datap, SIZEOF_VOID_P);
230 /* patcher_invokevirtual *******************************************************
234 <patched call position>
235 81830000 lwz r12,0(r3)
236 81ac0088 lwz r13,136(r12)
240 *******************************************************************************/
242 bool patcher_invokevirtual(patchref_t *pr)
246 unresolved_method *um;
250 /* get stuff from the stack */
254 um = (unresolved_method *) pr->ref;
256 /* get the fieldinfo */
258 if (!(m = resolve_method_eager(um)))
261 /* patch back original code */
263 *((u4 *) ra) = mcode;
265 /* synchronize instruction cache */
267 md_icacheflush(ra, 4);
269 /* if we show disassembly, we have to skip the nop */
274 /* patch vftbl index */
276 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
278 *((s4 *) (ra + 4)) |= (disp & 0x0000ffff);
280 /* synchronize instruction cache */
282 md_icacheflush(ra, 2 * 4);
288 /* patcher_invokeinterface *****************************************************
292 <patched call position>
293 81830000 lwz r12,0(r3)
294 818cffd0 lwz r12,-48(r12)
295 81ac000c lwz r13,12(r12)
299 *******************************************************************************/
301 bool patcher_invokeinterface(patchref_t *pr)
305 unresolved_method *um;
309 /* get stuff from the stack */
313 um = (unresolved_method *) pr->ref;
315 /* get the fieldinfo */
317 if (!(m = resolve_method_eager(um)))
320 /* patch back original code */
322 *((u4 *) ra) = mcode;
324 /* synchronize instruction cache */
326 md_icacheflush(ra, 4);
328 /* if we show disassembly, we have to skip the nop */
333 /* patch interfacetable index */
335 disp = OFFSET(vftbl_t, interfacetable[0]) -
336 sizeof(methodptr*) * m->clazz->index;
338 /* XXX TWISTI: check displacement */
340 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
342 /* patch method offset */
344 disp = sizeof(methodptr) * (m - m->clazz->methods);
346 /* XXX TWISTI: check displacement */
348 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
350 /* synchronize instruction cache */
352 md_icacheflush(ra, 3 * 4);
358 /* patcher_checkcast_interface **************************************
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)
370 *******************************************************************************/
372 bool patcher_checkcast_interface(patchref_t *pr)
375 constant_classref *cr;
380 /* get stuff from stack */
383 cr = (constant_classref *) pr->ref;
385 /* get the fieldinfo */
386 if (!(c = resolve_classref_eager(cr))) {
390 /* patch back original code */
391 *((u4 *) ra) = mcode;
393 /* synchronize instruction cache */
395 md_icacheflush(ra, 4);
397 /* if we show NOPs, we have to skip them */
401 /* patch super class index */
404 *((s4*)(ra + 2*4)) |= (disp & 0x0000ffff);
406 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
408 *((s4 *)(ra + 5*4)) |= (disp & 0x0000ffff);
410 /* sync instruction cache */
411 md_icacheflush(ra, 6*4);
417 /* patcher_instanceof_interface **************************************
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)
428 *******************************************************************************/
430 bool patcher_instanceof_interface(patchref_t *pr)
434 constant_classref *cr;
438 /* get stuff from the stack */
442 cr = (constant_classref *) pr->ref;
444 /* get the fieldinfo */
446 if (!(c = resolve_classref_eager(cr)))
449 /* patch back original code */
451 *((u4 *) ra) = mcode;
453 /* synchronize instruction cache */
455 md_icacheflush(ra, 4);
457 /* if we show disassembly, we have to skip the nop */
462 /* patch super class index */
466 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
468 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
470 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
472 /* synchronize instruction cache */
474 md_icacheflush(ra, 5 * 4);
480 /* patcher_resolve_classref_to_classinfo ***************************************
484 <patched call postition>
485 806dffc4 lwz r3,-60(r13)
486 81adffc0 lwz r13,-64(r13)
493 <patched call position>
494 808dffc0 lwz r4,-64(r13)
495 38a10038 addi r5,r1,56
496 81adffbc lwz r13,-68(r13)
503 <patched call position>
504 808dffd8 lwz r4,-40(r13)
505 81adffd4 lwz r13,-44(r13)
509 *******************************************************************************/
511 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
513 constant_classref *cr;
518 /* get stuff from the stack */
522 cr = (constant_classref *) pr->ref;
523 datap = (u1 *) pr->datap;
525 /* get the classinfo */
527 if (!(c = resolve_classref_eager(cr)))
530 /* patch back original code */
532 *((u4 *) ra) = mcode;
534 /* synchronize instruction cache */
536 md_icacheflush(ra, 4);
538 /* patch the classinfo pointer */
540 *((ptrint *) datap) = (ptrint) c;
542 /* synchronize data cache */
544 md_dcacheflush(datap, SIZEOF_VOID_P);
550 /* patcher_resolve_classref_to_vftbl *******************************************
554 <patched call position>
555 81870000 lwz r12,0(r7)
556 800c0014 lwz r0,20(r12)
557 818dff78 lwz r12,-136(r13)
562 <patched call position>
563 817d0000 lwz r11,0(r29)
564 818dff8c lwz r12,-116(r13)
566 *******************************************************************************/
568 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
570 constant_classref *cr;
575 /* get stuff from the stack */
579 cr = (constant_classref *) pr->ref;
580 datap = (u1 *) pr->datap;
582 /* get the fieldinfo */
584 if (!(c = resolve_classref_eager(cr)))
587 /* patch back original code */
589 *((u4 *) ra) = mcode;
591 /* synchronize instruction cache */
593 md_icacheflush(ra, 4);
595 /* patch super class' vftbl */
597 *((ptrint *) datap) = (ptrint) c->vftbl;
599 /* synchronize data cache */
601 md_dcacheflush(datap, SIZEOF_VOID_P);
606 /* patcher_resolve_classref_to_flags *******************************************
608 CHECKCAST/INSTANCEOF:
610 <patched call position>
611 818dff7c lwz r12,-132(r13)
613 *******************************************************************************/
615 bool patcher_resolve_classref_to_flags(patchref_t *pr)
617 constant_classref *cr;
622 /* get stuff from the stack */
626 cr = (constant_classref *) pr->ref;
627 datap = (u1 *) pr->datap;
629 /* get the fieldinfo */
631 if (!(c = resolve_classref_eager(cr)))
634 /* patch back original code */
636 *((u4 *) ra) = mcode;
638 /* synchronize instruction cache */
640 md_icacheflush(ra, 4);
642 /* patch class flags */
644 *((s4 *) datap) = (s4) c->flags;
646 /* synchronize data cache */
648 md_dcacheflush(datap, SIZEOF_VOID_P);
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 * ---------------------------------------------------------------------
661 * indent-tabs-mode: t
665 * vim:noexpandtab:sw=4:ts=4: