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
5 Copyright (C) 2008 Theobroma Systems Ltd.
7 This file is part of CACAO.
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2, or (at
12 your option) any later version.
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "vm/jit/powerpc64/md.h"
36 #include "mm/memory.hpp"
38 #include "native/native.hpp"
40 #include "vm/jit/builtin.hpp"
41 #include "vm/class.hpp"
42 #include "vm/field.hpp"
43 #include "vm/initialize.hpp"
44 #include "vm/options.h"
45 #include "vm/references.h"
46 #include "vm/resolve.hpp"
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/methodheader.h"
50 #include "vm/jit/patcher-common.hpp"
53 /* patcher_patch_code **********************************************************
55 Just patches back the original machine code.
57 *******************************************************************************/
59 void patcher_patch_code(patchref_t *pr)
61 // Patch back original code.
62 *((uint32_t*) pr->mpc) = pr->mcode;
64 // Synchronize instruction cache.
65 md_icacheflush((void*) pr->mpc, 1 * 4);
69 /* patcher_get_putstatic *******************************************************
73 <patched call position>
74 816dffc8 lwz r11,-56(r13)
75 80ab0000 lwz r5,0(r11)
77 *******************************************************************************/
79 bool patcher_get_putstatic(patchref_t* pr)
81 unresolved_field* uf = (unresolved_field*) pr->ref;
82 uintptr_t* datap = (uintptr_t*) pr->datap;
85 fieldinfo* fi = resolve_field_eager(uf);
90 // Check if the field's class is initialized.
91 if (!(fi->clazz->state & CLASS_INITIALIZED))
92 if (!initialize_class(fi->clazz))
95 // Patch the field value's address.
96 *datap = (uintptr_t) fi->value;
98 // Synchronize data cache.
99 md_dcacheflush(datap, SIZEOF_VOID_P);
101 // Patch back the original code.
102 patcher_patch_code(pr);
108 /* patcher_get_putfield ********************************************************
112 <patched call position>
113 811f0014 lwz r8,20(r31)
115 *******************************************************************************/
117 bool patcher_get_putfield(patchref_t* pr)
119 unresolved_field* uf = (unresolved_field*) pr->ref;
121 // Resolve the field.
122 fieldinfo* fi = resolve_field_eager(uf);
127 // Patch the field offset in the patcher. We also need this to
128 // validate patchers.
129 pr->mcode |= (int16_t) (fi->offset & 0x0000ffff);
131 // Patch back the original code.
132 patcher_patch_code(pr);
138 /* patcher_invokestatic_special ************************************************
142 <patched call position>
143 81adffd8 lwz r13,-40(r13)
147 ******************************************************************************/
149 bool patcher_invokestatic_special(patchref_t* pr)
151 unresolved_method* um = (unresolved_method*) pr->ref;
152 uintptr_t* datap = (uintptr_t*) pr->datap;
154 // Resolve the method.
155 methodinfo* m = resolve_method_eager(um);
160 // Patch stubroutine.
161 *datap = (uintptr_t) m->stubroutine;
163 // Synchronize data cache.
164 md_dcacheflush(datap, SIZEOF_VOID_P);
166 // Patch back the original code.
167 patcher_patch_code(pr);
173 /* patcher_invokevirtual *******************************************************
177 <patched call position>
178 81830000 lwz r12,0(r3)
179 81ac0088 lwz r13,136(r12)
183 *******************************************************************************/
185 bool patcher_invokevirtual(patchref_t* pr)
187 uint32_t* pc = (uint32_t*) pr->mpc;
188 unresolved_method* um = (unresolved_method*) pr->ref;
190 // Resolve the method.
191 methodinfo* m = resolve_method_eager(um);
196 // Patch vftbl index.
197 int32_t disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
199 pc[1] |= (disp & 0x0000ffff);
201 // Synchronize instruction cache.
202 md_icacheflush(pc + 1, 1 * 4);
204 // Patch back the original code.
205 patcher_patch_code(pr);
211 /* patcher_invokeinterface *****************************************************
215 <patched call position>
216 81830000 lwz r12,0(r3)
217 818cffd0 lwz r12,-48(r12)
218 81ac000c lwz r13,12(r12)
222 *******************************************************************************/
224 bool patcher_invokeinterface(patchref_t* pr)
226 uint32_t* pc = (uint32_t*) pr->mpc;
227 unresolved_method* um = (unresolved_method*) pr->ref;
229 // Resolve the method.
230 methodinfo* m = resolve_method_eager(um);
235 // Patch interfacetable index.
236 int32_t disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index;
238 // XXX TWISTI: check displacement
239 pc[1] |= (disp & 0x0000ffff);
241 // Patch method offset.
242 disp = sizeof(methodptr) * (m - m->clazz->methods);
244 // XXX TWISTI: check displacement
245 pc[2] |= (disp & 0x0000ffff);
247 // Synchronize instruction cache.
248 md_icacheflush(pc + 1, 2 * 4);
250 // Patch back the original code.
251 patcher_patch_code(pr);
257 /* patcher_checkcast_interface **************************************
261 <patched call position>
262 81870000 lwz r12,0(r7)
263 800c0010 lwz r0,16(r12)
264 34000000 addic. r0,r0,0
265 408101fc bgt- 0x3002e518 FIXME
266 83c00003 lwz r30,3(0) FIXME
267 800c0000 lwz r0,0(r12)
269 *******************************************************************************/
271 bool patcher_checkcast_interface(patchref_t* pr)
273 uint32_t* pc = (uint32_t*) pr->mpc;
274 constant_classref* cr = (constant_classref*) pr->ref;
276 // Resolve the class.
277 classinfo* c = resolve_classref_eager(cr);
282 // Patch super class index.
283 int32_t disp = -(c->index);
284 pc[2] |= (disp & 0x0000ffff);
286 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
287 pc[5] |= (disp & 0x0000ffff);
289 // Synchronize instruction cache.
290 md_icacheflush(pc + 2, 4 * 4);
292 // Patch back the original code.
293 patcher_patch_code(pr);
299 /* patcher_instanceof_interface **************************************
303 <patched call position>
304 81870000 lwz r12,0(r7)
305 800c0010 lwz r0,16(r12)
306 34000000 addic. r0,r0,0
307 408101fc ble- 0x3002e518
308 800c0000 lwz r0,0(r12)
310 *******************************************************************************/
312 bool patcher_instanceof_interface(patchref_t* pr)
314 uint32_t* pc = (uint32_t*) pr->mpc;
315 constant_classref* cr = (constant_classref*) pr->ref;
317 // Resolve the class.
318 classinfo* c = resolve_classref_eager(cr);
323 // Patch super class index.
324 int32_t disp = -(c->index);
325 pc[2] |= (disp & 0x0000ffff);
327 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
328 pc[4] |= (disp & 0x0000ffff);
330 // Synchronize instruction cache.
331 md_icacheflush(pc + 2, 3 * 4);
333 // Patch back the original code.
334 patcher_patch_code(pr);
340 /* patcher_resolve_classref_to_classinfo ***************************************
344 <patched call postition>
345 806dffc4 lwz r3,-60(r13)
346 81adffc0 lwz r13,-64(r13)
353 <patched call position>
354 808dffc0 lwz r4,-64(r13)
355 38a10038 addi r5,r1,56
356 81adffbc lwz r13,-68(r13)
363 <patched call position>
364 808dffd8 lwz r4,-40(r13)
365 81adffd4 lwz r13,-44(r13)
369 *******************************************************************************/
371 bool patcher_resolve_classref_to_classinfo(patchref_t* pr)
373 constant_classref* cr = (constant_classref*) pr->ref;
374 uintptr_t* datap = (uintptr_t*) pr->datap;
376 // Resolve the class.
377 classinfo* c = resolve_classref_eager(cr);
382 // Patch the classinfo pointer.
383 *datap = (uintptr_t) c;
385 // Synchronize data cache.
386 md_dcacheflush(datap, SIZEOF_VOID_P);
388 // Patch back the original code.
389 patcher_patch_code(pr);
395 /* patcher_resolve_classref_to_vftbl *******************************************
399 <patched call position>
400 81870000 lwz r12,0(r7)
401 800c0014 lwz r0,20(r12)
402 818dff78 lwz r12,-136(r13)
407 <patched call position>
408 817d0000 lwz r11,0(r29)
409 818dff8c lwz r12,-116(r13)
411 *******************************************************************************/
413 bool patcher_resolve_classref_to_vftbl(patchref_t* pr)
415 constant_classref* cr = (constant_classref*) pr->ref;
416 uintptr_t* datap = (uintptr_t*) pr->datap;
418 // Resolve the class.
419 classinfo* c = resolve_classref_eager(cr);
424 // Patch super class' vftbl.
425 *datap = (uintptr_t) c->vftbl;
427 // Synchronize data cache.
428 md_dcacheflush(datap, SIZEOF_VOID_P);
430 // Patch back the original code.
431 patcher_patch_code(pr);
436 /* patcher_resolve_classref_to_flags *******************************************
438 CHECKCAST/INSTANCEOF:
440 <patched call position>
441 818dff7c lwz r12,-132(r13)
443 *******************************************************************************/
445 bool patcher_resolve_classref_to_flags(patchref_t* pr)
447 constant_classref* cr = (constant_classref*) pr->ref;
448 int32_t* datap = (int32_t*) pr->datap;
450 // Resolve the class.
451 classinfo* c = resolve_classref_eager(cr);
456 // Patch class flags.
457 *datap = (int32_t) c->flags;
459 // Synchronize data cache.
460 md_dcacheflush(datap, SIZEOF_VOID_P);
462 // Patch back the original code.
463 patcher_patch_code(pr);
470 * These are local overrides for various environment variables in Emacs.
471 * Please do not remove this and leave it at the end of the file, where
472 * Emacs will automagically detect them.
473 * ---------------------------------------------------------------------
476 * indent-tabs-mode: t
480 * vim:noexpandtab:sw=4:ts=4: