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.
61 *((uint32_t*) pr->mpc) = pr->mcode;
63 // Synchronize instruction cache.
64 md_icacheflush((void*) pr->mpc, 1 * 4);
68 /* patcher_get_putstatic *******************************************************
72 <patched call position>
73 816dffc8 lwz r11,-56(r13)
74 80ab0000 lwz r5,0(r11)
76 *******************************************************************************/
78 bool patcher_get_putstatic(patchref_t *pr)
86 /* get stuff from the stack */
90 uf = (unresolved_field *) pr->ref;
91 datap = (u1 *) pr->datap;
93 /* get the fieldinfo */
95 if (!(fi = resolve_field_eager(uf)))
98 /* check if the field's class is initialized */
100 if (!(fi->clazz->state & CLASS_INITIALIZED))
101 if (!initialize_class(fi->clazz))
104 /* patch the field value's address */
106 *((intptr_t *) datap) = (intptr_t) fi->value;
108 /* synchronize data cache */
110 md_dcacheflush(datap, SIZEOF_VOID_P);
112 // Patch back the original code.
113 patcher_patch_code(pr);
119 /* patcher_get_putfield ********************************************************
123 <patched call position>
124 811f0014 lwz r8,20(r31)
126 *******************************************************************************/
128 bool patcher_get_putfield(patchref_t *pr)
132 unresolved_field *uf;
137 uf = (unresolved_field *) pr->ref;
139 /* get the fieldinfo */
141 if (!(fi = resolve_field_eager(uf)))
144 // Patch the field offset in the patcher. We also need this to
145 // validate patchers.
146 pr->mcode |= (int16_t) (fi->offset & 0x0000ffff);
148 // Patch back the original code.
149 patcher_patch_code(pr);
155 /* patcher_invokestatic_special ************************************************
159 <patched call position>
160 81adffd8 lwz r13,-40(r13)
164 ******************************************************************************/
166 bool patcher_invokestatic_special(patchref_t *pr)
170 unresolved_method *um;
174 /* get stuff from the stack */
178 um = (unresolved_method *) pr->ref;
179 datap = (u1 *) pr->datap;
181 /* get the fieldinfo */
183 if (!(m = resolve_method_eager(um)))
186 // Patch stubroutine.
187 *((ptrint *) datap) = (ptrint) m->stubroutine;
189 // Synchronize data cache.
190 md_dcacheflush(datap, SIZEOF_VOID_P);
192 // Patch back the original code.
193 patcher_patch_code(pr);
199 /* patcher_invokevirtual *******************************************************
203 <patched call position>
204 81830000 lwz r12,0(r3)
205 81ac0088 lwz r13,136(r12)
209 *******************************************************************************/
211 bool patcher_invokevirtual(patchref_t *pr)
215 unresolved_method *um;
219 /* get stuff from the stack */
223 um = (unresolved_method *) pr->ref;
225 /* get the fieldinfo */
227 if (!(m = resolve_method_eager(um)))
230 // Patch vftbl index.
231 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
233 *((uint32_t*) (ra + 1 * 4)) |= (disp & 0x0000ffff);
235 // Synchronize instruction cache.
236 md_icacheflush(ra, 2 * 4);
238 // Patch back the original code.
239 patcher_patch_code(pr);
245 /* patcher_invokeinterface *****************************************************
249 <patched call position>
250 81830000 lwz r12,0(r3)
251 818cffd0 lwz r12,-48(r12)
252 81ac000c lwz r13,12(r12)
256 *******************************************************************************/
258 bool patcher_invokeinterface(patchref_t *pr)
262 unresolved_method *um;
266 /* get stuff from the stack */
270 um = (unresolved_method *) pr->ref;
272 /* get the fieldinfo */
274 if (!(m = resolve_method_eager(um)))
277 // Patch interfacetable index.
278 disp = OFFSET(vftbl_t, interfacetable[0]) -
279 sizeof(methodptr*) * m->clazz->index;
281 // XXX TWISTI: check displacement
282 *((uint32_t*) (ra + 1 * 4)) |= (disp & 0x0000ffff);
284 // Patch method offset.
285 disp = sizeof(methodptr) * (m - m->clazz->methods);
287 // XXX TWISTI: check displacement
288 *((uint32_t*) (ra + 2 * 4)) |= (disp & 0x0000ffff);
290 // Synchronize instruction cache.
291 md_icacheflush(ra, 3 * 4);
293 // Patch back the original code.
294 patcher_patch_code(pr);
300 /* patcher_checkcast_interface **************************************
304 <patched call position>
305 81870000 lwz r12,0(r7)
306 800c0010 lwz r0,16(r12)
307 34000000 addic. r0,r0,0
308 408101fc bgt- 0x3002e518 FIXME
309 83c00003 lwz r30,3(0) FIXME
310 800c0000 lwz r0,0(r12)
312 *******************************************************************************/
314 bool patcher_checkcast_interface(patchref_t *pr)
317 constant_classref *cr;
322 /* get stuff from stack */
325 cr = (constant_classref *) pr->ref;
327 /* get the fieldinfo */
328 if (!(c = resolve_classref_eager(cr))) {
332 // Patch super class index.
334 *((uint32_t*) (ra + 2 * 4)) |= (disp & 0x0000ffff);
336 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
337 *((uint32_t*) (ra + 5 * 4)) |= (disp & 0x0000ffff);
339 // Synchronize instruction cache.
340 md_icacheflush(ra, 6 * 4);
342 // Patch back the original code.
343 patcher_patch_code(pr);
349 /* patcher_instanceof_interface **************************************
353 <patched call position>
354 81870000 lwz r12,0(r7)
355 800c0010 lwz r0,16(r12)
356 34000000 addic. r0,r0,0
357 408101fc ble- 0x3002e518
358 800c0000 lwz r0,0(r12)
360 *******************************************************************************/
362 bool patcher_instanceof_interface(patchref_t *pr)
366 constant_classref *cr;
370 /* get stuff from the stack */
374 cr = (constant_classref *) pr->ref;
376 /* get the fieldinfo */
378 if (!(c = resolve_classref_eager(cr)))
381 // Patch super class index.
383 *((uint32_t*) (ra + 2 * 4)) |= (disp & 0x0000ffff);
385 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
386 *((uint32_t*) (ra + 4 * 4)) |= (disp & 0x0000ffff);
388 // Synchronize instruction cache.
389 md_icacheflush(ra, 5 * 4);
391 // Patch back the original code.
392 patcher_patch_code(pr);
398 /* patcher_resolve_classref_to_classinfo ***************************************
402 <patched call postition>
403 806dffc4 lwz r3,-60(r13)
404 81adffc0 lwz r13,-64(r13)
411 <patched call position>
412 808dffc0 lwz r4,-64(r13)
413 38a10038 addi r5,r1,56
414 81adffbc lwz r13,-68(r13)
421 <patched call position>
422 808dffd8 lwz r4,-40(r13)
423 81adffd4 lwz r13,-44(r13)
427 *******************************************************************************/
429 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
431 constant_classref *cr;
436 /* get stuff from the stack */
440 cr = (constant_classref *) pr->ref;
441 datap = (u1 *) pr->datap;
443 /* get the classinfo */
445 if (!(c = resolve_classref_eager(cr)))
448 // Patch the classinfo pointer.
449 *((uintptr_t*) datap) = (uintptr_t) c;
451 // Synchronize data cache.
452 md_dcacheflush(datap, SIZEOF_VOID_P);
454 // Patch back the original code.
455 patcher_patch_code(pr);
461 /* patcher_resolve_classref_to_vftbl *******************************************
465 <patched call position>
466 81870000 lwz r12,0(r7)
467 800c0014 lwz r0,20(r12)
468 818dff78 lwz r12,-136(r13)
473 <patched call position>
474 817d0000 lwz r11,0(r29)
475 818dff8c lwz r12,-116(r13)
477 *******************************************************************************/
479 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
481 constant_classref *cr;
486 /* get stuff from the stack */
490 cr = (constant_classref *) pr->ref;
491 datap = (u1 *) pr->datap;
493 /* get the fieldinfo */
495 if (!(c = resolve_classref_eager(cr)))
498 // Patch super class' vftbl.
499 *((uintptr_t*) datap) = (uintptr_t) c->vftbl;
501 // Synchronize data cache.
502 md_dcacheflush(datap, SIZEOF_VOID_P);
504 // Patch back the original code.
505 patcher_patch_code(pr);
510 /* patcher_resolve_classref_to_flags *******************************************
512 CHECKCAST/INSTANCEOF:
514 <patched call position>
515 818dff7c lwz r12,-132(r13)
517 *******************************************************************************/
519 bool patcher_resolve_classref_to_flags(patchref_t *pr)
521 constant_classref *cr;
526 /* get stuff from the stack */
530 cr = (constant_classref *) pr->ref;
531 datap = (u1 *) pr->datap;
533 /* get the fieldinfo */
535 if (!(c = resolve_classref_eager(cr)))
538 // Patch class flags.
539 *((int32_t*) datap) = (int32_t) c->flags;
541 // Synchronize data cache.
542 md_dcacheflush(datap, SIZEOF_VOID_P);
544 // Patch back the original code.
545 patcher_patch_code(pr);
552 * These are local overrides for various environment variables in Emacs.
553 * Please do not remove this and leave it at the end of the file, where
554 * Emacs will automagically detect them.
555 * ---------------------------------------------------------------------
558 * indent-tabs-mode: t
562 * vim:noexpandtab:sw=4:ts=4: