* src/vm/jit/powerpc64/codegen.c (codegen):
[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 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    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28
29    Changes:
30
31    $Id: patcher.c 5880 2006-10-31 13:40:55Z tbfg $
32
33 */
34
35
36 #include "config.h"
37
38 #include <assert.h>
39
40 #include "vm/types.h"
41
42 #include "mm/memory.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
45 #include "vm/class.h"
46 #include "vm/exceptions.h"
47 #include "vm/field.h"
48 #include "vm/initialize.h"
49 #include "vm/options.h"
50 #include "vm/resolve.h"
51 #include "vm/references.h"
52 #include "vm/jit/asmpart.h"
53 #include "vm/jit/patcher.h"
54 #include "vm/jit/methodheader.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_showdisassemble)
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_showdisassemble)
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_showdisassemble)
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
621
622 /* patcher_checkcast_instanceof_interface **************************************
623
624    Machine code:
625
626    <patched call position>
627    81870000    lwz   r12,0(r7)
628    800c0010    lwz   r0,16(r12)
629    34000000    addic.        r0,r0,0
630    408101fc    ble-  0x3002e518
631    800c0000    lwz   r0,0(r12)
632
633 *******************************************************************************/
634
635 bool patcher_checkcast_instanceof_interface(u1 *sp)
636 {
637         u1                *ra;
638         u4                 mcode;
639         constant_classref *cr;
640         classinfo         *c;
641         s4                 disp;
642
643         /* get stuff from the stack */
644
645         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
646         mcode =                       *((u4 *)     (sp + 3 * 8));
647         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
648
649         /* get the fieldinfo */
650
651         if (!(c = resolve_classref_eager(cr)))
652                 return false;
653
654         /* patch back original code */
655
656         *((u4 *) ra) = mcode;
657
658         /* if we show disassembly, we have to skip the nop */
659
660         if (opt_showdisassemble)
661                 ra = ra + 4;
662
663         /* patch super class index */
664
665         disp = -(c->index);
666
667         *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
668
669         disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
670
671         *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
672
673         /* synchronize instruction cache */
674
675         md_icacheflush(ra, 5 * 4);
676
677         return true;
678 }
679
680
681 /* patcher_checkcast_class *****************************************************
682
683    Machine code:
684
685    <patched call position>
686    81870000    lwz   r12,0(r7)
687    800c0014    lwz   r0,20(r12)
688    818dff78    lwz   r12,-136(r13)
689
690 *******************************************************************************/
691
692 bool patcher_checkcast_class(u1 *sp)
693 {
694         u1                *ra;
695         u4                 mcode;
696         constant_classref *cr;
697         s4                 disp;
698         u1                *pv;
699         classinfo         *c;
700
701         /* get stuff from the stack */
702
703         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
704         mcode =                       *((u4 *)     (sp + 3 * 8));
705         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
706         disp  =                       *((s4 *)     (sp + 1 * 8));
707         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
708
709         /* get the fieldinfo */
710
711         if (!(c = resolve_classref_eager(cr)))
712                 return false;
713
714         /* patch back original code */
715
716         *((u4 *) ra) = mcode;
717
718         /* synchronize instruction cache */
719
720         md_icacheflush(ra, 4);
721
722         /* patch super class' vftbl */
723
724         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
725
726         /* synchronize data cache */
727
728         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
729
730         return true;
731 }
732
733
734 /* patcher_instanceof_class ****************************************************
735
736    Machine code:
737
738    <patched call position>
739    817d0000    lwz   r11,0(r29)
740    818dff8c    lwz   r12,-116(r13)
741
742 *******************************************************************************/
743
744 bool patcher_instanceof_class(u1 *sp)
745 {
746         u1                *ra;
747         u4                 mcode;
748         constant_classref *cr;
749         s4                 disp;
750         u1                *pv;
751         classinfo         *c;
752
753         /* get stuff from the stack */
754
755         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
756         mcode =                       *((u4 *)     (sp + 3 * 8));
757         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
758         disp  =                       *((s4 *)     (sp + 1 * 8));
759         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
760
761         /* get the fieldinfo */
762
763         if (!(c = resolve_classref_eager(cr)))
764                 return false;
765
766         /* patch back original code */
767
768         *((u4 *) ra) = mcode;
769
770         /* synchronize instruction cache */
771
772         md_icacheflush(ra, 4);
773
774         /* patch super class' vftbl */
775
776         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
777
778         /* synchronize data cache */
779
780         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
781
782         return true;
783 }
784
785
786 /* patcher_clinit **************************************************************
787
788    XXX
789
790 *******************************************************************************/
791
792 bool patcher_clinit(u1 *sp)
793 {
794         u1        *ra;
795         u4         mcode;
796         classinfo *c;
797
798         /* get stuff from the stack */
799
800         ra    = (u1 *)        *((ptrint *) (sp + 5 * 8));
801         mcode =               *((u4 *)     (sp + 3 * 8));
802         c     = (classinfo *) *((ptrint *) (sp + 2 * 8));
803
804         /* check if the class is initialized */
805
806         if (!(c->state & CLASS_INITIALIZED))
807                 if (!initialize_class(c))
808                         return false;
809
810         /* patch back original code */
811
812         *((u4 *) ra) = mcode;
813
814         /* synchronize instruction cache */
815
816         md_icacheflush(ra, 4);
817
818         return true;
819 }
820
821
822 /* patcher_athrow_areturn ******************************************************
823
824    Machine code:
825
826    <patched call position>
827
828 *******************************************************************************/
829
830 #ifdef ENABLE_VERIFIER
831 bool patcher_athrow_areturn(u1 *sp)
832 {
833         u1               *ra;
834         u4                mcode;
835         unresolved_class *uc;
836         classinfo        *c;
837
838         /* get stuff from the stack */
839
840         ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
841         mcode =                      *((u4 *)     (sp + 3 * 8));
842         uc    = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
843
844         /* resolve the class */
845
846         if (!resolve_class(uc, resolveEager, false, &c))
847                 return false;
848
849         /* patch back original code */
850
851         *((u4 *) ra) = mcode;
852
853         /* synchronize instruction cache */
854
855         md_icacheflush(ra, 4);
856
857         return true;
858 }
859 #endif /* ENABLE_VERIFIER */
860
861
862 /* patcher_resolve_native ******************************************************
863
864    XXX
865
866 *******************************************************************************/
867
868 #if !defined(WITH_STATIC_CLASSPATH)
869 bool patcher_resolve_native(u1 *sp)
870 {
871         u1          *ra;
872         u4           mcode;
873         methodinfo  *m;
874         s4           disp;
875         u1          *pv;
876         functionptr  f;
877
878         /* get stuff from the stack */
879
880         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
881         mcode =                       *((u4 *)     (sp + 3 * 8));
882         m     = (methodinfo *)        *((ptrint *) (sp + 2 * 8));
883         disp  =                       *((s4 *)     (sp + 1 * 8));
884         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
885
886         /* calculate and set the new return address */
887
888         ra = ra - 1 * 4;
889         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
890
891         /* resolve native function */
892
893         if (!(f = native_resolve_function(m)))
894                 return false;
895
896         /* patch back original code */
897
898         *((u4 *) ra) = mcode;
899
900         /* synchronize instruction cache */
901
902         md_icacheflush(ra, 4);
903
904         /* patch native function pointer */
905
906         *((ptrint *) (pv + disp)) = (ptrint) f;
907
908         /* synchronize data cache */
909
910         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
911
912         return true;
913 }
914 #endif /* !defined(WITH_STATIC_CLASSPATH) */
915
916
917 /*
918  * These are local overrides for various environment variables in Emacs.
919  * Please do not remove this and leave it at the end of the file, where
920  * Emacs will automagically detect them.
921  * ---------------------------------------------------------------------
922  * Local variables:
923  * mode: c
924  * indent-tabs-mode: t
925  * c-basic-offset: 4
926  * tab-width: 4
927  * End:
928  * vim:noexpandtab:sw=4:ts=4:
929  */