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_patch_code **********************************************************
58 Just patches back the original machine code.
60 *******************************************************************************/
62 void patcher_patch_code(patchref_t *pr)
64 /* patch back original code */
66 *((u4 *) pr->mpc) = pr->mcode;
68 /* synchronize instruction cache */
70 md_icacheflush(pr->mpc, 4);
74 /* patcher_get_putstatic *******************************************************
78 <patched call position>
79 816dffc8 lwz r11,-56(r13)
80 80ab0000 lwz r5,0(r11)
82 *******************************************************************************/
84 bool patcher_get_putstatic(patchref_t *pr)
92 /* get stuff from the stack */
96 uf = (unresolved_field *) pr->ref;
97 datap = (u1 *) pr->datap;
99 /* get the fieldinfo */
101 if (!(fi = resolve_field_eager(uf)))
104 /* check if the field's class is initialized */
106 if (!(fi->class->state & CLASS_INITIALIZED))
107 if (!initialize_class(fi->class))
110 /* patch back original code */
112 *((u4 *) ra) = mcode;
114 /* synchronize instruction cache */
116 md_icacheflush(ra, 4);
118 /* patch the field value's address */
120 *((intptr_t *) datap) = (intptr_t) fi->value;
122 /* synchronize data cache */
124 md_dcacheflush(datap, SIZEOF_VOID_P);
130 /* patcher_get_putfield ********************************************************
134 <patched call position>
135 811f0014 lwz r8,20(r31)
137 *******************************************************************************/
139 bool patcher_get_putfield(patchref_t *pr)
143 unresolved_field *uf;
148 uf = (unresolved_field *) pr->ref;
150 /* get the fieldinfo */
152 if (!(fi = resolve_field_eager(uf)))
155 /* patch back original code */
157 *((u4 *) ra) = mcode;
159 /* synchronize instruction cache */
161 md_icacheflush(ra, 4);
163 /* if we show disassembly, we have to skip the nop */
168 /* patch the field's offset */
170 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
172 /* synchronize instruction cache */
174 md_icacheflush(ra, 8);
180 /* patcher_invokestatic_special ************************************************
184 <patched call position>
185 81adffd8 lwz r13,-40(r13)
189 ******************************************************************************/
191 bool patcher_invokestatic_special(patchref_t *pr)
195 unresolved_method *um;
199 /* get stuff from the stack */
203 um = (unresolved_method *) pr->ref;
204 datap = (u1 *) pr->datap;
206 /* get the fieldinfo */
208 if (!(m = resolve_method_eager(um)))
211 /* patch back original code */
213 *((u4 *) ra) = mcode;
215 /* synchronize instruction cache */
217 md_icacheflush(ra, 4);
219 /* patch stubroutine */
221 *((ptrint *) datap) = (ptrint) m->stubroutine;
223 /* synchronize data cache */
225 md_dcacheflush(datap, SIZEOF_VOID_P);
231 /* patcher_invokevirtual *******************************************************
235 <patched call position>
236 81830000 lwz r12,0(r3)
237 81ac0088 lwz r13,136(r12)
241 *******************************************************************************/
243 bool patcher_invokevirtual(patchref_t *pr)
247 unresolved_method *um;
251 /* get stuff from the stack */
255 um = (unresolved_method *) pr->ref;
257 /* get the fieldinfo */
259 if (!(m = resolve_method_eager(um)))
262 /* patch back original code */
264 *((u4 *) ra) = mcode;
266 /* synchronize instruction cache */
268 md_icacheflush(ra, 4);
270 /* if we show disassembly, we have to skip the nop */
275 /* patch vftbl index */
277 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
279 *((s4 *) (ra + 4)) |= (disp & 0x0000ffff);
281 /* synchronize instruction cache */
283 md_icacheflush(ra, 2 * 4);
289 /* patcher_invokeinterface *****************************************************
293 <patched call position>
294 81830000 lwz r12,0(r3)
295 818cffd0 lwz r12,-48(r12)
296 81ac000c lwz r13,12(r12)
300 *******************************************************************************/
302 bool patcher_invokeinterface(patchref_t *pr)
306 unresolved_method *um;
310 /* get stuff from the stack */
314 um = (unresolved_method *) pr->ref;
316 /* get the fieldinfo */
318 if (!(m = resolve_method_eager(um)))
321 /* patch back original code */
323 *((u4 *) ra) = mcode;
325 /* synchronize instruction cache */
327 md_icacheflush(ra, 4);
329 /* if we show disassembly, we have to skip the nop */
334 /* patch interfacetable index */
336 disp = OFFSET(vftbl_t, interfacetable[0]) -
337 sizeof(methodptr*) * m->class->index;
339 /* XXX TWISTI: check displacement */
341 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
343 /* patch method offset */
345 disp = sizeof(methodptr) * (m - m->class->methods);
347 /* XXX TWISTI: check displacement */
349 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
351 /* synchronize instruction cache */
353 md_icacheflush(ra, 3 * 4);
359 /* patcher_checkcast_interface **************************************
363 <patched call position>
364 81870000 lwz r12,0(r7)
365 800c0010 lwz r0,16(r12)
366 34000000 addic. r0,r0,0
367 408101fc bgt- 0x3002e518 FIXME
368 83c00003 lwz r30,3(0) FIXME
369 800c0000 lwz r0,0(r12)
371 *******************************************************************************/
373 bool patcher_checkcast_interface(patchref_t *pr)
376 constant_classref *cr;
381 /* get stuff from stack */
384 cr = (constant_classref *) pr->ref;
386 /* get the fieldinfo */
387 if (!(c = resolve_classref_eager(cr))) {
391 /* patch back original code */
392 *((u4 *) ra) = mcode;
394 /* synchronize instruction cache */
396 md_icacheflush(ra, 4);
398 /* if we show NOPs, we have to skip them */
402 /* patch super class index */
405 *((s4*)(ra + 2*4)) |= (disp & 0x0000ffff);
407 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
409 *((s4 *)(ra + 5*4)) |= (disp & 0x0000ffff);
411 /* sync instruction cache */
412 md_icacheflush(ra, 6*4);
418 /* patcher_instanceof_interface **************************************
422 <patched call position>
423 81870000 lwz r12,0(r7)
424 800c0010 lwz r0,16(r12)
425 34000000 addic. r0,r0,0
426 408101fc ble- 0x3002e518
427 800c0000 lwz r0,0(r12)
429 *******************************************************************************/
431 bool patcher_instanceof_interface(patchref_t *pr)
435 constant_classref *cr;
439 /* get stuff from the stack */
443 cr = (constant_classref *) pr->ref;
445 /* get the fieldinfo */
447 if (!(c = resolve_classref_eager(cr)))
450 /* patch back original code */
452 *((u4 *) ra) = mcode;
454 /* synchronize instruction cache */
456 md_icacheflush(ra, 4);
458 /* if we show disassembly, we have to skip the nop */
463 /* patch super class index */
467 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
469 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
471 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
473 /* synchronize instruction cache */
475 md_icacheflush(ra, 5 * 4);
481 /* patcher_resolve_classref_to_classinfo ***************************************
485 <patched call postition>
486 806dffc4 lwz r3,-60(r13)
487 81adffc0 lwz r13,-64(r13)
494 <patched call position>
495 808dffc0 lwz r4,-64(r13)
496 38a10038 addi r5,r1,56
497 81adffbc lwz r13,-68(r13)
504 <patched call position>
505 808dffd8 lwz r4,-40(r13)
506 81adffd4 lwz r13,-44(r13)
510 *******************************************************************************/
512 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
514 constant_classref *cr;
519 /* get stuff from the stack */
523 cr = (constant_classref *) pr->ref;
524 datap = (u1 *) pr->datap;
526 /* get the classinfo */
528 if (!(c = resolve_classref_eager(cr)))
531 /* patch back original code */
533 *((u4 *) ra) = mcode;
535 /* synchronize instruction cache */
537 md_icacheflush(ra, 4);
539 /* patch the classinfo pointer */
541 *((ptrint *) datap) = (ptrint) c;
543 /* synchronize data cache */
545 md_dcacheflush(datap, SIZEOF_VOID_P);
551 /* patcher_resolve_classref_to_vftbl *******************************************
555 <patched call position>
556 81870000 lwz r12,0(r7)
557 800c0014 lwz r0,20(r12)
558 818dff78 lwz r12,-136(r13)
563 <patched call position>
564 817d0000 lwz r11,0(r29)
565 818dff8c lwz r12,-116(r13)
567 *******************************************************************************/
569 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
571 constant_classref *cr;
576 /* get stuff from the stack */
580 cr = (constant_classref *) pr->ref;
581 datap = (u1 *) pr->datap;
583 /* get the fieldinfo */
585 if (!(c = resolve_classref_eager(cr)))
588 /* patch back original code */
590 *((u4 *) ra) = mcode;
592 /* synchronize instruction cache */
594 md_icacheflush(ra, 4);
596 /* patch super class' vftbl */
598 *((ptrint *) datap) = (ptrint) c->vftbl;
600 /* synchronize data cache */
602 md_dcacheflush(datap, SIZEOF_VOID_P);
607 /* patcher_resolve_classref_to_flags *******************************************
609 CHECKCAST/INSTANCEOF:
611 <patched call position>
612 818dff7c lwz r12,-132(r13)
614 *******************************************************************************/
616 bool patcher_resolve_classref_to_flags(patchref_t *pr)
618 constant_classref *cr;
623 /* get stuff from the stack */
627 cr = (constant_classref *) pr->ref;
628 datap = (u1 *) pr->datap;
630 /* get the fieldinfo */
632 if (!(c = resolve_classref_eager(cr)))
635 /* patch back original code */
637 *((u4 *) ra) = mcode;
639 /* synchronize instruction cache */
641 md_icacheflush(ra, 4);
643 /* patch class flags */
645 *((s4 *) datap) = (s4) c->flags;
647 /* synchronize data cache */
649 md_dcacheflush(datap, SIZEOF_VOID_P);
656 * These are local overrides for various environment variables in Emacs.
657 * Please do not remove this and leave it at the end of the file, where
658 * Emacs will automagically detect them.
659 * ---------------------------------------------------------------------
662 * indent-tabs-mode: t
666 * vim:noexpandtab:sw=4:ts=4: