1 /* src/vm/jit/powerpc64/patcher.c - PowerPC64 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 "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/md.h"
45 #include "vm/jit/methodheader.h"
46 #include "vm/jit/patcher-common.h"
47 #include "vm/jit/stacktrace.h"
49 #include "vmcore/class.h"
50 #include "vmcore/field.h"
51 #include "vmcore/options.h"
52 #include "vmcore/references.h"
53 #include "vm/resolve.h"
56 /* patcher_get_putstatic *******************************************************
60 <patched call position>
61 816dffc8 lwz r11,-56(r13)
62 80ab0000 lwz r5,0(r11)
64 *******************************************************************************/
66 bool patcher_get_putstatic(patchref_t *pr)
74 /* get stuff from the stack */
78 uf = (unresolved_field *) pr->ref;
79 datap = (u1 *) pr->datap;
81 /* get the fieldinfo */
83 if (!(fi = resolve_field_eager(uf)))
86 /* check if the field's class is initialized */
88 if (!(fi->class->state & CLASS_INITIALIZED))
89 if (!initialize_class(fi->class))
92 /* patch back original code */
96 /* synchronize instruction cache */
98 md_icacheflush(ra, 4);
100 /* patch the field value's address */
102 *((intptr_t *) datap) = (intptr_t) fi->value;
104 /* synchronize data cache */
106 md_dcacheflush(datap, SIZEOF_VOID_P);
112 /* patcher_get_putfield ********************************************************
116 <patched call position>
117 811f0014 lwz r8,20(r31)
119 *******************************************************************************/
121 bool patcher_get_putfield(patchref_t *pr)
125 unresolved_field *uf;
130 uf = (unresolved_field *) pr->ref;
132 /* get the fieldinfo */
134 if (!(fi = resolve_field_eager(uf)))
137 /* patch back original code */
139 *((u4 *) ra) = mcode;
141 /* synchronize instruction cache */
143 md_icacheflush(ra, 4);
145 /* if we show disassembly, we have to skip the nop */
150 /* patch the field's offset */
152 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
154 /* synchronize instruction cache */
156 md_icacheflush(ra, 8);
162 /* patcher_invokestatic_special ************************************************
166 <patched call position>
167 81adffd8 lwz r13,-40(r13)
171 ******************************************************************************/
173 bool patcher_invokestatic_special(patchref_t *pr)
177 unresolved_method *um;
181 /* get stuff from the stack */
185 um = (unresolved_method *) pr->ref;
186 datap = (u1 *) pr->datap;
188 /* get the fieldinfo */
190 if (!(m = resolve_method_eager(um)))
193 /* patch back original code */
195 *((u4 *) ra) = mcode;
197 /* synchronize instruction cache */
199 md_icacheflush(ra, 4);
201 /* patch stubroutine */
203 *((ptrint *) datap) = (ptrint) m->stubroutine;
205 /* synchronize data cache */
207 md_dcacheflush(datap, SIZEOF_VOID_P);
213 /* patcher_invokevirtual *******************************************************
217 <patched call position>
218 81830000 lwz r12,0(r3)
219 81ac0088 lwz r13,136(r12)
223 *******************************************************************************/
225 bool patcher_invokevirtual(patchref_t *pr)
229 unresolved_method *um;
233 /* get stuff from the stack */
237 um = (unresolved_method *) pr->ref;
239 /* get the fieldinfo */
241 if (!(m = resolve_method_eager(um)))
244 /* patch back original code */
246 *((u4 *) ra) = mcode;
248 /* synchronize instruction cache */
250 md_icacheflush(ra, 4);
252 /* if we show disassembly, we have to skip the nop */
257 /* patch vftbl index */
259 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
261 *((s4 *) (ra + 4)) |= (disp & 0x0000ffff);
263 /* synchronize instruction cache */
265 md_icacheflush(ra, 2 * 4);
271 /* patcher_invokeinterface *****************************************************
275 <patched call position>
276 81830000 lwz r12,0(r3)
277 818cffd0 lwz r12,-48(r12)
278 81ac000c lwz r13,12(r12)
282 *******************************************************************************/
284 bool patcher_invokeinterface(patchref_t *pr)
288 unresolved_method *um;
292 /* get stuff from the stack */
296 um = (unresolved_method *) pr->ref;
298 /* get the fieldinfo */
300 if (!(m = resolve_method_eager(um)))
303 /* patch back original code */
305 *((u4 *) ra) = mcode;
307 /* synchronize instruction cache */
309 md_icacheflush(ra, 4);
311 /* if we show disassembly, we have to skip the nop */
316 /* patch interfacetable index */
318 disp = OFFSET(vftbl_t, interfacetable[0]) -
319 sizeof(methodptr*) * m->class->index;
321 /* XXX TWISTI: check displacement */
323 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
325 /* patch method offset */
327 disp = sizeof(methodptr) * (m - m->class->methods);
329 /* XXX TWISTI: check displacement */
331 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
333 /* synchronize instruction cache */
335 md_icacheflush(ra, 3 * 4);
341 /* patcher_checkcast_interface **************************************
345 <patched call position>
346 81870000 lwz r12,0(r7)
347 800c0010 lwz r0,16(r12)
348 34000000 addic. r0,r0,0
349 408101fc bgt- 0x3002e518 FIXME
350 83c00003 lwz r30,3(0) FIXME
351 800c0000 lwz r0,0(r12)
353 *******************************************************************************/
355 bool patcher_checkcast_interface(patchref_t *pr)
358 constant_classref *cr;
363 /* get stuff from stack */
366 cr = (constant_classref *) pr->ref;
368 /* get the fieldinfo */
369 if (!(c = resolve_classref_eager(cr))) {
373 /* patch back original code */
374 *((u4 *) ra) = mcode;
376 /* synchronize instruction cache */
378 md_icacheflush(ra, 4);
380 /* if we show NOPs, we have to skip them */
384 /* patch super class index */
387 *((s4*)(ra + 2*4)) |= (disp & 0x0000ffff);
389 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
391 *((s4 *)(ra + 5*4)) |= (disp & 0x0000ffff);
393 /* sync instruction cache */
394 md_icacheflush(ra, 6*4);
400 /* patcher_instanceof_interface **************************************
404 <patched call position>
405 81870000 lwz r12,0(r7)
406 800c0010 lwz r0,16(r12)
407 34000000 addic. r0,r0,0
408 408101fc ble- 0x3002e518
409 800c0000 lwz r0,0(r12)
411 *******************************************************************************/
413 bool patcher_instanceof_interface(patchref_t *pr)
417 constant_classref *cr;
421 /* get stuff from the stack */
425 cr = (constant_classref *) pr->ref;
427 /* get the fieldinfo */
429 if (!(c = resolve_classref_eager(cr)))
432 /* patch back original code */
434 *((u4 *) ra) = mcode;
436 /* synchronize instruction cache */
438 md_icacheflush(ra, 4);
440 /* if we show disassembly, we have to skip the nop */
445 /* patch super class index */
449 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
451 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
453 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
455 /* synchronize instruction cache */
457 md_icacheflush(ra, 5 * 4);
463 /* patcher_resolve_classref_to_classinfo ***************************************
467 <patched call postition>
468 806dffc4 lwz r3,-60(r13)
469 81adffc0 lwz r13,-64(r13)
476 <patched call position>
477 808dffc0 lwz r4,-64(r13)
478 38a10038 addi r5,r1,56
479 81adffbc lwz r13,-68(r13)
486 <patched call position>
487 808dffd8 lwz r4,-40(r13)
488 81adffd4 lwz r13,-44(r13)
492 *******************************************************************************/
494 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
496 constant_classref *cr;
501 /* get stuff from the stack */
505 cr = (constant_classref *) pr->ref;
506 datap = (u1 *) pr->datap;
508 /* get the classinfo */
510 if (!(c = resolve_classref_eager(cr)))
513 /* patch back original code */
515 *((u4 *) ra) = mcode;
517 /* synchronize instruction cache */
519 md_icacheflush(ra, 4);
521 /* patch the classinfo pointer */
523 *((ptrint *) datap) = (ptrint) c;
525 /* synchronize data cache */
527 md_dcacheflush(datap, SIZEOF_VOID_P);
533 /* patcher_resolve_classref_to_vftbl *******************************************
537 <patched call position>
538 81870000 lwz r12,0(r7)
539 800c0014 lwz r0,20(r12)
540 818dff78 lwz r12,-136(r13)
545 <patched call position>
546 817d0000 lwz r11,0(r29)
547 818dff8c lwz r12,-116(r13)
549 *******************************************************************************/
551 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
553 constant_classref *cr;
558 /* get stuff from the stack */
562 cr = (constant_classref *) pr->ref;
563 datap = (u1 *) pr->datap;
565 /* get the fieldinfo */
567 if (!(c = resolve_classref_eager(cr)))
570 /* patch back original code */
572 *((u4 *) ra) = mcode;
574 /* synchronize instruction cache */
576 md_icacheflush(ra, 4);
578 /* patch super class' vftbl */
580 *((ptrint *) datap) = (ptrint) c->vftbl;
582 /* synchronize data cache */
584 md_dcacheflush(datap, SIZEOF_VOID_P);
589 /* patcher_resolve_classref_to_flags *******************************************
591 CHECKCAST/INSTANCEOF:
593 <patched call position>
594 818dff7c lwz r12,-132(r13)
596 *******************************************************************************/
598 bool patcher_resolve_classref_to_flags(patchref_t *pr)
600 constant_classref *cr;
605 /* get stuff from the stack */
609 cr = (constant_classref *) pr->ref;
610 datap = (u1 *) pr->datap;
612 /* get the fieldinfo */
614 if (!(c = resolve_classref_eager(cr)))
617 /* patch back original code */
619 *((u4 *) ra) = mcode;
621 /* synchronize instruction cache */
623 md_icacheflush(ra, 4);
625 /* patch class flags */
627 *((s4 *) datap) = (s4) c->flags;
629 /* synchronize data cache */
631 md_dcacheflush(datap, SIZEOF_VOID_P);
636 /* patcher_initialize_class ****************************************************
640 *******************************************************************************/
642 bool patcher_initialize_class(patchref_t *pr)
648 /* get stuff from the stack */
652 c = (classinfo *) pr->ref;
654 /* check if the class is initialized */
656 if (!(c->state & CLASS_INITIALIZED))
657 if (!initialize_class(c))
660 /* patch back original code */
662 *((u4 *) ra) = mcode;
664 /* synchronize instruction cache */
666 md_icacheflush(ra, 4);
672 /* patcher_athrow_areturn ******************************************************
676 <patched call position>
678 *******************************************************************************/
680 #ifdef ENABLE_VERIFIER
681 bool patcher_resolve_class(patchref_t *pr)
685 unresolved_class *uc;
687 /* get stuff from the stack */
691 uc = (unresolved_class *) pr->ref;
693 /* resolve the class and check subtype constraints */
695 if (!resolve_class_eager_no_access_check(uc))
698 /* patch back original code */
700 *((u4 *) ra) = mcode;
702 /* synchronize instruction cache */
704 md_icacheflush(ra, 4);
708 #endif /* ENABLE_VERIFIER */
711 /* patcher_resolve_native_function *********************************************
715 *******************************************************************************/
717 bool patcher_resolve_native_function(patchref_t *pr)
725 /* get stuff from the stack */
730 m = (methodinfo *) pr->ref;
731 datap = (u1 *) pr->datap;
733 /* resolve native function */
735 if (!(f = native_resolve_function(m)))
738 /* patch back original code */
740 *((u4 *) ra) = mcode;
742 /* synchronize instruction cache */
744 md_icacheflush(ra, 4);
746 /* patch native function pointer */
748 *((ptrint *) datap) = (ptrint) f;
750 /* synchronize data cache */
752 md_dcacheflush(datap, SIZEOF_VOID_P);
759 * These are local overrides for various environment variables in Emacs.
760 * Please do not remove this and leave it at the end of the file, where
761 * Emacs will automagically detect them.
762 * ---------------------------------------------------------------------
765 * indent-tabs-mode: t
769 * vim:noexpandtab:sw=4:ts=4: