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