dce048b35ecb01f911b233ce35151a49a43bee92
[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 7909 2007-05-15 10:32:16Z 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, 6*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, *ra;
822         u4         mcode;
823         classinfo         *c;
824
825         /* get stuff from the stack */
826
827         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
828         mcode =                       *((u4 *)     (sp + 3 * 8));
829         cr   = (constant_classref *) *((ptrint *) (sp + 2 * 8));
830         disp =                       *((s4 *)     (sp + 1 * 8));
831         pv   = (u1 *)                *((ptrint *) (sp + 0 * 8));
832
833         /* get the classinfo */
834
835         if (!(c = resolve_classref_eager(cr)))
836                 return false;
837
838         /* patch back original code */
839
840         *((u4 *) ra) = mcode;
841
842         /* synchronize instruction cache */
843
844         md_icacheflush(ra, 4);
845
846         /* patch the classinfo pointer */
847
848         *((ptrint *) (pv + disp)) = (ptrint) c;
849
850         /* synchronize data cache */
851
852         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
853
854         return true;
855 }
856
857
858
859 /* patcher_instanceof_class ****************************************************
860
861    Machine code:
862
863    <patched call position>
864    817d0000    lwz   r11,0(r29)
865    818dff8c    lwz   r12,-116(r13)
866
867 *******************************************************************************/
868
869 bool patcher_instanceof_class(u1 *sp)
870 {
871         u1                *ra;
872         u4                 mcode;
873         constant_classref *cr;
874         s4                 disp;
875         u1                *pv;
876         classinfo         *c;
877
878         /* get stuff from the stack */
879
880         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
881         mcode =                       *((u4 *)     (sp + 3 * 8));
882         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
883         disp  =                       *((s4 *)     (sp + 1 * 8));
884         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
885
886         /* get the fieldinfo */
887
888         if (!(c = resolve_classref_eager(cr)))
889                 return false;
890
891         /* patch back original code */
892
893         *((u4 *) ra) = mcode;
894
895         /* synchronize instruction cache */
896
897         md_icacheflush(ra, 4);
898
899         /* patch super class' vftbl */
900
901         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
902
903         /* synchronize data cache */
904
905         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
906
907         return true;
908 }
909
910 /* patcher_resolve_classref_to_vftbl *******************************************
911
912    CHECKCAST (class):
913
914    <patched call position>
915    81870000    lwz   r12,0(r7)
916    800c0014    lwz   r0,20(r12)
917    818dff78    lwz   r12,-136(r13)
918
919
920    INSTANCEOF (class):
921
922    <patched call position>
923    817d0000    lwz   r11,0(r29)
924    818dff8c    lwz   r12,-116(r13)
925
926 *******************************************************************************/
927
928 bool patcher_resolve_classref_to_vftbl(u1 *sp)
929 {
930         constant_classref *cr;
931         s4                 disp;
932         u1                *pv, *ra;
933         u4         mcode;
934         classinfo         *c;
935
936         /* get stuff from the stack */
937
938         ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
939         mcode =                       *((u4 *)     (sp + 3 * 8));
940         cr   = (constant_classref *) *((ptrint *) (sp + 2 * 8));
941         disp =                       *((s4 *)     (sp + 1 * 8));
942         pv   = (u1 *)                *((ptrint *) (sp + 0 * 8));
943
944         /* get the fieldinfo */
945
946         if (!(c = resolve_classref_eager(cr)))
947                 return false;
948
949         /* patch back original code */
950
951         *((u4 *) ra) = mcode;
952
953         /* synchronize instruction cache */
954
955         md_icacheflush(ra, 4);
956
957         /* patch super class' vftbl */
958
959         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
960
961         /* synchronize data cache */
962
963         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
964
965         return true;
966 }
967
968 /* patcher_resolve_classref_to_flags *******************************************
969
970    CHECKCAST/INSTANCEOF:
971
972    <patched call position>
973    818dff7c    lwz   r12,-132(r13)
974
975 *******************************************************************************/
976
977 bool patcher_resolve_classref_to_flags(u1 *sp)
978 {
979         constant_classref *cr;
980         s4                 disp;
981         u1                *pv, *ra;
982         u4         mcode;
983         classinfo         *c;
984
985         /* get stuff from the stack */
986
987         ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
988         mcode =                       *((u4 *)     (sp + 3 * 8));
989         cr   = (constant_classref *) *((ptrint *) (sp + 2 * 8));
990         disp =                       *((s4 *)     (sp + 1 * 8));
991         pv   = (u1 *)                *((ptrint *) (sp + 0 * 8));
992
993         /* get the fieldinfo */
994
995         if (!(c = resolve_classref_eager(cr)))
996                 return false;
997
998         /* patch back original code */
999
1000         *((u4 *) ra) = mcode;
1001
1002         /* synchronize instruction cache */
1003
1004         md_icacheflush(ra, 4);
1005
1006         /* patch class flags */
1007
1008         *((s4 *) (pv + disp)) = (s4) c->flags;
1009
1010         /* synchronize data cache */
1011
1012         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
1013
1014         return true;
1015 }
1016
1017 /* patcher_clinit **************************************************************
1018
1019    XXX
1020
1021 *******************************************************************************/
1022
1023 bool patcher_clinit(u1 *sp)
1024 {
1025         u1        *ra;
1026         u4         mcode;
1027         classinfo *c;
1028
1029         /* get stuff from the stack */
1030
1031         ra    = (u1 *)        *((ptrint *) (sp + 5 * 8));
1032         mcode =               *((u4 *)     (sp + 3 * 8));
1033         c     = (classinfo *) *((ptrint *) (sp + 2 * 8));
1034
1035         /* check if the class is initialized */
1036
1037         if (!(c->state & CLASS_INITIALIZED))
1038                 if (!initialize_class(c))
1039                         return false;
1040
1041         /* patch back original code */
1042
1043         *((u4 *) ra) = mcode;
1044
1045         /* synchronize instruction cache */
1046
1047         md_icacheflush(ra, 4);
1048
1049         return true;
1050 }
1051
1052
1053 /* patcher_athrow_areturn ******************************************************
1054
1055    Machine code:
1056
1057    <patched call position>
1058
1059 *******************************************************************************/
1060
1061 #ifdef ENABLE_VERIFIER
1062 bool patcher_athrow_areturn(u1 *sp)
1063 {
1064         u1               *ra;
1065         u4                mcode;
1066         unresolved_class *uc;
1067
1068         /* get stuff from the stack */
1069
1070         ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
1071         mcode =                      *((u4 *)     (sp + 3 * 8));
1072         uc    = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
1073
1074         /* resolve the class and check subtype constraints */
1075
1076         if (!resolve_class_eager_no_access_check(uc))
1077                 return false;
1078
1079         /* patch back original code */
1080
1081         *((u4 *) ra) = mcode;
1082
1083         /* synchronize instruction cache */
1084
1085         md_icacheflush(ra, 4);
1086
1087         return true;
1088 }
1089 #endif /* ENABLE_VERIFIER */
1090
1091
1092 /* patcher_resolve_native ******************************************************
1093
1094    XXX
1095
1096 *******************************************************************************/
1097
1098 #if !defined(WITH_STATIC_CLASSPATH)
1099 bool patcher_resolve_native(u1 *sp)
1100 {
1101         u1          *ra;
1102         u4           mcode;
1103         methodinfo  *m;
1104         s4           disp;
1105         u1          *pv;
1106         functionptr  f;
1107
1108         /* get stuff from the stack */
1109
1110         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
1111         mcode =                       *((u4 *)     (sp + 3 * 8));
1112         m     = (methodinfo *)        *((ptrint *) (sp + 2 * 8));
1113         disp  =                       *((s4 *)     (sp + 1 * 8));
1114         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
1115
1116         /* resolve native function */
1117
1118         if (!(f = native_resolve_function(m)))
1119                 return false;
1120
1121         /* patch back original code */
1122
1123         *((u4 *) ra) = mcode;
1124
1125         /* synchronize instruction cache */
1126
1127         md_icacheflush(ra, 4);
1128
1129         /* patch native function pointer */
1130
1131         *((ptrint *) (pv + disp)) = (ptrint) f;
1132
1133         /* synchronize data cache */
1134
1135         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
1136
1137         return true;
1138 }
1139 #endif /* !defined(WITH_STATIC_CLASSPATH) */
1140
1141
1142 /*
1143  * These are local overrides for various environment variables in Emacs.
1144  * Please do not remove this and leave it at the end of the file, where
1145  * Emacs will automagically detect them.
1146  * ---------------------------------------------------------------------
1147  * Local variables:
1148  * mode: c
1149  * indent-tabs-mode: t
1150  * c-basic-offset: 4
1151  * tab-width: 4
1152  * End:
1153  * vim:noexpandtab:sw=4:ts=4:
1154  */