* Removed all Id tags.
[cacao.git] / src / vm / jit / sparc64 / patcher.c
1 /* src/vm/jit/mips/patcher.c - SPARC code patching functions
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25 */
26
27
28 #include "config.h"
29
30 #include <assert.h>
31 #include <stdint.h>
32
33 #include "vm/types.h"
34
35 #include "mm/memory.h"
36
37 #include "vm/jit/sparc64/md-abi.h"
38 #include "vm/jit/sparc64/codegen.h"
39
40 #include "native/native.h"
41 #include "vm/builtin.h"
42 #include "vm/exceptions.h"
43 #include "vm/initialize.h"
44
45 #include "vm/jit/asmpart.h"
46 #include "vm/jit/patcher.h"
47 #include "vm/jit/md.h"
48 #include "vm/jit/methodheader.h"
49 #include "vm/jit/stacktrace.h"
50
51 #include "vmcore/class.h"
52 #include "vmcore/field.h"
53 #include "vmcore/options.h"
54 #include "vmcore/references.h"
55 #include "vm/resolve.h"
56
57 #include "vm/jit/sparc64/solaris/macro_rename.h"
58
59 /* patcher_wrapper *************************************************************
60
61    Wrapper for all patchers.  It also creates the stackframe info
62    structure.
63
64    If the return value of the patcher function is false, it gets the
65    exception object, clears the exception pointer and returns the
66    exception.
67
68 *******************************************************************************/
69
70 java_object_t *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
71 {
72         stackframeinfo     sfi;
73         u1                *xpc;
74         u1                *javasp;
75         java_object_t *o;
76 #if SIZEOF_VOID_P == 8
77         u8                mcode;
78 #else
79         u4                mcode[2];
80 #endif
81         functionptr        f;
82         bool               result;
83         java_handle_t *e;
84         
85         /* define the patcher function */
86
87         bool (*patcher_function)(u1 *);
88
89         assert(pv != NULL);
90
91         /* get stuff from the stack */
92
93         xpc = (u1 *)                *((ptrint *) (sp + 5 * 8));
94         o   = (java_object_t *) *((ptrint *) (sp + 4 * 8));
95         f   = (functionptr)         *((ptrint *) (sp + 0 * 8));
96
97         /* store PV into the patcher function position */
98
99         *((ptrint *) (sp + 0 * 8)) = (ptrint) pv;
100
101         /* cast the passed function to a patcher function */
102
103         patcher_function = (bool (*)(u1 *)) (ptrint) f;
104
105         /* enter a monitor on the patching position */
106
107         PATCHER_MONITORENTER;
108         
109         /* the (data) sp points directly to the patcher fields */
110         /* calculate the real sp of the current java function considering the WINSAVE regs */
111         
112         javasp = sp - JITSTACK_CNT * 8 - BIAS;
113
114         /* create the stackframeinfo */
115
116         stacktrace_create_extern_stackframeinfo(&sfi, pv, javasp, ra, xpc);
117
118         /* call the proper patcher function */
119
120         result = (patcher_function)(sp);
121
122         /* remove the stackframeinfo */
123
124         stacktrace_remove_stackframeinfo(&sfi);
125
126         /* check for return value and exit accordingly */
127
128         if (result == false) {
129                 e = exceptions_get_and_clear_exception();
130
131                 PATCHER_MONITOREXIT;
132
133                 return e;
134         }
135
136         /* patch back original (potentially patched) code */
137
138 #if SIZEOF_VOID_P == 8
139         mcode    =                      *((u8 *)     (sp + 3 * 8));
140
141         *((u4 *) (xpc + 0 * 4)) = mcode >> 32;
142         *((u4 *) (xpc + 1 * 4)) = mcode;
143 #else
144         mcode[0] =                      *((u4 *)     (sp + 3 * 8));
145         mcode[1] =                      *((u4 *)     (sp + 3 * 8 + 4));
146
147         *((u4 *) (xpc + 0 * 4)) = mcode[0];
148         *((u4 *) (xpc + 1 * 4)) = mcode[1];
149 #endif
150
151
152         /* synchronize instruction cache */
153
154         md_icacheflush(xpc, PATCHER_CALL_SIZE);
155
156         PATCHER_MARK_PATCHED_MONITOREXIT;
157
158         return NULL;
159 }
160
161
162 /* patcher_get_putstatic *******************************************************
163
164    Machine code:
165
166    <patched call position>
167    xxx         ldx      at,-72(pv)
168    xxx         ld       a1,0(at)
169
170 *******************************************************************************/
171
172 bool patcher_get_putstatic(u1 *sp)
173 {
174         unresolved_field *uf;
175         s4                disp;
176         u1               *pv;
177         fieldinfo        *fi;
178
179         /* get stuff from the stack */
180
181         uf       = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
182         disp     =                      *((s4 *)     (sp + 1 * 8));
183         pv       = (u1 *)               *((ptrint *) (sp + 0 * 8));
184
185         /* get the fieldinfo */
186
187         if (!(fi = resolve_field_eager(uf)))
188                 return false;
189
190         /* check if the field's class is initialized */
191
192         if (!(fi->class->state & CLASS_INITIALIZED))
193                 if (!initialize_class(fi->class))
194                         return false;
195
196         /* patch the field value's address */
197
198         *((intptr_t *) (pv + disp)) = (intptr_t) fi->value;
199
200         /* synchronize data cache */
201
202         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
203
204         return true;
205 }
206
207
208 /* patcher_get_putfield ********************************************************
209
210    Machine code:
211
212    <patched call position>
213    8ee90020    lw       a5,32(s7)
214
215 *******************************************************************************/
216
217 bool patcher_get_putfield(u1 *sp)
218 {
219         u1               *ra;
220         unresolved_field *uf;
221         fieldinfo        *fi;
222
223
224         ra       = (u1 *)               *((ptrint *) (sp + 5 * 8));
225         uf       = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
226
227         /* get the fieldinfo */
228
229         if (!(fi = resolve_field_eager(uf)))
230                 return false;
231
232         /* if we show disassembly, we have to skip the nop's */
233
234         if (opt_shownops) {
235                 /* patch the field's offset into the instruction */
236
237                 *((u4 *) (ra + 2 * 4)) |= (s2) (fi->offset & 0x00001fff);
238
239                 /* synchronize instruction cache */
240
241                 md_icacheflush(ra + 2 * 4, 1 * 4);
242         }
243         else {
244                 /* otherwise store the patched instruction on the stack */
245
246                 *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
247         }
248
249         return true;
250 }
251
252
253 /* patcher_aconst **************************************************************
254
255    Machine code:
256
257    <patched call postition>
258    xxx         ld       a0,-104(pv)
259
260 *******************************************************************************/
261
262 bool patcher_aconst(u1 *sp)
263 {
264         constant_classref *cr;
265         s4                 disp;
266         u1                *pv;
267         classinfo         *c;
268
269         /* get stuff from the stack */
270
271         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
272         disp     =                       *((s4 *)     (sp + 1 * 8));
273         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
274
275         /* get the classinfo */
276
277         if (!(c = resolve_classref_eager(cr)))
278                 return false;
279
280         /* patch the classinfo pointer */
281
282         *((ptrint *) (pv + disp)) = (ptrint) c;
283
284         /* synchronize data cache */
285
286         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
287
288         return true;
289 }
290
291
292 /* patcher_builtin_multianewarray **********************************************
293
294    Machine code:
295
296    <patched call position>
297    dfc5ff90    ld       a1,-112(s8)
298    03a03025    move     a2,sp
299    dfd9ff88    ld       t9,-120(s8)
300    0320f809    jalr     t9
301    00000000    nop
302
303 *******************************************************************************/
304
305 bool patcher_builtin_multianewarray(u1 *sp)
306 {
307         constant_classref *cr;
308         s4                 disp;
309         u1                *pv;
310         classinfo         *c;
311
312         /* get stuff from the stack */
313
314         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
315         disp     =                       *((s4 *)     (sp + 1 * 8));
316         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
317
318         /* get the classinfo */
319
320         if (!(c = resolve_classref_eager(cr)))
321                 return false;
322
323         /* patch the classinfo pointer */
324
325         *((ptrint *) (pv + disp)) = (ptrint) c;
326
327         /* synchronize data cache */
328
329         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
330
331         return true;
332 }
333
334
335 /* patcher_builtin_arraycheckcast **********************************************
336
337    Machine code:
338
339    <patched call position>
340    dfc5ffc0    ld       a1,-64(s8)
341    dfd9ffb8    ld       t9,-72(s8)
342    0320f809    jalr     t9
343    00000000    nop
344
345 *******************************************************************************/
346
347 bool patcher_builtin_arraycheckcast(u1 *sp)
348 {
349         constant_classref *cr;
350         s4                 disp;
351         u1                *pv;
352         classinfo         *c;
353
354         /* get stuff from the stack */
355
356         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
357         disp     =                       *((s4 *)     (sp + 1 * 8));
358         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
359
360         /* get the classinfo */
361
362         if (!(c = resolve_classref_eager(cr)))
363                 return false;
364
365         /* patch the classinfo pointer */
366
367         *((ptrint *) (pv + disp)) = (ptrint) c;
368
369         /* synchronize data cache */
370
371         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
372
373         return true;
374 }
375
376
377 /* patcher_invokestatic_special ************************************************
378
379    Machine code:
380
381    <patched call position>
382    dfdeffc0    ld       s8,-64(s8)
383    03c0f809    jalr     s8
384    00000000    nop
385
386 ******************************************************************************/
387
388 bool patcher_invokestatic_special(u1 *sp)
389 {
390         unresolved_method *um;
391         s4                 disp;
392         u1                *pv;
393         methodinfo        *m;
394
395         /* get stuff from the stack */
396
397         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
398         disp     =                       *((s4 *)     (sp + 1 * 8));
399         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
400
401         /* get the fieldinfo */
402
403         if (!(m = resolve_method_eager(um)))
404                 return false;
405
406         /* patch stubroutine */
407
408         *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
409
410         /* synchronize data cache */
411
412         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
413
414         return true;
415 }
416
417
418 /* patcher_invokevirtual *******************************************************
419
420    Machine code:
421
422    <patched call position>
423    xxx         ldx      g2,0(o0)
424    xxx         ldx      o5,64(g2)
425    xxx         jmpl     o5
426    xxx         nop
427
428 *******************************************************************************/
429
430 bool patcher_invokevirtual(u1 *sp)
431 {
432         u1                *ra;
433         unresolved_method *um;
434         methodinfo        *m;
435
436         /* get stuff from the stack */
437
438         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
439         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
440
441         /* get the fieldinfo */
442
443         if (!(m = resolve_method_eager(um)))
444                 return false;
445
446         /* if we show disassembly, we have to skip the nop's */
447
448         if (opt_shownops) {
449                 ra = ra + PATCHER_CALL_SIZE;
450
451                 /* patch vftbl index */
452
453                 *((s4 *) (ra + 1 * 4)) |=
454                         (s4) ((OFFSET(vftbl_t, table[0]) +
455                                    sizeof(methodptr) * m->vftblindex) & 0x00001fff);
456
457                 /* synchronize instruction cache */
458
459                 md_icacheflush(ra + 1 * 4, 1 * 4);
460         }
461         else {
462                 /* patch vftbl index */
463
464                 *((s4 *) (sp + 3 * 8 + 4)) |=
465                         (s4) ((OFFSET(vftbl_t, table[0]) +
466                                    sizeof(methodptr) * m->vftblindex) & 0x00001fff);
467         }
468
469         return true;
470 }
471
472
473 /* patcher_invokeinterface *****************************************************
474
475    Machine code:
476
477    <patched call position>
478    dc990000    ld       t9,0(a0)
479    df39ffa0    ld       t9,-96(t9)
480    df3e0018    ld       s8,24(t9)
481    03c0f809    jalr     s8
482    00000000    nop
483
484 *******************************************************************************/
485
486 bool patcher_invokeinterface(u1 *sp)
487 {
488         u1                *ra;
489         unresolved_method *um;
490         methodinfo        *m;
491
492         /* get stuff from the stack */
493
494         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
495         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
496
497         /* get the fieldinfo */
498
499         if (!(m = resolve_method_eager(um)))
500                 return false;
501
502         /* if we show disassembly, we have to skip the nop's */
503
504         if (opt_shownops) {
505                 ra = ra + PATCHER_CALL_SIZE;
506
507                 /* patch interfacetable index */
508
509                 *((s4 *) (ra + 1 * 4)) |= 
510                         (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
511                                 sizeof(methodptr*) * m->class->index) & 0x00001fff);
512
513                 /* patch method offset */
514
515                 *((s4 *) (ra + 2 * 4)) |=
516                         (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
517
518                 /* synchronize instruction cache */
519
520                 md_icacheflush(ra + 1 * 4, 2 * 4);
521         }
522 else {
523                 /* patch interfacetable index */
524
525                 *((s4 *) (sp + 3 * 8 + 4)) |=
526                         (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
527                                 sizeof(methodptr*) * m->class->index) & 0x00001fff);
528
529                 /* patch method offset */
530
531                 *((s4 *) (ra + 2 * 4)) |=
532                         (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
533
534                 /* synchronize instruction cache */
535
536                 md_icacheflush(ra + 2 * 4, 1 * 4);
537         }
538
539         return true;
540 }
541
542
543 /* patcher_checkcast_instanceof_flags ******************************************
544
545    Machine code:
546
547    <patched call position>
548    8fc3ff24    lw       v1,-220(s8)
549    30630200    andi     v1,v1,512
550    1060000d    beq      v1,zero,0x000000001051824c
551    00000000    nop
552
553 *******************************************************************************/
554
555 bool patcher_checkcast_instanceof_flags(u1 *sp)
556 {
557         constant_classref *cr;
558         s4                 disp;
559         u1                *pv;
560         classinfo         *c;
561
562         /* get stuff from the stack */
563
564         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
565         disp     =                       *((s4 *)     (sp + 1 * 8));
566         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
567
568         /* get the fieldinfo */
569
570         if (!(c = resolve_classref_eager(cr)))
571                 return false;
572
573         /* patch class flags */
574
575         *((s4 *) (pv + disp)) = (s4) c->flags;
576
577         /* synchronize data cache */
578
579         md_dcacheflush(pv + disp, sizeof(s4));
580
581         return true;
582 }
583
584
585 /* patcher_checkcast_interface **************************************
586
587    Machine code:
588
589    <patched call position>
590    dd030000    ld       v1,0(a4)
591    8c79001c    lw       t9,28(v1)
592    27390000    addiu    t9,t9,0
593    1b200082    blez     t9,zero,0x000000001051843c
594    00000000    nop
595    dc790000    ld       t9,0(v1)
596
597 *******************************************************************************/
598
599 bool patcher_checkcast_interface(u1 *sp)
600 {
601         u1                *ra;
602         constant_classref *cr;
603         classinfo         *c;
604
605         /* get stuff from the stack */
606
607         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
608         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
609
610         /* get the fieldinfo */
611
612         if (!(c = resolve_classref_eager(cr)))
613                 return false;
614
615         /* if we show disassembly, we have to skip the nop's */
616
617         if (opt_shownops)
618                 ra = ra + PATCHER_CALL_SIZE;
619
620         /* patch super class index */
621
622         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
623
624         *((s4 *) (ra + (3 + EXCEPTION_CHECK_INSTRUCTIONS) * 4)) |= 
625                 (s4) ((OFFSET(vftbl_t, interfacetable[0])
626                 - c->index * sizeof(methodptr*)) & 0x00001fff);
627
628         /* synchronize instruction cache */
629
630         if (opt_shownops)
631                 md_icacheflush(ra - 2 * 4, (6 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
632         else
633                 md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
634
635         return true;
636 }
637
638 /* patcher_instanceof_interface ************************************************
639
640    Machine code:
641
642    <patched call position>
643    dd030000    ld       v1,0(a4)
644    8c79001c    lw       t9,28(v1)
645    27390000    addiu    t9,t9,0
646    1b200082    blez     t9,zero,0x000000001051843c
647    00000000    nop
648    dc790000    ld       t9,0(v1)
649
650 *******************************************************************************/
651
652 bool patcher_instanceof_interface(u1 *sp)
653 {
654         u1                *ra;
655         constant_classref *cr;
656         classinfo         *c;
657
658         /* get stuff from the stack */
659
660         ra = (u1 *)                *((ptrint *) (sp + 5 * 8));
661         cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
662
663         /* get the fieldinfo */
664
665         if (!(c = resolve_classref_eager(cr)))
666                 return false;
667
668         /* if we show disassembly, we have to skip the nop's */
669
670         if (opt_shownops)
671                 ra = ra + PATCHER_CALL_SIZE;
672
673         /* patch super class index */
674
675         *((s4 *) (ra + 2 * 4)) |= (s4) ((c->index) & 0x00001fff);
676         *((s4 *) (ra + 5 * 4)) |=
677                 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
678                                  c->index * sizeof(methodptr*)) & 0x00001fff);
679
680         /* synchronize instruction cache */
681
682         if (opt_shownops)
683                 md_icacheflush(ra - PATCHER_CALL_SIZE * 4, 8 * 4);
684         else
685                 md_icacheflush(ra, 6 * 4);
686
687         return true;
688 }
689
690
691 /* patcher_checkcast_instanceof_class ******************************************
692
693    Machine code:
694
695    <patched call position>
696    dd030000    ld       v1,0(a4)
697    dfd9ff18    ld       t9,-232(s8)
698
699 *******************************************************************************/
700
701 bool patcher_checkcast_instanceof_class(u1 *sp)
702 {
703         constant_classref *cr;
704         s4                 disp;
705         u1                *pv;
706         classinfo         *c;
707
708         /* get stuff from the stack */
709
710         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
711         disp     =                       *((s4 *)     (sp + 1 * 8));
712         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
713
714         /* get the fieldinfo */
715
716         if (!(c = resolve_classref_eager(cr)))
717                 return false;
718
719         /* patch super class' vftbl */
720
721         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
722
723         /* synchronize data cache */
724
725         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
726
727         return true;
728 }
729
730
731 /* patcher_clinit **************************************************************
732
733    No special machine code.
734
735 *******************************************************************************/
736
737 bool patcher_clinit(u1 *sp)
738 {
739         classinfo *c;
740
741         /* get stuff from the stack */
742
743         c        = (classinfo *) *((ptrint *) (sp + 2 * 8));
744
745         /* check if the class is initialized */
746
747         if (!(c->state & CLASS_INITIALIZED))
748                 if (!initialize_class(c))
749                         return false;
750
751         return true;
752 }
753
754
755 /* patcher_athrow_areturn ******************************************************
756
757    Machine code:
758
759    <patched call position>
760
761 *******************************************************************************/
762
763 #ifdef ENABLE_VERIFIER
764 bool patcher_athrow_areturn(u1 *sp)
765 {
766         unresolved_class *uc;
767
768         /* get stuff from the stack */
769
770         uc       = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
771
772         /* resolve the class and check subtype constraints */
773
774         if (!resolve_class_eager_no_access_check(uc))
775                 return false;
776
777         return true;
778 }
779 #endif /* ENABLE_VERIFIER */
780
781
782 /* patcher_resolve_native ******************************************************
783
784    XXX
785
786 *******************************************************************************/
787
788 #if !defined(WITH_STATIC_CLASSPATH)
789 bool patcher_resolve_native(u1 *sp)
790 {
791         methodinfo  *m;
792         s4           disp;
793         u1          *pv;
794         functionptr  f;
795
796         /* get stuff from the stack */
797
798         m        = (methodinfo *) *((ptrint *) (sp + 2 * 8));
799         disp     =                *((s4 *)     (sp + 1 * 8));
800         pv       = (u1 *)         *((ptrint *) (sp + 0 * 8));
801
802         /* return address on SPARC is address of jump, therefore correct */
803
804         /* resolve native function */
805
806         if (!(f = native_resolve_function(m)))
807                 return false;
808
809         /* patch native function pointer */
810
811         *((ptrint *) (pv + disp)) = (ptrint) f;
812
813         /* synchronize data cache */
814
815         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
816
817         return true;
818 }
819 #endif /* !defined(WITH_STATIC_CLASSPATH) */
820
821
822 /*
823  * These are local overrides for various environment variables in Emacs.
824  * Please do not remove this and leave it at the end of the file, where
825  * Emacs will automagically detect them.
826  * ---------------------------------------------------------------------
827  * Local variables:
828  * mode: c
829  * indent-tabs-mode: t
830  * c-basic-offset: 4
831  * tab-width: 4
832  * End:
833  * vim:noexpandtab:sw=4:ts=4:
834  */