1 /* src/vm/jit/mips/patcher.c - MIPS 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/mips/codegen.h"
34 #include "vm/jit/mips/md.h"
36 #include "mm/memory.h"
38 #include "native/native.h"
40 #include "vm/builtin.h"
41 #include "vm/exceptions.h"
42 #include "vm/initialize.h"
44 #include "vm/jit/asmpart.h"
45 #include "vm/jit/patcher-common.h"
47 #include "vmcore/class.h"
48 #include "vmcore/field.h"
49 #include "vmcore/options.h"
50 #include "vm/resolve.h"
51 #include "vmcore/references.h"
54 #define PATCH_BACK_ORIGINAL_MCODE \
55 *((u4 *) pr->mpc) = (u4) pr->mcode; \
56 md_icacheflush((u1 *) pr->mpc, PATCHER_CALL_SIZE);
59 /* patcher_patch_code **********************************************************
61 Just patches back the original machine code.
63 *******************************************************************************/
65 void patcher_patch_code(patchref_t *pr)
67 PATCH_BACK_ORIGINAL_MCODE;
71 /* patcher_get_putstatic *******************************************************
75 <patched call position>
76 dfc1ffb8 ld at,-72(s8)
79 *******************************************************************************/
81 bool patcher_get_putstatic(patchref_t *pr)
87 /* get stuff from the stack */
89 uf = (unresolved_field *) pr->ref;
90 datap = (u1 *) pr->datap;
92 /* get the fieldinfo */
94 if (!(fi = resolve_field_eager(uf)))
97 /* check if the field's class is initialized */
99 if (!(fi->clazz->state & CLASS_INITIALIZED))
100 if (!initialize_class(fi->clazz))
103 PATCH_BACK_ORIGINAL_MCODE;
105 /* patch the field value's address */
107 *((intptr_t *) datap) = (intptr_t) fi->value;
109 /* synchronize data cache */
111 md_dcacheflush(datap, SIZEOF_VOID_P);
117 /* patcher_get_putfield ********************************************************
121 <patched call position>
122 8ee90020 lw a5,32(s7)
124 *******************************************************************************/
126 bool patcher_get_putfield(patchref_t *pr)
129 unresolved_field *uf;
132 /* get stuff from the stack */
135 uf = (unresolved_field *) pr->ref;
137 /* get the fieldinfo */
139 if (!(fi = resolve_field_eager(uf)))
142 PATCH_BACK_ORIGINAL_MCODE;
144 /* if we show disassembly, we have to skip the nop's */
147 ra = ra + PATCHER_CALL_SIZE;
149 #if SIZEOF_VOID_P == 4
150 if (IS_LNG_TYPE(fi->type)) {
151 # if WORDS_BIGENDIAN == 1
152 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
153 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
154 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
156 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
157 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
158 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
163 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
165 /* synchronize instruction cache */
167 md_icacheflush(ra, 2 * 4);
173 /* patcher_resolve_classref_to_classinfo ***************************************
177 <patched call postition>
178 dfc4ff98 ld a0,-104(s8)
182 <patched call position>
183 dfc5ff90 ld a1,-112(s8)
185 dfd9ff88 ld t9,-120(s8)
191 <patched call position>
192 dfc5ffc0 ld a1,-64(s8)
193 dfd9ffb8 ld t9,-72(s8)
197 *******************************************************************************/
199 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
201 constant_classref *cr;
205 /* get stuff from the stack */
207 cr = (constant_classref *) pr->ref;
208 datap = (u1 *) pr->datap;
210 /* get the classinfo */
212 if (!(c = resolve_classref_eager(cr)))
215 PATCH_BACK_ORIGINAL_MCODE;
217 /* patch the classinfo pointer */
219 *((intptr_t *) datap) = (intptr_t) c;
221 /* synchronize data cache */
223 md_dcacheflush(datap, SIZEOF_VOID_P);
229 /* patcher_resolve_classref_to_vftbl *******************************************
234 <patched call position>
236 dfd9ff18 ld t9,-232(s8)
238 *******************************************************************************/
240 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
242 constant_classref *cr;
246 /* get stuff from the stack */
248 cr = (constant_classref *) pr->ref;
249 datap = (u1 *) pr->datap;
251 /* get the fieldinfo */
253 if (!(c = resolve_classref_eager(cr)))
256 PATCH_BACK_ORIGINAL_MCODE;
258 /* patch super class' vftbl */
260 *((intptr_t *) datap) = (intptr_t) c->vftbl;
262 /* synchronize data cache */
264 md_dcacheflush(datap, SIZEOF_VOID_P);
270 /* patcher_resolve_classref_to_flags *******************************************
272 CHECKCAST/INSTANCEOF:
274 <patched call position>
275 8fc3ff24 lw v1,-220(s8)
276 30630200 andi v1,v1,512
277 1060000d beq v1,zero,0x000000001051824c
280 *******************************************************************************/
282 bool patcher_resolve_classref_to_flags(patchref_t *pr)
284 constant_classref *cr;
288 /* get stuff from the stack */
290 cr = (constant_classref *) pr->ref;
291 datap = (u1 *) pr->datap;
293 /* get the fieldinfo */
295 if (!(c = resolve_classref_eager(cr)))
298 PATCH_BACK_ORIGINAL_MCODE;
300 /* patch class flags */
302 *((int32_t *) datap) = (int32_t) c->flags;
304 /* synchronize data cache */
306 md_dcacheflush(datap, sizeof(int32_t));
312 /* patcher_invokestatic_special ************************************************
316 <patched call position>
317 dfdeffc0 ld s8,-64(s8)
321 ******************************************************************************/
323 bool patcher_invokestatic_special(patchref_t *pr)
325 unresolved_method *um;
329 /* get stuff from the stack */
331 um = (unresolved_method *) pr->ref;
332 datap = (u1 *) pr->datap;
334 /* get the fieldinfo */
336 if (!(m = resolve_method_eager(um)))
339 PATCH_BACK_ORIGINAL_MCODE;
341 /* patch stubroutine */
343 *((ptrint *) datap) = (ptrint) m->stubroutine;
345 /* synchronize data cache */
347 md_dcacheflush(datap, SIZEOF_VOID_P);
353 /* patcher_invokevirtual *******************************************************
357 <patched call position>
359 df3e0040 ld s8,64(t9)
363 *******************************************************************************/
365 bool patcher_invokevirtual(patchref_t *pr)
368 unresolved_method *um;
371 /* get stuff from the stack */
374 um = (unresolved_method *) pr->ref;
376 /* get the fieldinfo */
378 if (!(m = resolve_method_eager(um)))
381 PATCH_BACK_ORIGINAL_MCODE;
383 /* if we show disassembly, we have to skip the nop's */
386 ra = ra + PATCHER_CALL_SIZE;
388 /* patch vftbl index */
390 *((s4 *) (ra + 1 * 4)) |=
391 (s4) ((OFFSET(vftbl_t, table[0]) +
392 sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
394 /* synchronize instruction cache */
396 md_icacheflush(ra + 1 * 4, 1 * 4);
402 /* patcher_invokeinterface *****************************************************
406 <patched call position>
408 df39ffa0 ld t9,-96(t9)
409 df3e0018 ld s8,24(t9)
413 *******************************************************************************/
415 bool patcher_invokeinterface(patchref_t *pr)
418 unresolved_method *um;
421 /* get stuff from the stack */
424 um = (unresolved_method *) pr->ref;
426 /* get the fieldinfo */
428 if (!(m = resolve_method_eager(um)))
431 PATCH_BACK_ORIGINAL_MCODE;
433 /* if we show disassembly, we have to skip the nop's */
436 ra = ra + PATCHER_CALL_SIZE;
438 /* patch interfacetable index */
440 *((s4 *) (ra + 1 * 4)) |=
441 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
442 sizeof(methodptr*) * m->clazz->index) & 0x0000ffff);
444 /* patch method offset */
446 *((s4 *) (ra + 2 * 4)) |=
447 (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x0000ffff);
449 /* synchronize instruction cache */
451 md_icacheflush(ra + 1 * 4, 2 * 4);
457 /* patcher_checkcast_interface *************************************************
461 <patched call position>
463 8c79001c lw t9,28(v1)
464 27390000 addiu t9,t9,0
465 1b200082 blez t9,zero,0x000000001051843c
469 *******************************************************************************/
471 bool patcher_checkcast_interface(patchref_t *pr)
474 constant_classref *cr;
477 /* get stuff from the stack */
480 cr = (constant_classref *) pr->ref;
482 /* get the fieldinfo */
484 if (!(c = resolve_classref_eager(cr)))
487 PATCH_BACK_ORIGINAL_MCODE;
489 /* if we show disassembly, we have to skip the nop's */
492 ra = ra + PATCHER_CALL_SIZE;
494 /* patch super class index */
496 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
497 /* *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
498 /* c->index * sizeof(methodptr*)) & 0x0000ffff); */
499 *((s4 *) (ra + 6 * 4)) |=
500 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
501 c->index * sizeof(methodptr*)) & 0x0000ffff);
503 /* synchronize instruction cache */
505 md_icacheflush(ra + 2 * 4, 5 * 4);
511 /* patcher_instanceof_interface ************************************************
515 <patched call position>
517 8c79001c lw t9,28(v1)
518 27390000 addiu t9,t9,0
519 1b200082 blez t9,zero,0x000000001051843c
523 *******************************************************************************/
525 bool patcher_instanceof_interface(patchref_t *pr)
528 constant_classref *cr;
531 /* get stuff from the stack */
534 cr = (constant_classref *) pr->ref;
536 /* get the fieldinfo */
538 if (!(c = resolve_classref_eager(cr)))
541 PATCH_BACK_ORIGINAL_MCODE;
543 /* if we show disassembly, we have to skip the nop's */
546 ra = ra + PATCHER_CALL_SIZE;
548 /* patch super class index */
550 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
551 *((s4 *) (ra + 5 * 4)) |=
552 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
553 c->index * sizeof(methodptr*)) & 0x0000ffff);
555 /* synchronize instruction cache */
557 md_icacheflush(ra + 2 * 4, 4 * 4);
564 * These are local overrides for various environment variables in Emacs.
565 * Please do not remove this and leave it at the end of the file, where
566 * Emacs will automagically detect them.
567 * ---------------------------------------------------------------------
570 * indent-tabs-mode: t
574 * vim:noexpandtab:sw=4:ts=4: