1 /* src/vm/jit/powerpc/patcher.c - PowerPC 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/powerpc/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 "vm/resolve.h"
54 #include "vmcore/references.h"
57 #define PATCH_BACK_ORIGINAL_MCODE \
58 *((u4 *) pr->mpc) = (u4) pr->mcode; \
59 md_icacheflush((u1 *) pr->mpc, 4);
62 /* patcher_patch_code **********************************************************
64 Just patches back the original machine code.
66 *******************************************************************************/
68 void patcher_patch_code(patchref_t *pr)
70 PATCH_BACK_ORIGINAL_MCODE;
74 /* patcher_resolve_classref_to_classinfo ***************************************
78 <patched call postition>
79 806dffc4 lwz r3,-60(r13)
80 81adffc0 lwz r13,-64(r13)
87 <patched call position>
88 808dffc0 lwz r4,-64(r13)
89 38a10038 addi r5,r1,56
90 81adffbc lwz r13,-68(r13)
97 <patched call position>
98 808dffd8 lwz r4,-40(r13)
99 81adffd4 lwz r13,-44(r13)
103 *******************************************************************************/
105 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
107 constant_classref *cr;
111 /* get stuff from the stack */
113 cr = (constant_classref *) pr->ref;
114 datap = (u1 *) pr->datap;
116 /* get the classinfo */
118 if (!(c = resolve_classref_eager(cr)))
121 PATCH_BACK_ORIGINAL_MCODE;
123 /* patch the classinfo pointer */
125 *((ptrint *) datap) = (ptrint) c;
127 /* synchronize data cache */
129 md_dcacheflush(datap, SIZEOF_VOID_P);
135 /* patcher_resolve_classref_to_vftbl *******************************************
139 <patched call position>
140 81870000 lwz r12,0(r7)
141 800c0014 lwz r0,20(r12)
142 818dff78 lwz r12,-136(r13)
147 <patched call position>
148 817d0000 lwz r11,0(r29)
149 818dff8c lwz r12,-116(r13)
151 *******************************************************************************/
153 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
155 constant_classref *cr;
159 /* get stuff from the stack */
161 cr = (constant_classref *) pr->ref;
162 datap = (u1 *) pr->datap;
164 /* get the fieldinfo */
166 if (!(c = resolve_classref_eager(cr)))
169 PATCH_BACK_ORIGINAL_MCODE;
171 /* patch super class' vftbl */
173 *((ptrint *) datap) = (ptrint) c->vftbl;
175 /* synchronize data cache */
177 md_dcacheflush(datap, SIZEOF_VOID_P);
183 /* patcher_resolve_classref_to_flags *******************************************
185 CHECKCAST/INSTANCEOF:
187 <patched call position>
188 818dff7c lwz r12,-132(r13)
190 *******************************************************************************/
192 bool patcher_resolve_classref_to_flags(patchref_t *pr)
194 constant_classref *cr;
198 /* get stuff from the stack */
200 cr = (constant_classref *) pr->ref;
201 datap = (u1 *) pr->datap;
203 /* get the fieldinfo */
205 if (!(c = resolve_classref_eager(cr)))
208 PATCH_BACK_ORIGINAL_MCODE;
210 /* patch class flags */
212 *((s4 *) datap) = (s4) c->flags;
214 /* synchronize data cache */
216 md_dcacheflush(datap, SIZEOF_VOID_P);
222 /* patcher_get_putstatic *******************************************************
226 <patched call position>
227 816dffc8 lwz r11,-56(r13)
228 80ab0000 lwz r5,0(r11)
230 *******************************************************************************/
232 bool patcher_get_putstatic(patchref_t *pr)
235 unresolved_field *uf;
239 /* get stuff from the stack */
242 uf = (unresolved_field *) pr->ref;
243 datap = (u1 *) pr->datap;
245 /* get the fieldinfo */
247 if (!(fi = resolve_field_eager(uf)))
250 /* check if the field's class is initialized */
252 if (!(fi->class->state & CLASS_INITIALIZED))
253 if (!initialize_class(fi->class))
256 PATCH_BACK_ORIGINAL_MCODE;
258 /* patch the field value's address */
260 *((intptr_t *) datap) = (intptr_t) fi->value;
262 /* synchronize data cache */
264 md_dcacheflush(datap, SIZEOF_VOID_P);
270 /* patcher_get_putfield ********************************************************
274 <patched call position>
275 811f0014 lwz r8,20(r31)
277 *******************************************************************************/
279 bool patcher_get_putfield(patchref_t *pr)
282 unresolved_field *uf;
287 uf = (unresolved_field *) pr->ref;
289 /* get the fieldinfo */
291 if (!(fi = resolve_field_eager(uf)))
294 PATCH_BACK_ORIGINAL_MCODE;
296 /* if we show NOPs, we have to skip them */
301 /* patch the field's offset */
303 if (IS_LNG_TYPE(fi->type)) {
304 /* If the field has type long, we have to patch two
305 instructions. But we have to check which instruction
306 is first. We do that with the offset of the first
309 disp = *((u4 *) (ra + 0 * 4));
312 *((u4 *) (ra + 0 * 4)) &= 0xffff0000;
313 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
314 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
317 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
318 *((u4 *) (ra + 1 * 4)) &= 0xffff0000;
319 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
323 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
325 /* synchronize instruction cache */
327 md_icacheflush(ra + 0 * 4, 2 * 4);
333 /* patcher_invokestatic_special ************************************************
337 <patched call position>
338 81adffd8 lwz r13,-40(r13)
342 ******************************************************************************/
344 bool patcher_invokestatic_special(patchref_t *pr)
346 unresolved_method *um;
350 /* get stuff from the stack */
352 um = (unresolved_method *) pr->ref;
353 datap = (u1 *) pr->datap;
355 /* get the fieldinfo */
357 if (!(m = resolve_method_eager(um)))
360 PATCH_BACK_ORIGINAL_MCODE;
362 /* patch stubroutine */
364 *((ptrint *) datap) = (ptrint) m->stubroutine;
366 /* synchronize data cache */
368 md_dcacheflush(datap, SIZEOF_VOID_P);
374 /* patcher_invokevirtual *******************************************************
378 <patched call position>
379 81830000 lwz r12,0(r3)
380 81ac0088 lwz r13,136(r12)
384 *******************************************************************************/
386 bool patcher_invokevirtual(patchref_t *pr)
389 unresolved_method *um;
393 /* get stuff from the stack */
396 um = (unresolved_method *) pr->ref;
398 /* get the fieldinfo */
400 if (!(m = resolve_method_eager(um)))
403 PATCH_BACK_ORIGINAL_MCODE;
405 /* if we show NOPs, we have to skip them */
410 /* patch vftbl index */
412 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
414 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
416 /* synchronize instruction cache */
418 md_icacheflush(ra + 1 * 4, 1 * 4);
424 /* patcher_invokeinterface *****************************************************
428 <patched call position>
429 81830000 lwz r12,0(r3)
430 818cffd0 lwz r12,-48(r12)
431 81ac000c lwz r13,12(r12)
435 *******************************************************************************/
437 bool patcher_invokeinterface(patchref_t *pr)
440 unresolved_method *um;
444 /* get stuff from the stack */
447 um = (unresolved_method *) pr->ref;
449 /* get the fieldinfo */
451 if (!(m = resolve_method_eager(um)))
454 PATCH_BACK_ORIGINAL_MCODE;
456 /* if we show NOPs, we have to skip them */
461 /* patch interfacetable index */
463 disp = OFFSET(vftbl_t, interfacetable[0]) -
464 sizeof(methodptr*) * m->class->index;
466 /* XXX TWISTI: check displacement */
468 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
470 /* patch method offset */
472 disp = sizeof(methodptr) * (m - m->class->methods);
474 /* XXX TWISTI: check displacement */
476 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
478 /* synchronize instruction cache */
480 md_icacheflush(ra + 1 * 4, 2 * 4);
486 /* patcher_checkcast_interface *************************************************
490 <patched call position>
491 81870000 lwz r12,0(r7)
492 800c0010 lwz r0,16(r12)
493 34000000 addic. r0,r0,0
494 41810008 bgt- 0x014135d8
495 83c00003 lwz r30,3(0)
496 800c0000 lwz r0,0(r12)
498 *******************************************************************************/
500 bool patcher_checkcast_interface(patchref_t *pr)
503 constant_classref *cr;
507 /* get stuff from the stack */
510 cr = (constant_classref *) pr->ref;
512 /* get the fieldinfo */
514 if (!(c = resolve_classref_eager(cr)))
517 PATCH_BACK_ORIGINAL_MCODE;
519 /* if we show NOPs, we have to skip them */
524 /* patch super class index */
528 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
530 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
532 *((s4 *) (ra + 5 * 4)) |= (disp & 0x0000ffff);
534 /* synchronize instruction cache */
536 md_icacheflush(ra + 2 * 4, 4 * 4);
542 /* patcher_instanceof_interface ************************************************
546 <patched call position>
547 81870000 lwz r12,0(r7)
548 800c0010 lwz r0,16(r12)
549 34000000 addic. r0,r0,0
550 41810008 bgt- 0x014135d8
551 83c00003 lwz r30,3(0)
552 800c0000 lwz r0,0(r12)
554 *******************************************************************************/
556 bool patcher_instanceof_interface(patchref_t *pr)
559 constant_classref *cr;
563 /* get stuff from the stack */
566 cr = (constant_classref *) pr->ref;
568 /* get the fieldinfo */
570 if (!(c = resolve_classref_eager(cr)))
573 PATCH_BACK_ORIGINAL_MCODE;
575 /* if we show NOPs, we have to skip them */
580 /* patch super class index */
584 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
586 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
588 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
590 /* synchronize instruction cache */
592 md_icacheflush(ra + 2 * 4, 3 * 4);
599 * These are local overrides for various environment variables in Emacs.
600 * Please do not remove this and leave it at the end of the file, where
601 * Emacs will automagically detect them.
602 * ---------------------------------------------------------------------
605 * indent-tabs-mode: t
609 * vim:noexpandtab:sw=4:ts=4: