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