replace helper_* calls in the pathers with calls to resolve_*_eager
[cacao.git] / src / vm / jit / powerpc / patcher.c
1 /* src/vm/jit/powerpc/patcher.c - PowerPC code patching functions
2
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
7
8    This file is part of CACAO.
9
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.
14
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.
19
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
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Thalinger
28
29    Changes:
30
31    $Id: patcher.c 3461 2005-10-20 09:53:00Z edwin $
32
33 */
34
35
36 #include "config.h"
37 #include "vm/types.h"
38
39 #include "mm/memory.h"
40 #include "native/native.h"
41 #include "vm/builtin.h"
42 #include "vm/field.h"
43 #include "vm/initialize.h"
44 #include "vm/options.h"
45 #include "vm/references.h"
46 #include "vm/jit/asmpart.h"
47 #include "vm/jit/helper.h"
48 #include "vm/jit/patcher.h"
49
50
51 /* patcher_get_putstatic *******************************************************
52
53    Machine code:
54
55    <patched call position>
56    816dffc8    lwz   r11,-56(r13)
57    80ab0000    lwz   r5,0(r11)
58
59 *******************************************************************************/
60
61 bool patcher_get_putstatic(u1 *sp)
62 {
63         u1                *ra;
64         java_objectheader *o;
65         u4                 mcode;
66         unresolved_field  *uf;
67         s4                 disp;
68         u1                *pv;
69         fieldinfo         *fi;
70
71         /* get stuff from the stack */
72
73         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
74         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
75         mcode =                       *((u4 *)     (sp + 3 * 4));
76         uf    = (unresolved_field *)  *((ptrint *) (sp + 2 * 4));
77         disp  =                       *((s4 *)     (sp + 1 * 4));
78         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
79
80         /* calculate and set the new return address */
81
82         ra = ra - 4;
83         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
84
85         PATCHER_MONITORENTER;
86
87         /* get the fieldinfo */
88
89         if (!(fi = resolve_field_eager(uf))) {
90                 PATCHER_MONITOREXIT;
91
92                 return false;
93         }
94
95         /* check if the field's class is initialized */
96
97         if (!fi->class->initialized) {
98                 if (!initialize_class(fi->class)) {
99                         PATCHER_MONITOREXIT;
100
101                         return false;
102                 }
103         }
104
105         /* patch back original code */
106
107         *((u4 *) ra) = mcode;
108
109         /* synchronize instruction cache */
110
111         asm_cacheflush(ra, 4);
112
113         /* patch the field value's address */
114
115         *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
116
117         PATCHER_MARK_PATCHED_MONITOREXIT;
118
119         return true;
120 }
121
122
123 /* patcher_get_putfield ********************************************************
124
125    Machine code:
126
127    <patched call position>
128    811f0014    lwz   r8,20(r31)
129
130 *******************************************************************************/
131
132 bool patcher_get_putfield(u1 *sp)
133 {
134         u1                *ra;
135         java_objectheader *o;
136         u4                 mcode;
137         unresolved_field  *uf;
138         u1                *pv;
139         fieldinfo         *fi;
140
141         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
142         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
143         mcode =                       *((u4 *)     (sp + 3 * 4));
144         uf    = (unresolved_field *)  *((ptrint *) (sp + 2 * 4));
145         pv    = (u1 *)                *((ptrint *) (sp + 1 * 4));
146
147         /* calculate and set the new return address */
148
149         ra = ra - 4;
150         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
151
152         PATCHER_MONITORENTER;
153
154         /* get the fieldinfo */
155
156         if (!(fi = resolve_field_eager(uf))) {
157                 PATCHER_MONITOREXIT;
158
159                 return false;
160         }
161
162         /* patch back original code */
163
164         *((u4 *) ra) = mcode;
165
166         /* if we show disassembly, we have to skip the nop */
167
168         if (opt_showdisassemble)
169                 ra = ra + 4;
170
171         /* patch the field's offset */
172
173         if (fi->type == TYPE_LNG) {
174                 /* if the field has type long, we have to patch two instructions */
175
176                 *((u4 *) ra) |= (s2) ((fi->offset + 4) & 0x0000ffff);
177                 *((u4 *) (ra + 4)) |= (s2) (fi->offset & 0x0000ffff);
178
179         } else {
180                 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
181         }
182
183         /* synchronize instruction cache */
184
185         asm_cacheflush(ra, 8);
186
187         PATCHER_MARK_PATCHED_MONITOREXIT;
188
189         return true;
190 }
191
192
193 /* patcher_builtin_new *********************************************************
194
195    Machine code:
196
197    806dffc4    lwz   r3,-60(r13)
198    <patched call postition>
199    81adffc0    lwz   r13,-64(r13)
200    7da903a6    mtctr r13
201    4e800421    bctrl
202
203    NOTICE: Only the displacement for the function address is passed,
204    but the address of the classinfo pointer is one below (above, in
205    addresses speaking). This is for sure.
206
207 *******************************************************************************/
208
209 bool patcher_builtin_new(u1 *sp)
210 {
211         u1                *ra;
212         java_objectheader *o;
213         u4                 mcode;
214         constant_classref *cr;
215         s4                 disp;
216         u1                *pv;
217         classinfo         *c;
218
219         /* get stuff from the stack */
220
221         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
222         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
223         mcode =                       *((u4 *)     (sp + 3 * 4));
224         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
225         disp  =                       *((s4 *)     (sp + 1 * 4));
226         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
227
228         /* calculate and set the new return address */
229
230         ra = ra - (2 * 4);
231         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
232
233         PATCHER_MONITORENTER;
234
235         /* get the classinfo */
236
237         if (!(c = resolve_classref_eager_nonabstract(cr))) {
238                 PATCHER_MONITOREXIT;
239
240                 return false;
241         }
242
243         /* patch back original code */
244
245         *((u4 *) (ra + 4)) = mcode;
246
247         /* synchronize instruction cache */
248
249         asm_cacheflush(ra + 4, 4);
250
251         /* patch the classinfo pointer */
252
253         *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c;
254
255         /* patch new function address */
256
257         *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_new;
258
259         PATCHER_MARK_PATCHED_MONITOREXIT;
260
261         return true;
262 }
263
264
265 /* patcher_builtin_newarray ****************************************************
266
267    Machine code:
268
269    808dffc8    lwz   r4,-56(r13)
270    <patched call position>
271    81adffc4    lwz   r13,-60(r13)
272    7da903a6    mtctr r13
273    4e800421    bctrl
274
275    NOTICE: Only the displacement for the function address is passed,
276    but the address of the vftbl pointer is one below (above, in
277    addresses speaking). This is for sure.
278
279 *******************************************************************************/
280
281 bool patcher_builtin_newarray(u1 *sp)
282 {
283         u1                *ra;
284         java_objectheader *o;
285         u4                 mcode;
286         constant_classref *cr;
287         u1                *pv;
288         s4                 disp;
289         classinfo         *c;
290
291         /* get stuff from the stack */
292
293         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
294         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
295         mcode =                       *((u4 *)     (sp + 3 * 4));
296         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
297         disp  =                       *((s4 *)     (sp + 1 * 4));
298         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
299
300         /* calculate and set the new return address */
301
302         ra = ra - 2 * 4;
303         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
304
305         PATCHER_MONITORENTER;
306
307         /* get the classinfo */
308
309         if (!(c = resolve_classref_eager(cr))) {
310                 PATCHER_MONITOREXIT;
311
312                 return false;
313         }
314
315         /* patch back original code */
316
317         *((u4 *) (ra + 4)) = mcode;
318
319         /* synchronize instruction cache */
320
321         asm_cacheflush(ra + 4, 4);
322
323         /* patch the class' vftbl pointer */
324
325         *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c->vftbl;
326
327         /* patch new function address */
328
329         *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_newarray;
330
331         PATCHER_MARK_PATCHED_MONITOREXIT;
332
333         return true;
334 }
335
336
337 /* patcher_builtin_multianewarray **********************************************
338
339    Machine code:
340
341    <patched call position>
342    808dffc0    lwz   r4,-64(r13)
343    38a10038    addi  r5,r1,56
344    81adffbc    lwz   r13,-68(r13)
345    7da903a6    mtctr r13
346    4e800421    bctrl
347
348 *******************************************************************************/
349
350 bool patcher_builtin_multianewarray(u1 *sp)
351 {
352         u1                *ra;
353         java_objectheader *o;
354         u4                 mcode;
355         constant_classref *cr;
356         s4                 disp;
357         u1                *pv;
358         classinfo         *c;
359
360         /* get stuff from the stack */
361
362         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
363         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
364         mcode =                       *((u4 *)     (sp + 3 * 4));
365         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
366         disp  =                       *((s4 *)     (sp + 1 * 4));
367         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
368
369         /* calculate and set the new return address */
370
371         ra = ra - 4;
372         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
373
374         PATCHER_MONITORENTER;
375
376         /* get the classinfo */
377
378         if (!(c = resolve_classref_eager(cr))) {
379                 PATCHER_MONITOREXIT;
380
381                 return false;
382         }
383
384         /* patch back original code */
385
386         *((u4 *) ra) = mcode;
387
388         /* synchronize instruction cache */
389
390         asm_cacheflush(ra, 4);
391
392         /* patch the class' vftbl pointer */
393
394         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
395
396         PATCHER_MARK_PATCHED_MONITOREXIT;
397
398         return true;
399 }
400
401
402 /* patcher_builtin_arraycheckcast **********************************************
403
404    Machine code:
405
406    <patched call position>
407    808dffd8    lwz   r4,-40(r13)
408    81adffd4    lwz   r13,-44(r13)
409    7da903a6    mtctr r13
410    4e800421    bctrl
411
412    NOTICE: Only the displacement of the vftbl pointer address is
413    passed, but the address of the function pointer is one above
414    (below, in addresses speaking). This is for sure.
415
416 *******************************************************************************/
417
418 bool patcher_builtin_arraycheckcast(u1 *sp)
419 {
420         u1                *ra;
421         java_objectheader *o;
422         u4                 mcode;
423         constant_classref *cr;
424         s4                 disp;
425         u1                *pv;
426         classinfo         *c;
427
428         /* get stuff from the stack */
429
430         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
431         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
432         mcode =                       *((u4 *)     (sp + 3 * 4));
433         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
434         disp  =                       *((s4 *)     (sp + 1 * 4));
435         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
436
437         /* calculate and set the new return address */
438
439         ra = ra - 1 * 4;
440         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
441
442         PATCHER_MONITORENTER;
443
444         /* get the classinfo */
445
446         if (!(c = resolve_classref_eager(cr))) {
447                 PATCHER_MONITOREXIT;
448
449                 return false;
450         }
451
452         /* patch back original code */
453
454         *((u4 *) ra) = mcode;
455
456         /* synchronize instruction cache */
457
458         asm_cacheflush(ra, 4);
459
460         /* patch the class' vftbl pointer */
461
462         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
463
464         /* patch new function address */
465
466         *((ptrint *) (pv + (disp - SIZEOF_VOID_P))) =
467                 (ptrint) BUILTIN_arraycheckcast;
468
469         PATCHER_MARK_PATCHED_MONITOREXIT;
470
471         return true;
472 }
473
474
475 /* patcher_builtin_arrayinstanceof *********************************************
476
477    Machine code:
478
479    808dff50    lwz   r4,-176(r13)
480    <patched call position>
481    81adff4c    lwz   r13,-180(r13)
482    7da903a6    mtctr r13
483    4e800421    bctrl
484
485    NOTICE: Only the displacement for the function address is passed,
486    but the address of the vftbl pointer is one below (above, in
487    addresses speaking). This is for sure.
488
489 *******************************************************************************/
490
491 bool patcher_builtin_arrayinstanceof(u1 *sp)
492 {
493         u1                *ra;
494         java_objectheader *o;
495         u4                 mcode;
496         constant_classref *cr;
497         s4                 disp;
498         u1                *pv;
499         classinfo         *c;
500
501         /* get stuff from the stack */
502
503         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
504         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
505         mcode =                       *((u4 *)     (sp + 3 * 4));
506         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
507         disp  =                       *((s4 *)     (sp + 1 * 4));
508         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
509
510         /* calculate and set the new return address */
511
512         ra = ra - 2 * 4;
513         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
514
515         PATCHER_MONITORENTER;
516
517         /* get the classinfo */
518
519         if (!(c = resolve_classref_eager(cr))) {
520                 PATCHER_MONITOREXIT;
521
522                 return false;
523         }
524
525         /* patch back original code */
526
527         *((u4 *) (ra + 4)) = mcode;
528
529         /* synchronize instruction cache */
530
531         asm_cacheflush(ra + 4, 4);
532
533         /* patch the class' vftbl pointer */
534         
535         *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c->vftbl;
536
537         /* patch new function address */
538
539         *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_arrayinstanceof;
540
541         PATCHER_MARK_PATCHED_MONITOREXIT;
542
543         return true;
544 }
545
546
547 /* patcher_invokestatic_special ************************************************
548
549    Machine code:
550
551    <patched call position>
552    81adffd8    lwz   r13,-40(r13)
553    7da903a6    mtctr r13
554    4e800421    bctrl
555
556 ******************************************************************************/
557
558 bool patcher_invokestatic_special(u1 *sp)
559 {
560         u1                *ra;
561         java_objectheader *o;
562         u4                 mcode;
563         unresolved_method *um;
564         s4                 disp;
565         u1                *pv;
566         methodinfo        *m;
567
568         /* get stuff from the stack */
569
570         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
571         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
572         mcode =                       *((u4 *)     (sp + 3 * 4));
573         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
574         disp  =                       *((s4 *)     (sp + 1 * 4));
575         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
576
577         /* calculate and set the new return address */
578
579         ra = ra - 4;
580         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
581
582         PATCHER_MONITORENTER;
583
584         /* get the fieldinfo */
585
586         if (!(m = resolve_method_eager(um))) {
587                 PATCHER_MONITOREXIT;
588
589                 return false;
590         }
591
592         /* patch back original code */
593
594         *((u4 *) ra) = mcode;
595
596         /* synchronize instruction cache */
597
598         asm_cacheflush(ra, 4);
599
600         /* patch stubroutine */
601
602         *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
603
604         PATCHER_MARK_PATCHED_MONITOREXIT;
605
606         return true;
607 }
608
609
610 /* patcher_invokevirtual *******************************************************
611
612    Machine code:
613
614    <patched call position>
615    81830000    lwz   r12,0(r3)
616    81ac0088    lwz   r13,136(r12)
617    7da903a6    mtctr r13
618    4e800421    bctrl
619
620 *******************************************************************************/
621
622 bool patcher_invokevirtual(u1 *sp)
623 {
624         u1                *ra;
625         java_objectheader *o;
626         u4                 mcode;
627         unresolved_method *um;
628         methodinfo        *m;
629
630         /* get stuff from the stack */
631
632         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
633         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
634         mcode =                       *((u4 *)     (sp + 3 * 4));
635         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
636
637         /* calculate and set the new return address */
638
639         ra = ra - 4;
640         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
641
642         PATCHER_MONITORENTER;
643
644         /* get the fieldinfo */
645
646         if (!(m = resolve_method_eager(um))) {
647                 PATCHER_MONITOREXIT;
648
649                 return false;
650         }
651
652         /* patch back original code */
653
654         *((u4 *) ra) = mcode;
655
656         /* if we show disassembly, we have to skip the nop */
657
658         if (opt_showdisassemble)
659                 ra = ra + 4;
660
661         /* patch vftbl index */
662
663         *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
664                                                                  sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
665
666         /* synchronize instruction cache */
667
668         asm_cacheflush(ra, 2 * 4);
669
670         PATCHER_MARK_PATCHED_MONITOREXIT;
671
672         return true;
673 }
674
675
676 /* patcher_invokeinterface *****************************************************
677
678    Machine code:
679
680    <patched call position>
681    81830000    lwz   r12,0(r3)
682    818cffd0    lwz   r12,-48(r12)
683    81ac000c    lwz   r13,12(r12)
684    7da903a6    mtctr r13
685    4e800421    bctrl
686
687 *******************************************************************************/
688
689 bool patcher_invokeinterface(u1 *sp)
690 {
691         u1                *ra;
692         java_objectheader *o;
693         u4                 mcode;
694         unresolved_method *um;
695         methodinfo        *m;
696
697         /* get stuff from the stack */
698
699         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
700         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
701         mcode =                       *((u4 *)     (sp + 3 * 4));
702         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
703
704         /* calculate and set the new return address */
705
706         ra = ra - 4;
707         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
708
709         PATCHER_MONITORENTER;
710
711         /* get the fieldinfo */
712
713         if (!(m = resolve_method_eager(um))) {
714                 PATCHER_MONITOREXIT;
715
716                 return false;
717         }
718
719         /* patch back original code */
720
721         *((u4 *) ra) = mcode;
722
723         /* if we show disassembly, we have to skip the nop */
724
725         if (opt_showdisassemble)
726                 ra = ra + 4;
727
728         /* patch interfacetable index */
729
730         *((s4 *) (ra + 1 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
731                                                                  sizeof(methodptr*) * m->class->index) & 0x0000ffff);
732
733         /* patch method offset */
734
735         *((s4 *) (ra + 2 * 4)) |=
736                 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
737
738         /* synchronize instruction cache */
739
740         asm_cacheflush(ra, 3 * 4);
741
742         PATCHER_MARK_PATCHED_MONITOREXIT;
743
744         return true;
745 }
746
747
748 /* patcher_checkcast_instanceof_flags ******************************************
749
750    Machine code:
751
752    <patched call position>
753    818dff7c    lwz   r12,-132(r13)
754
755 *******************************************************************************/
756
757 bool patcher_checkcast_instanceof_flags(u1 *sp)
758 {
759         u1                *ra;
760         java_objectheader *o;
761         u4                 mcode;
762         constant_classref *cr;
763         s4                 disp;
764         u1                *pv;
765         classinfo         *c;
766
767         /* get stuff from the stack */
768
769         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
770         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
771         mcode =                       *((u4 *)     (sp + 3 * 4));
772         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
773         disp  =                       *((s4 *)     (sp + 1 * 4));
774         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
775
776         /* calculate and set the new return address */
777
778         ra = ra - 4;
779         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
780
781         PATCHER_MONITORENTER;
782
783         /* get the fieldinfo */
784
785         if (!(c = resolve_classref_eager(cr))) {
786                 PATCHER_MONITOREXIT;
787
788                 return false;
789         }
790
791         /* patch back original code */
792
793         *((u4 *) ra) = mcode;
794
795         /* synchronize instruction cache */
796
797         asm_cacheflush(ra, 4);
798
799         /* patch class flags */
800
801         *((s4 *) (pv + disp)) = (s4) c->flags;
802
803         PATCHER_MARK_PATCHED_MONITOREXIT;
804
805         return true;
806 }
807
808
809 /* patcher_checkcast_instanceof_interface **************************************
810
811    Machine code:
812
813    <patched call position>
814    81870000    lwz   r12,0(r7)
815    800c0010    lwz   r0,16(r12)
816    34000000    addic.        r0,r0,0
817    408101fc    ble-  0x3002e518
818    800c0000    lwz   r0,0(r12)
819
820 *******************************************************************************/
821
822 bool patcher_checkcast_instanceof_interface(u1 *sp)
823 {
824         u1                *ra;
825         java_objectheader *o;
826         u4                 mcode;
827         constant_classref *cr;
828         classinfo         *c;
829
830         /* get stuff from the stack */
831
832         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
833         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
834         mcode =                       *((u4 *)     (sp + 3 * 4));
835         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
836
837         /* calculate and set the new return address */
838
839         ra = ra - 4;
840         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
841
842         PATCHER_MONITORENTER;
843
844         /* get the fieldinfo */
845
846         if (!(c = resolve_classref_eager(cr))) {
847                 PATCHER_MONITOREXIT;
848
849                 return false;
850         }
851
852         /* patch back original code */
853
854         *((u4 *) ra) = mcode;
855
856         /* if we show disassembly, we have to skip the nop */
857
858         if (opt_showdisassemble)
859                 ra = ra + 4;
860
861         /* patch super class index */
862
863         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
864
865         *((s4 *) (ra + 4 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
866                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
867
868         /* synchronize instruction cache */
869
870         asm_cacheflush(ra, 5 * 4);
871
872         PATCHER_MARK_PATCHED_MONITOREXIT;
873
874         return true;
875 }
876
877
878 /* patcher_checkcast_class *****************************************************
879
880    Machine code:
881
882    <patched call position>
883    81870000    lwz   r12,0(r7)
884    800c0014    lwz   r0,20(r12)
885    818dff78    lwz   r12,-136(r13)
886
887 *******************************************************************************/
888
889 bool patcher_checkcast_class(u1 *sp)
890 {
891         u1                *ra;
892         java_objectheader *o;
893         u4                 mcode;
894         constant_classref *cr;
895         s4                 disp;
896         u1                *pv;
897         classinfo         *c;
898
899         /* get stuff from the stack */
900
901         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
902         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
903         mcode =                       *((u4 *)     (sp + 3 * 4));
904         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
905         disp  =                       *((s4 *)     (sp + 1 * 4));
906         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
907
908         /* calculate and set the new return address */
909
910         ra = ra - 4;
911         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
912
913         PATCHER_MONITORENTER;
914
915         /* get the fieldinfo */
916
917         if (!(c = resolve_classref_eager(cr))) {
918                 PATCHER_MONITOREXIT;
919
920                 return false;
921         }
922
923         /* patch back original code */
924
925         *((u4 *) ra) = mcode;
926
927         /* synchronize instruction cache */
928
929         asm_cacheflush(ra, 4);
930
931         /* patch super class' vftbl */
932
933         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
934
935         PATCHER_MARK_PATCHED_MONITOREXIT;
936
937         return true;
938 }
939
940
941 /* patcher_instanceof_class ****************************************************
942
943    Machine code:
944
945    <patched call position>
946    817d0000    lwz   r11,0(r29)
947    818dff8c    lwz   r12,-116(r13)
948
949 *******************************************************************************/
950
951 bool patcher_instanceof_class(u1 *sp)
952 {
953         u1                *ra;
954         java_objectheader *o;
955         u4                 mcode;
956         constant_classref *cr;
957         s4                 disp;
958         u1                *pv;
959         classinfo         *c;
960
961         /* get stuff from the stack */
962
963         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
964         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
965         mcode =                       *((u4 *)     (sp + 3 * 4));
966         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
967         disp  =                       *((s4 *)     (sp + 1 * 4));
968         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
969
970         /* calculate and set the new return address */
971
972         ra = ra - 4;
973         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
974
975         PATCHER_MONITORENTER;
976
977         /* get the fieldinfo */
978
979         if (!(c = resolve_classref_eager(cr))) {
980                 PATCHER_MONITOREXIT;
981
982                 return false;
983         }
984
985         /* patch back original code */
986
987         *((u4 *) ra) = mcode;
988
989         /* synchronize instruction cache */
990
991         asm_cacheflush(ra, 4);
992
993         /* patch super class' vftbl */
994
995         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
996
997         PATCHER_MARK_PATCHED_MONITOREXIT;
998
999         return true;
1000 }
1001
1002
1003 /* patcher_clinit **************************************************************
1004
1005    XXX
1006
1007 *******************************************************************************/
1008
1009 bool patcher_clinit(u1 *sp)
1010 {
1011         u1                *ra;
1012         java_objectheader *o;
1013         u4                 mcode;
1014         classinfo         *c;
1015
1016         /* get stuff from the stack */
1017
1018         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
1019         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
1020         mcode =                       *((u4 *)     (sp + 3 * 4));
1021         c     = (classinfo *)         *((ptrint *) (sp + 2 * 4));
1022
1023         /* calculate and set the new return address */
1024
1025         ra = ra - 4;
1026         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
1027
1028         PATCHER_MONITORENTER;
1029
1030         /* check if the class is initialized */
1031
1032         if (!c->initialized) {
1033                 if (!initialize_class(c)) {
1034                         PATCHER_MONITOREXIT;
1035
1036                         return false;
1037                 }
1038         }
1039
1040         /* patch back original code */
1041
1042         *((u4 *) ra) = mcode;
1043
1044         /* synchronize instruction cache */
1045
1046         asm_cacheflush(ra, 4);
1047
1048         PATCHER_MARK_PATCHED_MONITOREXIT;
1049
1050         return true;
1051 }
1052
1053
1054 /* patcher_resolve_native ******************************************************
1055
1056    XXX
1057
1058 *******************************************************************************/
1059
1060 #if !defined(ENABLE_STATICVM)
1061 bool patcher_resolve_native(u1 *sp)
1062 {
1063         u1                *ra;
1064         java_objectheader *o;
1065         u4                 mcode;
1066         methodinfo        *m;
1067         s4                 disp;
1068         u1                *pv;
1069         functionptr        f;
1070
1071         /* get stuff from the stack */
1072
1073         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
1074         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
1075         mcode =                       *((u4 *)     (sp + 3 * 4));
1076         m     = (methodinfo *)        *((ptrint *) (sp + 2 * 4));
1077         disp  =                       *((s4 *)     (sp + 1 * 4));
1078         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
1079
1080         /* calculate and set the new return address */
1081
1082         ra = ra - 4;
1083         *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
1084
1085         PATCHER_MONITORENTER;
1086
1087         /* resolve native function */
1088
1089         if (!(f = native_resolve_function(m))) {
1090                 PATCHER_MONITOREXIT;
1091
1092                 return false;
1093         }
1094
1095         /* patch back original code */
1096
1097         *((u4 *) ra) = mcode;
1098
1099         /* synchronize instruction cache */
1100
1101         asm_cacheflush(ra, 4);
1102
1103         /* patch native function pointer */
1104
1105         *((ptrint *) (pv + disp)) = (ptrint) f;
1106
1107         PATCHER_MARK_PATCHED_MONITOREXIT;
1108
1109         return true;
1110 }
1111 #endif /* !defined(ENABLE_STATICVM) */
1112
1113
1114 /*
1115  * These are local overrides for various environment variables in Emacs.
1116  * Please do not remove this and leave it at the end of the file, where
1117  * Emacs will automagically detect them.
1118  * ---------------------------------------------------------------------
1119  * Local variables:
1120  * mode: c
1121  * indent-tabs-mode: t
1122  * c-basic-offset: 4
1123  * tab-width: 4
1124  * End:
1125  * vim:noexpandtab:sw=4:ts=4:
1126  */