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