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