* patcher_get_putfield: Fixed TYPE_LNG on mips32.
[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 3520 2005-10-28 17:50:55Z 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_builtin_new *********************************************************
232
233    Machine code:
234
235    dfc4ff98    ld       a0,-104(s8)
236    <patched call postition>
237    dfd9ff90    ld       t9,-112(s8)
238    0320f809    jalr     t9
239    00000000    nop
240
241    NOTICE: Only the displacement for the function address is passed,
242    but the address of the classinfo pointer is one below (above, in
243    addresses speaking). This is for sure.
244
245 *******************************************************************************/
246
247 bool patcher_builtin_new(u1 *sp)
248 {
249         u1                *ra;
250         java_objectheader *o;
251 #if SIZEOF_VOID_P == 8
252         u8                 mcode;
253 #else
254         u4                 mcode[2];
255 #endif
256         constant_classref *cr;
257         s4                 disp;
258         u1                *pv;
259         classinfo         *c;
260
261         /* get stuff from the stack */
262
263         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
264         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
265 #if SIZEOF_VOID_P == 8
266         mcode    =                       *((u8 *)     (sp + 3 * 8));
267 #else
268         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
269         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
270 #endif
271         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
272         disp     =                       *((s4 *)     (sp + 1 * 8));
273         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
274
275         /* calculate and set the new return address */
276
277         ra = ra - 1 * 4;
278         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
279
280         PATCHER_MONITORENTER;
281
282         /* get the classinfo */
283
284         if (!(c = resolve_classref_eager_nonabstract(cr))) {
285                 PATCHER_MONITOREXIT;
286
287                 return false;
288         }
289
290         /* patch back original code */
291
292 #if SIZEOF_VOID_P == 8
293         *((u4 *) (ra + 1 * 4)) = mcode;
294         *((u4 *) (ra + 2 * 4)) = mcode >> 32;
295 #else
296         *((u4 *) (ra + 1 * 4)) = mcode[0];
297         *((u4 *) (ra + 2 * 4)) = mcode[1];
298 #endif
299
300         /* synchronize instruction cache */
301
302         cacheflush(ra + 1 * 4, 2 * 4, ICACHE);
303
304         /* patch the classinfo pointer */
305
306         *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c;
307
308         /* patch new function address */
309
310         *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_new;
311
312         /* synchronize data cache */
313
314         cacheflush(pv + disp, SIZEOF_VOID_P * 2, DCACHE);
315
316         PATCHER_MARK_PATCHED_MONITOREXIT;
317
318         return true;
319 }
320
321
322 /* patcher_builtin_newarray ****************************************************
323
324    Machine code:
325
326    dfc5ffa0    ld       a1,-96(s8)
327    <patched call position>
328    dfd9ff98    ld       t9,-104(s8)
329    0320f809    jalr     t9
330    00000000    nop
331
332    NOTICE: Only the displacement for the function address is passed,
333    but the address of the classinfo pointer is one below (above, in
334    addresses speaking). This is for sure.
335
336 *******************************************************************************/
337
338 bool patcher_builtin_newarray(u1 *sp)
339 {
340         u1                *ra;
341         java_objectheader *o;
342 #if SIZEOF_VOID_P == 8
343         u8                 mcode;
344 #else
345         u4                 mcode[2];
346 #endif
347         constant_classref *cr;
348         s4                 disp;
349         u1                *pv;
350         classinfo         *c;
351
352         /* get stuff from the stack */
353
354         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
355         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
356 #if SIZEOF_VOID_P == 8
357         mcode    =                       *((u8 *)     (sp + 3 * 8));
358 #else
359         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
360         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
361 #endif
362         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
363         disp     =                       *((s4 *)     (sp + 1 * 8));
364         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
365
366         /* calculate and set the new return address */
367
368         ra = ra - 1 * 4;
369         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
370
371         PATCHER_MONITORENTER;
372
373         /* get the classinfo */
374
375         if (!(c = resolve_classref_eager(cr))) {
376                 PATCHER_MONITOREXIT;
377
378                 return false;
379         }
380
381         /* patch back original code */
382
383 #if SIZEOF_VOID_P == 8
384         *((u4 *) (ra + 1 * 4)) = mcode;
385         *((u4 *) (ra + 2 * 4)) = mcode >> 32;
386 #else
387         *((u4 *) (ra + 1 * 4)) = mcode[0];
388         *((u4 *) (ra + 2 * 4)) = mcode[1];
389 #endif
390
391         /* synchronize instruction cache */
392
393         cacheflush(ra + 1 * 4, 2 * 4, ICACHE);
394
395         /* patch the class' vftbl pointer */
396
397         *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c->vftbl;
398
399         /* patch new function address */
400
401         *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_newarray;
402
403         /* synchronize data cache */
404
405         cacheflush(pv + disp, SIZEOF_VOID_P * 2, DCACHE);
406
407         PATCHER_MARK_PATCHED_MONITOREXIT;
408
409         return true;
410 }
411
412
413 /* patcher_builtin_multianewarray **********************************************
414
415    Machine code:
416
417    <patched call position>
418    dfc5ff90    ld       a1,-112(s8)
419    03a03025    move     a2,sp
420    dfd9ff88    ld       t9,-120(s8)
421    0320f809    jalr     t9
422    00000000    nop
423
424 *******************************************************************************/
425
426 bool patcher_builtin_multianewarray(u1 *sp)
427 {
428         u1                *ra;
429         java_objectheader *o;
430 #if SIZEOF_VOID_P == 8
431         u8                 mcode;
432 #else   
433         u4                 mcode[2];
434 #endif
435         constant_classref *cr;
436         s4                 disp;
437         u1                *pv;
438         classinfo         *c;
439
440         /* get stuff from the stack */
441
442         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
443         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
444 #if SIZEOF_VOID_P == 8
445         mcode    =                       *((u8 *)     (sp + 3 * 8));
446 #else
447         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
448         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
449 #endif
450         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
451         disp     =                       *((s4 *)     (sp + 1 * 8));
452         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
453
454         PATCHER_MONITORENTER;
455
456         /* get the classinfo */
457
458         if (!(c = resolve_classref_eager(cr))) {
459                 PATCHER_MONITOREXIT;
460
461                 return false;
462         }
463
464         /* patch back original code */
465
466 #if SIZEOF_VOID_P == 8
467         *((u4 *) (ra + 0 * 4)) = mcode;
468         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
469 #else
470         *((u4 *) (ra + 0 * 4)) = mcode[0];
471         *((u4 *) (ra + 1 * 4)) = mcode[1];
472 #endif
473
474         /* synchronize instruction cache */
475
476         cacheflush(ra, 2 * 4, ICACHE);
477
478         /* patch the class' vftbl pointer */
479
480         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
481
482         /* synchronize data cache */
483
484         cacheflush(pv + disp, SIZEOF_VOID_P, DCACHE);
485
486         PATCHER_MARK_PATCHED_MONITOREXIT;
487
488         return true;
489 }
490
491
492 /* patcher_builtin_arraycheckcast **********************************************
493
494    Machine code:
495
496    <patched call position>
497    dfc5ffc0    ld       a1,-64(s8)
498    dfd9ffb8    ld       t9,-72(s8)
499    0320f809    jalr     t9
500    00000000    nop
501
502    NOTICE: Only the displacement of the vftbl pointer address is
503    passed, but the address of the function pointer is one above
504    (below, in addresses speaking). This is for sure.
505
506 *******************************************************************************/
507
508 bool patcher_builtin_arraycheckcast(u1 *sp)
509 {
510         u1                *ra;
511         java_objectheader *o;
512 #if SIZEOF_VOID_P == 8
513         u8                 mcode;
514 #else
515         u4                 mcode[2];
516 #endif
517         constant_classref *cr;
518         s4                 disp;
519         u1                *pv;
520         classinfo         *c;
521
522         /* get stuff from the stack */
523
524         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
525         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
526 #if SIZEOF_VOID_P == 8
527         mcode    =                       *((u8 *)     (sp + 3 * 8));
528 #else
529         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
530         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
531 #endif
532         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
533         disp     =                       *((s4 *)     (sp + 1 * 8));
534         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
535
536         PATCHER_MONITORENTER;
537
538         /* get the classinfo */
539
540         if (!(c = resolve_classref_eager(cr))) {
541                 PATCHER_MONITOREXIT;
542
543                 return false;
544         }
545
546         /* patch back original code */
547
548 #if SIZEOF_VOID_P == 8
549         *((u4 *) (ra + 0 * 4)) = mcode;
550         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
551 #else
552         *((u4 *) (ra + 0 * 4)) = mcode[0];
553         *((u4 *) (ra + 1 * 4)) = mcode[1];
554 #endif
555
556         /* synchronize instruction cache */
557
558         cacheflush(ra, 2 * 4, ICACHE);
559
560         /* patch the class' vftbl pointer */
561
562         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
563
564         /* patch new function address */
565
566         *((ptrint *) (pv + (disp - SIZEOF_VOID_P))) =
567                 (ptrint) BUILTIN_arraycheckcast;
568
569         /* synchronize data cache */
570
571         cacheflush(pv + disp - SIZEOF_VOID_P, SIZEOF_VOID_P * 2, DCACHE);
572
573         PATCHER_MARK_PATCHED_MONITOREXIT;
574
575         return true;
576 }
577
578
579 /* patcher_builtin_arrayinstanceof *********************************************
580
581    Machine code:
582
583    dfc5fe98    ld       a1,-360(s8)
584    <patched call position>
585    dfd9fe90    ld       t9,-368(s8)
586    0320f809    jalr     t9
587    00000000    nop
588
589    NOTICE: Only the displacement for the function address is passed,
590    but the address of the vftbl pointer is one below (above, in
591    addresses speaking). This is for sure.
592
593 *******************************************************************************/
594
595 bool patcher_builtin_arrayinstanceof(u1 *sp)
596 {
597         u1                *ra;
598         java_objectheader *o;
599 #if SIZEOF_VOID_P == 8
600         u8                 mcode;
601 #else
602         u4                 mcode[2];
603 #endif
604         constant_classref *cr;
605         s4                 disp;
606         u1                *pv;
607         classinfo         *c;
608
609         /* get stuff from the stack */
610
611         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
612         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
613 #if SIZEOF_VOID_P == 8
614         mcode    =                       *((u8 *)     (sp + 3 * 8));
615 #else
616         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
617         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
618 #endif
619         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
620         disp     =                       *((s4 *)     (sp + 1 * 8));
621         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
622
623         /* calculate and set the new return address */
624
625         ra = ra - 1 * 4;
626         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
627
628         PATCHER_MONITORENTER;
629
630         /* get the classinfo */
631
632         if (!(c = resolve_classref_eager(cr))) {
633                 PATCHER_MONITOREXIT;
634
635                 return false;
636         }
637
638         /* patch back original code */
639
640 #if SIZEOF_VOID_P == 8
641         *((u4 *) (ra + 1 * 4)) = mcode;
642         *((u4 *) (ra + 2 * 4)) = mcode >> 32;
643 #else
644         *((u4 *) (ra + 1 * 4)) = mcode[0];
645         *((u4 *) (ra + 2 * 4)) = mcode[1];
646 #endif
647
648         /* synchronize instruction cache */
649
650         cacheflush(ra + 1 * 4, 2 * 4, ICACHE);
651
652         /* patch the class' vftbl pointer */
653         
654         *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c->vftbl;
655
656         /* patch new function address */
657
658         *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_arrayinstanceof;
659
660         /* synchronize data cache */
661
662         cacheflush(pv + disp, SIZEOF_VOID_P * 2, DCACHE);
663
664         PATCHER_MARK_PATCHED_MONITOREXIT;
665
666         return true;
667 }
668
669
670 /* patcher_invokestatic_special ************************************************
671
672    Machine code:
673
674    <patched call position>
675    dfdeffc0    ld       s8,-64(s8)
676    03c0f809    jalr     s8
677    00000000    nop
678
679 ******************************************************************************/
680
681 bool patcher_invokestatic_special(u1 *sp)
682 {
683         u1                *ra;
684         java_objectheader *o;
685 #if SIZEOF_VOID_P == 8
686         u8                 mcode;
687 #else
688         u4                 mcode[2];
689 #endif
690         unresolved_method *um;
691         s4                 disp;
692         u1                *pv;
693         methodinfo        *m;
694
695         /* get stuff from the stack */
696
697         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
698         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
699 #if SIZEOF_VOID_P == 8
700         mcode    =                       *((u8 *)     (sp + 3 * 8));
701 #else
702         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
703         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
704 #endif
705         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
706         disp     =                       *((s4 *)     (sp + 1 * 8));
707         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
708
709         PATCHER_MONITORENTER;
710
711         /* get the fieldinfo */
712
713         if (!(m = resolve_method_eager(um))) {
714                 PATCHER_MONITOREXIT;
715
716                 return false;
717         }
718
719         /* patch back original code */
720
721 #if SIZEOF_VOID_P == 8
722         *((u4 *) (ra + 0 * 4)) = mcode;
723         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
724 #else
725         *((u4 *) (ra + 0 * 4)) = mcode[0];
726         *((u4 *) (ra + 1 * 4)) = mcode[1];
727 #endif
728
729         /* synchronize instruction cache */
730
731         cacheflush(ra, 2 * 4, ICACHE);
732
733         /* patch stubroutine */
734
735         *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
736
737         /* synchronize data cache */
738
739         cacheflush(pv + disp, SIZEOF_VOID_P, DCACHE);
740
741         PATCHER_MARK_PATCHED_MONITOREXIT;
742
743         return true;
744 }
745
746
747 /* patcher_invokevirtual *******************************************************
748
749    Machine code:
750
751    <patched call position>
752    dc990000    ld       t9,0(a0)
753    df3e0040    ld       s8,64(t9)
754    03c0f809    jalr     s8
755    00000000    nop
756
757 *******************************************************************************/
758
759 bool patcher_invokevirtual(u1 *sp)
760 {
761         u1                *ra;
762         java_objectheader *o;
763 #if SIZEOF_VOID_P == 8
764         u8                 mcode;
765 #else
766         u4                 mcode[2];
767 #endif
768         unresolved_method *um;
769         methodinfo        *m;
770
771         /* get stuff from the stack */
772
773         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
774         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
775 #if SIZEOF_VOID_P == 8
776         mcode    =                       *((u8 *)     (sp + 3 * 8));
777 #else
778         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
779         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
780 #endif
781         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
782
783         PATCHER_MONITORENTER;
784
785         /* get the fieldinfo */
786
787         if (!(m = resolve_method_eager(um))) {
788                 PATCHER_MONITOREXIT;
789
790                 return false;
791         }
792
793         /* patch back original code */
794
795 #if SIZEOF_VOID_P == 8
796         *((u4 *) (ra + 0 * 4)) = mcode;
797         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
798 #else
799         *((u4 *) (ra + 0 * 4)) = mcode[0];
800         *((u4 *) (ra + 1 * 4)) = mcode[1];
801 #endif
802
803         /* if we show disassembly, we have to skip the nop's */
804
805         if (opt_showdisassemble)
806                 ra = ra + 2 * 4;
807
808         /* patch vftbl index */
809
810         *((s4 *) (ra + 1 * 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
811                                                                          sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
812
813         /* synchronize instruction cache */
814
815         if (opt_showdisassemble)
816                 cacheflush(ra - 2 * 4, 4 * 4, ICACHE);
817         else
818                 cacheflush(ra, 2 * 4, ICACHE);
819
820         PATCHER_MARK_PATCHED_MONITOREXIT;
821
822         return true;
823 }
824
825
826 /* patcher_invokeinterface *****************************************************
827
828    Machine code:
829
830    <patched call position>
831    dc990000    ld       t9,0(a0)
832    df39ffa0    ld       t9,-96(t9)
833    df3e0018    ld       s8,24(t9)
834    03c0f809    jalr     s8
835    00000000    nop
836
837 *******************************************************************************/
838
839 bool patcher_invokeinterface(u1 *sp)
840 {
841         u1                *ra;
842         java_objectheader *o;
843 #if SIZEOF_VOID_P == 8
844         u8                 mcode;
845 #else
846         u4                 mcode[2];
847 #endif
848         unresolved_method *um;
849         methodinfo        *m;
850
851         /* get stuff from the stack */
852
853         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
854         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
855 #if SIZEOF_VOID_P == 8
856         mcode    =                       *((u8 *)     (sp + 3 * 8));
857 #else
858         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
859         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
860 #endif
861         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
862
863         PATCHER_MONITORENTER;
864
865         /* get the fieldinfo */
866
867         if (!(m = resolve_method_eager(um))) {
868                 PATCHER_MONITOREXIT;
869
870                 return false;
871         }
872
873         /* patch back original code */
874
875 #if SIZEOF_VOID_P == 8
876         *((u4 *) (ra + 0 * 4)) = mcode;
877         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
878 #else
879         *((u4 *) (ra + 0 * 4)) = mcode[0];
880         *((u4 *) (ra + 1 * 4)) = mcode[1];
881 #endif
882
883         /* if we show disassembly, we have to skip the nop's */
884
885         if (opt_showdisassemble)
886                 ra = ra + 2 * 4;
887
888         /* patch interfacetable index */
889
890         *((s4 *) (ra + 1 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
891                                                                          sizeof(methodptr*) * m->class->index) & 0x0000ffff);
892
893         /* patch method offset */
894
895         *((s4 *) (ra + 2 * 4)) |=
896                 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
897
898         /* synchronize instruction cache */
899
900         if (opt_showdisassemble)
901                 cacheflush(ra - 2 * 4, 5 * 4, ICACHE);
902         else
903                 cacheflush(ra, 3 * 4, ICACHE);
904
905         PATCHER_MARK_PATCHED_MONITOREXIT;
906
907         return true;
908 }
909
910
911 /* patcher_checkcast_instanceof_flags ******************************************
912
913    Machine code:
914
915    <patched call position>
916    8fc3ff24    lw       v1,-220(s8)
917    30630200    andi     v1,v1,512
918    1060000d    beq      v1,zero,0x000000001051824c
919    00000000    nop
920
921 *******************************************************************************/
922
923 bool patcher_checkcast_instanceof_flags(u1 *sp)
924 {
925         u1                *ra;
926         java_objectheader *o;
927 #if SIZEOF_VOID_P == 8
928         u8                 mcode;
929 #else
930         u4                 mcode[2];
931 #endif
932         constant_classref *cr;
933         s4                 disp;
934         u1                *pv;
935         classinfo         *c;
936
937         /* get stuff from the stack */
938
939         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
940         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
941 #if SIZEOF_VOID_P == 8
942         mcode    =                       *((u8 *)     (sp + 3 * 8));
943 #else
944         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
945         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
946 #endif
947         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
948         disp     =                       *((s4 *)     (sp + 1 * 8));
949         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
950
951         PATCHER_MONITORENTER;
952
953         /* get the fieldinfo */
954
955         if (!(c = resolve_classref_eager(cr))) {
956                 PATCHER_MONITOREXIT;
957
958                 return false;
959         }
960
961         /* patch back original code */
962
963 #if SIZEOF_VOID_P == 8
964         *((u4 *) (ra + 0 * 4)) = mcode;
965         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
966 #else
967         *((u4 *) (ra + 0 * 4)) = mcode[0];
968         *((u4 *) (ra + 1 * 4)) = mcode[1];
969 #endif
970
971         /* synchronize instruction cache */
972
973         cacheflush(ra, 2 * 4, ICACHE);
974
975         /* patch class flags */
976
977         *((s4 *) (pv + disp)) = (s4) c->flags;
978
979         /* synchronize data cache */
980
981         cacheflush(pv + disp, sizeof(s4), DCACHE);
982
983         PATCHER_MARK_PATCHED_MONITOREXIT;
984
985         return true;
986 }
987
988
989 /* patcher_checkcast_instanceof_interface **************************************
990
991    Machine code:
992
993    <patched call position>
994    dd030000    ld       v1,0(a4)
995    8c79001c    lw       t9,28(v1)
996    27390000    addiu    t9,t9,0
997    1b200082    blez     t9,zero,0x000000001051843c
998    00000000    nop
999    dc790000    ld       t9,0(v1)
1000
1001 *******************************************************************************/
1002
1003 bool patcher_checkcast_instanceof_interface(u1 *sp)
1004 {
1005         u1                *ra;
1006         java_objectheader *o;
1007 #if SIZEOF_VOID_P == 8
1008         u8                 mcode;
1009 #else
1010         u4                 mcode[2];
1011 #endif
1012         constant_classref *cr;
1013         classinfo         *c;
1014
1015         /* get stuff from the stack */
1016
1017         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
1018         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
1019 #if SIZEOF_VOID_P == 8
1020         mcode    =                       *((u8 *)     (sp + 3 * 8));
1021 #else
1022         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
1023         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
1024 #endif
1025         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
1026
1027         PATCHER_MONITORENTER;
1028
1029         /* get the fieldinfo */
1030
1031         if (!(c = resolve_classref_eager(cr))) {
1032                 PATCHER_MONITOREXIT;
1033
1034                 return false;
1035         }
1036
1037         /* patch back original code */
1038
1039 #if SIZEOF_VOID_P == 8
1040         *((u4 *) (ra + 0 * 4)) = mcode;
1041         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
1042 #else
1043         *((u4 *) (ra + 0 * 4)) = mcode[0];
1044         *((u4 *) (ra + 1 * 4)) = mcode[1];
1045 #endif
1046
1047         /* if we show disassembly, we have to skip the nop's */
1048
1049         if (opt_showdisassemble)
1050                 ra = ra + 2 * 4;
1051
1052         /* patch super class index */
1053
1054         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
1055
1056         *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
1057                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
1058
1059         /* synchronize instruction cache */
1060
1061         if (opt_showdisassemble)
1062                 cacheflush(ra - 2 * 4, 8 * 4, ICACHE);
1063         else
1064                 cacheflush(ra, 6 * 4, ICACHE);
1065
1066         PATCHER_MARK_PATCHED_MONITOREXIT;
1067
1068         return true;
1069 }
1070
1071
1072 /* patcher_checkcast_instanceof_class ******************************************
1073
1074    Machine code:
1075
1076    <patched call position>
1077    dd030000    ld       v1,0(a4)
1078    dfd9ff18    ld       t9,-232(s8)
1079
1080 *******************************************************************************/
1081
1082 bool patcher_checkcast_instanceof_class(u1 *sp)
1083 {
1084         u1                *ra;
1085         java_objectheader *o;
1086 #if SIZEOF_VOID_P == 8
1087         u8                 mcode;
1088 #else
1089         u4                 mcode[2];
1090 #endif
1091         constant_classref *cr;
1092         s4                 disp;
1093         u1                *pv;
1094         classinfo         *c;
1095
1096         /* get stuff from the stack */
1097
1098         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
1099         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
1100 #if SIZEOF_VOID_P == 8
1101         mcode    =                       *((u8 *)     (sp + 3 * 8));
1102 #else
1103         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
1104         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
1105 #endif
1106         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
1107         disp     =                       *((s4 *)     (sp + 1 * 8));
1108         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
1109
1110         PATCHER_MONITORENTER;
1111
1112         /* get the fieldinfo */
1113
1114         if (!(c = resolve_classref_eager(cr))) {
1115                 PATCHER_MONITOREXIT;
1116
1117                 return false;
1118         }
1119
1120         /* patch back original code */
1121
1122 #if SIZEOF_VOID_P == 8
1123         *((u4 *) (ra + 0 * 4)) = mcode;
1124         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
1125 #else
1126         *((u4 *) (ra + 0 * 4)) = mcode[0];
1127         *((u4 *) (ra + 1 * 4)) = mcode[1];
1128 #endif
1129
1130         /* synchronize instruction cache */
1131
1132         cacheflush(ra, 2 * 4, ICACHE);
1133
1134         /* patch super class' vftbl */
1135
1136         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
1137
1138         /* synchronize data cache */
1139
1140         cacheflush(pv + disp, SIZEOF_VOID_P, DCACHE);
1141
1142         PATCHER_MARK_PATCHED_MONITOREXIT;
1143
1144         return true;
1145 }
1146
1147
1148 /* patcher_clinit **************************************************************
1149
1150    No special machine code.
1151
1152 *******************************************************************************/
1153
1154 bool patcher_clinit(u1 *sp)
1155 {
1156         u1                *ra;
1157         java_objectheader *o;
1158 #if SIZEOF_VOID_P == 8
1159         u8                 mcode;
1160 #else
1161         u4                 mcode[2];
1162 #endif
1163         classinfo         *c;
1164
1165         /* get stuff from the stack */
1166
1167         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
1168         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
1169 #if SIZEOF_VOID_P == 8
1170         mcode    =                       *((u8 *)     (sp + 3 * 8));
1171 #else
1172         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
1173         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
1174 #endif
1175         c        = (classinfo *)         *((ptrint *) (sp + 2 * 8));
1176
1177         PATCHER_MONITORENTER;
1178
1179         /* check if the class is initialized */
1180
1181         if (!c->initialized) {
1182                 if (!initialize_class(c)) {
1183                         PATCHER_MONITOREXIT;
1184
1185                         return false;
1186                 }
1187         }
1188
1189         /* patch back original code */
1190
1191 #if SIZEOF_VOID_P == 8
1192         *((u4 *) (ra + 0 * 4)) = mcode;
1193         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
1194 #else
1195         *((u4 *) (ra + 0 * 4)) = mcode[0];
1196         *((u4 *) (ra + 1 * 4)) = mcode[1];
1197 #endif
1198
1199         /* synchronize instruction cache */
1200
1201         cacheflush(ra, 2 * 4, ICACHE);
1202
1203         PATCHER_MARK_PATCHED_MONITOREXIT;
1204
1205         return true;
1206 }
1207
1208
1209 /* patcher_athrow_areturn ******************************************************
1210
1211    Machine code:
1212
1213    <patched call position>
1214
1215 *******************************************************************************/
1216
1217 bool patcher_athrow_areturn(u1 *sp)
1218 {
1219         u1                *ra;
1220         java_objectheader *o;
1221 #if SIZEOF_VOID_P == 8
1222         u8                 mcode;
1223 #else
1224         u4                 mcode[2];
1225 #endif
1226         unresolved_class  *uc;
1227         classinfo         *c;
1228
1229         /* get stuff from the stack */
1230
1231         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
1232         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
1233 #if SIZEOF_VOID_P == 8
1234         mcode    =                       *((u8 *)     (sp + 3 * 8));
1235 #else
1236         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
1237         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
1238 #endif
1239         uc       = (unresolved_class *)  *((ptrint *) (sp + 2 * 8));
1240
1241         PATCHER_MONITORENTER;
1242
1243         /* resolve the class */
1244
1245         if (!resolve_class(uc, resolveEager, false, &c)) {
1246                 PATCHER_MONITOREXIT;
1247
1248                 return false;
1249         }
1250
1251         /* patch back original code */
1252
1253 #if SIZEOF_VOID_P == 8
1254         *((u4 *) (ra + 0 * 4)) = mcode;
1255         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
1256 #else
1257         *((u4 *) (ra + 0 * 4)) = mcode[0];
1258         *((u4 *) (ra + 1 * 4)) = mcode[1];
1259 #endif
1260
1261         /* synchronize instruction cache */
1262
1263         cacheflush(ra, 2 * 4, ICACHE);
1264
1265         PATCHER_MARK_PATCHED_MONITOREXIT;
1266
1267         return true;
1268 }
1269
1270
1271 /* patcher_resolve_native ******************************************************
1272
1273    XXX
1274
1275 *******************************************************************************/
1276
1277 #if !defined(ENABLE_STATICVM)
1278 bool patcher_resolve_native(u1 *sp)
1279 {
1280         u1                *ra;
1281         java_objectheader *o;
1282 #if SIZEOF_VOID_P == 8
1283         u8                 mcode;
1284 #else
1285         u4                 mcode[2];
1286 #endif
1287         methodinfo        *m;
1288         s4                 disp;
1289         u1                *pv;
1290         functionptr        f;
1291
1292         /* get stuff from the stack */
1293
1294         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
1295         o        = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
1296 #if SIZEOF_VOID_P == 8
1297         mcode    =                       *((u8 *)     (sp + 3 * 8));
1298 #else
1299         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
1300         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
1301 #endif
1302         m        = (methodinfo *)        *((ptrint *) (sp + 2 * 8));
1303         disp     =                       *((s4 *)     (sp + 1 * 8));
1304         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
1305
1306         /* calculate and set the new return address */
1307
1308         ra = ra - 2 * 4;
1309         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
1310
1311         PATCHER_MONITORENTER;
1312
1313         /* resolve native function */
1314
1315         if (!(f = native_resolve_function(m))) {
1316                 PATCHER_MONITOREXIT;
1317
1318                 return false;
1319         }
1320
1321         /* patch back original code */
1322
1323 #if SIZEOF_VOID_P == 8
1324         *((u4 *) (ra + 0 * 4)) = mcode;
1325         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
1326 #else
1327         *((u4 *) (ra + 0 * 4)) = mcode[0];
1328         *((u4 *) (ra + 1 * 4)) = mcode[1];
1329 #endif
1330
1331         /* synchronize instruction cache */
1332
1333         cacheflush(ra, 2 * 4, ICACHE);
1334
1335         /* patch native function pointer */
1336
1337         *((ptrint *) (pv + disp)) = (ptrint) f;
1338
1339         /* synchronize data cache */
1340
1341         cacheflush(pv + disp, SIZEOF_VOID_P, DCACHE);
1342
1343         PATCHER_MARK_PATCHED_MONITOREXIT;
1344
1345         return true;
1346 }
1347 #endif /* !defined(ENABLE_STATICVM) */
1348
1349
1350 /*
1351  * These are local overrides for various environment variables in Emacs.
1352  * Please do not remove this and leave it at the end of the file, where
1353  * Emacs will automagically detect them.
1354  * ---------------------------------------------------------------------
1355  * Local variables:
1356  * mode: c
1357  * indent-tabs-mode: t
1358  * c-basic-offset: 4
1359  * tab-width: 4
1360  * End:
1361  * vim:noexpandtab:sw=4:ts=4:
1362  */