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