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