* types.h: Include path fixes.
[cacao.git] / src / vm / jit / mips / patcher.c
1 /* src/vm/jit/mips/patcher.c - MIPS code patching functions
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Thalinger
28
29    Changes:
30
31    $Id: patcher.c 3323 2005-10-04 18:33:30Z twisti $
32
33 */
34
35
36 #include <sys/cachectl.h>
37
38 #include "config.h"
39 #include "vm/types.h"
40
41 #include "mm/memory.h"
42 #include "native/native.h"
43 #include "vm/builtin.h"
44 #include "vm/field.h"
45 #include "vm/initialize.h"
46 #include "vm/options.h"
47 #include "vm/references.h"
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/helper.h"
50 #include "vm/jit/patcher.h"
51
52
53 /* patcher_get_putstatic *******************************************************
54
55    Machine code:
56
57    <patched call position>
58    dfc1ffb8    ld       at,-72(s8)
59    fc250000    sd       a1,0(at)
60
61 *******************************************************************************/
62
63 bool patcher_get_putstatic(u1 *sp)
64 {
65         u1                *ra;
66         java_objectheader *o;
67 #if SIZEOF_VOID_P == 8
68         u8                 mcode;
69 #else
70         u4                 mcode[2];
71 #endif
72         unresolved_field  *uf;
73         s4                 disp;
74         u1                *pv;
75         fieldinfo         *fi;
76
77         /* get stuff from the stack */
78
79         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
80         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
81 #if SIZEOF_VOID_P == 8
82         mcode    =                       *((u8 *)     (sp + 3 * 8));
83 #else
84         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
85         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
86 #endif
87         uf       = (unresolved_field *)  *((ptrint *) (sp + 2 * 8));
88         disp     =                       *((s4 *)     (sp + 1 * 8));
89         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
90
91         /* calculate and set the new return address */
92
93         ra = ra - 2 * 4;
94         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
95
96         PATCHER_MONITORENTER;
97
98         /* get the fieldinfo */
99
100         if (!(fi = helper_resolve_fieldinfo(uf))) {
101                 PATCHER_MONITOREXIT;
102
103                 return false;
104         }
105
106         /* check if the field's class is initialized */
107
108         if (!fi->class->initialized) {
109                 if (!initialize_class(fi->class)) {
110                         PATCHER_MONITOREXIT;
111
112                         return false;
113                 }
114         }
115
116         /* patch back original code */
117
118 #if SIZEOF_VOID_P == 8
119         *((u4 *) (ra + 0 * 4)) = mcode;
120         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
121 #else
122         *((u4 *) (ra + 0 * 4)) = mcode[0];
123         *((u4 *) (ra + 1 * 4)) = mcode[1];
124 #endif
125
126         /* synchronize instruction cache */
127
128         cacheflush(ra, 2 * 4, ICACHE);
129
130         /* patch the field value's address */
131
132         *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
133
134         /* synchronize data cache */
135
136         cacheflush(pv + disp, SIZEOF_VOID_P, DCACHE);
137
138         PATCHER_MARK_PATCHED_MONITOREXIT;
139
140         return true;
141 }
142
143
144 /* patcher_get_putfield ********************************************************
145
146    Machine code:
147
148    <patched call position>
149    8ee90020    lw       a5,32(s7)
150
151 *******************************************************************************/
152
153 bool patcher_get_putfield(u1 *sp)
154 {
155         u1                *ra;
156         java_objectheader *o;
157 #if SIZEOF_VOID_P == 8
158         u8                 mcode;
159 #else
160         u4                 mcode[2];
161 #endif
162         unresolved_field  *uf;
163         fieldinfo         *fi;
164
165         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
166         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
167 #if SIZEOF_VOID_P == 8
168         mcode    =                       *((u8 *)     (sp + 3 * 8));
169 #else
170         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
171         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
172 #endif
173         uf       = (unresolved_field *)  *((ptrint *) (sp + 2 * 8));
174
175         /* calculate and set the new return address */
176
177         ra = ra - 2 * 4;
178         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
179
180         PATCHER_MONITORENTER;
181
182         /* get the fieldinfo */
183
184         if (!(fi = helper_resolve_fieldinfo(uf))) {
185                 PATCHER_MONITOREXIT;
186
187                 return false;
188         }
189
190         /* patch back original code */
191
192 #if SIZEOF_VOID_P == 8
193         *((u4 *) (ra + 0 * 4)) = mcode;
194         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
195 #else
196         *((u4 *) (ra + 0 * 4)) = mcode[0];
197         *((u4 *) (ra + 1 * 4)) = mcode[1];
198 #endif
199
200         /* if we show disassembly, we have to skip the nop's */
201
202         if (opt_showdisassemble)
203                 ra = ra + 2 * 4;
204
205         /* patch the field's offset */
206
207         *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
208
209         /* synchronize instruction cache */
210
211         if (opt_showdisassemble)
212                 cacheflush(ra - 2 * 4, 3 * 4, ICACHE);
213         else
214                 cacheflush(ra, 2 * 4, ICACHE);
215
216         PATCHER_MARK_PATCHED_MONITOREXIT;
217
218         return true;
219 }
220
221
222 /* patcher_builtin_new *********************************************************
223
224    Machine code:
225
226    dfc4ff98    ld       a0,-104(s8)
227    <patched call postition>
228    dfd9ff90    ld       t9,-112(s8)
229    0320f809    jalr     t9
230    00000000    nop
231
232    NOTICE: Only the displacement for the function address is passed,
233    but the address of the classinfo pointer is one below (above, in
234    addresses speaking). This is for sure.
235
236 *******************************************************************************/
237
238 bool patcher_builtin_new(u1 *sp)
239 {
240         u1                *ra;
241         java_objectheader *o;
242 #if SIZEOF_VOID_P == 8
243         u8                 mcode;
244 #else
245         u4                 mcode[2];
246 #endif
247         constant_classref *cr;
248         s4                 disp;
249         u1                *pv;
250         classinfo         *c;
251
252         /* get stuff from the stack */
253
254         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
255         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
256 #if SIZEOF_VOID_P == 8
257         mcode    =                       *((u8 *)     (sp + 3 * 8));
258 #else
259         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
260         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
261 #endif
262         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
263         disp     =                       *((s4 *)     (sp + 1 * 8));
264         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
265
266         /* calculate and set the new return address */
267
268         ra = ra - (3 * 4);
269         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
270
271         PATCHER_MONITORENTER;
272
273         /* get the classinfo */
274
275         if (!(c = helper_resolve_classinfo(cr))) {
276                 PATCHER_MONITOREXIT;
277
278                 return false;
279         }
280
281         /* patch back original code */
282
283 #if SIZEOF_VOID_P == 8
284         *((u4 *) (ra + 1 * 4)) = mcode;
285         *((u4 *) (ra + 2 * 4)) = mcode >> 32;
286 #else
287         *((u4 *) (ra + 1 * 4)) = mcode[0];
288         *((u4 *) (ra + 2 * 4)) = mcode[1];
289 #endif
290
291         /* synchronize instruction cache */
292
293         cacheflush(ra + 1 * 4, 2 * 4, ICACHE);
294
295         /* patch the classinfo pointer */
296
297         *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c;
298
299         /* patch new function address */
300
301         *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_new;
302
303         PATCHER_MARK_PATCHED_MONITOREXIT;
304
305         return true;
306 }
307
308
309 /* patcher_builtin_newarray ****************************************************
310
311    Machine code:
312
313    dfc5ffa0    ld       a1,-96(s8)
314    <patched call position>
315    dfd9ff98    ld       t9,-104(s8)
316    0320f809    jalr     t9
317    00000000    nop
318
319    NOTICE: Only the displacement for the function address is passed,
320    but the address of the classinfo pointer is one below (above, in
321    addresses speaking). This is for sure.
322
323 *******************************************************************************/
324
325 bool patcher_builtin_newarray(u1 *sp)
326 {
327         u1                *ra;
328         java_objectheader *o;
329 #if SIZEOF_VOID_P == 8
330         u8                 mcode;
331 #else
332         u4                 mcode[2];
333 #endif
334         constant_classref *cr;
335         s4                 disp;
336         u1                *pv;
337         classinfo         *c;
338
339         /* get stuff from the stack */
340
341         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
342         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
343 #if SIZEOF_VOID_P == 8
344         mcode    =                       *((u8 *)     (sp + 3 * 8));
345 #else
346         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
347         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
348 #endif
349         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
350         disp     =                       *((s4 *)     (sp + 1 * 8));
351         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
352
353         /* calculate and set the new return address */
354
355         ra = ra - (3 * 4);
356         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
357
358         PATCHER_MONITORENTER;
359
360         /* get the classinfo */
361
362         if (!(c = helper_resolve_classinfo(cr))) {
363                 PATCHER_MONITOREXIT;
364
365                 return false;
366         }
367
368         /* patch back original code */
369
370 #if SIZEOF_VOID_P == 8
371         *((u4 *) (ra + 1 * 4)) = mcode;
372         *((u4 *) (ra + 2 * 4)) = mcode >> 32;
373 #else
374         *((u4 *) (ra + 1 * 4)) = mcode[0];
375         *((u4 *) (ra + 2 * 4)) = mcode[1];
376 #endif
377
378         /* synchronize instruction cache */
379
380         cacheflush(ra + 1 * 4, 2 * 4, ICACHE);
381
382         /* patch the class' vftbl pointer */
383
384         *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c->vftbl;
385
386         /* patch new function address */
387
388         *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_newarray;
389
390         PATCHER_MARK_PATCHED_MONITOREXIT;
391
392         return true;
393 }
394
395
396 /* patcher_builtin_multianewarray **********************************************
397
398    Machine code:
399
400    <patched call position>
401    dfc5ff90    ld       a1,-112(s8)
402    03a03025    move     a2,sp
403    dfd9ff88    ld       t9,-120(s8)
404    0320f809    jalr     t9
405    00000000    nop
406
407 *******************************************************************************/
408
409 bool patcher_builtin_multianewarray(u1 *sp)
410 {
411         u1                *ra;
412         java_objectheader *o;
413 #if SIZEOF_VOID_P == 8
414         u8                 mcode;
415 #else   
416         u4                 mcode[2];
417 #endif
418         constant_classref *cr;
419         s4                 disp;
420         u1                *pv;
421         classinfo         *c;
422
423         /* get stuff from the stack */
424
425         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
426         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
427 #if SIZEOF_VOID_P == 8
428         mcode    =                       *((u8 *)     (sp + 3 * 8));
429 #else
430         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
431         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
432 #endif
433         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
434         disp     =                       *((s4 *)     (sp + 1 * 8));
435         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
436
437         /* calculate and set the new return address */
438
439         ra = ra - 2 * 4;
440         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
441
442         PATCHER_MONITORENTER;
443
444         /* get the classinfo */
445
446         if (!(c = helper_resolve_classinfo(cr))) {
447                 PATCHER_MONITOREXIT;
448
449                 return false;
450         }
451
452         /* patch back original code */
453
454 #if SIZEOF_VOID_P == 8
455         *((u4 *) (ra + 0 * 4)) = mcode;
456         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
457 #else
458         *((u4 *) (ra + 0 * 4)) = mcode[0];
459         *((u4 *) (ra + 1 * 4)) = mcode[1];
460 #endif
461
462         /* synchronize instruction cache */
463
464         cacheflush(ra, 2 * 4, ICACHE);
465
466         /* patch the class' vftbl pointer */
467
468         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
469
470         PATCHER_MARK_PATCHED_MONITOREXIT;
471
472         return true;
473 }
474
475
476 /* patcher_builtin_arraycheckcast **********************************************
477
478    Machine code:
479
480    <patched call position>
481    dfc5ffc0    ld       a1,-64(s8)
482    dfd9ffb8    ld       t9,-72(s8)
483    0320f809    jalr     t9
484    00000000    nop
485
486    NOTICE: Only the displacement of the vftbl pointer address is
487    passed, but the address of the function pointer is one above
488    (below, in addresses speaking). This is for sure.
489
490 *******************************************************************************/
491
492 bool patcher_builtin_arraycheckcast(u1 *sp)
493 {
494         u1                *ra;
495         java_objectheader *o;
496 #if SIZEOF_VOID_P == 8
497         u8                 mcode;
498 #else
499         u4                 mcode[2];
500 #endif
501         constant_classref *cr;
502         s4                 disp;
503         u1                *pv;
504         classinfo         *c;
505
506         /* get stuff from the stack */
507
508         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
509         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
510 #if SIZEOF_VOID_P == 8
511         mcode    =                       *((u8 *)     (sp + 3 * 8));
512 #else
513         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
514         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
515 #endif
516         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
517         disp     =                       *((s4 *)     (sp + 1 * 8));
518         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
519
520         /* calculate and set the new return address */
521
522         ra = ra - 2 * 4;
523         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
524
525         PATCHER_MONITORENTER;
526
527         /* get the classinfo */
528
529         if (!(c = helper_resolve_classinfo(cr))) {
530                 PATCHER_MONITOREXIT;
531
532                 return false;
533         }
534
535         /* patch back original code */
536
537 #if SIZEOF_VOID_P == 8
538         *((u4 *) (ra + 0 * 4)) = mcode;
539         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
540 #else
541         *((u4 *) (ra + 0 * 4)) = mcode[0];
542         *((u4 *) (ra + 1 * 4)) = mcode[1];
543 #endif
544
545         /* synchronize instruction cache */
546
547         cacheflush(ra, 2 * 4, ICACHE);
548
549         /* patch the class' vftbl pointer */
550
551         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
552
553         /* patch new function address */
554
555         *((ptrint *) (pv + (disp - SIZEOF_VOID_P))) =
556                 (ptrint) BUILTIN_arraycheckcast;
557
558         PATCHER_MARK_PATCHED_MONITOREXIT;
559
560         return true;
561 }
562
563
564 /* patcher_builtin_arrayinstanceof *********************************************
565
566    Machine code:
567
568    dfc5fe98    ld       a1,-360(s8)
569    <patched call position>
570    dfd9fe90    ld       t9,-368(s8)
571    0320f809    jalr     t9
572    00000000    nop
573
574    NOTICE: Only the displacement for the function address is passed,
575    but the address of the vftbl pointer is one below (above, in
576    addresses speaking). This is for sure.
577
578 *******************************************************************************/
579
580 bool patcher_builtin_arrayinstanceof(u1 *sp)
581 {
582         u1                *ra;
583         java_objectheader *o;
584 #if SIZEOF_VOID_P == 8
585         u8                 mcode;
586 #else
587         u4                 mcode[2];
588 #endif
589         constant_classref *cr;
590         s4                 disp;
591         u1                *pv;
592         classinfo         *c;
593
594         /* get stuff from the stack */
595
596         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
597         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
598 #if SIZEOF_VOID_P == 8
599         mcode    =                       *((u8 *)     (sp + 3 * 8));
600 #else
601         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
602         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
603 #endif
604         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
605         disp     =                       *((s4 *)     (sp + 1 * 8));
606         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
607
608         /* calculate and set the new return address */
609
610         ra = ra - 3 * 4;
611         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
612
613         PATCHER_MONITORENTER;
614
615         /* get the classinfo */
616
617         if (!(c = helper_resolve_classinfo(cr))) {
618                 PATCHER_MONITOREXIT;
619
620                 return false;
621         }
622
623         /* patch back original code */
624
625 #if SIZEOF_VOID_P == 8
626         *((u4 *) (ra + 1 * 4)) = mcode;
627         *((u4 *) (ra + 2 * 4)) = mcode >> 32;
628 #else
629         *((u4 *) (ra + 1 * 4)) = mcode[0];
630         *((u4 *) (ra + 2 * 4)) = mcode[1];
631 #endif
632
633         /* synchronize instruction cache */
634
635         cacheflush(ra + 1 * 4, 2 * 4, ICACHE);
636
637         /* patch the class' vftbl pointer */
638         
639         *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c->vftbl;
640
641         /* patch new function address */
642
643         *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_arrayinstanceof;
644
645         PATCHER_MARK_PATCHED_MONITOREXIT;
646
647         return true;
648 }
649
650
651 /* patcher_invokestatic_special ************************************************
652
653    Machine code:
654
655    <patched call position>
656    dfdeffc0    ld       s8,-64(s8)
657    03c0f809    jalr     s8
658    00000000    nop
659
660 ******************************************************************************/
661
662 bool patcher_invokestatic_special(u1 *sp)
663 {
664         u1                *ra;
665         java_objectheader *o;
666 #if SIZEOF_VOID_P == 8
667         u8                 mcode;
668 #else
669         u4                 mcode[2];
670 #endif
671         unresolved_method *um;
672         s4                 disp;
673         u1                *pv;
674         methodinfo        *m;
675
676         /* get stuff from the stack */
677
678         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
679         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
680 #if SIZEOF_VOID_P == 8
681         mcode    =                       *((u8 *)     (sp + 3 * 8));
682 #else
683         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
684         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
685 #endif
686         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
687         disp     =                       *((s4 *)     (sp + 1 * 8));
688         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
689
690         /* calculate and set the new return address */
691
692         ra = ra - 2 * 4;
693         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
694
695         PATCHER_MONITORENTER;
696
697         /* get the fieldinfo */
698
699         if (!(m = helper_resolve_methodinfo(um))) {
700                 PATCHER_MONITOREXIT;
701
702                 return false;
703         }
704
705         /* patch back original code */
706
707 #if SIZEOF_VOID_P == 8
708         *((u4 *) (ra + 0 * 4)) = mcode;
709         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
710 #else
711         *((u4 *) (ra + 0 * 4)) = mcode[0];
712         *((u4 *) (ra + 1 * 4)) = mcode[1];
713 #endif
714
715         /* synchronize instruction cache */
716
717         cacheflush(ra, 2 * 4, ICACHE);
718
719         /* patch stubroutine */
720
721         *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
722
723         PATCHER_MARK_PATCHED_MONITOREXIT;
724
725         return true;
726 }
727
728
729 /* patcher_invokevirtual *******************************************************
730
731    Machine code:
732
733    <patched call position>
734    dc990000    ld       t9,0(a0)
735    df3e0040    ld       s8,64(t9)
736    03c0f809    jalr     s8
737    00000000    nop
738
739 *******************************************************************************/
740
741 bool patcher_invokevirtual(u1 *sp)
742 {
743         u1                *ra;
744         java_objectheader *o;
745 #if SIZEOF_VOID_P == 8
746         u8                 mcode;
747 #else
748         u4                 mcode[2];
749 #endif
750         unresolved_method *um;
751         methodinfo        *m;
752
753         /* get stuff from the stack */
754
755         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
756         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
757 #if SIZEOF_VOID_P == 8
758         mcode    =                       *((u8 *)     (sp + 3 * 8));
759 #else
760         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
761         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
762 #endif
763         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
764
765         /* calculate and set the new return address */
766
767         ra = ra - 2 * 4;
768         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
769
770         PATCHER_MONITORENTER;
771
772         /* get the fieldinfo */
773
774         if (!(m = helper_resolve_methodinfo(um))) {
775                 PATCHER_MONITOREXIT;
776
777                 return false;
778         }
779
780         /* patch back original code */
781
782 #if SIZEOF_VOID_P == 8
783         *((u4 *) (ra + 0 * 4)) = mcode;
784         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
785 #else
786         *((u4 *) (ra + 0 * 4)) = mcode[0];
787         *((u4 *) (ra + 1 * 4)) = mcode[1];
788 #endif
789
790         /* if we show disassembly, we have to skip the nop's */
791
792         if (opt_showdisassemble)
793                 ra = ra + 2 * 4;
794
795         /* patch vftbl index */
796
797         *((s4 *) (ra + 1 * 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
798                                                                          sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
799
800         /* synchronize instruction cache */
801
802         if (opt_showdisassemble)
803                 cacheflush(ra - 2 * 4, 4 * 4, ICACHE);
804         else
805                 cacheflush(ra, 2 * 4, ICACHE);
806
807         PATCHER_MARK_PATCHED_MONITOREXIT;
808
809         return true;
810 }
811
812
813 /* patcher_invokeinterface *****************************************************
814
815    Machine code:
816
817    <patched call position>
818    dc990000    ld       t9,0(a0)
819    df39ffa0    ld       t9,-96(t9)
820    df3e0018    ld       s8,24(t9)
821    03c0f809    jalr     s8
822    00000000    nop
823
824 *******************************************************************************/
825
826 bool patcher_invokeinterface(u1 *sp)
827 {
828         u1                *ra;
829         java_objectheader *o;
830 #if SIZEOF_VOID_P == 8
831         u8                 mcode;
832 #else
833         u4                 mcode[2];
834 #endif
835         unresolved_method *um;
836         methodinfo        *m;
837
838         /* get stuff from the stack */
839
840         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
841         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
842 #if SIZEOF_VOID_P == 8
843         mcode    =                       *((u8 *)     (sp + 3 * 8));
844 #else
845         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
846         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
847 #endif
848         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
849
850         /* calculate and set the new return address */
851
852         ra = ra - 2 * 4;
853         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
854
855         PATCHER_MONITORENTER;
856
857         /* get the fieldinfo */
858
859         if (!(m = helper_resolve_methodinfo(um))) {
860                 PATCHER_MONITOREXIT;
861
862                 return false;
863         }
864
865         /* patch back original code */
866
867 #if SIZEOF_VOID_P == 8
868         *((u4 *) (ra + 0 * 4)) = mcode;
869         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
870 #else
871         *((u4 *) (ra + 0 * 4)) = mcode[0];
872         *((u4 *) (ra + 1 * 4)) = mcode[1];
873 #endif
874
875         /* if we show disassembly, we have to skip the nop's */
876
877         if (opt_showdisassemble)
878                 ra = ra + 2 * 4;
879
880         /* patch interfacetable index */
881
882         *((s4 *) (ra + 1 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
883                                                                          sizeof(methodptr*) * m->class->index) & 0x0000ffff);
884
885         /* patch method offset */
886
887         *((s4 *) (ra + 2 * 4)) |=
888                 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
889
890         /* synchronize instruction cache */
891
892         if (opt_showdisassemble)
893                 cacheflush(ra - 2 * 4, 5 * 4, ICACHE);
894         else
895                 cacheflush(ra, 3 * 4, ICACHE);
896
897         PATCHER_MARK_PATCHED_MONITOREXIT;
898
899         return true;
900 }
901
902
903 /* patcher_checkcast_instanceof_flags ******************************************
904
905    Machine code:
906
907    <patched call position>
908    8fc3ff24    lw       v1,-220(s8)
909    30630200    andi     v1,v1,512
910    1060000d    beq      v1,zero,0x000000001051824c
911    00000000    nop
912
913 *******************************************************************************/
914
915 bool patcher_checkcast_instanceof_flags(u1 *sp)
916 {
917         u1                *ra;
918         java_objectheader *o;
919 #if SIZEOF_VOID_P == 8
920         u8                 mcode;
921 #else
922         u4                 mcode[2];
923 #endif
924         constant_classref *cr;
925         s4                 disp;
926         u1                *pv;
927         classinfo         *c;
928
929         /* get stuff from the stack */
930
931         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
932         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
933 #if SIZEOF_VOID_P == 8
934         mcode    =                       *((u8 *)     (sp + 3 * 8));
935 #else
936         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
937         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
938 #endif
939         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
940         disp     =                       *((s4 *)     (sp + 1 * 8));
941         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
942
943         /* calculate and set the new return address */
944
945         ra = ra - 2 * 4;
946         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
947
948         PATCHER_MONITORENTER;
949
950         /* get the fieldinfo */
951
952         if (!(c = helper_resolve_classinfo(cr))) {
953                 PATCHER_MONITOREXIT;
954
955                 return false;
956         }
957
958         /* patch back original code */
959
960 #if SIZEOF_VOID_P == 8
961         *((u4 *) (ra + 0 * 4)) = mcode;
962         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
963 #else
964         *((u4 *) (ra + 0 * 4)) = mcode[0];
965         *((u4 *) (ra + 1 * 4)) = mcode[1];
966 #endif
967
968         /* synchronize instruction cache */
969
970         cacheflush(ra, 2 * 4, ICACHE);
971
972         /* patch class flags */
973
974         *((s4 *) (pv + disp)) = (s4) c->flags;
975
976         PATCHER_MARK_PATCHED_MONITOREXIT;
977
978         return true;
979 }
980
981
982 /* patcher_checkcast_instanceof_interface **************************************
983
984    Machine code:
985
986    <patched call position>
987    dd030000    ld       v1,0(a4)
988    8c79001c    lw       t9,28(v1)
989    27390000    addiu    t9,t9,0
990    1b200082    blez     t9,zero,0x000000001051843c
991    00000000    nop
992    dc790000    ld       t9,0(v1)
993
994 *******************************************************************************/
995
996 bool patcher_checkcast_instanceof_interface(u1 *sp)
997 {
998         u1                *ra;
999         java_objectheader *o;
1000 #if SIZEOF_VOID_P == 8
1001         u8                 mcode;
1002 #else
1003         u4                 mcode[2];
1004 #endif
1005         constant_classref *cr;
1006         classinfo         *c;
1007
1008         /* get stuff from the stack */
1009
1010         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
1011         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
1012 #if SIZEOF_VOID_P == 8
1013         mcode    =                       *((u8 *)     (sp + 3 * 8));
1014 #else
1015         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
1016         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
1017 #endif
1018         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
1019
1020         /* calculate and set the new return address */
1021
1022         ra = ra - 2 * 4;
1023         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
1024
1025         PATCHER_MONITORENTER;
1026
1027         /* get the fieldinfo */
1028
1029         if (!(c = helper_resolve_classinfo(cr))) {
1030                 PATCHER_MONITOREXIT;
1031
1032                 return false;
1033         }
1034
1035         /* patch back original code */
1036
1037 #if SIZEOF_VOID_P == 8
1038         *((u4 *) (ra + 0 * 4)) = mcode;
1039         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
1040 #else
1041         *((u4 *) (ra + 0 * 4)) = mcode[0];
1042         *((u4 *) (ra + 1 * 4)) = mcode[1];
1043 #endif
1044
1045         /* if we show disassembly, we have to skip the nop's */
1046
1047         if (opt_showdisassemble)
1048                 ra = ra + 2 * 4;
1049
1050         /* patch super class index */
1051
1052         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
1053
1054         *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
1055                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
1056
1057         /* synchronize instruction cache */
1058
1059         if (opt_showdisassemble)
1060                 cacheflush(ra - 2 * 4, 8 * 4, ICACHE);
1061         else
1062                 cacheflush(ra, 6 * 4, ICACHE);
1063
1064         PATCHER_MARK_PATCHED_MONITOREXIT;
1065
1066         return true;
1067 }
1068
1069
1070 /* patcher_checkcast_instanceof_class ******************************************
1071
1072    Machine code:
1073
1074    <patched call position>
1075    dd030000    ld       v1,0(a4)
1076    dfd9ff18    ld       t9,-232(s8)
1077
1078 *******************************************************************************/
1079
1080 bool patcher_checkcast_instanceof_class(u1 *sp)
1081 {
1082         u1                *ra;
1083         java_objectheader *o;
1084 #if SIZEOF_VOID_P == 8
1085         u8                 mcode;
1086 #else
1087         u4                 mcode[2];
1088 #endif
1089         constant_classref *cr;
1090         s4                 disp;
1091         u1                *pv;
1092         classinfo         *c;
1093
1094         /* get stuff from the stack */
1095
1096         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
1097         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
1098 #if SIZEOF_VOID_P == 8
1099         mcode    =                       *((u8 *)     (sp + 3 * 8));
1100 #else
1101         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
1102         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
1103 #endif
1104         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
1105         disp     =                       *((s4 *)     (sp + 1 * 8));
1106         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
1107
1108         /* calculate and set the new return address */
1109
1110         ra = ra - 2 * 4;
1111         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
1112
1113         PATCHER_MONITORENTER;
1114
1115         /* get the fieldinfo */
1116
1117         if (!(c = helper_resolve_classinfo(cr))) {
1118                 PATCHER_MONITOREXIT;
1119
1120                 return false;
1121         }
1122
1123         /* patch back original code */
1124
1125 #if SIZEOF_VOID_P == 8
1126         *((u4 *) (ra + 0 * 4)) = mcode;
1127         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
1128 #else
1129         *((u4 *) (ra + 0 * 4)) = mcode[0];
1130         *((u4 *) (ra + 1 * 4)) = mcode[1];
1131 #endif
1132
1133         /* synchronize instruction cache */
1134
1135         cacheflush(ra, 2 * 4, ICACHE);
1136
1137         /* patch super class' vftbl */
1138
1139         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
1140
1141         PATCHER_MARK_PATCHED_MONITOREXIT;
1142
1143         return true;
1144 }
1145
1146
1147 /* patcher_clinit **************************************************************
1148
1149    No special machine code.
1150
1151 *******************************************************************************/
1152
1153 bool patcher_clinit(u1 *sp)
1154 {
1155         u1                *ra;
1156         java_objectheader *o;
1157 #if SIZEOF_VOID_P == 8
1158         u8                 mcode;
1159 #else
1160         u4                 mcode[2];
1161 #endif
1162         classinfo         *c;
1163
1164         /* get stuff from the stack */
1165
1166         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
1167         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
1168 #if SIZEOF_VOID_P == 8
1169         mcode    =                       *((u8 *)     (sp + 3 * 8));
1170 #else
1171         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
1172         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
1173 #endif
1174         c        = (classinfo *)         *((ptrint *) (sp + 2 * 8));
1175
1176         /* calculate and set the new return address */
1177
1178         ra = ra - 2 * 4;
1179         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
1180
1181         PATCHER_MONITORENTER;
1182
1183         /* check if the class is initialized */
1184
1185         if (!c->initialized) {
1186                 if (!initialize_class(c)) {
1187                         PATCHER_MONITOREXIT;
1188
1189                         return false;
1190                 }
1191         }
1192
1193         /* patch back original code */
1194
1195 #if SIZEOF_VOID_P == 8
1196         *((u4 *) (ra + 0 * 4)) = mcode;
1197         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
1198 #else
1199         *((u4 *) (ra + 0 * 4)) = mcode[0];
1200         *((u4 *) (ra + 1 * 4)) = mcode[1];
1201 #endif
1202
1203         /* synchronize instruction cache */
1204
1205         cacheflush(ra, 2 * 4, ICACHE);
1206
1207         PATCHER_MARK_PATCHED_MONITOREXIT;
1208
1209         return true;
1210 }
1211
1212
1213 /* patcher_resolve_native ******************************************************
1214
1215    XXX
1216
1217 *******************************************************************************/
1218
1219 #if !defined(ENABLE_STATICVM)
1220 bool patcher_resolve_native(u1 *sp)
1221 {
1222         u1                *ra;
1223         java_objectheader *o;
1224 #if SIZEOF_VOID_P == 8
1225         u8                 mcode;
1226 #else
1227         u4                 mcode[2];
1228 #endif
1229         methodinfo        *m;
1230         s4                 disp;
1231         u1                *pv;
1232         functionptr        f;
1233
1234         /* get stuff from the stack */
1235
1236         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
1237         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
1238 #if SIZEOF_VOID_P == 8
1239         mcode    =                       *((u8 *)     (sp + 3 * 8));
1240 #else
1241         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
1242         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
1243 #endif
1244         m        = (methodinfo *)        *((ptrint *) (sp + 2 * 8));
1245         disp     =                       *((s4 *)     (sp + 1 * 8));
1246         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
1247
1248         /* calculate and set the new return address */
1249
1250         ra = ra - 2 * 4;
1251         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
1252
1253         PATCHER_MONITORENTER;
1254
1255         /* resolve native function */
1256
1257         if (!(f = native_resolve_function(m))) {
1258                 PATCHER_MONITOREXIT;
1259
1260                 return false;
1261         }
1262
1263         /* patch back original code */
1264
1265 #if SIZEOF_VOID_P == 8
1266         *((u4 *) (ra + 0 * 4)) = mcode;
1267         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
1268 #else
1269         *((u4 *) (ra + 0 * 4)) = mcode[0];
1270         *((u4 *) (ra + 1 * 4)) = mcode[1];
1271 #endif
1272
1273         /* synchronize instruction cache */
1274
1275         cacheflush(ra, 2 * 4, ICACHE);
1276
1277         /* patch native function pointer */
1278
1279         *((ptrint *) (pv + disp)) = (ptrint) f;
1280
1281         PATCHER_MARK_PATCHED_MONITOREXIT;
1282
1283         return true;
1284 }
1285 #endif /* !defined(ENABLE_STATICVM) */
1286
1287
1288 /*
1289  * These are local overrides for various environment variables in Emacs.
1290  * Please do not remove this and leave it at the end of the file, where
1291  * Emacs will automagically detect them.
1292  * ---------------------------------------------------------------------
1293  * Local variables:
1294  * mode: c
1295  * indent-tabs-mode: t
1296  * c-basic-offset: 4
1297  * tab-width: 4
1298  * End:
1299  * vim:noexpandtab:sw=4:ts=4:
1300  */