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