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_patch_code **********************************************************
63 Just patches back the original machine code.
65 *******************************************************************************/
67 void patcher_patch_code(patchref_t *pr)
69 PATCH_BACK_ORIGINAL_MCODE;
73 /* patcher_get_putstatic *******************************************************
77 <patched call position>
78 dfc1ffb8 ld at,-72(s8)
81 *******************************************************************************/
83 bool patcher_get_putstatic(patchref_t *pr)
89 /* get stuff from the stack */
91 uf = (unresolved_field *) pr->ref;
92 datap = (u1 *) pr->datap;
94 /* get the fieldinfo */
96 if (!(fi = resolve_field_eager(uf)))
99 /* check if the field's class is initialized */
101 if (!(fi->class->state & CLASS_INITIALIZED))
102 if (!initialize_class(fi->class))
105 PATCH_BACK_ORIGINAL_MCODE;
107 /* patch the field value's address */
109 *((intptr_t *) datap) = (intptr_t) fi->value;
111 /* synchronize data cache */
113 md_dcacheflush(datap, SIZEOF_VOID_P);
119 /* patcher_get_putfield ********************************************************
123 <patched call position>
124 8ee90020 lw a5,32(s7)
126 *******************************************************************************/
128 bool patcher_get_putfield(patchref_t *pr)
131 unresolved_field *uf;
134 /* get stuff from the stack */
137 uf = (unresolved_field *) pr->ref;
139 /* get the fieldinfo */
141 if (!(fi = resolve_field_eager(uf)))
144 PATCH_BACK_ORIGINAL_MCODE;
146 /* if we show disassembly, we have to skip the nop's */
149 ra = ra + PATCHER_CALL_SIZE;
151 #if SIZEOF_VOID_P == 4
152 if (IS_LNG_TYPE(fi->type)) {
153 # if WORDS_BIGENDIAN == 1
154 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
155 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
156 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
158 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
159 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
160 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
165 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
167 /* synchronize instruction cache */
169 md_icacheflush(ra, 2 * 4);
175 /* patcher_resolve_classref_to_classinfo ***************************************
179 <patched call postition>
180 dfc4ff98 ld a0,-104(s8)
184 <patched call position>
185 dfc5ff90 ld a1,-112(s8)
187 dfd9ff88 ld t9,-120(s8)
193 <patched call position>
194 dfc5ffc0 ld a1,-64(s8)
195 dfd9ffb8 ld t9,-72(s8)
199 *******************************************************************************/
201 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
203 constant_classref *cr;
207 /* get stuff from the stack */
209 cr = (constant_classref *) pr->ref;
210 datap = (u1 *) pr->datap;
212 /* get the classinfo */
214 if (!(c = resolve_classref_eager(cr)))
217 PATCH_BACK_ORIGINAL_MCODE;
219 /* patch the classinfo pointer */
221 *((intptr_t *) datap) = (intptr_t) c;
223 /* synchronize data cache */
225 md_dcacheflush(datap, SIZEOF_VOID_P);
231 /* patcher_resolve_classref_to_vftbl *******************************************
236 <patched call position>
238 dfd9ff18 ld t9,-232(s8)
240 *******************************************************************************/
242 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
244 constant_classref *cr;
248 /* get stuff from the stack */
250 cr = (constant_classref *) pr->ref;
251 datap = (u1 *) pr->datap;
253 /* get the fieldinfo */
255 if (!(c = resolve_classref_eager(cr)))
258 PATCH_BACK_ORIGINAL_MCODE;
260 /* patch super class' vftbl */
262 *((intptr_t *) datap) = (intptr_t) c->vftbl;
264 /* synchronize data cache */
266 md_dcacheflush(datap, SIZEOF_VOID_P);
272 /* patcher_resolve_classref_to_flags *******************************************
274 CHECKCAST/INSTANCEOF:
276 <patched call position>
277 8fc3ff24 lw v1,-220(s8)
278 30630200 andi v1,v1,512
279 1060000d beq v1,zero,0x000000001051824c
282 *******************************************************************************/
284 bool patcher_resolve_classref_to_flags(patchref_t *pr)
286 constant_classref *cr;
290 /* get stuff from the stack */
292 cr = (constant_classref *) pr->ref;
293 datap = (u1 *) pr->datap;
295 /* get the fieldinfo */
297 if (!(c = resolve_classref_eager(cr)))
300 PATCH_BACK_ORIGINAL_MCODE;
302 /* patch class flags */
304 *((int32_t *) datap) = (int32_t) c->flags;
306 /* synchronize data cache */
308 md_dcacheflush(datap, sizeof(int32_t));
314 /* patcher_resolve_native ******************************************************
318 *******************************************************************************/
320 bool patcher_resolve_native_function(patchref_t *pr)
326 /* get stuff from the stack */
328 m = (methodinfo *) pr->ref;
329 datap = (u1 *) pr->datap;
331 /* resolve native function */
333 if (!(f = native_resolve_function(m)))
336 PATCH_BACK_ORIGINAL_MCODE;
338 /* patch native function pointer */
340 *((ptrint *) datap) = (ptrint) f;
342 /* synchronize data cache */
344 md_dcacheflush(datap, SIZEOF_VOID_P);
350 /* patcher_invokestatic_special ************************************************
354 <patched call position>
355 dfdeffc0 ld s8,-64(s8)
359 ******************************************************************************/
361 bool patcher_invokestatic_special(patchref_t *pr)
363 unresolved_method *um;
367 /* get stuff from the stack */
369 um = (unresolved_method *) pr->ref;
370 datap = (u1 *) pr->datap;
372 /* get the fieldinfo */
374 if (!(m = resolve_method_eager(um)))
377 PATCH_BACK_ORIGINAL_MCODE;
379 /* patch stubroutine */
381 *((ptrint *) datap) = (ptrint) m->stubroutine;
383 /* synchronize data cache */
385 md_dcacheflush(datap, SIZEOF_VOID_P);
391 /* patcher_invokevirtual *******************************************************
395 <patched call position>
397 df3e0040 ld s8,64(t9)
401 *******************************************************************************/
403 bool patcher_invokevirtual(patchref_t *pr)
406 unresolved_method *um;
409 /* get stuff from the stack */
412 um = (unresolved_method *) pr->ref;
414 /* get the fieldinfo */
416 if (!(m = resolve_method_eager(um)))
419 PATCH_BACK_ORIGINAL_MCODE;
421 /* if we show disassembly, we have to skip the nop's */
424 ra = ra + PATCHER_CALL_SIZE;
426 /* patch vftbl index */
428 *((s4 *) (ra + 1 * 4)) |=
429 (s4) ((OFFSET(vftbl_t, table[0]) +
430 sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
432 /* synchronize instruction cache */
434 md_icacheflush(ra + 1 * 4, 1 * 4);
440 /* patcher_invokeinterface *****************************************************
444 <patched call position>
446 df39ffa0 ld t9,-96(t9)
447 df3e0018 ld s8,24(t9)
451 *******************************************************************************/
453 bool patcher_invokeinterface(patchref_t *pr)
456 unresolved_method *um;
459 /* get stuff from the stack */
462 um = (unresolved_method *) pr->ref;
464 /* get the fieldinfo */
466 if (!(m = resolve_method_eager(um)))
469 PATCH_BACK_ORIGINAL_MCODE;
471 /* if we show disassembly, we have to skip the nop's */
474 ra = ra + PATCHER_CALL_SIZE;
476 /* patch interfacetable index */
478 *((s4 *) (ra + 1 * 4)) |=
479 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
480 sizeof(methodptr*) * m->class->index) & 0x0000ffff);
482 /* patch method offset */
484 *((s4 *) (ra + 2 * 4)) |=
485 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
487 /* synchronize instruction cache */
489 md_icacheflush(ra + 1 * 4, 2 * 4);
495 /* patcher_checkcast_interface *************************************************
499 <patched call position>
501 8c79001c lw t9,28(v1)
502 27390000 addiu t9,t9,0
503 1b200082 blez t9,zero,0x000000001051843c
507 *******************************************************************************/
509 bool patcher_checkcast_interface(patchref_t *pr)
512 constant_classref *cr;
515 /* get stuff from the stack */
518 cr = (constant_classref *) pr->ref;
520 /* get the fieldinfo */
522 if (!(c = resolve_classref_eager(cr)))
525 PATCH_BACK_ORIGINAL_MCODE;
527 /* if we show disassembly, we have to skip the nop's */
530 ra = ra + PATCHER_CALL_SIZE;
532 /* patch super class index */
534 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
535 /* *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
536 /* c->index * sizeof(methodptr*)) & 0x0000ffff); */
537 *((s4 *) (ra + 6 * 4)) |=
538 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
539 c->index * sizeof(methodptr*)) & 0x0000ffff);
541 /* synchronize instruction cache */
543 md_icacheflush(ra + 2 * 4, 5 * 4);
549 /* patcher_instanceof_interface ************************************************
553 <patched call position>
555 8c79001c lw t9,28(v1)
556 27390000 addiu t9,t9,0
557 1b200082 blez t9,zero,0x000000001051843c
561 *******************************************************************************/
563 bool patcher_instanceof_interface(patchref_t *pr)
566 constant_classref *cr;
569 /* get stuff from the stack */
572 cr = (constant_classref *) pr->ref;
574 /* get the fieldinfo */
576 if (!(c = resolve_classref_eager(cr)))
579 PATCH_BACK_ORIGINAL_MCODE;
581 /* if we show disassembly, we have to skip the nop's */
584 ra = ra + PATCHER_CALL_SIZE;
586 /* patch super class index */
588 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
589 *((s4 *) (ra + 5 * 4)) |=
590 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
591 c->index * sizeof(methodptr*)) & 0x0000ffff);
593 /* synchronize instruction cache */
595 md_icacheflush(ra + 2 * 4, 4 * 4);
602 * These are local overrides for various environment variables in Emacs.
603 * Please do not remove this and leave it at the end of the file, where
604 * Emacs will automagically detect them.
605 * ---------------------------------------------------------------------
608 * indent-tabs-mode: t
612 * vim:noexpandtab:sw=4:ts=4: