1 /* src/vm/jit/powerpc/patcher.c - PowerPC 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/powerpc/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 "vm/resolve.h"
52 #include "vmcore/references.h"
55 #define PATCH_BACK_ORIGINAL_MCODE \
56 *((u4 *) pr->mpc) = (u4) pr->mcode; \
57 md_icacheflush((u1 *) pr->mpc, 4);
60 /* patcher_patch_code **********************************************************
62 Just patches back the original machine code.
64 *******************************************************************************/
66 void patcher_patch_code(patchref_t *pr)
68 PATCH_BACK_ORIGINAL_MCODE;
72 /* patcher_resolve_classref_to_classinfo ***************************************
76 <patched call postition>
77 806dffc4 lwz r3,-60(r13)
78 81adffc0 lwz r13,-64(r13)
85 <patched call position>
86 808dffc0 lwz r4,-64(r13)
87 38a10038 addi r5,r1,56
88 81adffbc lwz r13,-68(r13)
95 <patched call position>
96 808dffd8 lwz r4,-40(r13)
97 81adffd4 lwz r13,-44(r13)
101 *******************************************************************************/
103 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
105 constant_classref *cr;
109 /* get stuff from the stack */
111 cr = (constant_classref *) pr->ref;
112 datap = (u1 *) pr->datap;
114 /* get the classinfo */
116 if (!(c = resolve_classref_eager(cr)))
119 PATCH_BACK_ORIGINAL_MCODE;
121 /* patch the classinfo pointer */
123 *((ptrint *) datap) = (ptrint) c;
125 /* synchronize data cache */
127 md_dcacheflush(datap, SIZEOF_VOID_P);
133 /* patcher_resolve_classref_to_vftbl *******************************************
137 <patched call position>
138 81870000 lwz r12,0(r7)
139 800c0014 lwz r0,20(r12)
140 818dff78 lwz r12,-136(r13)
145 <patched call position>
146 817d0000 lwz r11,0(r29)
147 818dff8c lwz r12,-116(r13)
149 *******************************************************************************/
151 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
153 constant_classref *cr;
157 /* get stuff from the stack */
159 cr = (constant_classref *) pr->ref;
160 datap = (u1 *) pr->datap;
162 /* get the fieldinfo */
164 if (!(c = resolve_classref_eager(cr)))
167 PATCH_BACK_ORIGINAL_MCODE;
169 /* patch super class' vftbl */
171 *((ptrint *) datap) = (ptrint) c->vftbl;
173 /* synchronize data cache */
175 md_dcacheflush(datap, SIZEOF_VOID_P);
181 /* patcher_resolve_classref_to_flags *******************************************
183 CHECKCAST/INSTANCEOF:
185 <patched call position>
186 818dff7c lwz r12,-132(r13)
188 *******************************************************************************/
190 bool patcher_resolve_classref_to_flags(patchref_t *pr)
192 constant_classref *cr;
196 /* get stuff from the stack */
198 cr = (constant_classref *) pr->ref;
199 datap = (u1 *) pr->datap;
201 /* get the fieldinfo */
203 if (!(c = resolve_classref_eager(cr)))
206 PATCH_BACK_ORIGINAL_MCODE;
208 /* patch class flags */
210 *((s4 *) datap) = (s4) c->flags;
212 /* synchronize data cache */
214 md_dcacheflush(datap, SIZEOF_VOID_P);
220 /* patcher_get_putstatic *******************************************************
224 <patched call position>
225 816dffc8 lwz r11,-56(r13)
226 80ab0000 lwz r5,0(r11)
228 *******************************************************************************/
230 bool patcher_get_putstatic(patchref_t *pr)
233 unresolved_field *uf;
237 /* get stuff from the stack */
240 uf = (unresolved_field *) pr->ref;
241 datap = (u1 *) pr->datap;
243 /* get the fieldinfo */
245 if (!(fi = resolve_field_eager(uf)))
248 /* check if the field's class is initialized */
250 if (!(fi->clazz->state & CLASS_INITIALIZED))
251 if (!initialize_class(fi->clazz))
254 PATCH_BACK_ORIGINAL_MCODE;
256 /* patch the field value's address */
258 *((intptr_t *) datap) = (intptr_t) fi->value;
260 /* synchronize data cache */
262 md_dcacheflush(datap, SIZEOF_VOID_P);
268 /* patcher_get_putfield ********************************************************
272 <patched call position>
273 811f0014 lwz r8,20(r31)
275 *******************************************************************************/
277 bool patcher_get_putfield(patchref_t *pr)
280 unresolved_field *uf;
285 uf = (unresolved_field *) pr->ref;
287 /* get the fieldinfo */
289 if (!(fi = resolve_field_eager(uf)))
292 PATCH_BACK_ORIGINAL_MCODE;
294 /* if we show NOPs, we have to skip them */
299 /* patch the field's offset */
301 if (IS_LNG_TYPE(fi->type)) {
302 /* If the field has type long, we have to patch two
303 instructions. But we have to check which instruction
304 is first. We do that with the offset of the first
307 disp = *((u4 *) (ra + 0 * 4));
310 *((u4 *) (ra + 0 * 4)) &= 0xffff0000;
311 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
312 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
315 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
316 *((u4 *) (ra + 1 * 4)) &= 0xffff0000;
317 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
321 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
323 /* synchronize instruction cache */
325 md_icacheflush(ra + 0 * 4, 2 * 4);
331 /* patcher_invokestatic_special ************************************************
335 <patched call position>
336 81adffd8 lwz r13,-40(r13)
340 ******************************************************************************/
342 bool patcher_invokestatic_special(patchref_t *pr)
344 unresolved_method *um;
348 /* get stuff from the stack */
350 um = (unresolved_method *) pr->ref;
351 datap = (u1 *) pr->datap;
353 /* get the fieldinfo */
355 if (!(m = resolve_method_eager(um)))
358 PATCH_BACK_ORIGINAL_MCODE;
360 /* patch stubroutine */
362 *((ptrint *) datap) = (ptrint) m->stubroutine;
364 /* synchronize data cache */
366 md_dcacheflush(datap, SIZEOF_VOID_P);
372 /* patcher_invokevirtual *******************************************************
376 <patched call position>
377 81830000 lwz r12,0(r3)
378 81ac0088 lwz r13,136(r12)
382 *******************************************************************************/
384 bool patcher_invokevirtual(patchref_t *pr)
387 unresolved_method *um;
391 /* get stuff from the stack */
394 um = (unresolved_method *) pr->ref;
396 /* get the fieldinfo */
398 if (!(m = resolve_method_eager(um)))
401 PATCH_BACK_ORIGINAL_MCODE;
403 /* if we show NOPs, we have to skip them */
408 /* patch vftbl index */
410 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
412 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
414 /* synchronize instruction cache */
416 md_icacheflush(ra + 1 * 4, 1 * 4);
422 /* patcher_invokeinterface *****************************************************
426 <patched call position>
427 81830000 lwz r12,0(r3)
428 818cffd0 lwz r12,-48(r12)
429 81ac000c lwz r13,12(r12)
433 *******************************************************************************/
435 bool patcher_invokeinterface(patchref_t *pr)
438 unresolved_method *um;
442 /* get stuff from the stack */
445 um = (unresolved_method *) pr->ref;
447 /* get the fieldinfo */
449 if (!(m = resolve_method_eager(um)))
452 PATCH_BACK_ORIGINAL_MCODE;
454 /* if we show NOPs, we have to skip them */
459 /* patch interfacetable index */
461 disp = OFFSET(vftbl_t, interfacetable[0]) -
462 sizeof(methodptr*) * m->clazz->index;
464 /* XXX TWISTI: check displacement */
466 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
468 /* patch method offset */
470 disp = sizeof(methodptr) * (m - m->clazz->methods);
472 /* XXX TWISTI: check displacement */
474 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
476 /* synchronize instruction cache */
478 md_icacheflush(ra + 1 * 4, 2 * 4);
484 /* patcher_checkcast_interface *************************************************
488 <patched call position>
489 81870000 lwz r12,0(r7)
490 800c0010 lwz r0,16(r12)
491 34000000 addic. r0,r0,0
492 41810008 bgt- 0x014135d8
493 83c00003 lwz r30,3(0)
494 800c0000 lwz r0,0(r12)
496 *******************************************************************************/
498 bool patcher_checkcast_interface(patchref_t *pr)
501 constant_classref *cr;
505 /* get stuff from the stack */
508 cr = (constant_classref *) pr->ref;
510 /* get the fieldinfo */
512 if (!(c = resolve_classref_eager(cr)))
515 PATCH_BACK_ORIGINAL_MCODE;
517 /* if we show NOPs, we have to skip them */
522 /* patch super class index */
526 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
528 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
530 *((s4 *) (ra + 5 * 4)) |= (disp & 0x0000ffff);
532 /* synchronize instruction cache */
534 md_icacheflush(ra + 2 * 4, 4 * 4);
540 /* patcher_instanceof_interface ************************************************
544 <patched call position>
545 81870000 lwz r12,0(r7)
546 800c0010 lwz r0,16(r12)
547 34000000 addic. r0,r0,0
548 41810008 bgt- 0x014135d8
549 83c00003 lwz r30,3(0)
550 800c0000 lwz r0,0(r12)
552 *******************************************************************************/
554 bool patcher_instanceof_interface(patchref_t *pr)
557 constant_classref *cr;
561 /* get stuff from the stack */
564 cr = (constant_classref *) pr->ref;
566 /* get the fieldinfo */
568 if (!(c = resolve_classref_eager(cr)))
571 PATCH_BACK_ORIGINAL_MCODE;
573 /* if we show NOPs, we have to skip them */
578 /* patch super class index */
582 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
584 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
586 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
588 /* synchronize instruction cache */
590 md_icacheflush(ra + 2 * 4, 3 * 4);
597 * These are local overrides for various environment variables in Emacs.
598 * Please do not remove this and leave it at the end of the file, where
599 * Emacs will automagically detect them.
600 * ---------------------------------------------------------------------
603 * indent-tabs-mode: t
607 * vim:noexpandtab:sw=4:ts=4: