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 2537 2005-05-31 15:54:27Z twisti $
36 #include "vm/jit/powerpc/types.h"
37 #include "vm/builtin.h"
39 #include "vm/initialize.h"
40 #include "vm/options.h"
41 #include "vm/references.h"
42 #include "vm/jit/asmpart.h"
43 #include "vm/jit/helper.h"
44 #include "vm/jit/patcher.h"
47 /* patcher_get_putstatic *******************************************************
51 <patched call position>
52 816dffc8 lwz r11,-56(r13)
53 80ab0000 lwz r5,0(r11)
55 *******************************************************************************/
57 bool patcher_get_putstatic(u1 *sp)
67 /* get stuff from the stack */
69 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
70 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
71 mcode = *((u4 *) (sp + 1 * 4));
72 uf = (unresolved_field *) *((ptrint *) (sp + 0 * 4));
73 pv = (u1 *) *((ptrint *) (sp - 2 * 4));
75 /* calculate and set the new return address */
78 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
82 /* get the fieldinfo */
84 if (!(fi = helper_resolve_fieldinfo(uf))) {
90 /* check if the field's class is initialized */
92 if (!fi->class->initialized) {
93 if (!initialize_class(fi->class)) {
100 /* patch back original code */
102 *((u4 *) ra) = mcode;
104 /* if we show disassembly, we have to skip the nop */
109 /* get the offset from machine instruction */
111 offset = (s2) (*((u4 *) ra) & 0x0000ffff);
113 /* patch the field value's address */
115 *((ptrint *) (pv + offset)) = (ptrint) &(fi->value);
117 /* synchronize instruction cache */
119 asm_cacheflush(ra, 4);
121 PATCHER_MARK_PATCHED_MONITOREXIT;
127 /* patcher_get_putfield ********************************************************
131 <patched call position>
132 811f0014 lwz r8,20(r31)
134 *******************************************************************************/
136 bool patcher_get_putfield(u1 *sp)
139 java_objectheader *o;
141 unresolved_field *uf;
145 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
146 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
147 mcode = *((u4 *) (sp + 1 * 4));
148 uf = (unresolved_field *) *((ptrint *) (sp + 0 * 4));
149 pv = (u1 *) *((ptrint *) (sp - 2 * 4));
151 /* calculate and set the new return address */
154 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
156 PATCHER_MONITORENTER;
158 /* get the fieldinfo */
160 if (!(fi = helper_resolve_fieldinfo(uf))) {
166 /* patch back original code */
168 *((u4 *) ra) = mcode;
170 /* if we show disassembly, we have to skip the nop */
175 /* patch the field's offset */
177 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
179 /* if the field has type long, we need to patch the second move too */
181 if (fi->type == TYPE_LNG)
182 *((u4 *) (ra + 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
184 /* synchronize instruction cache */
186 asm_cacheflush(ra, 8);
188 PATCHER_MARK_PATCHED_MONITOREXIT;
194 /* patcher_builtin_new *********************************************************
198 806dffc4 lwz r3,-60(r13)
199 <patched call postition>
200 81adffc0 lwz r13,-64(r13)
204 *******************************************************************************/
206 bool patcher_builtin_new(u1 *sp)
209 java_objectheader *o;
211 constant_classref *cr;
216 /* get stuff from the stack */
218 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
219 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
220 mcode = *((u4 *) (sp + 1 * 4));
221 cr = (constant_classref *) *((ptrint *) (sp + 0 * 4));
222 pv = (u1 *) *((ptrint *) (sp - 2 * 4));
224 /* calculate and set the new return address */
227 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
229 PATCHER_MONITORENTER;
231 /* get the classinfo */
233 if (!(c = helper_resolve_classinfo(cr))) {
239 /* patch back original code */
241 *((u4 *) (ra + 4)) = mcode;
243 /* get the offset from machine instruction */
245 offset = (s2) (*((u4 *) ra) & 0x0000ffff);
247 /* patch the classinfo pointer */
249 *((ptrint *) (pv + offset)) = (ptrint) c;
251 /* if we show disassembly, we have to skip the nop */
256 /* get the offset from machine instruction */
258 offset = (s2) (*((u4 *) (ra + 4)) & 0x0000ffff);
260 /* patch new function address */
262 *((ptrint *) (pv + offset)) = (ptrint) BUILTIN_new;
264 /* synchronize instruction cache */
266 asm_cacheflush(ra + 4, 4);
268 PATCHER_MARK_PATCHED_MONITOREXIT;
274 /* patcher_builtin_newarray ****************************************************
278 808dffc8 lwz r4,-56(r13)
279 <patched call position>
280 81adffc4 lwz r13,-60(r13)
284 *******************************************************************************/
286 bool patcher_builtin_newarray(u1 *sp)
289 java_objectheader *o;
291 constant_classref *cr;
296 /* get stuff from the stack */
298 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
299 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
300 mcode = *((u4 *) (sp + 1 * 4));
301 cr = (constant_classref *) *((ptrint *) (sp + 0 * 4));
302 pv = (u1 *) *((ptrint *) (sp - 2 * 4));
304 /* calculate and set the new return address */
307 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
309 PATCHER_MONITORENTER;
311 /* get the classinfo */
313 if (!(c = helper_resolve_classinfo(cr))) {
319 /* patch back original code */
321 *((u4 *) (ra + 4)) = mcode;
323 /* get the offset from machine instruction */
325 offset = (s2) (*((u4 *) ra) & 0x0000ffff);
327 /* patch the class' vftbl pointer */
329 *((ptrint *) (pv + offset)) = (ptrint) c->vftbl;
331 /* if we show disassembly, we have to skip the nop */
336 /* get the offset from machine instruction */
338 offset = (s2) (*((u4 *) (ra + 4)) & 0x0000ffff);
340 /* patch new function address */
342 *((ptrint *) (pv + offset)) = (ptrint) BUILTIN_newarray;
344 /* synchronize instruction cache */
346 asm_cacheflush(ra, 4);
348 PATCHER_MARK_PATCHED_MONITOREXIT;
354 /* patcher_builtin_multianewarray **********************************************
358 <patched call position>
360 808dffc0 lwz r4,-64(r13)
361 38a10038 addi r5,r1,56
362 81adffbc lwz r13,-68(r13)
366 *******************************************************************************/
368 bool patcher_builtin_multianewarray(u1 *sp)
371 java_objectheader *o;
373 constant_classref *cr;
378 /* get stuff from the stack */
380 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
381 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
382 mcode = *((u4 *) (sp + 1 * 4));
383 cr = (constant_classref *) *((ptrint *) (sp + 0 * 4));
384 pv = (u1 *) *((ptrint *) (sp - 2 * 4));
386 /* calculate and set the new return address */
389 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
391 PATCHER_MONITORENTER;
393 /* get the classinfo */
395 if (!(c = helper_resolve_classinfo(cr))) {
401 /* patch back original code */
403 *((u4 *) ra) = mcode;
405 /* if we show disassembly, we have to skip the nop */
410 /* get the offset from machine instruction */
412 offset = (s2) (*((u4 *) (ra + 4)) & 0x0000ffff);
414 /* patch the class' vftbl pointer */
416 *((ptrint *) (pv + offset)) = (ptrint) c->vftbl;
418 /* synchronize instruction cache */
420 asm_cacheflush(ra, 4);
422 PATCHER_MARK_PATCHED_MONITOREXIT;
428 /* patcher_builtin_arraycheckcast **********************************************
432 808dffd8 lwz r4,-40(r13)
433 <patched call position>
434 81adffd4 lwz r13,-44(r13)
438 *******************************************************************************/
440 bool patcher_builtin_arraycheckcast(u1 *sp)
443 java_objectheader *o;
445 constant_classref *cr;
450 /* get stuff from the stack */
452 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
453 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
454 mcode = *((u4 *) (sp + 1 * 4));
455 cr = (constant_classref *) *((ptrint *) (sp + 0 * 4));
456 pv = (u1 *) *((ptrint *) (sp - 2 * 4));
458 /* calculate and set the new return address */
461 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
463 PATCHER_MONITORENTER;
465 /* get the classinfo */
467 if (!(c = helper_resolve_classinfo(cr))) {
473 /* patch back original code */
475 *((u4 *) (ra + 4)) = mcode;
477 /* get the offset from machine instruction */
479 offset = (s2) (*((u4 *) ra) & 0x0000ffff);
481 /* patch the class' vftbl pointer */
483 *((ptrint *) (pv + offset)) = (ptrint) c->vftbl;
485 /* if we show disassembly, we have to skip the nop */
490 /* get the offset from machine instruction */
492 offset = (s2) (*((u4 *) (ra + 4)) & 0x0000ffff);
494 /* patch new function address */
496 *((ptrint *) (pv + offset)) = (ptrint) BUILTIN_arraycheckcast;
498 /* synchronize instruction cache */
500 asm_cacheflush(ra + 4, 4);
502 PATCHER_MARK_PATCHED_MONITOREXIT;
508 /* patcher_builtin_arrayinstanceof *********************************************
512 808dff50 lwz r4,-176(r13)
513 <patched call position>
514 81adff4c lwz r13,-180(r13)
518 *******************************************************************************/
520 bool patcher_builtin_arrayinstanceof(u1 *sp)
523 java_objectheader *o;
525 constant_classref *cr;
530 /* get stuff from the stack */
532 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
533 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
534 mcode = *((u4 *) (sp + 1 * 4));
535 cr = (constant_classref *) *((ptrint *) (sp + 0 * 4));
536 pv = (u1 *) *((ptrint *) (sp - 2 * 4));
538 /* calculate and set the new return address */
541 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
543 PATCHER_MONITORENTER;
545 /* get the classinfo */
547 if (!(c = helper_resolve_classinfo(cr))) {
553 /* patch back original code */
555 *((u4 *) (ra + 4)) = mcode;
557 /* get the offset from machine instruction */
559 offset = (s2) (*((u4 *) ra) & 0x0000ffff);
561 /* patch the class' vftbl pointer */
563 *((ptrint *) (pv + offset)) = (ptrint) c->vftbl;
565 /* if we show disassembly, we have to skip the nop */
570 /* get the offset from machine instruction */
572 offset = (s2) (*((u4 *) (ra + 4)) & 0x0000ffff);
574 /* patch new function address */
576 *((ptrint *) (pv + offset)) = (ptrint) BUILTIN_arrayinstanceof;
578 /* synchronize instruction cache */
580 asm_cacheflush(ra + 4, 4);
582 PATCHER_MARK_PATCHED_MONITOREXIT;
588 /* patcher_invokestatic_special ************************************************
592 <patched call position>
593 81adffd8 lwz r13,-40(r13)
597 ******************************************************************************/
599 bool patcher_invokestatic_special(u1 *sp)
602 java_objectheader *o;
604 unresolved_method *um;
609 /* get stuff from the stack */
611 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
612 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
613 mcode = *((u4 *) (sp + 1 * 4));
614 um = (unresolved_method *) *((ptrint *) (sp + 0 * 4));
615 pv = (u1 *) *((ptrint *) (sp - 2 * 4));
617 /* calculate and set the new return address */
620 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
622 PATCHER_MONITORENTER;
624 /* get the fieldinfo */
626 if (!(m = helper_resolve_methodinfo(um))) {
632 /* patch back original code */
634 *((u4 *) ra) = mcode;
636 /* if we show disassembly, we have to skip the nop */
641 /* get the offset from machine instruction */
643 offset = (s2) (*((u4 *) ra) & 0x0000ffff);
645 /* patch stubroutine */
647 *((ptrint *) (pv + offset)) = (ptrint) m->stubroutine;
649 /* synchronize instruction cache */
651 asm_cacheflush(ra, 4);
653 PATCHER_MARK_PATCHED_MONITOREXIT;
659 /* patcher_invokevirtual *******************************************************
663 <patched call position>
664 81830000 lwz r12,0(r3)
665 81ac0088 lwz r13,136(r12)
669 *******************************************************************************/
671 bool patcher_invokevirtual(u1 *sp)
674 java_objectheader *o;
676 unresolved_method *um;
679 /* get stuff from the stack */
681 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
682 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
683 mcode = *((u4 *) (sp + 1 * 4));
684 um = (unresolved_method *) *((ptrint *) (sp + 0 * 4));
686 /* calculate and set the new return address */
689 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
691 PATCHER_MONITORENTER;
693 /* get the fieldinfo */
695 if (!(m = helper_resolve_methodinfo(um))) {
701 /* patch back original code */
703 *((u4 *) ra) = mcode;
705 /* if we show disassembly, we have to skip the nop */
710 /* patch vftbl index */
712 *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
713 sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
715 /* synchronize instruction cache */
717 asm_cacheflush(ra, 2 * 4);
719 PATCHER_MARK_PATCHED_MONITOREXIT;
725 /* patcher_invokeinterface *****************************************************
729 <patched call position>
730 81830000 lwz r12,0(r3)
731 818cffd0 lwz r12,-48(r12)
732 81ac000c lwz r13,12(r12)
736 *******************************************************************************/
738 bool patcher_invokeinterface(u1 *sp)
741 java_objectheader *o;
743 unresolved_method *um;
746 /* get stuff from the stack */
748 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
749 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
750 mcode = *((u4 *) (sp + 1 * 4));
751 um = (unresolved_method *) *((ptrint *) (sp + 0 * 4));
753 /* calculate and set the new return address */
756 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
758 PATCHER_MONITORENTER;
760 /* get the fieldinfo */
762 if (!(m = helper_resolve_methodinfo(um))) {
768 /* patch back original code */
770 *((u4 *) ra) = mcode;
772 /* if we show disassembly, we have to skip the nop */
777 /* patch interfacetable index */
779 *((s4 *) (ra + 1 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
780 sizeof(methodptr*) * m->class->index) & 0x0000ffff);
782 /* patch method offset */
784 *((s4 *) (ra + 2 * 4)) |=
785 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
787 /* synchronize instruction cache */
789 asm_cacheflush(ra, 3 * 4);
791 PATCHER_MARK_PATCHED_MONITOREXIT;
797 /* patcher_checkcast_instanceof_flags ******************************************
801 <patched call position>
803 *******************************************************************************/
805 bool patcher_checkcast_instanceof_flags(u1 *sp)
808 java_objectheader *o;
810 constant_classref *cr;
815 /* get stuff from the stack */
817 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
818 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
819 mcode = *((u4 *) (sp + 1 * 4));
820 cr = (constant_classref *) *((ptrint *) (sp + 0 * 4));
821 pv = (u1 *) *((ptrint *) (sp - 2 * 4));
823 /* calculate and set the new return address */
826 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
828 PATCHER_MONITORENTER;
830 /* get the fieldinfo */
832 if (!(c = helper_resolve_classinfo(cr))) {
838 /* patch back original code */
840 *((u4 *) ra) = mcode;
842 /* synchronize instruction cache */
844 asm_cacheflush(ra, 4);
846 /* if we show disassembly, we have to skip the nop */
851 /* get the offset from machine instruction */
853 offset = (s2) (*((u4 *) ra) & 0x0000ffff);
855 /* patch class flags */
857 *((s4 *) (pv + offset)) = (s4) c->flags;
859 PATCHER_MARK_PATCHED_MONITOREXIT;
865 /* patcher_checkcast_instanceof_interface **************************************
869 <patched call position>
871 *******************************************************************************/
873 bool patcher_checkcast_instanceof_interface(u1 *sp)
876 java_objectheader *o;
878 constant_classref *cr;
881 /* get stuff from the stack */
883 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
884 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
885 mcode = *((u4 *) (sp + 1 * 4));
886 cr = (constant_classref *) *((ptrint *) (sp + 0 * 4));
888 /* calculate and set the new return address */
891 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
893 PATCHER_MONITORENTER;
895 /* get the fieldinfo */
897 if (!(c = helper_resolve_classinfo(cr))) {
903 /* patch back original code */
905 *((u4 *) ra) = mcode;
907 /* if we show disassembly, we have to skip the nop */
912 /* patch super class index */
914 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
916 *((s4 *) (ra + 4 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
917 c->index * sizeof(methodptr*)) & 0x0000ffff);
919 /* synchronize instruction cache */
921 asm_cacheflush(ra, 5 * 4);
923 PATCHER_MARK_PATCHED_MONITOREXIT;
929 /* patcher_checkcast_class *****************************************************
933 <patched call position>
935 *******************************************************************************/
937 bool patcher_checkcast_class(u1 *sp)
940 java_objectheader *o;
942 constant_classref *cr;
947 /* get stuff from the stack */
949 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
950 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
951 mcode = *((u4 *) (sp + 1 * 4));
952 cr = (constant_classref *) *((ptrint *) (sp + 0 * 4));
953 pv = (u1 *) *((ptrint *) (sp - 2 * 4));
955 /* calculate and set the new return address */
958 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
960 PATCHER_MONITORENTER;
962 /* get the fieldinfo */
964 if (!(c = helper_resolve_classinfo(cr))) {
970 /* patch back original code */
972 *((u4 *) ra) = mcode;
974 /* synchronize instruction cache */
976 asm_cacheflush(ra, 4);
978 /* if we show disassembly, we have to skip the nop */
983 /* get the offset from machine instruction */
985 offset = (s2) (*((u4 *) (ra + 2 * 4)) & 0x0000ffff);
987 /* patch super class' vftbl */
989 *((ptrint *) (pv + offset)) = (ptrint) c->vftbl;
991 PATCHER_MARK_PATCHED_MONITOREXIT;
997 /* patcher_instanceof_class ****************************************************
1001 <patched call position>
1003 *******************************************************************************/
1005 bool patcher_instanceof_class(u1 *sp)
1008 java_objectheader *o;
1010 constant_classref *cr;
1015 /* get stuff from the stack */
1017 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
1018 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
1019 mcode = *((u4 *) (sp + 1 * 4));
1020 cr = (constant_classref *) *((ptrint *) (sp + 0 * 4));
1021 pv = (u1 *) *((ptrint *) (sp - 2 * 4));
1023 /* calculate and set the new return address */
1026 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
1028 PATCHER_MONITORENTER;
1030 /* get the fieldinfo */
1032 if (!(c = helper_resolve_classinfo(cr))) {
1033 PATCHER_MONITOREXIT;
1038 /* patch back original code */
1040 *((u4 *) ra) = mcode;
1042 /* synchronize instruction cache */
1044 asm_cacheflush(ra, 4);
1046 /* if we show disassembly, we have to skip the nop */
1048 if (showdisassemble)
1051 /* get the offset from machine instruction */
1053 offset = (s2) (*((u4 *) (ra + 1 * 4)) & 0x0000ffff);
1055 /* patch super class' vftbl */
1057 *((ptrint *) (pv + offset)) = (ptrint) c->vftbl;
1059 PATCHER_MARK_PATCHED_MONITOREXIT;
1065 /* patcher_clinit **************************************************************
1069 *******************************************************************************/
1071 bool patcher_clinit(u1 *sp)
1074 java_objectheader *o;
1078 /* get stuff from the stack */
1080 ra = (u1 *) *((ptrint *) (sp + 3 * 4));
1081 o = (java_objectheader *) *((ptrint *) (sp + 2 * 4));
1082 mcode = *((u4 *) (sp + 1 * 4));
1083 c = (classinfo *) *((ptrint *) (sp + 0 * 4));
1085 /* calculate and set the new return address */
1088 *((ptrint *) (sp + 3 * 4)) = (ptrint) ra;
1090 PATCHER_MONITORENTER;
1092 /* check if the class is initialized */
1094 if (!c->initialized) {
1095 if (!initialize_class(c)) {
1096 PATCHER_MONITOREXIT;
1102 /* patch back original code */
1104 *((u4 *) ra) = mcode;
1106 /* synchronize instruction cache */
1108 asm_cacheflush(ra, 4);
1110 PATCHER_MARK_PATCHED_MONITOREXIT;
1117 * These are local overrides for various environment variables in Emacs.
1118 * Please do not remove this and leave it at the end of the file, where
1119 * Emacs will automagically detect them.
1120 * ---------------------------------------------------------------------
1123 * indent-tabs-mode: t
1127 * vim:noexpandtab:sw=4:ts=4: