1 /* src/vm/jit/mips/patcher.c - MIPS code patching functions
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
35 #include "vm/jit/mips/codegen.h"
37 #include "mm/memory.h"
39 #include "native/native.h"
41 #include "vm/builtin.h"
42 #include "vm/exceptions.h"
43 #include "vm/initialize.h"
45 #include "vm/jit/asmpart.h"
46 #include "vm/jit/md.h"
47 #include "vm/jit/patcher-common.h"
49 #include "vmcore/class.h"
50 #include "vmcore/field.h"
51 #include "vmcore/options.h"
52 #include "vm/resolve.h"
53 #include "vmcore/references.h"
56 #define PATCH_BACK_ORIGINAL_MCODE \
57 *((u4 *) pr->mpc) = (u4) pr->mcode; \
58 md_icacheflush((u1 *) pr->mpc, PATCHER_CALL_SIZE);
61 /* patcher_initialize_class ****************************************************
63 Initalizes a given classinfo pointer. This function does not patch
66 *******************************************************************************/
68 bool patcher_initialize_class(patchref_t *pr)
72 /* get stuff from the stack */
74 c = (classinfo *) pr->ref;
76 /* check if the class is initialized */
78 if (!(c->state & CLASS_INITIALIZED))
79 if (!initialize_class(c))
82 PATCH_BACK_ORIGINAL_MCODE;
88 /* patcher_resolve_class *****************************************************
90 Initalizes a given classinfo pointer. This function does not patch
93 *******************************************************************************/
95 #ifdef ENABLE_VERIFIER
96 bool patcher_resolve_class(patchref_t *pr)
100 /* get stuff from the stack */
102 uc = (unresolved_class *) pr->ref;
104 /* resolve the class and check subtype constraints */
106 if (!resolve_class_eager_no_access_check(uc))
109 PATCH_BACK_ORIGINAL_MCODE;
113 #endif /* ENABLE_VERIFIER */
116 /* patcher_get_putstatic *******************************************************
120 <patched call position>
121 dfc1ffb8 ld at,-72(s8)
124 *******************************************************************************/
126 bool patcher_get_putstatic(patchref_t *pr)
128 unresolved_field *uf;
132 /* get stuff from the stack */
134 uf = (unresolved_field *) pr->ref;
135 datap = (u1 *) pr->datap;
137 /* get the fieldinfo */
139 if (!(fi = resolve_field_eager(uf)))
142 /* check if the field's class is initialized */
144 if (!(fi->class->state & CLASS_INITIALIZED))
145 if (!initialize_class(fi->class))
148 PATCH_BACK_ORIGINAL_MCODE;
150 /* patch the field value's address */
152 *((intptr_t *) datap) = (intptr_t) fi->value;
154 /* synchronize data cache */
156 md_dcacheflush(datap, SIZEOF_VOID_P);
162 /* patcher_get_putfield ********************************************************
166 <patched call position>
167 8ee90020 lw a5,32(s7)
169 *******************************************************************************/
171 bool patcher_get_putfield(patchref_t *pr)
174 unresolved_field *uf;
177 /* get stuff from the stack */
180 uf = (unresolved_field *) pr->ref;
182 /* get the fieldinfo */
184 if (!(fi = resolve_field_eager(uf)))
187 PATCH_BACK_ORIGINAL_MCODE;
189 /* if we show disassembly, we have to skip the nop's */
192 ra = ra + PATCHER_CALL_SIZE;
194 #if SIZEOF_VOID_P == 4
195 if (IS_LNG_TYPE(fi->type)) {
196 # if WORDS_BIGENDIAN == 1
197 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
198 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
199 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
201 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
202 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
203 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
208 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
210 /* synchronize instruction cache */
212 md_icacheflush(ra, 2 * 4);
218 /* patcher_resolve_classref_to_classinfo ***************************************
222 <patched call postition>
223 dfc4ff98 ld a0,-104(s8)
227 <patched call position>
228 dfc5ff90 ld a1,-112(s8)
230 dfd9ff88 ld t9,-120(s8)
236 <patched call position>
237 dfc5ffc0 ld a1,-64(s8)
238 dfd9ffb8 ld t9,-72(s8)
242 *******************************************************************************/
244 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
246 constant_classref *cr;
250 /* get stuff from the stack */
252 cr = (constant_classref *) pr->ref;
253 datap = (u1 *) pr->datap;
255 /* get the classinfo */
257 if (!(c = resolve_classref_eager(cr)))
260 PATCH_BACK_ORIGINAL_MCODE;
262 /* patch the classinfo pointer */
264 *((intptr_t *) datap) = (intptr_t) c;
266 /* synchronize data cache */
268 md_dcacheflush(datap, SIZEOF_VOID_P);
274 /* patcher_resolve_classref_to_vftbl *******************************************
279 <patched call position>
281 dfd9ff18 ld t9,-232(s8)
283 *******************************************************************************/
285 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
287 constant_classref *cr;
291 /* get stuff from the stack */
293 cr = (constant_classref *) pr->ref;
294 datap = (u1 *) pr->datap;
296 /* get the fieldinfo */
298 if (!(c = resolve_classref_eager(cr)))
301 PATCH_BACK_ORIGINAL_MCODE;
303 /* patch super class' vftbl */
305 *((intptr_t *) datap) = (intptr_t) c->vftbl;
307 /* synchronize data cache */
309 md_dcacheflush(datap, SIZEOF_VOID_P);
315 /* patcher_resolve_classref_to_flags *******************************************
317 CHECKCAST/INSTANCEOF:
319 <patched call position>
320 8fc3ff24 lw v1,-220(s8)
321 30630200 andi v1,v1,512
322 1060000d beq v1,zero,0x000000001051824c
325 *******************************************************************************/
327 bool patcher_resolve_classref_to_flags(patchref_t *pr)
329 constant_classref *cr;
333 /* get stuff from the stack */
335 cr = (constant_classref *) pr->ref;
336 datap = (u1 *) pr->datap;
338 /* get the fieldinfo */
340 if (!(c = resolve_classref_eager(cr)))
343 PATCH_BACK_ORIGINAL_MCODE;
345 /* patch class flags */
347 *((int32_t *) datap) = (int32_t) c->flags;
349 /* synchronize data cache */
351 md_dcacheflush(datap, sizeof(int32_t));
357 /* patcher_resolve_native ******************************************************
361 *******************************************************************************/
363 #if !defined(WITH_STATIC_CLASSPATH)
364 bool patcher_resolve_native_function(patchref_t *pr)
370 /* get stuff from the stack */
372 m = (methodinfo *) pr->ref;
373 datap = (u1 *) pr->datap;
375 /* resolve native function */
377 if (!(f = native_resolve_function(m)))
380 PATCH_BACK_ORIGINAL_MCODE;
382 /* patch native function pointer */
384 *((ptrint *) datap) = (ptrint) f;
386 /* synchronize data cache */
388 md_dcacheflush(datap, SIZEOF_VOID_P);
392 #endif /* !defined(WITH_STATIC_CLASSPATH) */
395 /* patcher_invokestatic_special ************************************************
399 <patched call position>
400 dfdeffc0 ld s8,-64(s8)
404 ******************************************************************************/
406 bool patcher_invokestatic_special(patchref_t *pr)
408 unresolved_method *um;
412 /* get stuff from the stack */
414 um = (unresolved_method *) pr->ref;
415 datap = (u1 *) pr->datap;
417 /* get the fieldinfo */
419 if (!(m = resolve_method_eager(um)))
422 PATCH_BACK_ORIGINAL_MCODE;
424 /* patch stubroutine */
426 *((ptrint *) datap) = (ptrint) m->stubroutine;
428 /* synchronize data cache */
430 md_dcacheflush(datap, SIZEOF_VOID_P);
436 /* patcher_invokevirtual *******************************************************
440 <patched call position>
442 df3e0040 ld s8,64(t9)
446 *******************************************************************************/
448 bool patcher_invokevirtual(patchref_t *pr)
451 unresolved_method *um;
454 /* get stuff from the stack */
457 um = (unresolved_method *) pr->ref;
459 /* get the fieldinfo */
461 if (!(m = resolve_method_eager(um)))
464 PATCH_BACK_ORIGINAL_MCODE;
466 /* if we show disassembly, we have to skip the nop's */
469 ra = ra + PATCHER_CALL_SIZE;
471 /* patch vftbl index */
473 *((s4 *) (ra + 1 * 4)) |=
474 (s4) ((OFFSET(vftbl_t, table[0]) +
475 sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
477 /* synchronize instruction cache */
479 md_icacheflush(ra + 1 * 4, 1 * 4);
485 /* patcher_invokeinterface *****************************************************
489 <patched call position>
491 df39ffa0 ld t9,-96(t9)
492 df3e0018 ld s8,24(t9)
496 *******************************************************************************/
498 bool patcher_invokeinterface(patchref_t *pr)
501 unresolved_method *um;
504 /* get stuff from the stack */
507 um = (unresolved_method *) pr->ref;
509 /* get the fieldinfo */
511 if (!(m = resolve_method_eager(um)))
514 PATCH_BACK_ORIGINAL_MCODE;
516 /* if we show disassembly, we have to skip the nop's */
519 ra = ra + PATCHER_CALL_SIZE;
521 /* patch interfacetable index */
523 *((s4 *) (ra + 1 * 4)) |=
524 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
525 sizeof(methodptr*) * m->class->index) & 0x0000ffff);
527 /* patch method offset */
529 *((s4 *) (ra + 2 * 4)) |=
530 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
532 /* synchronize instruction cache */
534 md_icacheflush(ra + 1 * 4, 2 * 4);
540 /* patcher_checkcast_interface *************************************************
544 <patched call position>
546 8c79001c lw t9,28(v1)
547 27390000 addiu t9,t9,0
548 1b200082 blez t9,zero,0x000000001051843c
552 *******************************************************************************/
554 bool patcher_checkcast_interface(patchref_t *pr)
557 constant_classref *cr;
560 /* get stuff from the stack */
563 cr = (constant_classref *) pr->ref;
565 /* get the fieldinfo */
567 if (!(c = resolve_classref_eager(cr)))
570 PATCH_BACK_ORIGINAL_MCODE;
572 /* if we show disassembly, we have to skip the nop's */
575 ra = ra + PATCHER_CALL_SIZE;
577 /* patch super class index */
579 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
580 /* *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
581 /* c->index * sizeof(methodptr*)) & 0x0000ffff); */
582 *((s4 *) (ra + 6 * 4)) |=
583 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
584 c->index * sizeof(methodptr*)) & 0x0000ffff);
586 /* synchronize instruction cache */
588 md_icacheflush(ra + 2 * 4, 5 * 4);
594 /* patcher_instanceof_interface ************************************************
598 <patched call position>
600 8c79001c lw t9,28(v1)
601 27390000 addiu t9,t9,0
602 1b200082 blez t9,zero,0x000000001051843c
606 *******************************************************************************/
608 bool patcher_instanceof_interface(patchref_t *pr)
611 constant_classref *cr;
614 /* get stuff from the stack */
617 cr = (constant_classref *) pr->ref;
619 /* get the fieldinfo */
621 if (!(c = resolve_classref_eager(cr)))
624 PATCH_BACK_ORIGINAL_MCODE;
626 /* if we show disassembly, we have to skip the nop's */
629 ra = ra + PATCHER_CALL_SIZE;
631 /* patch super class index */
633 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
634 *((s4 *) (ra + 5 * 4)) |=
635 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
636 c->index * sizeof(methodptr*)) & 0x0000ffff);
638 /* synchronize instruction cache */
640 md_icacheflush(ra + 2 * 4, 4 * 4);
647 * These are local overrides for various environment variables in Emacs.
648 * Please do not remove this and leave it at the end of the file, where
649 * Emacs will automagically detect them.
650 * ---------------------------------------------------------------------
653 * indent-tabs-mode: t
657 * vim:noexpandtab:sw=4:ts=4: