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);
70 * Check if the trap instruction at the given PC is valid.
72 * @param pc Program counter.
74 * @return true if valid, false otherwise.
76 bool patcher_is_valid_trap_instruction_at(void* pc)
78 uint32_t mcode = *((uint32_t*) pc);
80 // Check for the undefined instruction we use.
81 return (mcode == 0x00000000);
85 /* patcher_get_putstatic *******************************************************
89 <patched call position>
90 816dffc8 lwz r11,-56(r13)
91 80ab0000 lwz r5,0(r11)
93 *******************************************************************************/
95 bool patcher_get_putstatic(patchref_t* pr)
97 unresolved_field* uf = (unresolved_field*) pr->ref;
98 uintptr_t* datap = (uintptr_t*) pr->datap;
100 // Resolve the field.
101 fieldinfo* fi = resolve_field_eager(uf);
106 // Check if the field's class is initialized.
107 if (!(fi->clazz->state & CLASS_INITIALIZED))
108 if (!initialize_class(fi->clazz))
111 // Patch the field value's address.
112 *datap = (uintptr_t) fi->value;
114 // Synchronize data cache.
115 md_dcacheflush(datap, SIZEOF_VOID_P);
117 // Patch back the original code.
118 patcher_patch_code(pr);
124 /* patcher_get_putfield ********************************************************
128 <patched call position>
129 811f0014 lwz r8,20(r31)
131 *******************************************************************************/
133 bool patcher_get_putfield(patchref_t* pr)
135 unresolved_field* uf = (unresolved_field*) pr->ref;
137 // Resolve the field.
138 fieldinfo* fi = resolve_field_eager(uf);
143 // Patch the field offset in the patcher. We also need this to
144 // validate patchers.
145 pr->mcode |= (int16_t) (fi->offset & 0x0000ffff);
147 // Patch back the original code.
148 patcher_patch_code(pr);
154 /* patcher_invokestatic_special ************************************************
158 <patched call position>
159 81adffd8 lwz r13,-40(r13)
163 ******************************************************************************/
165 bool patcher_invokestatic_special(patchref_t* pr)
167 unresolved_method* um = (unresolved_method*) pr->ref;
168 uintptr_t* datap = (uintptr_t*) pr->datap;
170 // Resolve the method.
171 methodinfo* m = resolve_method_eager(um);
176 // Patch stubroutine.
177 *datap = (uintptr_t) m->stubroutine;
179 // Synchronize data cache.
180 md_dcacheflush(datap, SIZEOF_VOID_P);
182 // Patch back the original code.
183 patcher_patch_code(pr);
189 /* patcher_invokevirtual *******************************************************
193 <patched call position>
194 81830000 lwz r12,0(r3)
195 81ac0088 lwz r13,136(r12)
199 *******************************************************************************/
201 bool patcher_invokevirtual(patchref_t* pr)
203 uint32_t* pc = (uint32_t*) pr->mpc;
204 unresolved_method* um = (unresolved_method*) pr->ref;
206 // Resolve the method.
207 methodinfo* m = resolve_method_eager(um);
212 // Patch vftbl index.
213 int32_t disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
215 pc[1] |= (disp & 0x0000ffff);
217 // Synchronize instruction cache.
218 md_icacheflush(pc + 1, 1 * 4);
220 // Patch back the original code.
221 patcher_patch_code(pr);
227 /* patcher_invokeinterface *****************************************************
231 <patched call position>
232 81830000 lwz r12,0(r3)
233 818cffd0 lwz r12,-48(r12)
234 81ac000c lwz r13,12(r12)
238 *******************************************************************************/
240 bool patcher_invokeinterface(patchref_t* pr)
242 uint32_t* pc = (uint32_t*) pr->mpc;
243 unresolved_method* um = (unresolved_method*) pr->ref;
245 // Resolve the method.
246 methodinfo* m = resolve_method_eager(um);
251 // Patch interfacetable index.
252 int32_t disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index;
254 // XXX TWISTI: check displacement
255 pc[1] |= (disp & 0x0000ffff);
257 // Patch method offset.
258 disp = sizeof(methodptr) * (m - m->clazz->methods);
260 // XXX TWISTI: check displacement
261 pc[2] |= (disp & 0x0000ffff);
263 // Synchronize instruction cache.
264 md_icacheflush(pc + 1, 2 * 4);
266 // Patch back the original code.
267 patcher_patch_code(pr);
273 /* patcher_checkcast_interface **************************************
277 <patched call position>
278 81870000 lwz r12,0(r7)
279 800c0010 lwz r0,16(r12)
280 34000000 addic. r0,r0,0
281 408101fc bgt- 0x3002e518 FIXME
282 83c00003 lwz r30,3(0) FIXME
283 800c0000 lwz r0,0(r12)
285 *******************************************************************************/
287 bool patcher_checkcast_interface(patchref_t* pr)
289 uint32_t* pc = (uint32_t*) pr->mpc;
290 constant_classref* cr = (constant_classref*) pr->ref;
292 // Resolve the class.
293 classinfo* c = resolve_classref_eager(cr);
298 // Patch super class index.
299 int32_t disp = -(c->index);
300 pc[2] |= (disp & 0x0000ffff);
302 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
303 pc[5] |= (disp & 0x0000ffff);
305 // Synchronize instruction cache.
306 md_icacheflush(pc + 2, 4 * 4);
308 // Patch back the original code.
309 patcher_patch_code(pr);
315 /* patcher_instanceof_interface **************************************
319 <patched call position>
320 81870000 lwz r12,0(r7)
321 800c0010 lwz r0,16(r12)
322 34000000 addic. r0,r0,0
323 408101fc ble- 0x3002e518
324 800c0000 lwz r0,0(r12)
326 *******************************************************************************/
328 bool patcher_instanceof_interface(patchref_t* pr)
330 uint32_t* pc = (uint32_t*) pr->mpc;
331 constant_classref* cr = (constant_classref*) pr->ref;
333 // Resolve the class.
334 classinfo* c = resolve_classref_eager(cr);
339 // Patch super class index.
340 int32_t disp = -(c->index);
341 pc[2] |= (disp & 0x0000ffff);
343 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
344 pc[4] |= (disp & 0x0000ffff);
346 // Synchronize instruction cache.
347 md_icacheflush(pc + 2, 3 * 4);
349 // Patch back the original code.
350 patcher_patch_code(pr);
356 /* patcher_resolve_classref_to_classinfo ***************************************
360 <patched call postition>
361 806dffc4 lwz r3,-60(r13)
362 81adffc0 lwz r13,-64(r13)
369 <patched call position>
370 808dffc0 lwz r4,-64(r13)
371 38a10038 addi r5,r1,56
372 81adffbc lwz r13,-68(r13)
379 <patched call position>
380 808dffd8 lwz r4,-40(r13)
381 81adffd4 lwz r13,-44(r13)
385 *******************************************************************************/
387 bool patcher_resolve_classref_to_classinfo(patchref_t* pr)
389 constant_classref* cr = (constant_classref*) pr->ref;
390 uintptr_t* datap = (uintptr_t*) pr->datap;
392 // Resolve the class.
393 classinfo* c = resolve_classref_eager(cr);
398 // Patch the classinfo pointer.
399 *datap = (uintptr_t) c;
401 // Synchronize data cache.
402 md_dcacheflush(datap, SIZEOF_VOID_P);
404 // Patch back the original code.
405 patcher_patch_code(pr);
411 /* patcher_resolve_classref_to_vftbl *******************************************
415 <patched call position>
416 81870000 lwz r12,0(r7)
417 800c0014 lwz r0,20(r12)
418 818dff78 lwz r12,-136(r13)
423 <patched call position>
424 817d0000 lwz r11,0(r29)
425 818dff8c lwz r12,-116(r13)
427 *******************************************************************************/
429 bool patcher_resolve_classref_to_vftbl(patchref_t* pr)
431 constant_classref* cr = (constant_classref*) pr->ref;
432 uintptr_t* datap = (uintptr_t*) pr->datap;
434 // Resolve the class.
435 classinfo* c = resolve_classref_eager(cr);
440 // Patch super class' vftbl.
441 *datap = (uintptr_t) c->vftbl;
443 // Synchronize data cache.
444 md_dcacheflush(datap, SIZEOF_VOID_P);
446 // Patch back the original code.
447 patcher_patch_code(pr);
452 /* patcher_resolve_classref_to_flags *******************************************
454 CHECKCAST/INSTANCEOF:
456 <patched call position>
457 818dff7c lwz r12,-132(r13)
459 *******************************************************************************/
461 bool patcher_resolve_classref_to_flags(patchref_t* pr)
463 constant_classref* cr = (constant_classref*) pr->ref;
464 int32_t* datap = (int32_t*) pr->datap;
466 // Resolve the class.
467 classinfo* c = resolve_classref_eager(cr);
472 // Patch class flags.
473 *datap = (int32_t) c->flags;
475 // Synchronize data cache.
476 md_dcacheflush(datap, SIZEOF_VOID_P);
478 // Patch back the original code.
479 patcher_patch_code(pr);
486 * These are local overrides for various environment variables in Emacs.
487 * Please do not remove this and leave it at the end of the file, where
488 * Emacs will automagically detect them.
489 * ---------------------------------------------------------------------
492 * indent-tabs-mode: t
496 * vim:noexpandtab:sw=4:ts=4: