1 /* src/vm/jit/powerpc/patcher.c - PowerPC 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/powerpc/md.h"
36 #include "mm/memory.h"
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_resolve_classref_to_classinfo ***************************************
89 <patched call postition>
90 806dffc4 lwz r3,-60(r13)
91 81adffc0 lwz r13,-64(r13)
98 <patched call position>
99 808dffc0 lwz r4,-64(r13)
100 38a10038 addi r5,r1,56
101 81adffbc lwz r13,-68(r13)
108 <patched call position>
109 808dffd8 lwz r4,-40(r13)
110 81adffd4 lwz r13,-44(r13)
114 *******************************************************************************/
116 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
118 constant_classref * cr = (constant_classref*) pr->ref;
119 uintptr_t* datap = (uintptr_t*) pr->datap;
121 // Resolve the class.
122 classinfo* c = resolve_classref_eager(cr);
127 // Patch the class pointer.
128 *datap = (uintptr_t) c;
130 // Synchronize data cache.
131 md_dcacheflush(datap, SIZEOF_VOID_P);
133 // Patch back the original code.
134 patcher_patch_code(pr);
140 /* patcher_resolve_classref_to_vftbl *******************************************
144 <patched call position>
145 81870000 lwz r12,0(r7)
146 800c0014 lwz r0,20(r12)
147 818dff78 lwz r12,-136(r13)
152 <patched call position>
153 817d0000 lwz r11,0(r29)
154 818dff8c lwz r12,-116(r13)
156 *******************************************************************************/
158 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
160 constant_classref* cr = (constant_classref*) pr->ref;
161 uintptr_t* datap = (uintptr_t*) pr->datap;
163 // Resolve the class.
164 classinfo* c = resolve_classref_eager(cr);
169 // Patch super class' vftbl.
170 *datap = (uintptr_t) c->vftbl;
172 // Synchronize data cache.
173 md_dcacheflush(datap, SIZEOF_VOID_P);
175 // Patch back the original code.
176 patcher_patch_code(pr);
182 /* patcher_resolve_classref_to_flags *******************************************
184 CHECKCAST/INSTANCEOF:
186 <patched call position>
187 818dff7c lwz r12,-132(r13)
189 *******************************************************************************/
191 bool patcher_resolve_classref_to_flags(patchref_t *pr)
193 constant_classref* cr = (constant_classref*) pr->ref;
194 int32_t* datap = (int32_t*) pr->datap;
196 // Resolve the class.
197 classinfo* c = resolve_classref_eager(cr);
202 // Patch class flags.
205 // Synchronize data cache.
206 md_dcacheflush(datap, SIZEOF_VOID_P);
208 // Patch back the original code.
209 patcher_patch_code(pr);
215 /* patcher_get_putstatic *******************************************************
219 <patched call position>
220 816dffc8 lwz r11,-56(r13)
221 80ab0000 lwz r5,0(r11)
223 *******************************************************************************/
225 bool patcher_get_putstatic(patchref_t *pr)
227 unresolved_field* uf = (unresolved_field*) pr->ref;
228 uintptr_t* datap = (uintptr_t*) pr->datap;
230 // Resolve the field.
231 fieldinfo* fi = resolve_field_eager(uf);
236 // Check if the field's class is initialized.
237 if (!(fi->clazz->state & CLASS_INITIALIZED))
238 if (!initialize_class(fi->clazz))
241 // Patch the field value's address.
242 *datap = (uintptr_t) fi->value;
244 // Synchronize data cache.
245 md_dcacheflush(datap, SIZEOF_VOID_P);
247 // Patch back the original code.
248 patcher_patch_code(pr);
254 /* patcher_get_putfield ********************************************************
258 <patched call position>
259 811f0014 lwz r8,20(r31)
261 *******************************************************************************/
263 bool patcher_get_putfield(patchref_t *pr)
265 uint32_t* pc = (uint32_t*) pr->mpc;
266 unresolved_field* uf = (unresolved_field*) pr->ref;
268 // Resolve the field.
269 fieldinfo* fi = resolve_field_eager(uf);
274 // Patch the field's offset.
275 if (IS_LNG_TYPE(fi->type)) {
276 /* If the field has type long, we have to patch two
277 instructions. But we have to check which instruction
278 is first. We do that with the offset of the first
281 uint32_t disp = (pr->mcode & 0x0000ffff);
284 pr->mcode &= 0xffff0000;
285 pr->mcode |= ((fi->offset + 4) & 0x0000ffff);
286 pc[1] |= ((fi->offset + 0) & 0x0000ffff);
289 pr->mcode |= ((fi->offset + 0) & 0x0000ffff);
291 pc[1] |= ((fi->offset + 4) & 0x0000ffff);
294 // Synchronize instruction cache.
295 md_icacheflush(pc + 1, 1 * 4);
298 pr->mcode |= (fi->offset & 0x0000ffff);
301 // Patch back the original code.
302 patcher_patch_code(pr);
308 /* patcher_invokestatic_special ************************************************
312 <patched call position>
313 81adffd8 lwz r13,-40(r13)
317 ******************************************************************************/
319 bool patcher_invokestatic_special(patchref_t *pr)
321 unresolved_method* um = (unresolved_method*) pr->ref;
322 uintptr_t* datap = (uintptr_t*) pr->datap;
324 // Resolve the method.
325 methodinfo* m = resolve_method_eager(um);
330 // Patch stubroutine.
331 *datap = (uintptr_t) m->stubroutine;
333 // Synchronize data cache.
334 md_dcacheflush(datap, SIZEOF_VOID_P);
336 // Patch back the original code.
337 patcher_patch_code(pr);
343 /* patcher_invokevirtual *******************************************************
347 <patched call position>
348 81830000 lwz r12,0(r3)
349 81ac0088 lwz r13,136(r12)
353 *******************************************************************************/
355 bool patcher_invokevirtual(patchref_t *pr)
357 uint32_t* pc = (uint32_t*) pr->mpc;
358 unresolved_method* um = (unresolved_method*) pr->ref;
360 // Resolve the method.
361 methodinfo* m = resolve_method_eager(um);
366 // Patch vftbl index.
367 int32_t disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
369 pc[1] |= (disp & 0x0000ffff);
371 // Synchronize instruction cache.
372 md_icacheflush(pc + 1, 1 * 4);
374 // Patch back the original code.
375 patcher_patch_code(pr);
381 /* patcher_invokeinterface *****************************************************
385 <patched call position>
386 81830000 lwz r12,0(r3)
387 818cffd0 lwz r12,-48(r12)
388 81ac000c lwz r13,12(r12)
392 *******************************************************************************/
394 bool patcher_invokeinterface(patchref_t *pr)
396 uint32_t* pc = (uint32_t*) pr->mpc;
397 unresolved_method* um = (unresolved_method*) pr->ref;
399 // Resolve the method.
400 methodinfo* m = resolve_method_eager(um);
405 // Patch interfacetable index.
406 int32_t disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index;
408 /* XXX TWISTI: check displacement */
409 pc[1] |= (disp & 0x0000ffff);
411 // Patch method offset.
412 disp = sizeof(methodptr) * (m - m->clazz->methods);
414 /* XXX TWISTI: check displacement */
415 pc[2] |= (disp & 0x0000ffff);
417 // Synchronize instruction cache.
418 md_icacheflush(pc + 1, 2 * 4);
420 // Patch back the original code.
421 patcher_patch_code(pr);
427 /* patcher_checkcast_interface *************************************************
431 <patched call position>
432 81870000 lwz r12,0(r7)
433 800c0010 lwz r0,16(r12)
434 34000000 addic. r0,r0,0
435 41810008 bgt- 0x014135d8
436 83c00003 lwz r30,3(0)
437 800c0000 lwz r0,0(r12)
439 *******************************************************************************/
441 bool patcher_checkcast_interface(patchref_t *pr)
443 uint32_t* pc = (uint32_t*) pr->mpc;
444 constant_classref* cr = (constant_classref*) pr->ref;
446 // Resolve the class.
447 classinfo* c = resolve_classref_eager(cr);
452 // Patch super class index.
453 int32_t disp = -(c->index);
454 pc[2] |= (disp & 0x0000ffff);
456 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
457 pc[5] |= (disp & 0x0000ffff);
459 // Synchronize instruction cache.
460 md_icacheflush(pc + 2, 4 * 4);
462 // Patch back the original code.
463 patcher_patch_code(pr);
469 /* patcher_instanceof_interface ************************************************
473 <patched call position>
474 81870000 lwz r12,0(r7)
475 800c0010 lwz r0,16(r12)
476 34000000 addic. r0,r0,0
477 41810008 bgt- 0x014135d8
478 83c00003 lwz r30,3(0)
479 800c0000 lwz r0,0(r12)
481 *******************************************************************************/
483 bool patcher_instanceof_interface(patchref_t *pr)
485 uint32_t* pc = (uint32_t*) pr->mpc;
486 constant_classref* cr = (constant_classref*) pr->ref;
488 // Resolve the class.
489 classinfo* c = resolve_classref_eager(cr);
494 // Patch super class index.
495 int32_t disp = -(c->index);
496 pc[2] |= (disp & 0x0000ffff);
498 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
499 pc[4] |= (disp & 0x0000ffff);
501 // Synchronize instruction cache.
502 md_icacheflush(pc + 2, 3 * 4);
504 // Patch back the original code.
505 patcher_patch_code(pr);
512 * These are local overrides for various environment variables in Emacs.
513 * Please do not remove this and leave it at the end of the file, where
514 * Emacs will automagically detect them.
515 * ---------------------------------------------------------------------
518 * indent-tabs-mode: t
522 * vim:noexpandtab:sw=4:ts=4: