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