1 /* src/vm/jit/mips/patcher.c - MIPS code patching functions
3 Copyright (C) 1996-2005, 2006 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 Contact: cacao@cacaojvm.org
27 Authors: Christian Thalinger
31 $Id: patcher.c 5164 2006-07-19 15:54:01Z twisti $
42 #include "vm/jit/sparc64/codegen.h"
44 #include "mm/memory.h"
45 #include "native/native.h"
46 #include "vm/builtin.h"
48 #include "vm/exceptions.h"
50 #include "vm/initialize.h"
51 #include "vm/options.h"
52 #include "vm/resolve.h"
53 #include "vm/references.h"
54 #include "vm/jit/asmpart.h"
55 #include "vm/jit/patcher.h"
57 #include "vm/jit/sparc64/md-abi.h"
60 /* patcher_wrapper *************************************************************
62 Wrapper for all patchers. It also creates the stackframe info
65 If the return value of the patcher function is false, it gets the
66 exception object, clears the exception pointer and returns the
69 *******************************************************************************/
71 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
77 #if SIZEOF_VOID_P == 8
87 /* define the patcher function */
89 bool (*patcher_function)(u1 *);
93 /* get stuff from the stack */
95 xpc = (u1 *) *((ptrint *) (sp + 5 * 8));
96 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
97 f = (functionptr) *((ptrint *) (sp + 0 * 8));
99 /* store PV into the patcher function position */
101 *((ptrint *) (sp + 0 * 8)) = (ptrint) pv;
103 /* cast the passed function to a patcher function */
105 patcher_function = (bool (*)(u1 *)) (ptrint) f;
107 /* enter a monitor on the patching position */
109 PATCHER_MONITORENTER;
111 /* calculate sp of the current java function considering the WINSAVE regs */
113 javasp = sp - 16 * 8 - BIAS;
115 /* create the stackframeinfo */
117 stacktrace_create_extern_stackframeinfo(&sfi, pv, javasp, ra, xpc);
119 /* call the proper patcher function */
121 result = (patcher_function)(sp);
123 /* remove the stackframeinfo */
125 stacktrace_remove_stackframeinfo(&sfi);
127 /* check for return value and exit accordingly */
129 if (result == false) {
130 e = exceptions_get_and_clear_exception();
137 /* patch back original code */
139 #if SIZEOF_VOID_P == 8
140 mcode = *((u8 *) (sp + 3 * 8));
142 *((u4 *) (xpc + 0 * 4)) = mcode;
143 *((u4 *) (xpc + 1 * 4)) = mcode >> 32;
145 mcode[0] = *((u4 *) (sp + 3 * 8));
146 mcode[1] = *((u4 *) (sp + 3 * 8 + 4));
148 *((u4 *) (xpc + 0 * 4)) = mcode[0];
149 *((u4 *) (xpc + 1 * 4)) = mcode[1];
153 /* synchronize instruction cache */
155 md_icacheflush(xpc, PATCHER_CALL_SIZE);
157 PATCHER_MARK_PATCHED_MONITOREXIT;
163 /* patcher_get_putstatic *******************************************************
167 <patched call position>
171 *******************************************************************************/
173 bool patcher_get_putstatic(u1 *sp)
175 unresolved_field *uf;
180 /* get stuff from the stack */
183 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
184 disp = *((s4 *) (sp + 1 * 8));
185 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
187 /* get the fieldinfo */
189 if (!(fi = resolve_field_eager(uf)))
192 /* check if the field's class is initialized */
194 if (!(fi->class->state & CLASS_INITIALIZED))
195 if (!initialize_class(fi->class))
198 /* patch the field value's address */
200 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
202 /* synchronize data cache */
204 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
210 /* patcher_get_putfield ********************************************************
214 <patched call position>
215 8ee90020 lw a5,32(s7)
217 *******************************************************************************/
219 bool patcher_get_putfield(u1 *sp)
222 #if SIZEOF_VOID_P == 8
227 unresolved_field *uf;
232 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
233 #if SIZEOF_VOID_P == 8
234 mcode = *((u8 *) (sp + 3 * 8));
236 mcode[0] = *((u4 *) (sp + 3 * 8));
237 mcode[1] = *((u4 *) (sp + 3 * 8 + 4));
239 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
241 /* get the fieldinfo */
243 if (!(fi = resolve_field_eager(uf)))
246 /* patch back original code */
248 #if SIZEOF_VOID_P == 8
249 *((u4 *) (ra + 0 * 4)) = mcode;
250 *((u4 *) (ra + 1 * 4)) = mcode >> 32;
252 *((u4 *) (ra + 0 * 4)) = mcode[0];
253 *((u4 *) (ra + 1 * 4)) = mcode[1];
256 /* if we show disassembly, we have to skip the nop's */
259 ra = ra + PATCHER_CALL_SIZE;
261 #if SIZEOF_VOID_P == 4
262 if (fi->type == TYPE_LNG) {
263 # if WORDS_BIGENDIAN == 1
264 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
265 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
266 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
268 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
269 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
270 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
274 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
276 /* synchronize instruction cache */
278 if (opt_showdisassemble) {
279 #if SIZEOF_VOID_P == 4
280 if (fi->type == TYPE_LNG)
281 md_icacheflush(ra - 2 * 4, 4 * 4);
284 md_icacheflush(ra - 2 * 4, 3 * 4);
287 md_icacheflush(ra, 2 * 4);
295 /* patcher_aconst **************************************************************
299 <patched call postition>
302 *******************************************************************************/
304 bool patcher_aconst(u1 *sp)
306 constant_classref *cr;
311 /* get stuff from the stack */
313 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
314 disp = *((s4 *) (sp + 1 * 8));
315 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
317 /* get the classinfo */
319 if (!(c = resolve_classref_eager(cr)))
322 /* patch the classinfo pointer */
324 *((ptrint *) (pv + disp)) = (ptrint) c;
326 /* synchronize data cache */
328 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
334 /* patcher_builtin_multianewarray **********************************************
338 <patched call position>
339 dfc5ff90 ld a1,-112(s8)
341 dfd9ff88 ld t9,-120(s8)
345 *******************************************************************************/
347 bool patcher_builtin_multianewarray(u1 *sp)
349 constant_classref *cr;
354 /* get stuff from the stack */
356 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
357 disp = *((s4 *) (sp + 1 * 8));
358 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
360 /* get the classinfo */
362 if (!(c = resolve_classref_eager(cr)))
365 /* patch the classinfo pointer */
367 *((ptrint *) (pv + disp)) = (ptrint) c;
369 /* synchronize data cache */
371 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
377 /* patcher_builtin_arraycheckcast **********************************************
381 <patched call position>
382 dfc5ffc0 ld a1,-64(s8)
383 dfd9ffb8 ld t9,-72(s8)
387 *******************************************************************************/
389 bool patcher_builtin_arraycheckcast(u1 *sp)
391 constant_classref *cr;
396 /* get stuff from the stack */
398 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
399 disp = *((s4 *) (sp + 1 * 8));
400 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
402 /* get the classinfo */
404 if (!(c = resolve_classref_eager(cr)))
407 /* patch the classinfo pointer */
409 *((ptrint *) (pv + disp)) = (ptrint) c;
411 /* synchronize data cache */
413 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
419 /* patcher_invokestatic_special ************************************************
423 <patched call position>
424 dfdeffc0 ld s8,-64(s8)
428 ******************************************************************************/
430 bool patcher_invokestatic_special(u1 *sp)
432 unresolved_method *um;
437 /* get stuff from the stack */
439 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
440 disp = *((s4 *) (sp + 1 * 8));
441 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
443 /* get the fieldinfo */
445 if (!(m = resolve_method_eager(um)))
448 /* patch stubroutine */
450 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
452 /* synchronize data cache */
454 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
460 /* patcher_invokevirtual *******************************************************
464 <patched call position>
470 *******************************************************************************/
472 bool patcher_invokevirtual(u1 *sp)
475 unresolved_method *um;
480 /* get stuff from the stack */
482 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
483 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
485 /* get the fieldinfo */
487 if (!(m = resolve_method_eager(um)))
490 /* if we show disassembly, we have to skip the nop's */
493 ra = ra + PATCHER_CALL_SIZE;
495 /* patch vftbl index */
497 *((s4 *) (ra + 1 * 4)) |=
498 (s4) ((OFFSET(vftbl_t, table[0]) +
499 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
501 /* synchronize instruction cache */
503 md_icacheflush(ra + 1 * 4, 1 * 4);
506 /* patch vftbl index */
508 *((s4 *) (sp + 3 * 8 + 4)) |=
509 (s4) ((OFFSET(vftbl_t, table[0]) +
510 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
517 /* patcher_invokeinterface *****************************************************
521 <patched call position>
523 df39ffa0 ld t9,-96(t9)
524 df3e0018 ld s8,24(t9)
528 *******************************************************************************/
530 bool patcher_invokeinterface(u1 *sp)
533 #if SIZEOF_VOID_P == 8
538 unresolved_method *um;
543 /* get stuff from the stack */
545 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
546 #if SIZEOF_VOID_P == 8
547 mcode = *((u8 *) (sp + 3 * 8));
549 mcode[0] = *((u4 *) (sp + 3 * 8));
550 mcode[1] = *((u4 *) (sp + 3 * 8 + 4));
552 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
554 /* get the fieldinfo */
556 if (!(m = resolve_method_eager(um)))
559 /* patch back original code */
561 #if SIZEOF_VOID_P == 8
562 *((u4 *) (ra + 0 * 4)) = mcode;
563 *((u4 *) (ra + 1 * 4)) = mcode >> 32;
565 *((u4 *) (ra + 0 * 4)) = mcode[0];
566 *((u4 *) (ra + 1 * 4)) = mcode[1];
569 /* if we show disassembly, we have to skip the nop's */
571 if (opt_showdisassemble)
574 /* patch interfacetable index */
576 *((s4 *) (ra + 1 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
577 sizeof(methodptr*) * m->class->index) & 0x0000ffff);
579 /* patch method offset */
581 *((s4 *) (ra + 2 * 4)) |=
582 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
584 /* synchronize instruction cache */
586 if (opt_showdisassemble)
587 md_icacheflush(ra - 2 * 4, 5 * 4);
589 md_icacheflush(ra, 3 * 4);
595 /* patcher_checkcast_instanceof_flags ******************************************
599 <patched call position>
600 8fc3ff24 lw v1,-220(s8)
601 30630200 andi v1,v1,512
602 1060000d beq v1,zero,0x000000001051824c
605 *******************************************************************************/
607 bool patcher_checkcast_instanceof_flags(u1 *sp)
609 constant_classref *cr;
614 /* get stuff from the stack */
616 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
617 disp = *((s4 *) (sp + 1 * 8));
618 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
620 /* get the fieldinfo */
622 if (!(c = resolve_classref_eager(cr)))
625 /* patch class flags */
627 *((s4 *) (pv + disp)) = (s4) c->flags;
629 /* synchronize data cache */
631 md_dcacheflush(pv + disp, sizeof(s4));
637 /* patcher_checkcast_instanceof_interface **************************************
641 <patched call position>
643 8c79001c lw t9,28(v1)
644 27390000 addiu t9,t9,0
645 1b200082 blez t9,zero,0x000000001051843c
649 *******************************************************************************/
651 bool patcher_checkcast_instanceof_interface(u1 *sp)
654 #if SIZEOF_VOID_P == 8
659 constant_classref *cr;
664 /* get stuff from the stack */
666 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
667 #if SIZEOF_VOID_P == 8
668 mcode = *((u8 *) (sp + 3 * 8));
670 mcode[0] = *((u4 *) (sp + 3 * 8));
671 mcode[1] = *((u4 *) (sp + 3 * 8 + 4));
673 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
675 /* get the fieldinfo */
677 if (!(c = resolve_classref_eager(cr)))
680 /* patch back original code */
682 #if SIZEOF_VOID_P == 8
683 *((u4 *) (ra + 0 * 4)) = mcode;
684 *((u4 *) (ra + 1 * 4)) = mcode >> 32;
686 *((u4 *) (ra + 0 * 4)) = mcode[0];
687 *((u4 *) (ra + 1 * 4)) = mcode[1];
690 /* if we show disassembly, we have to skip the nop's */
692 if (opt_showdisassemble)
695 /* patch super class index */
697 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
699 *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
700 c->index * sizeof(methodptr*)) & 0x0000ffff);
702 /* synchronize instruction cache */
704 if (opt_showdisassemble)
705 md_icacheflush(ra - 2 * 4, 8 * 4);
707 md_icacheflush(ra, 6 * 4);
713 /* patcher_checkcast_instanceof_class ******************************************
717 <patched call position>
719 dfd9ff18 ld t9,-232(s8)
721 *******************************************************************************/
723 bool patcher_checkcast_instanceof_class(u1 *sp)
725 constant_classref *cr;
730 /* get stuff from the stack */
732 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
733 disp = *((s4 *) (sp + 1 * 8));
734 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
736 /* get the fieldinfo */
738 if (!(c = resolve_classref_eager(cr)))
741 /* patch super class' vftbl */
743 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
745 /* synchronize data cache */
747 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
753 /* patcher_clinit **************************************************************
755 No special machine code.
757 *******************************************************************************/
759 bool patcher_clinit(u1 *sp)
763 /* get stuff from the stack */
765 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
767 /* check if the class is initialized */
769 if (!(c->state & CLASS_INITIALIZED))
770 if (!initialize_class(c))
777 /* patcher_athrow_areturn ******************************************************
781 <patched call position>
783 *******************************************************************************/
785 #ifdef ENABLE_VERIFIER
786 bool patcher_athrow_areturn(u1 *sp)
788 unresolved_class *uc;
791 /* get stuff from the stack */
793 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
795 /* resolve the class */
797 if (!resolve_class(uc, resolveEager, false, &c))
802 #endif /* ENABLE_VERIFIER */
805 /* patcher_resolve_native ******************************************************
809 *******************************************************************************/
811 #if !defined(WITH_STATIC_CLASSPATH)
812 bool patcher_resolve_native(u1 *sp)
819 /* get stuff from the stack */
821 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
822 disp = *((s4 *) (sp + 1 * 8));
823 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
825 /* return address on SPARC is address of jump, therefore correct */
827 /* resolve native function */
829 if (!(f = native_resolve_function(m)))
832 /* patch native function pointer */
834 *((ptrint *) (pv + disp)) = (ptrint) f;
836 /* synchronize data cache */
838 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
842 #endif /* !defined(WITH_STATIC_CLASSPATH) */
846 * These are local overrides for various environment variables in Emacs.
847 * Please do not remove this and leave it at the end of the file, where
848 * Emacs will automagically detect them.
849 * ---------------------------------------------------------------------
852 * indent-tabs-mode: t
856 * vim:noexpandtab:sw=4:ts=4: