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