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"
47 #include "vmcore/class.h"
48 #include "vmcore/field.h"
49 #include "vmcore/options.h"
50 #include "vmcore/references.h"
51 #include "vm/resolve.h"
54 /* patcher_patch_code **********************************************************
56 Just patches back the original machine code.
58 *******************************************************************************/
60 void patcher_patch_code(patchref_t *pr)
62 /* patch back original code */
64 *((u4 *) pr->mpc) = pr->mcode;
66 /* synchronize instruction cache */
68 md_icacheflush(pr->mpc, 4);
72 /* patcher_get_putstatic *******************************************************
76 <patched call position>
77 816dffc8 lwz r11,-56(r13)
78 80ab0000 lwz r5,0(r11)
80 *******************************************************************************/
82 bool patcher_get_putstatic(patchref_t *pr)
90 /* get stuff from the stack */
94 uf = (unresolved_field *) pr->ref;
95 datap = (u1 *) pr->datap;
97 /* get the fieldinfo */
99 if (!(fi = resolve_field_eager(uf)))
102 /* check if the field's class is initialized */
104 if (!(fi->clazz->state & CLASS_INITIALIZED))
105 if (!initialize_class(fi->clazz))
108 /* patch back original code */
110 *((u4 *) ra) = mcode;
112 /* synchronize instruction cache */
114 md_icacheflush(ra, 4);
116 /* patch the field value's address */
118 *((intptr_t *) datap) = (intptr_t) fi->value;
120 /* synchronize data cache */
122 md_dcacheflush(datap, SIZEOF_VOID_P);
128 /* patcher_get_putfield ********************************************************
132 <patched call position>
133 811f0014 lwz r8,20(r31)
135 *******************************************************************************/
137 bool patcher_get_putfield(patchref_t *pr)
141 unresolved_field *uf;
146 uf = (unresolved_field *) pr->ref;
148 /* get the fieldinfo */
150 if (!(fi = resolve_field_eager(uf)))
153 /* patch back original code */
155 *((u4 *) ra) = mcode;
157 /* synchronize instruction cache */
159 md_icacheflush(ra, 4);
161 /* if we show disassembly, we have to skip the nop */
166 /* patch the field's offset */
168 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
170 /* synchronize instruction cache */
172 md_icacheflush(ra, 8);
178 /* patcher_invokestatic_special ************************************************
182 <patched call position>
183 81adffd8 lwz r13,-40(r13)
187 ******************************************************************************/
189 bool patcher_invokestatic_special(patchref_t *pr)
193 unresolved_method *um;
197 /* get stuff from the stack */
201 um = (unresolved_method *) pr->ref;
202 datap = (u1 *) pr->datap;
204 /* get the fieldinfo */
206 if (!(m = resolve_method_eager(um)))
209 /* patch back original code */
211 *((u4 *) ra) = mcode;
213 /* synchronize instruction cache */
215 md_icacheflush(ra, 4);
217 /* patch stubroutine */
219 *((ptrint *) datap) = (ptrint) m->stubroutine;
221 /* synchronize data cache */
223 md_dcacheflush(datap, SIZEOF_VOID_P);
229 /* patcher_invokevirtual *******************************************************
233 <patched call position>
234 81830000 lwz r12,0(r3)
235 81ac0088 lwz r13,136(r12)
239 *******************************************************************************/
241 bool patcher_invokevirtual(patchref_t *pr)
245 unresolved_method *um;
249 /* get stuff from the stack */
253 um = (unresolved_method *) pr->ref;
255 /* get the fieldinfo */
257 if (!(m = resolve_method_eager(um)))
260 /* patch back original code */
262 *((u4 *) ra) = mcode;
264 /* synchronize instruction cache */
266 md_icacheflush(ra, 4);
268 /* if we show disassembly, we have to skip the nop */
273 /* patch vftbl index */
275 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
277 *((s4 *) (ra + 4)) |= (disp & 0x0000ffff);
279 /* synchronize instruction cache */
281 md_icacheflush(ra, 2 * 4);
287 /* patcher_invokeinterface *****************************************************
291 <patched call position>
292 81830000 lwz r12,0(r3)
293 818cffd0 lwz r12,-48(r12)
294 81ac000c lwz r13,12(r12)
298 *******************************************************************************/
300 bool patcher_invokeinterface(patchref_t *pr)
304 unresolved_method *um;
308 /* get stuff from the stack */
312 um = (unresolved_method *) pr->ref;
314 /* get the fieldinfo */
316 if (!(m = resolve_method_eager(um)))
319 /* patch back original code */
321 *((u4 *) ra) = mcode;
323 /* synchronize instruction cache */
325 md_icacheflush(ra, 4);
327 /* if we show disassembly, we have to skip the nop */
332 /* patch interfacetable index */
334 disp = OFFSET(vftbl_t, interfacetable[0]) -
335 sizeof(methodptr*) * m->clazz->index;
337 /* XXX TWISTI: check displacement */
339 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
341 /* patch method offset */
343 disp = sizeof(methodptr) * (m - m->clazz->methods);
345 /* XXX TWISTI: check displacement */
347 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
349 /* synchronize instruction cache */
351 md_icacheflush(ra, 3 * 4);
357 /* patcher_checkcast_interface **************************************
361 <patched call position>
362 81870000 lwz r12,0(r7)
363 800c0010 lwz r0,16(r12)
364 34000000 addic. r0,r0,0
365 408101fc bgt- 0x3002e518 FIXME
366 83c00003 lwz r30,3(0) FIXME
367 800c0000 lwz r0,0(r12)
369 *******************************************************************************/
371 bool patcher_checkcast_interface(patchref_t *pr)
374 constant_classref *cr;
379 /* get stuff from stack */
382 cr = (constant_classref *) pr->ref;
384 /* get the fieldinfo */
385 if (!(c = resolve_classref_eager(cr))) {
389 /* patch back original code */
390 *((u4 *) ra) = mcode;
392 /* synchronize instruction cache */
394 md_icacheflush(ra, 4);
396 /* if we show NOPs, we have to skip them */
400 /* patch super class index */
403 *((s4*)(ra + 2*4)) |= (disp & 0x0000ffff);
405 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
407 *((s4 *)(ra + 5*4)) |= (disp & 0x0000ffff);
409 /* sync instruction cache */
410 md_icacheflush(ra, 6*4);
416 /* patcher_instanceof_interface **************************************
420 <patched call position>
421 81870000 lwz r12,0(r7)
422 800c0010 lwz r0,16(r12)
423 34000000 addic. r0,r0,0
424 408101fc ble- 0x3002e518
425 800c0000 lwz r0,0(r12)
427 *******************************************************************************/
429 bool patcher_instanceof_interface(patchref_t *pr)
433 constant_classref *cr;
437 /* get stuff from the stack */
441 cr = (constant_classref *) pr->ref;
443 /* get the fieldinfo */
445 if (!(c = resolve_classref_eager(cr)))
448 /* patch back original code */
450 *((u4 *) ra) = mcode;
452 /* synchronize instruction cache */
454 md_icacheflush(ra, 4);
456 /* if we show disassembly, we have to skip the nop */
461 /* patch super class index */
465 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
467 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
469 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
471 /* synchronize instruction cache */
473 md_icacheflush(ra, 5 * 4);
479 /* patcher_resolve_classref_to_classinfo ***************************************
483 <patched call postition>
484 806dffc4 lwz r3,-60(r13)
485 81adffc0 lwz r13,-64(r13)
492 <patched call position>
493 808dffc0 lwz r4,-64(r13)
494 38a10038 addi r5,r1,56
495 81adffbc lwz r13,-68(r13)
502 <patched call position>
503 808dffd8 lwz r4,-40(r13)
504 81adffd4 lwz r13,-44(r13)
508 *******************************************************************************/
510 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
512 constant_classref *cr;
517 /* get stuff from the stack */
521 cr = (constant_classref *) pr->ref;
522 datap = (u1 *) pr->datap;
524 /* get the classinfo */
526 if (!(c = resolve_classref_eager(cr)))
529 /* patch back original code */
531 *((u4 *) ra) = mcode;
533 /* synchronize instruction cache */
535 md_icacheflush(ra, 4);
537 /* patch the classinfo pointer */
539 *((ptrint *) datap) = (ptrint) c;
541 /* synchronize data cache */
543 md_dcacheflush(datap, SIZEOF_VOID_P);
549 /* patcher_resolve_classref_to_vftbl *******************************************
553 <patched call position>
554 81870000 lwz r12,0(r7)
555 800c0014 lwz r0,20(r12)
556 818dff78 lwz r12,-136(r13)
561 <patched call position>
562 817d0000 lwz r11,0(r29)
563 818dff8c lwz r12,-116(r13)
565 *******************************************************************************/
567 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
569 constant_classref *cr;
574 /* get stuff from the stack */
578 cr = (constant_classref *) pr->ref;
579 datap = (u1 *) pr->datap;
581 /* get the fieldinfo */
583 if (!(c = resolve_classref_eager(cr)))
586 /* patch back original code */
588 *((u4 *) ra) = mcode;
590 /* synchronize instruction cache */
592 md_icacheflush(ra, 4);
594 /* patch super class' vftbl */
596 *((ptrint *) datap) = (ptrint) c->vftbl;
598 /* synchronize data cache */
600 md_dcacheflush(datap, SIZEOF_VOID_P);
605 /* patcher_resolve_classref_to_flags *******************************************
607 CHECKCAST/INSTANCEOF:
609 <patched call position>
610 818dff7c lwz r12,-132(r13)
612 *******************************************************************************/
614 bool patcher_resolve_classref_to_flags(patchref_t *pr)
616 constant_classref *cr;
621 /* get stuff from the stack */
625 cr = (constant_classref *) pr->ref;
626 datap = (u1 *) pr->datap;
628 /* get the fieldinfo */
630 if (!(c = resolve_classref_eager(cr)))
633 /* patch back original code */
635 *((u4 *) ra) = mcode;
637 /* synchronize instruction cache */
639 md_icacheflush(ra, 4);
641 /* patch class flags */
643 *((s4 *) datap) = (s4) c->flags;
645 /* synchronize data cache */
647 md_dcacheflush(datap, SIZEOF_VOID_P);
654 * These are local overrides for various environment variables in Emacs.
655 * Please do not remove this and leave it at the end of the file, where
656 * Emacs will automagically detect them.
657 * ---------------------------------------------------------------------
660 * indent-tabs-mode: t
664 * vim:noexpandtab:sw=4:ts=4: