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