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"
42 #include "vm/initialize.h"
43 #include "vm/options.h"
44 #include "vm/references.h"
45 #include "vm/resolve.h"
47 #include "vm/jit/asmpart.h"
48 #include "vm/jit/methodheader.h"
49 #include "vm/jit/patcher-common.h"
52 /* patcher_patch_code **********************************************************
54 Just patches back the original machine code.
56 *******************************************************************************/
58 void patcher_patch_code(patchref_t *pr)
60 /* patch back original code */
62 *((u4 *) pr->mpc) = pr->mcode;
64 /* synchronize instruction cache */
66 md_icacheflush(pr->mpc, 4);
70 /* patcher_get_putstatic *******************************************************
74 <patched call position>
75 816dffc8 lwz r11,-56(r13)
76 80ab0000 lwz r5,0(r11)
78 *******************************************************************************/
80 bool patcher_get_putstatic(patchref_t *pr)
88 /* get stuff from the stack */
92 uf = (unresolved_field *) pr->ref;
93 datap = (u1 *) pr->datap;
95 /* get the fieldinfo */
97 if (!(fi = resolve_field_eager(uf)))
100 /* check if the field's class is initialized */
102 if (!(fi->clazz->state & CLASS_INITIALIZED))
103 if (!initialize_class(fi->clazz))
106 /* patch back original code */
108 *((u4 *) ra) = mcode;
110 /* synchronize instruction cache */
112 md_icacheflush(ra, 4);
114 /* patch the field value's address */
116 *((intptr_t *) datap) = (intptr_t) fi->value;
118 /* synchronize data cache */
120 md_dcacheflush(datap, SIZEOF_VOID_P);
126 /* patcher_get_putfield ********************************************************
130 <patched call position>
131 811f0014 lwz r8,20(r31)
133 *******************************************************************************/
135 bool patcher_get_putfield(patchref_t *pr)
139 unresolved_field *uf;
144 uf = (unresolved_field *) pr->ref;
146 /* get the fieldinfo */
148 if (!(fi = resolve_field_eager(uf)))
151 /* patch back original code */
153 *((u4 *) ra) = mcode;
155 /* synchronize instruction cache */
157 md_icacheflush(ra, 4);
159 /* if we show disassembly, we have to skip the nop */
164 /* patch the field's offset */
166 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
168 /* synchronize instruction cache */
170 md_icacheflush(ra, 8);
176 /* patcher_invokestatic_special ************************************************
180 <patched call position>
181 81adffd8 lwz r13,-40(r13)
185 ******************************************************************************/
187 bool patcher_invokestatic_special(patchref_t *pr)
191 unresolved_method *um;
195 /* get stuff from the stack */
199 um = (unresolved_method *) pr->ref;
200 datap = (u1 *) pr->datap;
202 /* get the fieldinfo */
204 if (!(m = resolve_method_eager(um)))
207 /* patch back original code */
209 *((u4 *) ra) = mcode;
211 /* synchronize instruction cache */
213 md_icacheflush(ra, 4);
215 /* patch stubroutine */
217 *((ptrint *) datap) = (ptrint) m->stubroutine;
219 /* synchronize data cache */
221 md_dcacheflush(datap, SIZEOF_VOID_P);
227 /* patcher_invokevirtual *******************************************************
231 <patched call position>
232 81830000 lwz r12,0(r3)
233 81ac0088 lwz r13,136(r12)
237 *******************************************************************************/
239 bool patcher_invokevirtual(patchref_t *pr)
243 unresolved_method *um;
247 /* get stuff from the stack */
251 um = (unresolved_method *) pr->ref;
253 /* get the fieldinfo */
255 if (!(m = resolve_method_eager(um)))
258 /* patch back original code */
260 *((u4 *) ra) = mcode;
262 /* synchronize instruction cache */
264 md_icacheflush(ra, 4);
266 /* if we show disassembly, we have to skip the nop */
271 /* patch vftbl index */
273 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
275 *((s4 *) (ra + 4)) |= (disp & 0x0000ffff);
277 /* synchronize instruction cache */
279 md_icacheflush(ra, 2 * 4);
285 /* patcher_invokeinterface *****************************************************
289 <patched call position>
290 81830000 lwz r12,0(r3)
291 818cffd0 lwz r12,-48(r12)
292 81ac000c lwz r13,12(r12)
296 *******************************************************************************/
298 bool patcher_invokeinterface(patchref_t *pr)
302 unresolved_method *um;
306 /* get stuff from the stack */
310 um = (unresolved_method *) pr->ref;
312 /* get the fieldinfo */
314 if (!(m = resolve_method_eager(um)))
317 /* patch back original code */
319 *((u4 *) ra) = mcode;
321 /* synchronize instruction cache */
323 md_icacheflush(ra, 4);
325 /* if we show disassembly, we have to skip the nop */
330 /* patch interfacetable index */
332 disp = OFFSET(vftbl_t, interfacetable[0]) -
333 sizeof(methodptr*) * m->clazz->index;
335 /* XXX TWISTI: check displacement */
337 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
339 /* patch method offset */
341 disp = sizeof(methodptr) * (m - m->clazz->methods);
343 /* XXX TWISTI: check displacement */
345 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
347 /* synchronize instruction cache */
349 md_icacheflush(ra, 3 * 4);
355 /* patcher_checkcast_interface **************************************
359 <patched call position>
360 81870000 lwz r12,0(r7)
361 800c0010 lwz r0,16(r12)
362 34000000 addic. r0,r0,0
363 408101fc bgt- 0x3002e518 FIXME
364 83c00003 lwz r30,3(0) FIXME
365 800c0000 lwz r0,0(r12)
367 *******************************************************************************/
369 bool patcher_checkcast_interface(patchref_t *pr)
372 constant_classref *cr;
377 /* get stuff from stack */
380 cr = (constant_classref *) pr->ref;
382 /* get the fieldinfo */
383 if (!(c = resolve_classref_eager(cr))) {
387 /* patch back original code */
388 *((u4 *) ra) = mcode;
390 /* synchronize instruction cache */
392 md_icacheflush(ra, 4);
394 /* if we show NOPs, we have to skip them */
398 /* patch super class index */
401 *((s4*)(ra + 2*4)) |= (disp & 0x0000ffff);
403 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
405 *((s4 *)(ra + 5*4)) |= (disp & 0x0000ffff);
407 /* sync instruction cache */
408 md_icacheflush(ra, 6*4);
414 /* patcher_instanceof_interface **************************************
418 <patched call position>
419 81870000 lwz r12,0(r7)
420 800c0010 lwz r0,16(r12)
421 34000000 addic. r0,r0,0
422 408101fc ble- 0x3002e518
423 800c0000 lwz r0,0(r12)
425 *******************************************************************************/
427 bool patcher_instanceof_interface(patchref_t *pr)
431 constant_classref *cr;
435 /* get stuff from the stack */
439 cr = (constant_classref *) pr->ref;
441 /* get the fieldinfo */
443 if (!(c = resolve_classref_eager(cr)))
446 /* patch back original code */
448 *((u4 *) ra) = mcode;
450 /* synchronize instruction cache */
452 md_icacheflush(ra, 4);
454 /* if we show disassembly, we have to skip the nop */
459 /* patch super class index */
463 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
465 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
467 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
469 /* synchronize instruction cache */
471 md_icacheflush(ra, 5 * 4);
477 /* patcher_resolve_classref_to_classinfo ***************************************
481 <patched call postition>
482 806dffc4 lwz r3,-60(r13)
483 81adffc0 lwz r13,-64(r13)
490 <patched call position>
491 808dffc0 lwz r4,-64(r13)
492 38a10038 addi r5,r1,56
493 81adffbc lwz r13,-68(r13)
500 <patched call position>
501 808dffd8 lwz r4,-40(r13)
502 81adffd4 lwz r13,-44(r13)
506 *******************************************************************************/
508 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
510 constant_classref *cr;
515 /* get stuff from the stack */
519 cr = (constant_classref *) pr->ref;
520 datap = (u1 *) pr->datap;
522 /* get the classinfo */
524 if (!(c = resolve_classref_eager(cr)))
527 /* patch back original code */
529 *((u4 *) ra) = mcode;
531 /* synchronize instruction cache */
533 md_icacheflush(ra, 4);
535 /* patch the classinfo pointer */
537 *((ptrint *) datap) = (ptrint) c;
539 /* synchronize data cache */
541 md_dcacheflush(datap, SIZEOF_VOID_P);
547 /* patcher_resolve_classref_to_vftbl *******************************************
551 <patched call position>
552 81870000 lwz r12,0(r7)
553 800c0014 lwz r0,20(r12)
554 818dff78 lwz r12,-136(r13)
559 <patched call position>
560 817d0000 lwz r11,0(r29)
561 818dff8c lwz r12,-116(r13)
563 *******************************************************************************/
565 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
567 constant_classref *cr;
572 /* get stuff from the stack */
576 cr = (constant_classref *) pr->ref;
577 datap = (u1 *) pr->datap;
579 /* get the fieldinfo */
581 if (!(c = resolve_classref_eager(cr)))
584 /* patch back original code */
586 *((u4 *) ra) = mcode;
588 /* synchronize instruction cache */
590 md_icacheflush(ra, 4);
592 /* patch super class' vftbl */
594 *((ptrint *) datap) = (ptrint) c->vftbl;
596 /* synchronize data cache */
598 md_dcacheflush(datap, SIZEOF_VOID_P);
603 /* patcher_resolve_classref_to_flags *******************************************
605 CHECKCAST/INSTANCEOF:
607 <patched call position>
608 818dff7c lwz r12,-132(r13)
610 *******************************************************************************/
612 bool patcher_resolve_classref_to_flags(patchref_t *pr)
614 constant_classref *cr;
619 /* get stuff from the stack */
623 cr = (constant_classref *) pr->ref;
624 datap = (u1 *) pr->datap;
626 /* get the fieldinfo */
628 if (!(c = resolve_classref_eager(cr)))
631 /* patch back original code */
633 *((u4 *) ra) = mcode;
635 /* synchronize instruction cache */
637 md_icacheflush(ra, 4);
639 /* patch class flags */
641 *((s4 *) datap) = (s4) c->flags;
643 /* synchronize data cache */
645 md_dcacheflush(datap, SIZEOF_VOID_P);
652 * These are local overrides for various environment variables in Emacs.
653 * Please do not remove this and leave it at the end of the file, where
654 * Emacs will automagically detect them.
655 * ---------------------------------------------------------------------
658 * indent-tabs-mode: t
662 * vim:noexpandtab:sw=4:ts=4: