1 /* src/vm/jit/powerpc/patcher.c - PowerPC 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 5035 2006-06-19 21:00:05Z twisti $
42 #include "mm/memory.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
47 #include "vm/initialize.h"
48 #include "vm/options.h"
49 #include "vm/resolve.h"
50 #include "vm/references.h"
51 #include "vm/jit/asmpart.h"
52 #include "vm/jit/patcher.h"
55 /* patcher_get_putstatic *******************************************************
59 <patched call position>
60 816dffc8 lwz r11,-56(r13)
61 80ab0000 lwz r5,0(r11)
63 *******************************************************************************/
65 bool patcher_get_putstatic(u1 *sp)
75 /* get stuff from the stack */
77 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
78 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
79 mcode = *((u4 *) (sp + 3 * 4));
80 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
81 disp = *((s4 *) (sp + 1 * 4));
82 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
86 /* get the fieldinfo */
88 if (!(fi = resolve_field_eager(uf))) {
94 /* check if the field's class is initialized */
96 if (!(fi->class->state & CLASS_INITIALIZED)) {
97 if (!initialize_class(fi->class)) {
104 /* patch back original code */
106 *((u4 *) ra) = mcode;
108 /* synchronize instruction cache */
110 md_icacheflush(ra, 4);
112 /* patch the field value's address */
114 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
116 /* synchronize data cache */
118 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
120 PATCHER_MARK_PATCHED_MONITOREXIT;
126 /* patcher_get_putfield ********************************************************
130 <patched call position>
131 811f0014 lwz r8,20(r31)
133 *******************************************************************************/
135 bool patcher_get_putfield(u1 *sp)
138 java_objectheader *o;
140 unresolved_field *uf;
144 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
145 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
146 mcode = *((u4 *) (sp + 3 * 4));
147 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
148 pv = (u1 *) *((ptrint *) (sp + 1 * 4));
150 PATCHER_MONITORENTER;
152 /* get the fieldinfo */
154 if (!(fi = resolve_field_eager(uf))) {
160 /* patch back original code */
162 *((u4 *) ra) = mcode;
164 /* if we show disassembly, we have to skip the nop */
166 if (opt_showdisassemble)
169 /* patch the field's offset */
171 if (fi->type == TYPE_LNG) {
174 /* If the field has type long, we have to patch two
175 instructions. But we have to check which instruction is
176 first. We do that with the offset of the first
179 disp = *((u4 *) (ra + 0));
181 #if WORDS_BIGENDIAN == 1
183 *((u4 *) (ra + 0)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
184 *((u4 *) (ra + 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
187 *((u4 *) (ra + 0)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
188 *((u4 *) (ra + 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
194 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
197 /* synchronize instruction cache */
199 md_icacheflush(ra, 8);
201 PATCHER_MARK_PATCHED_MONITOREXIT;
207 /* patcher_aconst **************************************************************
211 <patched call postition>
212 806dffc4 lwz r3,-60(r13)
213 81adffc0 lwz r13,-64(r13)
217 *******************************************************************************/
219 bool patcher_aconst(u1 *sp)
222 java_objectheader *o;
224 constant_classref *cr;
229 /* get stuff from the stack */
231 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
232 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
233 mcode = *((u4 *) (sp + 3 * 4));
234 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
235 disp = *((s4 *) (sp + 1 * 4));
236 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
238 PATCHER_MONITORENTER;
240 /* get the classinfo */
242 if (!(c = resolve_classref_eager(cr))) {
248 /* patch back original code */
250 *((u4 *) ra) = mcode;
252 /* synchronize instruction cache */
254 md_icacheflush(ra, 4);
256 /* patch the classinfo pointer */
258 *((ptrint *) (pv + disp)) = (ptrint) c;
260 /* synchronize data cache */
262 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
264 PATCHER_MARK_PATCHED_MONITOREXIT;
270 /* patcher_builtin_multianewarray **********************************************
274 <patched call position>
275 808dffc0 lwz r4,-64(r13)
276 38a10038 addi r5,r1,56
277 81adffbc lwz r13,-68(r13)
281 *******************************************************************************/
283 bool patcher_builtin_multianewarray(u1 *sp)
286 java_objectheader *o;
288 constant_classref *cr;
293 /* get stuff from the stack */
295 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
296 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
297 mcode = *((u4 *) (sp + 3 * 4));
298 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
299 disp = *((s4 *) (sp + 1 * 4));
300 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
302 PATCHER_MONITORENTER;
304 /* get the classinfo */
306 if (!(c = resolve_classref_eager(cr))) {
312 /* patch back original code */
314 *((u4 *) ra) = mcode;
316 /* synchronize instruction cache */
318 md_icacheflush(ra, 4);
320 /* patch the classinfo pointer */
322 *((ptrint *) (pv + disp)) = (ptrint) c;
324 /* synchronize data cache */
326 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
328 PATCHER_MARK_PATCHED_MONITOREXIT;
334 /* patcher_builtin_arraycheckcast **********************************************
338 <patched call position>
339 808dffd8 lwz r4,-40(r13)
340 81adffd4 lwz r13,-44(r13)
344 *******************************************************************************/
346 bool patcher_builtin_arraycheckcast(u1 *sp)
349 java_objectheader *o;
351 constant_classref *cr;
356 /* get stuff from the stack */
358 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
359 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
360 mcode = *((u4 *) (sp + 3 * 4));
361 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
362 disp = *((s4 *) (sp + 1 * 4));
363 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
365 PATCHER_MONITORENTER;
367 /* get the classinfo */
369 if (!(c = resolve_classref_eager(cr))) {
375 /* patch back original code */
377 *((u4 *) ra) = mcode;
379 /* synchronize instruction cache */
381 md_icacheflush(ra, 4);
383 /* patch the classinfo pointer */
385 *((ptrint *) (pv + disp)) = (ptrint) c;
387 /* synchronize data cache */
389 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
391 PATCHER_MARK_PATCHED_MONITOREXIT;
397 /* patcher_invokestatic_special ************************************************
401 <patched call position>
402 81adffd8 lwz r13,-40(r13)
406 ******************************************************************************/
408 bool patcher_invokestatic_special(u1 *sp)
411 java_objectheader *o;
413 unresolved_method *um;
418 /* get stuff from the stack */
420 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
421 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
422 mcode = *((u4 *) (sp + 3 * 4));
423 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
424 disp = *((s4 *) (sp + 1 * 4));
425 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
427 PATCHER_MONITORENTER;
429 /* get the fieldinfo */
431 if (!(m = resolve_method_eager(um))) {
437 /* patch back original code */
439 *((u4 *) ra) = mcode;
441 /* synchronize instruction cache */
443 md_icacheflush(ra, 4);
445 /* patch stubroutine */
447 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
449 /* synchronize data cache */
451 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
453 PATCHER_MARK_PATCHED_MONITOREXIT;
459 /* patcher_invokevirtual *******************************************************
463 <patched call position>
464 81830000 lwz r12,0(r3)
465 81ac0088 lwz r13,136(r12)
469 *******************************************************************************/
471 bool patcher_invokevirtual(u1 *sp)
474 java_objectheader *o;
476 unresolved_method *um;
480 /* get stuff from the stack */
482 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
483 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
484 mcode = *((u4 *) (sp + 3 * 4));
485 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
487 PATCHER_MONITORENTER;
489 /* get the fieldinfo */
491 if (!(m = resolve_method_eager(um))) {
497 /* patch back original code */
499 *((u4 *) ra) = mcode;
501 /* if we show disassembly, we have to skip the nop */
503 if (opt_showdisassemble)
506 /* patch vftbl index */
508 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
510 *((s4 *) (ra + 4)) |= (disp & 0x0000ffff);
512 /* synchronize instruction cache */
514 md_icacheflush(ra, 2 * 4);
516 PATCHER_MARK_PATCHED_MONITOREXIT;
522 /* patcher_invokeinterface *****************************************************
526 <patched call position>
527 81830000 lwz r12,0(r3)
528 818cffd0 lwz r12,-48(r12)
529 81ac000c lwz r13,12(r12)
533 *******************************************************************************/
535 bool patcher_invokeinterface(u1 *sp)
538 java_objectheader *o;
540 unresolved_method *um;
544 /* get stuff from the stack */
546 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
547 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
548 mcode = *((u4 *) (sp + 3 * 4));
549 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
551 PATCHER_MONITORENTER;
553 /* get the fieldinfo */
555 if (!(m = resolve_method_eager(um))) {
561 /* patch back original code */
563 *((u4 *) ra) = mcode;
565 /* if we show disassembly, we have to skip the nop */
567 if (opt_showdisassemble)
570 /* patch interfacetable index */
572 disp = OFFSET(vftbl_t, interfacetable[0]) -
573 sizeof(methodptr*) * m->class->index;
575 /* XXX TWISTI: check displacement */
577 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
579 /* patch method offset */
581 disp = sizeof(methodptr) * (m - m->class->methods);
583 /* XXX TWISTI: check displacement */
585 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
587 /* synchronize instruction cache */
589 md_icacheflush(ra, 3 * 4);
591 PATCHER_MARK_PATCHED_MONITOREXIT;
597 /* patcher_checkcast_instanceof_flags ******************************************
601 <patched call position>
602 818dff7c lwz r12,-132(r13)
604 *******************************************************************************/
606 bool patcher_checkcast_instanceof_flags(u1 *sp)
609 java_objectheader *o;
611 constant_classref *cr;
616 /* get stuff from the stack */
618 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
619 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
620 mcode = *((u4 *) (sp + 3 * 4));
621 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
622 disp = *((s4 *) (sp + 1 * 4));
623 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
625 PATCHER_MONITORENTER;
627 /* get the fieldinfo */
629 if (!(c = resolve_classref_eager(cr))) {
635 /* patch back original code */
637 *((u4 *) ra) = mcode;
639 /* synchronize instruction cache */
641 md_icacheflush(ra, 4);
643 /* patch class flags */
645 *((s4 *) (pv + disp)) = (s4) c->flags;
647 /* synchronize data cache */
649 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
651 PATCHER_MARK_PATCHED_MONITOREXIT;
657 /* patcher_checkcast_instanceof_interface **************************************
661 <patched call position>
662 81870000 lwz r12,0(r7)
663 800c0010 lwz r0,16(r12)
664 34000000 addic. r0,r0,0
665 408101fc ble- 0x3002e518
666 800c0000 lwz r0,0(r12)
668 *******************************************************************************/
670 bool patcher_checkcast_instanceof_interface(u1 *sp)
673 java_objectheader *o;
675 constant_classref *cr;
679 /* get stuff from the stack */
681 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
682 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
683 mcode = *((u4 *) (sp + 3 * 4));
684 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
686 PATCHER_MONITORENTER;
688 /* get the fieldinfo */
690 if (!(c = resolve_classref_eager(cr))) {
696 /* patch back original code */
698 *((u4 *) ra) = mcode;
700 /* if we show disassembly, we have to skip the nop */
702 if (opt_showdisassemble)
705 /* patch super class index */
709 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
711 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
713 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
715 /* synchronize instruction cache */
717 md_icacheflush(ra, 5 * 4);
719 PATCHER_MARK_PATCHED_MONITOREXIT;
725 /* patcher_checkcast_class *****************************************************
729 <patched call position>
730 81870000 lwz r12,0(r7)
731 800c0014 lwz r0,20(r12)
732 818dff78 lwz r12,-136(r13)
734 *******************************************************************************/
736 bool patcher_checkcast_class(u1 *sp)
739 java_objectheader *o;
741 constant_classref *cr;
746 /* get stuff from the stack */
748 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
749 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
750 mcode = *((u4 *) (sp + 3 * 4));
751 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
752 disp = *((s4 *) (sp + 1 * 4));
753 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
755 PATCHER_MONITORENTER;
757 /* get the fieldinfo */
759 if (!(c = resolve_classref_eager(cr))) {
765 /* patch back original code */
767 *((u4 *) ra) = mcode;
769 /* synchronize instruction cache */
771 md_icacheflush(ra, 4);
773 /* patch super class' vftbl */
775 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
777 /* synchronize data cache */
779 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
781 PATCHER_MARK_PATCHED_MONITOREXIT;
787 /* patcher_instanceof_class ****************************************************
791 <patched call position>
792 817d0000 lwz r11,0(r29)
793 818dff8c lwz r12,-116(r13)
795 *******************************************************************************/
797 bool patcher_instanceof_class(u1 *sp)
800 java_objectheader *o;
802 constant_classref *cr;
807 /* get stuff from the stack */
809 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
810 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
811 mcode = *((u4 *) (sp + 3 * 4));
812 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
813 disp = *((s4 *) (sp + 1 * 4));
814 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
816 PATCHER_MONITORENTER;
818 /* get the fieldinfo */
820 if (!(c = resolve_classref_eager(cr))) {
826 /* patch back original code */
828 *((u4 *) ra) = mcode;
830 /* synchronize instruction cache */
832 md_icacheflush(ra, 4);
834 /* patch super class' vftbl */
836 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
838 /* synchronize data cache */
840 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
842 PATCHER_MARK_PATCHED_MONITOREXIT;
848 /* patcher_clinit **************************************************************
852 *******************************************************************************/
854 bool patcher_clinit(u1 *sp)
857 java_objectheader *o;
861 /* get stuff from the stack */
863 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
864 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
865 mcode = *((u4 *) (sp + 3 * 4));
866 c = (classinfo *) *((ptrint *) (sp + 2 * 4));
868 PATCHER_MONITORENTER;
870 /* check if the class is initialized */
872 if (!(c->state & CLASS_INITIALIZED)) {
873 if (!initialize_class(c)) {
880 /* patch back original code */
882 *((u4 *) ra) = mcode;
884 /* synchronize instruction cache */
886 md_icacheflush(ra, 4);
888 PATCHER_MARK_PATCHED_MONITOREXIT;
894 /* patcher_athrow_areturn ******************************************************
898 <patched call position>
900 *******************************************************************************/
902 #ifdef ENABLE_VERIFIER
903 bool patcher_athrow_areturn(u1 *sp)
906 java_objectheader *o;
908 unresolved_class *uc;
911 /* get stuff from the stack */
913 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
914 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
915 mcode = *((u4 *) (sp + 3 * 4));
916 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
918 PATCHER_MONITORENTER;
920 /* resolve the class */
922 if (!resolve_class(uc, resolveEager, false, &c)) {
928 /* patch back original code */
930 *((u4 *) ra) = mcode;
932 /* synchronize instruction cache */
934 md_icacheflush(ra, 4);
936 PATCHER_MARK_PATCHED_MONITOREXIT;
940 #endif /* ENABLE_VERIFIER */
943 /* patcher_resolve_native ******************************************************
947 *******************************************************************************/
949 #if !defined(WITH_STATIC_CLASSPATH)
950 bool patcher_resolve_native(u1 *sp)
953 java_objectheader *o;
960 /* get stuff from the stack */
962 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
963 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
964 mcode = *((u4 *) (sp + 3 * 4));
965 m = (methodinfo *) *((ptrint *) (sp + 2 * 4));
966 disp = *((s4 *) (sp + 1 * 4));
967 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
969 /* calculate and set the new return address */
972 *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
974 PATCHER_MONITORENTER;
976 /* resolve native function */
978 if (!(f = native_resolve_function(m))) {
984 /* patch back original code */
986 *((u4 *) ra) = mcode;
988 /* synchronize instruction cache */
990 md_icacheflush(ra, 4);
992 /* patch native function pointer */
994 *((ptrint *) (pv + disp)) = (ptrint) f;
996 /* synchronize data cache */
998 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
1000 PATCHER_MARK_PATCHED_MONITOREXIT;
1004 #endif /* !defined(WITH_STATIC_CLASSPATH) */
1008 * These are local overrides for various environment variables in Emacs.
1009 * Please do not remove this and leave it at the end of the file, where
1010 * Emacs will automagically detect them.
1011 * ---------------------------------------------------------------------
1014 * indent-tabs-mode: t
1018 * vim:noexpandtab:sw=4:ts=4: