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
25 $Id: patcher.c 7596 2007-03-28 21:05:53Z twisti $
36 #include "vm/jit/mips/codegen.h"
38 #include "mm/memory.h"
40 #include "native/native.h"
42 #include "vm/builtin.h"
43 #include "vm/exceptions.h"
44 #include "vm/initialize.h"
46 #include "vm/jit/asmpart.h"
47 #include "vm/jit/md.h"
48 #include "vm/jit/patcher.h"
50 #include "vmcore/class.h"
51 #include "vmcore/field.h"
52 #include "vmcore/options.h"
53 #include "vm/resolve.h"
54 #include "vmcore/references.h"
57 /* patcher_wrapper *************************************************************
59 Wrapper for all patchers. It also creates the stackframe info
62 If the return value of the patcher function is false, it gets the
63 exception object, clears the exception pointer and returns the
66 *******************************************************************************/
68 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
78 /* define the patcher function */
80 bool (*patcher_function)(u1 *);
84 /* get stuff from the stack */
86 xpc = (u1 *) *((ptrint *) (sp + 7 * 8));
87 o = (java_objectheader *) *((ptrint *) (sp + 6 * 8));
88 f = (functionptr) *((ptrint *) (sp + 0 * 8));
90 /* store PV into the patcher function position */
92 *((ptrint *) (sp + 0 * 8)) = (ptrint) pv;
94 /* cast the passed function to a patcher function */
96 patcher_function = (bool (*)(u1 *)) (ptrint) f;
98 /* enter a monitor on the patching position */
100 PATCHER_MONITORENTER;
102 /* create the stackframeinfo */
104 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 8 * 8, ra, xpc);
106 /* call the proper patcher function */
108 result = (patcher_function)(sp);
110 /* remove the stackframeinfo */
112 stacktrace_remove_stackframeinfo(&sfi);
114 /* check for return value and exit accordingly */
116 if (result == false) {
117 e = exceptions_get_and_clear_exception();
124 /* patch back original code */
126 mcode[0] = *((u4 *) (sp + 3 * 8 + 0));
127 mcode[1] = *((u4 *) (sp + 3 * 8 + 4));
129 mcode[2] = *((u4 *) (sp + 4 * 8 + 0));
130 mcode[3] = *((u4 *) (sp + 4 * 8 + 4));
131 mcode[4] = *((u4 *) (sp + 5 * 8 + 0));
133 *((u4 *) (xpc + 0 * 4)) = mcode[0];
134 *((u4 *) (xpc + 1 * 4)) = mcode[1];
136 *((u4 *) (xpc + 2 * 4)) = mcode[2];
137 *((u4 *) (xpc + 3 * 4)) = mcode[3];
138 *((u4 *) (xpc + 4 * 4)) = mcode[4];
140 /* synchronize instruction cache */
142 md_icacheflush(xpc, PATCHER_CALL_SIZE);
144 PATCHER_MARK_PATCHED_MONITOREXIT;
150 /* patcher_get_putstatic *******************************************************
154 <patched call position>
155 dfc1ffb8 ld at,-72(s8)
158 *******************************************************************************/
160 bool patcher_get_putstatic(u1 *sp)
162 unresolved_field *uf;
167 /* get stuff from the stack */
169 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
170 disp = *((s4 *) (sp + 1 * 8));
171 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
173 /* get the fieldinfo */
175 if (!(fi = resolve_field_eager(uf)))
178 /* check if the field's class is initialized */
180 if (!(fi->class->state & CLASS_INITIALIZED))
181 if (!initialize_class(fi->class))
184 /* patch the field value's address */
186 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
188 /* synchronize data cache */
190 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
196 /* patcher_get_putfield ********************************************************
200 <patched call position>
201 8ee90020 lw a5,32(s7)
203 *******************************************************************************/
205 bool patcher_get_putfield(u1 *sp)
208 unresolved_field *uf;
211 /* get stuff from the stack */
213 ra = (u1 *) *((ptrint *) (sp + 7 * 8));
214 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
216 /* get the fieldinfo */
218 if (!(fi = resolve_field_eager(uf)))
221 /* if we show disassembly, we have to skip the nop's */
224 ra = ra + PATCHER_CALL_SIZE;
226 #if SIZEOF_VOID_P == 4
227 if (IS_LNG_TYPE(fi->type)) {
228 # if WORDS_BIGENDIAN == 1
229 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
230 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
231 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
233 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
234 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
235 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
240 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
242 /* synchronize instruction cache */
244 md_icacheflush(ra, 2 * 4);
247 #if SIZEOF_VOID_P == 4
248 if (IS_LNG_TYPE(fi->type)) {
249 # if WORDS_BIGENDIAN == 1
250 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
251 *((u4 *) (sp + 3 * 8 + 0)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
252 *((u4 *) (sp + 3 * 8 + 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
254 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
255 *((u4 *) (sp + 3 * 8 + 0)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
256 *((u4 *) (sp + 3 * 8 + 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
261 *((u4 *) (sp + 3 * 8 + 0)) |= (s2) (fi->offset & 0x0000ffff);
268 /* patcher_aconst **************************************************************
272 <patched call postition>
273 dfc4ff98 ld a0,-104(s8)
275 *******************************************************************************/
277 bool patcher_aconst(u1 *sp)
279 constant_classref *cr;
284 /* get stuff from the stack */
286 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
287 disp = *((s4 *) (sp + 1 * 8));
288 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
290 /* get the classinfo */
292 if (!(c = resolve_classref_eager(cr)))
295 /* patch the classinfo pointer */
297 *((ptrint *) (pv + disp)) = (ptrint) c;
299 /* synchronize data cache */
301 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
307 /* patcher_builtin_multianewarray **********************************************
311 <patched call position>
312 dfc5ff90 ld a1,-112(s8)
314 dfd9ff88 ld t9,-120(s8)
318 *******************************************************************************/
320 bool patcher_builtin_multianewarray(u1 *sp)
322 constant_classref *cr;
327 /* get stuff from the stack */
329 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
330 disp = *((s4 *) (sp + 1 * 8));
331 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
333 /* get the classinfo */
335 if (!(c = resolve_classref_eager(cr)))
338 /* patch the classinfo pointer */
340 *((ptrint *) (pv + disp)) = (ptrint) c;
342 /* synchronize data cache */
344 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
350 /* patcher_builtin_arraycheckcast **********************************************
354 <patched call position>
355 dfc5ffc0 ld a1,-64(s8)
356 dfd9ffb8 ld t9,-72(s8)
360 *******************************************************************************/
362 bool patcher_builtin_arraycheckcast(u1 *sp)
364 constant_classref *cr;
369 /* get stuff from the stack */
371 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
372 disp = *((s4 *) (sp + 1 * 8));
373 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
375 /* get the classinfo */
377 if (!(c = resolve_classref_eager(cr)))
380 /* patch the classinfo pointer */
382 *((ptrint *) (pv + disp)) = (ptrint) c;
384 /* synchronize data cache */
386 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
392 /* patcher_invokestatic_special ************************************************
396 <patched call position>
397 dfdeffc0 ld s8,-64(s8)
401 ******************************************************************************/
403 bool patcher_invokestatic_special(u1 *sp)
405 unresolved_method *um;
410 /* get stuff from the stack */
412 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
413 disp = *((s4 *) (sp + 1 * 8));
414 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
416 /* get the fieldinfo */
418 if (!(m = resolve_method_eager(um)))
421 /* patch stubroutine */
423 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
425 /* synchronize data cache */
427 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
433 /* patcher_invokevirtual *******************************************************
437 <patched call position>
439 df3e0040 ld s8,64(t9)
443 *******************************************************************************/
445 bool patcher_invokevirtual(u1 *sp)
448 unresolved_method *um;
451 /* get stuff from the stack */
453 ra = (u1 *) *((ptrint *) (sp + 7 * 8));
454 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
456 /* get the fieldinfo */
458 if (!(m = resolve_method_eager(um)))
461 /* if we show disassembly, we have to skip the nop's */
464 ra = ra + PATCHER_CALL_SIZE;
466 /* patch vftbl index */
468 *((s4 *) (ra + 1 * 4)) |=
469 (s4) ((OFFSET(vftbl_t, table[0]) +
470 sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
472 /* synchronize instruction cache */
474 md_icacheflush(ra + 1 * 4, 1 * 4);
477 /* patch vftbl index */
479 *((s4 *) (sp + 3 * 8 + 4)) |=
480 (s4) ((OFFSET(vftbl_t, table[0]) +
481 sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
488 /* patcher_invokeinterface *****************************************************
492 <patched call position>
494 df39ffa0 ld t9,-96(t9)
495 df3e0018 ld s8,24(t9)
499 *******************************************************************************/
501 bool patcher_invokeinterface(u1 *sp)
504 unresolved_method *um;
507 /* get stuff from the stack */
509 ra = (u1 *) *((ptrint *) (sp + 7 * 8));
510 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
512 /* get the fieldinfo */
514 if (!(m = resolve_method_eager(um)))
517 /* if we show disassembly, we have to skip the nop's */
520 ra = ra + PATCHER_CALL_SIZE;
522 /* patch interfacetable index */
524 *((s4 *) (ra + 1 * 4)) |=
525 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
526 sizeof(methodptr*) * m->class->index) & 0x0000ffff);
528 /* patch method offset */
530 *((s4 *) (ra + 2 * 4)) |=
531 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
533 /* synchronize instruction cache */
535 md_icacheflush(ra + 1 * 4, 2 * 4);
538 /* patch interfacetable index */
540 *((s4 *) (sp + 3 * 8 + 4)) |=
541 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
542 sizeof(methodptr*) * m->class->index) & 0x0000ffff);
544 /* patch method offset */
546 *((s4 *) (sp + 4 * 8 + 0)) |=
547 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
554 /* patcher_checkcast_instanceof_flags ******************************************
558 <patched call position>
559 8fc3ff24 lw v1,-220(s8)
560 30630200 andi v1,v1,512
561 1060000d beq v1,zero,0x000000001051824c
564 *******************************************************************************/
566 bool patcher_checkcast_instanceof_flags(u1 *sp)
568 constant_classref *cr;
573 /* get stuff from the stack */
575 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
576 disp = *((s4 *) (sp + 1 * 8));
577 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
579 /* get the fieldinfo */
581 if (!(c = resolve_classref_eager(cr)))
584 /* patch class flags */
586 *((s4 *) (pv + disp)) = (s4) c->flags;
588 /* synchronize data cache */
590 md_dcacheflush(pv + disp, sizeof(s4));
596 /* patcher_checkcast_interface *************************************************
600 <patched call position>
602 8c79001c lw t9,28(v1)
603 27390000 addiu t9,t9,0
604 1b200082 blez t9,zero,0x000000001051843c
608 *******************************************************************************/
610 bool patcher_checkcast_interface(u1 *sp)
613 constant_classref *cr;
616 /* get stuff from the stack */
618 ra = (u1 *) *((ptrint *) (sp + 7 * 8));
619 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
621 /* get the fieldinfo */
623 if (!(c = resolve_classref_eager(cr)))
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)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
635 /* c->index * sizeof(methodptr*)) & 0x0000ffff); */
636 *((s4 *) (ra + 6 * 4)) |=
637 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
638 c->index * sizeof(methodptr*)) & 0x0000ffff);
640 /* synchronize instruction cache */
642 md_icacheflush(ra + 2 * 4, 5 * 4);
645 /* patch super class index */
647 *((s4 *) (sp + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
648 /* *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
649 /* c->index * sizeof(methodptr*)) & 0x0000ffff); */
650 *((s4 *) (ra + 6 * 4)) |=
651 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
652 c->index * sizeof(methodptr*)) & 0x0000ffff);
654 /* synchronize instruction cache */
656 md_icacheflush(ra + 6 * 4, 1 * 4);
663 /* patcher_instanceof_interface ************************************************
667 <patched call position>
669 8c79001c lw t9,28(v1)
670 27390000 addiu t9,t9,0
671 1b200082 blez t9,zero,0x000000001051843c
675 *******************************************************************************/
677 bool patcher_instanceof_interface(u1 *sp)
680 constant_classref *cr;
683 /* get stuff from the stack */
685 ra = (u1 *) *((ptrint *) (sp + 7 * 8));
686 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
688 /* get the fieldinfo */
690 if (!(c = resolve_classref_eager(cr)))
693 /* if we show disassembly, we have to skip the nop's */
696 ra = ra + PATCHER_CALL_SIZE;
698 /* patch super class index */
700 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
701 *((s4 *) (ra + 5 * 4)) |=
702 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
703 c->index * sizeof(methodptr*)) & 0x0000ffff);
705 /* synchronize instruction cache */
707 md_icacheflush(ra + 2 * 4, 4 * 4);
710 /* patch super class index */
712 *((s4 *) (sp + 4 * 8 + 0)) |= (s4) (-(c->index) & 0x0000ffff);
713 *((s4 *) (ra + 5 * 4)) |=
714 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
715 c->index * sizeof(methodptr*)) & 0x0000ffff);
717 /* synchronize instruction cache */
719 md_icacheflush(ra + 5 * 4, 1 * 4);
726 /* patcher_checkcast_instanceof_class ******************************************
730 <patched call position>
732 dfd9ff18 ld t9,-232(s8)
734 *******************************************************************************/
736 bool patcher_checkcast_instanceof_class(u1 *sp)
738 constant_classref *cr;
743 /* get stuff from the stack */
745 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
746 disp = *((s4 *) (sp + 1 * 8));
747 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
749 /* get the fieldinfo */
751 if (!(c = resolve_classref_eager(cr)))
754 /* patch super class' vftbl */
756 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
758 /* synchronize data cache */
760 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
766 /* patcher_clinit **************************************************************
768 No special machine code.
770 *******************************************************************************/
772 bool patcher_clinit(u1 *sp)
776 /* get stuff from the stack */
778 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
780 /* check if the class is initialized */
782 if (!(c->state & CLASS_INITIALIZED))
783 if (!initialize_class(c))
790 /* patcher_athrow_areturn ******************************************************
794 <patched call position>
796 *******************************************************************************/
798 #ifdef ENABLE_VERIFIER
799 bool patcher_athrow_areturn(u1 *sp)
801 unresolved_class *uc;
803 /* get stuff from the stack */
805 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
807 /* resolve the class and check subtype constraints */
809 if (!resolve_class_eager_no_access_check(uc))
814 #endif /* ENABLE_VERIFIER */
817 /* patcher_resolve_native ******************************************************
821 *******************************************************************************/
823 #if !defined(WITH_STATIC_CLASSPATH)
824 bool patcher_resolve_native(u1 *sp)
831 /* get stuff from the stack */
833 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
834 disp = *((s4 *) (sp + 1 * 8));
835 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
837 /* resolve native function */
839 if (!(f = native_resolve_function(m)))
842 /* patch native function pointer */
844 *((ptrint *) (pv + disp)) = (ptrint) f;
846 /* synchronize data cache */
848 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
852 #endif /* !defined(WITH_STATIC_CLASSPATH) */
856 * These are local overrides for various environment variables in Emacs.
857 * Please do not remove this and leave it at the end of the file, where
858 * Emacs will automagically detect them.
859 * ---------------------------------------------------------------------
862 * indent-tabs-mode: t
866 * vim:noexpandtab:sw=4:ts=4: