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