1 /* src/vm/jit/powerpc64/patcher.c - PowerPC64 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 5880 2006-10-31 13:40:55Z tbfg $
42 #include "mm/memory.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
46 #include "vm/exceptions.h"
48 #include "vm/initialize.h"
49 #include "vm/options.h"
50 #include "vm/resolve.h"
51 #include "vm/references.h"
52 #include "vm/jit/asmpart.h"
53 #include "vm/jit/patcher.h"
54 #include "vm/jit/methodheader.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)
77 /* define the patcher function */
79 bool (*patcher_function)(u1 *);
83 /* get stuff from the stack */
85 xpc = (u1 *) *((ptrint *) (sp + 5 * 8));
86 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
87 f = (functionptr) *((ptrint *) (sp + 0 * 8));
89 /* store PV into the patcher function position */
91 *((ptrint *) (sp + 0 * 8)) = (ptrint) pv;
93 /* cast the passed function to a patcher function */
95 patcher_function = (bool (*)(u1 *)) (ptrint) f;
97 /* enter a monitor on the patching position */
101 /* create the stackframeinfo */
103 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 8 * 8, ra, xpc);
105 /* call the proper patcher function */
107 result = (patcher_function)(sp);
109 /* remove the stackframeinfo */
111 stacktrace_remove_stackframeinfo(&sfi);
113 /* check for return value and exit accordingly */
115 if (result == false) {
116 e = exceptions_get_and_clear_exception();
123 PATCHER_MARK_PATCHED_MONITOREXIT;
129 /* patcher_get_putstatic *******************************************************
133 <patched call position>
134 816dffc8 lwz r11,-56(r13)
135 80ab0000 lwz r5,0(r11)
137 *******************************************************************************/
139 bool patcher_get_putstatic(u1 *sp)
143 unresolved_field *uf;
148 /* get stuff from the stack */
150 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
151 mcode = *((u4 *) (sp + 3 * 8));
152 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
153 disp = *((s4 *) (sp + 1 * 8));
154 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
156 /* get the fieldinfo */
158 if (!(fi = resolve_field_eager(uf)))
161 /* check if the field's class is initialized */
163 if (!(fi->class->state & CLASS_INITIALIZED))
164 if (!initialize_class(fi->class))
167 /* patch back original code */
169 *((u4 *) ra) = mcode;
171 /* synchronize instruction cache */
173 md_icacheflush(ra, 4);
175 /* patch the field value's address */
177 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
179 /* synchronize data cache */
181 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
187 /* patcher_get_putfield ********************************************************
191 <patched call position>
192 811f0014 lwz r8,20(r31)
194 *******************************************************************************/
196 bool patcher_get_putfield(u1 *sp)
200 unresolved_field *uf;
204 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
205 mcode = *((u4 *) (sp + 3 * 8));
206 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
207 pv = (u1 *) *((ptrint *) (sp + 1 * 8));
209 /* get the fieldinfo */
211 if (!(fi = resolve_field_eager(uf)))
214 /* patch back original code */
216 *((u4 *) ra) = mcode;
218 /* if we show disassembly, we have to skip the nop */
220 if (opt_showdisassemble)
223 /* patch the field's offset */
225 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
227 /* synchronize instruction cache */
229 md_icacheflush(ra, 8);
235 /* patcher_aconst **************************************************************
239 <patched call postition>
240 -------- ld r3,-64(r14)
241 -------- ld r14,-72(r14)
245 *******************************************************************************/
247 bool patcher_aconst(u1 *sp)
251 constant_classref *cr;
256 /* get stuff from the stack */
258 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
259 mcode = *((u4 *) (sp + 3 * 8));
260 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
261 disp = *((s4 *) (sp + 1 * 8));
262 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
264 /* get the classinfo */
266 if (!(c = resolve_classref_eager(cr)))
269 /* patch back original code */
271 *((u4 *) ra) = mcode;
273 /* synchronize instruction cache */
275 md_icacheflush(ra, 4);
277 /* patch the classinfo pointer */
279 *((ptrint *) (pv + disp)) = (ptrint) c;
281 /* synchronize data cache */
283 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
289 /* patcher_builtin_multianewarray **********************************************
293 <patched call position>
294 808dffc0 lwz r4,-64(r13)
295 38a10038 addi r5,r1,56
296 81adffbc lwz r13,-68(r13)
300 *******************************************************************************/
302 bool patcher_builtin_multianewarray(u1 *sp)
306 constant_classref *cr;
311 /* get stuff from the stack */
313 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
314 mcode = *((u4 *) (sp + 3 * 8));
315 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
316 disp = *((s4 *) (sp + 1 * 8));
317 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
319 /* get the classinfo */
321 if (!(c = resolve_classref_eager(cr)))
324 /* patch back original code */
326 *((u4 *) ra) = mcode;
328 /* synchronize instruction cache */
330 md_icacheflush(ra, 4);
332 /* patch the classinfo pointer */
334 *((ptrint *) (pv + disp)) = (ptrint) c;
336 /* synchronize data cache */
338 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
344 /* patcher_builtin_arraycheckcast **********************************************
348 <patched call position>
349 808dffd8 lwz r4,-40(r13)
350 81adffd4 lwz r13,-44(r13)
354 *******************************************************************************/
356 bool patcher_builtin_arraycheckcast(u1 *sp)
360 constant_classref *cr;
365 /* get stuff from the stack */
367 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
368 mcode = *((u4 *) (sp + 3 * 8));
369 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
370 disp = *((s4 *) (sp + 1 * 8));
371 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
373 /* get the classinfo */
375 if (!(c = resolve_classref_eager(cr)))
378 /* patch back original code */
380 *((u4 *) ra) = mcode;
382 /* synchronize instruction cache */
384 md_icacheflush(ra, 4);
386 /* patch the classinfo pointer */
388 *((ptrint *) (pv + disp)) = (ptrint) c;
390 /* synchronize data cache */
392 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
398 /* patcher_invokestatic_special ************************************************
402 <patched call position>
403 81adffd8 lwz r13,-40(r13)
407 ******************************************************************************/
409 bool patcher_invokestatic_special(u1 *sp)
413 unresolved_method *um;
418 /* get stuff from the stack */
420 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
421 mcode = *((u4 *) (sp + 3 * 8));
422 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
423 disp = *((s4 *) (sp + 1 * 8));
424 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
426 /* get the fieldinfo */
428 if (!(m = resolve_method_eager(um)))
431 /* patch back original code */
433 *((u4 *) ra) = mcode;
435 /* synchronize instruction cache */
437 md_icacheflush(ra, 4);
439 /* patch stubroutine */
441 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
443 /* synchronize data cache */
445 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
451 /* patcher_invokevirtual *******************************************************
455 <patched call position>
456 81830000 lwz r12,0(r3)
457 81ac0088 lwz r13,136(r12)
461 *******************************************************************************/
463 bool patcher_invokevirtual(u1 *sp)
467 unresolved_method *um;
471 /* get stuff from the stack */
473 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
474 mcode = *((u4 *) (sp + 3 * 8));
475 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
477 /* get the fieldinfo */
479 if (!(m = resolve_method_eager(um)))
482 /* patch back original code */
484 *((u4 *) ra) = mcode;
486 /* if we show disassembly, we have to skip the nop */
488 if (opt_showdisassemble)
491 /* patch vftbl index */
493 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
495 *((s4 *) (ra + 4)) |= (disp & 0x0000ffff);
497 /* synchronize instruction cache */
499 md_icacheflush(ra, 2 * 4);
505 /* patcher_invokeinterface *****************************************************
509 <patched call position>
510 81830000 lwz r12,0(r3)
511 818cffd0 lwz r12,-48(r12)
512 81ac000c lwz r13,12(r12)
516 *******************************************************************************/
518 bool patcher_invokeinterface(u1 *sp)
522 unresolved_method *um;
526 /* get stuff from the stack */
528 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
529 mcode = *((u4 *) (sp + 3 * 8));
530 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
532 /* get the fieldinfo */
534 if (!(m = resolve_method_eager(um)))
537 /* patch back original code */
539 *((u4 *) ra) = mcode;
541 /* if we show disassembly, we have to skip the nop */
543 if (opt_showdisassemble)
546 /* patch interfacetable index */
548 disp = OFFSET(vftbl_t, interfacetable[0]) -
549 sizeof(methodptr*) * m->class->index;
551 /* XXX TWISTI: check displacement */
553 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
555 /* patch method offset */
557 disp = sizeof(methodptr) * (m - m->class->methods);
559 /* XXX TWISTI: check displacement */
561 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
563 /* synchronize instruction cache */
565 md_icacheflush(ra, 3 * 4);
571 /* patcher_checkcast_instanceof_flags ******************************************
575 <patched call position>
576 818dff7c lwz r12,-132(r13)
578 *******************************************************************************/
580 bool patcher_checkcast_instanceof_flags(u1 *sp)
584 constant_classref *cr;
589 /* get stuff from the stack */
591 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
592 mcode = *((u4 *) (sp + 3 * 8));
593 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
594 disp = *((s4 *) (sp + 1 * 8));
595 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
597 /* get the fieldinfo */
599 if (!(c = resolve_classref_eager(cr)))
602 /* patch back original code */
604 *((u4 *) ra) = mcode;
606 /* synchronize instruction cache */
608 md_icacheflush(ra, 4);
610 /* patch class flags */
612 *((s4 *) (pv + disp)) = (s4) c->flags;
614 /* synchronize data cache */
616 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
622 /* patcher_checkcast_instanceof_interface **************************************
626 <patched call position>
627 81870000 lwz r12,0(r7)
628 800c0010 lwz r0,16(r12)
629 34000000 addic. r0,r0,0
630 408101fc ble- 0x3002e518
631 800c0000 lwz r0,0(r12)
633 *******************************************************************************/
635 bool patcher_checkcast_instanceof_interface(u1 *sp)
639 constant_classref *cr;
643 /* get stuff from the stack */
645 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
646 mcode = *((u4 *) (sp + 3 * 8));
647 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
649 /* get the fieldinfo */
651 if (!(c = resolve_classref_eager(cr)))
654 /* patch back original code */
656 *((u4 *) ra) = mcode;
658 /* if we show disassembly, we have to skip the nop */
660 if (opt_showdisassemble)
663 /* patch super class index */
667 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
669 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
671 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
673 /* synchronize instruction cache */
675 md_icacheflush(ra, 5 * 4);
681 /* patcher_checkcast_class *****************************************************
685 <patched call position>
686 81870000 lwz r12,0(r7)
687 800c0014 lwz r0,20(r12)
688 818dff78 lwz r12,-136(r13)
690 *******************************************************************************/
692 bool patcher_checkcast_class(u1 *sp)
696 constant_classref *cr;
701 /* get stuff from the stack */
703 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
704 mcode = *((u4 *) (sp + 3 * 8));
705 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
706 disp = *((s4 *) (sp + 1 * 8));
707 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
709 /* get the fieldinfo */
711 if (!(c = resolve_classref_eager(cr)))
714 /* patch back original code */
716 *((u4 *) ra) = mcode;
718 /* synchronize instruction cache */
720 md_icacheflush(ra, 4);
722 /* patch super class' vftbl */
724 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
726 /* synchronize data cache */
728 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
734 /* patcher_instanceof_class ****************************************************
738 <patched call position>
739 817d0000 lwz r11,0(r29)
740 818dff8c lwz r12,-116(r13)
742 *******************************************************************************/
744 bool patcher_instanceof_class(u1 *sp)
748 constant_classref *cr;
753 /* get stuff from the stack */
755 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
756 mcode = *((u4 *) (sp + 3 * 8));
757 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
758 disp = *((s4 *) (sp + 1 * 8));
759 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
761 /* get the fieldinfo */
763 if (!(c = resolve_classref_eager(cr)))
766 /* patch back original code */
768 *((u4 *) ra) = mcode;
770 /* synchronize instruction cache */
772 md_icacheflush(ra, 4);
774 /* patch super class' vftbl */
776 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
778 /* synchronize data cache */
780 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
786 /* patcher_clinit **************************************************************
790 *******************************************************************************/
792 bool patcher_clinit(u1 *sp)
798 /* get stuff from the stack */
800 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
801 mcode = *((u4 *) (sp + 3 * 8));
802 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
804 /* check if the class is initialized */
806 if (!(c->state & CLASS_INITIALIZED))
807 if (!initialize_class(c))
810 /* patch back original code */
812 *((u4 *) ra) = mcode;
814 /* synchronize instruction cache */
816 md_icacheflush(ra, 4);
822 /* patcher_athrow_areturn ******************************************************
826 <patched call position>
828 *******************************************************************************/
830 #ifdef ENABLE_VERIFIER
831 bool patcher_athrow_areturn(u1 *sp)
835 unresolved_class *uc;
838 /* get stuff from the stack */
840 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
841 mcode = *((u4 *) (sp + 3 * 8));
842 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
844 /* resolve the class */
846 if (!resolve_class(uc, resolveEager, false, &c))
849 /* patch back original code */
851 *((u4 *) ra) = mcode;
853 /* synchronize instruction cache */
855 md_icacheflush(ra, 4);
859 #endif /* ENABLE_VERIFIER */
862 /* patcher_resolve_native ******************************************************
866 *******************************************************************************/
868 #if !defined(WITH_STATIC_CLASSPATH)
869 bool patcher_resolve_native(u1 *sp)
878 /* get stuff from the stack */
880 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
881 mcode = *((u4 *) (sp + 3 * 8));
882 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
883 disp = *((s4 *) (sp + 1 * 8));
884 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
886 /* calculate and set the new return address */
889 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
891 /* resolve native function */
893 if (!(f = native_resolve_function(m)))
896 /* patch back original code */
898 *((u4 *) ra) = mcode;
900 /* synchronize instruction cache */
902 md_icacheflush(ra, 4);
904 /* patch native function pointer */
906 *((ptrint *) (pv + disp)) = (ptrint) f;
908 /* synchronize data cache */
910 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
914 #endif /* !defined(WITH_STATIC_CLASSPATH) */
918 * These are local overrides for various environment variables in Emacs.
919 * Please do not remove this and leave it at the end of the file, where
920 * Emacs will automagically detect them.
921 * ---------------------------------------------------------------------
924 * indent-tabs-mode: t
928 * vim:noexpandtab:sw=4:ts=4: