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