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