1 /* src/vm/jit/powerpc/patcher.c - PowerPC code patching functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Christian Thalinger
31 $Id: patcher.c 3869 2005-12-03 16:09:05Z twisti $
39 #include "mm/memory.h"
40 #include "native/native.h"
41 #include "vm/builtin.h"
44 #include "vm/initialize.h"
45 #include "vm/options.h"
46 #include "vm/resolve.h"
47 #include "vm/references.h"
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/patcher.h"
52 /* patcher_get_putstatic *******************************************************
56 <patched call position>
57 816dffc8 lwz r11,-56(r13)
58 80ab0000 lwz r5,0(r11)
60 *******************************************************************************/
62 bool patcher_get_putstatic(u1 *sp)
72 /* get stuff from the stack */
74 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
75 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
76 mcode = *((u4 *) (sp + 3 * 4));
77 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
78 disp = *((s4 *) (sp + 1 * 4));
79 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
83 /* get the fieldinfo */
85 if (!(fi = resolve_field_eager(uf))) {
91 /* check if the field's class is initialized */
93 if (!(fi->class->state & CLASS_INITIALIZED)) {
94 if (!initialize_class(fi->class)) {
101 /* patch back original code */
103 *((u4 *) ra) = mcode;
105 /* synchronize instruction cache */
107 asm_cacheflush(ra, 4);
109 /* patch the field value's address */
111 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
113 PATCHER_MARK_PATCHED_MONITOREXIT;
119 /* patcher_get_putfield ********************************************************
123 <patched call position>
124 811f0014 lwz r8,20(r31)
126 *******************************************************************************/
128 bool patcher_get_putfield(u1 *sp)
131 java_objectheader *o;
133 unresolved_field *uf;
137 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
138 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
139 mcode = *((u4 *) (sp + 3 * 4));
140 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
141 pv = (u1 *) *((ptrint *) (sp + 1 * 4));
143 PATCHER_MONITORENTER;
145 /* get the fieldinfo */
147 if (!(fi = resolve_field_eager(uf))) {
153 /* patch back original code */
155 *((u4 *) ra) = mcode;
157 /* if we show disassembly, we have to skip the nop */
159 if (opt_showdisassemble)
162 /* patch the field's offset */
164 if (fi->type == TYPE_LNG) {
165 /* if the field has type long, we have to patch two instructions */
167 *((u4 *) ra) |= (s2) ((fi->offset + 4) & 0x0000ffff);
168 *((u4 *) (ra + 4)) |= (s2) (fi->offset & 0x0000ffff);
171 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
174 /* synchronize instruction cache */
176 asm_cacheflush(ra, 8);
178 PATCHER_MARK_PATCHED_MONITOREXIT;
184 /* patcher_aconst **************************************************************
188 <patched call postition>
189 806dffc4 lwz r3,-60(r13)
190 81adffc0 lwz r13,-64(r13)
194 *******************************************************************************/
196 bool patcher_aconst(u1 *sp)
199 java_objectheader *o;
201 constant_classref *cr;
206 /* get stuff from the stack */
208 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
209 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
210 mcode = *((u4 *) (sp + 3 * 4));
211 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
212 disp = *((s4 *) (sp + 1 * 4));
213 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
215 PATCHER_MONITORENTER;
217 /* get the classinfo */
219 if (!(c = resolve_classref_eager(cr))) {
225 /* patch back original code */
227 *((u4 *) ra) = mcode;
229 /* synchronize instruction cache */
231 asm_cacheflush(ra, 4);
233 /* patch the classinfo pointer */
235 *((ptrint *) (pv + disp)) = (ptrint) c;
237 PATCHER_MARK_PATCHED_MONITOREXIT;
243 /* patcher_builtin_multianewarray **********************************************
247 <patched call position>
248 808dffc0 lwz r4,-64(r13)
249 38a10038 addi r5,r1,56
250 81adffbc lwz r13,-68(r13)
254 *******************************************************************************/
256 bool patcher_builtin_multianewarray(u1 *sp)
259 java_objectheader *o;
261 constant_classref *cr;
266 /* get stuff from the stack */
268 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
269 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
270 mcode = *((u4 *) (sp + 3 * 4));
271 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
272 disp = *((s4 *) (sp + 1 * 4));
273 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
275 PATCHER_MONITORENTER;
277 /* get the classinfo */
279 if (!(c = resolve_classref_eager(cr))) {
285 /* patch back original code */
287 *((u4 *) ra) = mcode;
289 /* synchronize instruction cache */
291 asm_cacheflush(ra, 4);
293 /* patch the classinfo pointer */
295 *((ptrint *) (pv + disp)) = (ptrint) c;
297 PATCHER_MARK_PATCHED_MONITOREXIT;
303 /* patcher_builtin_arraycheckcast **********************************************
307 <patched call position>
308 808dffd8 lwz r4,-40(r13)
309 81adffd4 lwz r13,-44(r13)
313 *******************************************************************************/
315 bool patcher_builtin_arraycheckcast(u1 *sp)
318 java_objectheader *o;
320 constant_classref *cr;
325 /* get stuff from the stack */
327 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
328 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
329 mcode = *((u4 *) (sp + 3 * 4));
330 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
331 disp = *((s4 *) (sp + 1 * 4));
332 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
334 PATCHER_MONITORENTER;
336 /* get the classinfo */
338 if (!(c = resolve_classref_eager(cr))) {
344 /* patch back original code */
346 *((u4 *) ra) = mcode;
348 /* synchronize instruction cache */
350 asm_cacheflush(ra, 4);
352 /* patch the classinfo pointer */
354 *((ptrint *) (pv + disp)) = (ptrint) c;
356 PATCHER_MARK_PATCHED_MONITOREXIT;
362 /* patcher_invokestatic_special ************************************************
366 <patched call position>
367 81adffd8 lwz r13,-40(r13)
371 ******************************************************************************/
373 bool patcher_invokestatic_special(u1 *sp)
376 java_objectheader *o;
378 unresolved_method *um;
383 /* get stuff from the stack */
385 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
386 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
387 mcode = *((u4 *) (sp + 3 * 4));
388 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
389 disp = *((s4 *) (sp + 1 * 4));
390 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
392 PATCHER_MONITORENTER;
394 /* get the fieldinfo */
396 if (!(m = resolve_method_eager(um))) {
402 /* patch back original code */
404 *((u4 *) ra) = mcode;
406 /* synchronize instruction cache */
408 asm_cacheflush(ra, 4);
410 /* patch stubroutine */
412 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
414 PATCHER_MARK_PATCHED_MONITOREXIT;
420 /* patcher_invokevirtual *******************************************************
424 <patched call position>
425 81830000 lwz r12,0(r3)
426 81ac0088 lwz r13,136(r12)
430 *******************************************************************************/
432 bool patcher_invokevirtual(u1 *sp)
435 java_objectheader *o;
437 unresolved_method *um;
440 /* get stuff from the stack */
442 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
443 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
444 mcode = *((u4 *) (sp + 3 * 4));
445 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
447 PATCHER_MONITORENTER;
449 /* get the fieldinfo */
451 if (!(m = resolve_method_eager(um))) {
457 /* patch back original code */
459 *((u4 *) ra) = mcode;
461 /* if we show disassembly, we have to skip the nop */
463 if (opt_showdisassemble)
466 /* patch vftbl index */
468 *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
469 sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
471 /* synchronize instruction cache */
473 asm_cacheflush(ra, 2 * 4);
475 PATCHER_MARK_PATCHED_MONITOREXIT;
481 /* patcher_invokeinterface *****************************************************
485 <patched call position>
486 81830000 lwz r12,0(r3)
487 818cffd0 lwz r12,-48(r12)
488 81ac000c lwz r13,12(r12)
492 *******************************************************************************/
494 bool patcher_invokeinterface(u1 *sp)
497 java_objectheader *o;
499 unresolved_method *um;
502 /* get stuff from the stack */
504 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
505 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
506 mcode = *((u4 *) (sp + 3 * 4));
507 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
509 PATCHER_MONITORENTER;
511 /* get the fieldinfo */
513 if (!(m = resolve_method_eager(um))) {
519 /* patch back original code */
521 *((u4 *) ra) = mcode;
523 /* if we show disassembly, we have to skip the nop */
525 if (opt_showdisassemble)
528 /* patch interfacetable index */
530 *((s4 *) (ra + 1 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
531 sizeof(methodptr*) * m->class->index) & 0x0000ffff);
533 /* patch method offset */
535 *((s4 *) (ra + 2 * 4)) |=
536 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
538 /* synchronize instruction cache */
540 asm_cacheflush(ra, 3 * 4);
542 PATCHER_MARK_PATCHED_MONITOREXIT;
548 /* patcher_checkcast_instanceof_flags ******************************************
552 <patched call position>
553 818dff7c lwz r12,-132(r13)
555 *******************************************************************************/
557 bool patcher_checkcast_instanceof_flags(u1 *sp)
560 java_objectheader *o;
562 constant_classref *cr;
567 /* get stuff from the stack */
569 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
570 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
571 mcode = *((u4 *) (sp + 3 * 4));
572 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
573 disp = *((s4 *) (sp + 1 * 4));
574 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
576 PATCHER_MONITORENTER;
578 /* get the fieldinfo */
580 if (!(c = resolve_classref_eager(cr))) {
586 /* patch back original code */
588 *((u4 *) ra) = mcode;
590 /* synchronize instruction cache */
592 asm_cacheflush(ra, 4);
594 /* patch class flags */
596 *((s4 *) (pv + disp)) = (s4) c->flags;
598 PATCHER_MARK_PATCHED_MONITOREXIT;
604 /* patcher_checkcast_instanceof_interface **************************************
608 <patched call position>
609 81870000 lwz r12,0(r7)
610 800c0010 lwz r0,16(r12)
611 34000000 addic. r0,r0,0
612 408101fc ble- 0x3002e518
613 800c0000 lwz r0,0(r12)
615 *******************************************************************************/
617 bool patcher_checkcast_instanceof_interface(u1 *sp)
620 java_objectheader *o;
622 constant_classref *cr;
625 /* get stuff from the stack */
627 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
628 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
629 mcode = *((u4 *) (sp + 3 * 4));
630 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
632 PATCHER_MONITORENTER;
634 /* get the fieldinfo */
636 if (!(c = resolve_classref_eager(cr))) {
642 /* patch back original code */
644 *((u4 *) ra) = mcode;
646 /* if we show disassembly, we have to skip the nop */
648 if (opt_showdisassemble)
651 /* patch super class index */
653 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
655 *((s4 *) (ra + 4 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
656 c->index * sizeof(methodptr*)) & 0x0000ffff);
658 /* synchronize instruction cache */
660 asm_cacheflush(ra, 5 * 4);
662 PATCHER_MARK_PATCHED_MONITOREXIT;
668 /* patcher_checkcast_class *****************************************************
672 <patched call position>
673 81870000 lwz r12,0(r7)
674 800c0014 lwz r0,20(r12)
675 818dff78 lwz r12,-136(r13)
677 *******************************************************************************/
679 bool patcher_checkcast_class(u1 *sp)
682 java_objectheader *o;
684 constant_classref *cr;
689 /* get stuff from the stack */
691 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
692 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
693 mcode = *((u4 *) (sp + 3 * 4));
694 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
695 disp = *((s4 *) (sp + 1 * 4));
696 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
698 PATCHER_MONITORENTER;
700 /* get the fieldinfo */
702 if (!(c = resolve_classref_eager(cr))) {
708 /* patch back original code */
710 *((u4 *) ra) = mcode;
712 /* synchronize instruction cache */
714 asm_cacheflush(ra, 4);
716 /* patch super class' vftbl */
718 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
720 PATCHER_MARK_PATCHED_MONITOREXIT;
726 /* patcher_instanceof_class ****************************************************
730 <patched call position>
731 817d0000 lwz r11,0(r29)
732 818dff8c lwz r12,-116(r13)
734 *******************************************************************************/
736 bool patcher_instanceof_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 asm_cacheflush(ra, 4);
773 /* patch super class' vftbl */
775 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
777 PATCHER_MARK_PATCHED_MONITOREXIT;
783 /* patcher_clinit **************************************************************
787 *******************************************************************************/
789 bool patcher_clinit(u1 *sp)
792 java_objectheader *o;
796 /* get stuff from the stack */
798 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
799 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
800 mcode = *((u4 *) (sp + 3 * 4));
801 c = (classinfo *) *((ptrint *) (sp + 2 * 4));
803 PATCHER_MONITORENTER;
805 /* check if the class is initialized */
807 if (!(c->state & CLASS_INITIALIZED)) {
808 if (!initialize_class(c)) {
815 /* patch back original code */
817 *((u4 *) ra) = mcode;
819 /* synchronize instruction cache */
821 asm_cacheflush(ra, 4);
823 PATCHER_MARK_PATCHED_MONITOREXIT;
829 /* patcher_athrow_areturn ******************************************************
833 <patched call position>
835 *******************************************************************************/
837 #ifdef ENABLE_VERIFIER
838 bool patcher_athrow_areturn(u1 *sp)
841 java_objectheader *o;
843 unresolved_class *uc;
846 /* get stuff from the stack */
848 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
849 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
850 mcode = *((u4 *) (sp + 3 * 4));
851 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
853 PATCHER_MONITORENTER;
855 /* resolve the class */
857 if (!resolve_class(uc, resolveEager, false, &c)) {
863 /* patch back original code */
865 *((u4 *) ra) = mcode;
867 /* synchronize instruction cache */
869 asm_cacheflush(ra, 4);
871 PATCHER_MARK_PATCHED_MONITOREXIT;
875 #endif /* ENABLE_VERIFIER */
878 /* patcher_resolve_native ******************************************************
882 *******************************************************************************/
884 #if !defined(ENABLE_STATICVM)
885 bool patcher_resolve_native(u1 *sp)
888 java_objectheader *o;
895 /* get stuff from the stack */
897 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
898 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
899 mcode = *((u4 *) (sp + 3 * 4));
900 m = (methodinfo *) *((ptrint *) (sp + 2 * 4));
901 disp = *((s4 *) (sp + 1 * 4));
902 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
904 /* calculate and set the new return address */
907 *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
909 PATCHER_MONITORENTER;
911 /* resolve native function */
913 if (!(f = native_resolve_function(m))) {
919 /* patch back original code */
921 *((u4 *) ra) = mcode;
923 /* synchronize instruction cache */
925 asm_cacheflush(ra, 4);
927 /* patch native function pointer */
929 *((ptrint *) (pv + disp)) = (ptrint) f;
931 PATCHER_MARK_PATCHED_MONITOREXIT;
935 #endif /* !defined(ENABLE_STATICVM) */
939 * These are local overrides for various environment variables in Emacs.
940 * Please do not remove this and leave it at the end of the file, where
941 * Emacs will automagically detect them.
942 * ---------------------------------------------------------------------
945 * indent-tabs-mode: t
949 * vim:noexpandtab:sw=4:ts=4: