* src/vm/jit/s390/asmpart.S
[cacao.git] / src / vm / jit / s390 / patcher.c
1 /* src/vm/jit/x86_64/patcher.c - x86_64 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    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28
29    Changes:
30
31    $Id: patcher.c 8096 2007-06-17 13:45:58Z pm $
32
33      GENERATED      PATCHER BRANCH           AFTER PATCH
34
35    Short patcher call:
36
37      foo            bras %r14, OFFSET        foo
38      bar     ===>   bar                ===>  bar
39      baz            baz                      baz
40
41    Short patcher call with nops:
42                                              PATCHER_NOPS_SKIP <-+
43                                                                  |
44      nop            bras %r14, OFFSET        nop               --+
45      nop     ===>   nop                ===>  nop                 |
46      nop            nop                      nop               --+
47      foo            foo                      foo
48
49    Long pacher call:
50                                 PATCHER_LONGBRANCHES_NOPS_SKIP <-+
51                                                                  |
52      br exit:       ild itmp3, disp(pv)      br exit            -+
53          nop            aadd pv, itmp3           aadd pv, itmp3      | 
54          nop     ===>   nop                ===>  nop                 |
55          .....          ....                     ....                |
56          nop            basr itmp3, itmp3        basr itmp3, itmp3  -+
57    exit:                                   exit:
58
59 */
60
61
62 #include "config.h"
63 #include "vm/types.h"
64
65 #include "vm/jit/s390/codegen.h"
66 #include "vm/jit/s390/md-abi.h"
67
68 #include "mm/memory.h"
69 #include "native/native.h"
70 #include "vm/builtin.h"
71 #include "vmcore/class.h"
72 #include "vm/exceptions.h"
73 #include "vmcore/field.h"
74 #include "vm/initialize.h"
75 #include "vmcore/options.h"
76 #include "vmcore/references.h"
77 #include "vm/resolve.h"
78 #include "vm/jit/patcher.h"
79 #include "vm/jit/stacktrace.h"
80
81 #include <assert.h>
82 #define OOPS() assert(0);
83 #define __PORTED__
84
85 /* A normal patcher branch done using BRAS */
86 #define PATCHER_IS_SHORTBRANCH(brcode) ((brcode & 0xFF0F0000) == 0xA7050000)
87
88 /* patcher_wrapper *************************************************************
89
90    Wrapper for all patchers.  It also creates the stackframe info
91    structure.
92
93    If the return value of the patcher function is false, it gets the
94    exception object, clears the exception pointer and returns the
95    exception.
96
97 *******************************************************************************/
98
99 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
100 {
101         stackframeinfo     sfi;
102         u1                *xpc;
103         java_objectheader *o;
104         functionptr        f;
105         bool               result;
106         java_objectheader *e;
107
108         /* define the patcher function */
109
110         bool (*patcher_function)(u1 *);
111
112         /* get stuff from the stack */
113
114         xpc = (u1 *)                *((ptrint *) (sp + 5 * 4));
115         o   = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
116         f   = (functionptr)         *((ptrint *) (sp + 0 * 4));
117         
118         /* For a normal branch, the patch position is SZ_BRAS bytes before the RA.
119          * For long branches it is PATCHER_LONGBRANCHES_NOPS_SKIP before the RA.
120          */
121
122         if (PATCHER_IS_SHORTBRANCH(*(u4 *)(xpc - SZ_BRAS))) {
123                 xpc = xpc - SZ_BRAS;
124         } else {
125                 xpc = xpc - PATCHER_LONGBRANCHES_NOPS_SKIP;
126         }
127
128         *((ptrint *) (sp + 5 * 4)) = (ptrint) xpc;
129
130         /* store PV into the patcher function position */
131
132         *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
133
134         /* cast the passed function to a patcher function */
135
136         patcher_function = (bool (*)(u1 *)) (ptrint) f;
137
138         /* enter a monitor on the patching position */
139
140         PATCHER_MONITORENTER;
141
142         /* create the stackframeinfo */
143
144         /* RA is passed as NULL, but the XPC is correct and can be used in
145            stacktrace_create_extern_stackframeinfo for
146            md_codegen_get_pv_from_pc. */
147
148         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + (6 * 4), ra, xpc);
149
150         /* call the proper patcher function */
151
152         result = (patcher_function)(sp);
153
154         /* remove the stackframeinfo */
155
156         stacktrace_remove_stackframeinfo(&sfi);
157
158         /* check for return value and exit accordingly */
159
160         if (result == false) {
161                 e = exceptions_get_and_clear_exception();
162
163                 PATCHER_MONITOREXIT;
164
165                 return e;
166         }
167
168         PATCHER_MARK_PATCHED_MONITOREXIT;
169
170         return NULL;
171 }
172
173
174 /* patcher_get_putstatic *******************************************************
175
176    Machine code:
177
178 *******************************************************************************/
179
180 bool patcher_get_putstatic(u1 *sp)
181 {
182         u1               *ra;
183         u4                mcode;
184         unresolved_field *uf;
185         s4                disp;
186         fieldinfo        *fi;
187         u1               *pv;
188
189         /* get stuff from the stack */
190
191         ra    = (u1 *)               *((ptrint *) (sp + 5 * 4));
192         mcode =                      *((u4 *)     (sp + 3 * 4));
193         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
194         disp  =                      *((s4 *)     (sp + 1 * 4));
195         pv    = (u1 *)               *((ptrint *) (sp + 0 * 4));
196
197         /* get the fieldinfo */
198
199         if (!(fi = resolve_field_eager(uf)))
200                 return false;
201
202         /* check if the field's class is initialized */
203
204         if (!(fi->class->state & CLASS_INITIALIZED))
205                 if (!initialize_class(fi->class))
206                         return false;
207
208         *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
209
210         /* patch back original code */
211
212         *((u4 *) ra) = mcode;
213
214         return true;
215 }
216
217
218 /* patcher_get_putfield ********************************************************
219
220    Machine code:
221
222 *******************************************************************************/
223
224 bool patcher_get_putfield(u1 *sp)
225 {
226         u1               *ra;
227         u4                mcode, brcode;
228         unresolved_field *uf;
229         fieldinfo        *fi;
230         u1                byte;
231         s4                disp;
232
233         /* get stuff from the stack */
234
235         ra    = (u1 *)               *((ptrint *) (sp + 5 * 4));
236         mcode =                      *((u4 *)     (sp + 3 * 4));
237         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
238         disp  =                      *((s4 *)     (sp + 1 * 4));
239
240         /* get the fieldinfo */
241
242         if (!(fi = resolve_field_eager(uf)))
243                 return false;
244
245         /* patch back original code */
246
247         brcode = *((u4 *) ra);
248         *((u4 *) ra) = mcode;
249
250         /* If NOPs are generated, skip them */
251
252         if (! PATCHER_IS_SHORTBRANCH(brcode))
253                 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
254         else if (opt_shownops)
255                 ra += PATCHER_NOPS_SKIP;
256
257         /* If there is an operand load before, skip the load size passed in disp (see ICMD_PUTFIELD) */
258
259         ra += disp;
260
261         /* patch correct offset */
262
263         if (fi->type == TYPE_LNG) {
264                 assert(N_VALID_DISP(fi->offset + 4));
265                 /* 2 RX operations, for 2 words; each already contains a 0 or 4 offset. */
266                 *((u4 *) ra ) |= (fi->offset + (*((u4 *) ra) & 0xF));
267                 ra += 4;
268                 *((u4 *) ra ) |= (fi->offset + (*((u4 *) ra) & 0xF));
269         } else {
270                 assert(N_VALID_DISP(fi->offset));
271                 /* 1 RX operation */
272                 *((u4 *) ra) |= fi->offset;
273         }
274
275         return true;
276 }
277
278 /* patcher_invokestatic_special ************************************************
279
280    Machine code:
281
282 *******************************************************************************/
283
284 __PORTED__ bool patcher_invokestatic_special(u1 *sp)
285 {
286         u1                *ra;
287         u4                 mcode;
288         unresolved_method *um;
289         s4                 disp;
290         u1                *pv;
291         methodinfo        *m;
292
293         /* get stuff from the stack */
294
295         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
296         mcode =                       *((u4 *)     (sp + 3 * 4));
297         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
298         disp  =                       *((s4 *)     (sp + 1 * 4));
299         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
300
301         /* get the fieldinfo */
302
303         if (!(m = resolve_method_eager(um)))
304                 return false;
305
306         *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
307
308         /* patch back original code */
309
310         *((u4 *) ra) = mcode;
311
312         /* patch stubroutine */
313
314         return true;
315 }
316
317
318 /* patcher_invokevirtual *******************************************************
319
320    Machine code:
321
322 *******************************************************************************/
323
324 bool patcher_invokevirtual(u1 *sp)
325 {
326         u1                *ra;
327         u4                 mcode, brcode;
328         unresolved_method *um;
329         methodinfo        *m;
330         s4                off;
331
332         /* get stuff from the stack */
333
334         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
335         mcode =                       *((u4 *)     (sp + 3 * 4));
336         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
337
338         /* get the fieldinfo */
339
340         if (!(m = resolve_method_eager(um)))
341                 return false;
342
343         /* patch back original code */
344
345         brcode = *((u4 *) ra);
346         *((u4 *) ra) = mcode;
347
348         /* If NOPs are generated, skip them */
349
350         if (! PATCHER_IS_SHORTBRANCH(brcode))
351                 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
352         else if (opt_shownops)
353                 ra += PATCHER_NOPS_SKIP;
354
355         /* patch vftbl index */
356
357
358         off = (s4) (OFFSET(vftbl_t, table[0]) +
359                                                                    sizeof(methodptr) * m->vftblindex);
360
361         assert(N_VALID_DISP(off));
362
363         *((s4 *)(ra + 4)) |= off;
364
365         return true;
366 }
367
368
369 /* patcher_invokeinterface *****************************************************
370
371    Machine code:
372
373 *******************************************************************************/
374
375 bool patcher_invokeinterface(u1 *sp)
376 {
377         u1                *ra;
378         u4                 mcode, brcode;
379         unresolved_method *um;
380         methodinfo        *m;
381         s4                 idx, off;
382
383         /* get stuff from the stack */
384
385         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
386         mcode =                       *((u4 *)     (sp + 3 * 4));
387         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
388
389         /* get the fieldinfo */
390
391         if (!(m = resolve_method_eager(um)))
392                 return false;
393
394         /* patch back original code */
395
396         brcode = *((u4 *) ra);
397         *((u4 *) ra) = mcode;
398
399         /* If NOPs are generated, skip them */
400
401         if (! PATCHER_IS_SHORTBRANCH(brcode))
402                 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
403         else if (opt_shownops)
404                 ra += PATCHER_NOPS_SKIP;
405
406         /* get interfacetable index */
407
408         idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
409                 sizeof(methodptr) * m->class->index) + 
410                 N_DISP_MAX;
411
412         ASSERT_VALID_DISP(idx);
413
414         /* get method offset */
415
416         off =
417                 (s4) (sizeof(methodptr) * (m - m->class->methods));
418         ASSERT_VALID_DISP(off);
419
420         /* patch them */
421
422         *((s4 *)(ra + 4)) |= idx;
423         *((s4 *)(ra + 4 + 4)) |= off;
424
425         return true;
426 }
427
428
429 /* patcher_resolve_classref_to_flags *******************************************
430
431    CHECKCAST/INSTANCEOF:
432
433    <patched call position>
434
435 *******************************************************************************/
436
437 __PORTED__ bool patcher_resolve_classref_to_flags(u1 *sp)
438 {
439         constant_classref *cr;
440         s4                 disp;
441         u1                *pv;
442         classinfo         *c;
443         u4                 mcode;
444         u1                *ra;
445
446         /* get stuff from the stack */
447
448         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
449         mcode =                       *((u4 *)     (sp + 3 * 4));
450         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
451         disp  =                       *((s4 *)     (sp + 1 * 4));
452         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
453
454         /* get the fieldinfo */
455
456         if (!(c = resolve_classref_eager(cr)))
457                 return false;
458
459         /* patch class flags */
460
461         *((s4 *) (pv + disp)) = (s4) c->flags;
462
463         /* patch back original code */
464
465         *((u4 *) ra) = mcode;
466
467         return true;
468 }
469
470 /* patcher_resolve_classref_to_classinfo ***************************************
471
472    ACONST:
473    MULTIANEWARRAY:
474    ARRAYCHECKCAST:
475
476 *******************************************************************************/
477
478 __PORTED__ bool patcher_resolve_classref_to_classinfo(u1 *sp)
479 {
480         constant_classref *cr;
481         s4                 disp;
482         u1                *pv;
483         classinfo         *c;
484         u4                 mcode;
485         u1                *ra;
486
487         /* get stuff from the stack */
488
489         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
490         mcode =                       *((u4 *)     (sp + 3 * 4));
491         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
492         disp  =                       *((s4 *)     (sp + 1 * 4));
493         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
494
495         /* get the classinfo */
496
497         if (!(c = resolve_classref_eager(cr)))
498                 return false;
499
500         /* patch the classinfo pointer */
501
502         *((ptrint *) (pv + disp)) = (ptrint) c;
503
504         /* patch back original code */
505
506         *((u4 *) ra) = mcode;
507
508         return true;
509 }
510
511 /* patcher_resolve_classref_to_vftbl *******************************************
512
513    CHECKCAST (class):
514    INSTANCEOF (class):
515
516 *******************************************************************************/
517
518 bool patcher_resolve_classref_to_vftbl(u1 *sp)
519 {
520         constant_classref *cr;
521         s4                 disp;
522         u1                *pv;
523         classinfo         *c;
524         u4                 mcode;
525         u1                *ra;
526
527         /* get stuff from the stack */
528
529         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
530         mcode =                       *((u4 *)     (sp + 3 * 4));
531         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
532         disp  =                       *((s4 *)     (sp + 1 * 4));
533         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
534
535         /* get the fieldinfo */
536
537         if (!(c = resolve_classref_eager(cr)))
538                 return false;
539
540         /* patch super class' vftbl */
541
542         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
543
544         /* patch back original code */
545
546         *((u4 *) ra) = mcode;
547
548         return true;
549 }
550
551 /* patcher_checkcast_instanceof_interface **************************************
552
553    Machine code:
554
555 *******************************************************************************/
556
557 bool patcher_checkcast_instanceof_interface(u1 *sp)
558 {
559         u1                *ra;
560         u4                 mcode, brcode;
561         constant_classref *cr;
562         classinfo         *c;
563
564         /* get stuff from the stack */
565
566         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
567         mcode =                       *((u4 *)     (sp + 3 * 4));
568         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
569
570         /* get the fieldinfo */
571
572         if (!(c = resolve_classref_eager(cr)))
573                 return false;
574
575         /* patch back original code */
576
577         brcode = *((u4 *) ra);
578         *((u4 *) ra) = mcode;
579
580         /* If NOPs are generated, skip them */
581
582         if (! PATCHER_IS_SHORTBRANCH(brcode))
583                 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
584         else if (opt_shownops)
585                 ra += PATCHER_NOPS_SKIP;
586
587         /* patch super class index */
588
589         /* From here, split your editor and open codegen.c */
590
591         switch (*(ra + 1) >> 4) {
592                 case REG_ITMP1: 
593                         /* First M_ALD is into ITMP1 */
594                         /* INSTANCEOF code */
595
596                         *(u4 *)(ra + SZ_L + SZ_L) |= (u2)(s2)(- c->index);
597                         *(u4 *)(ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC) |=
598                                 (u2)(s2)(OFFSET(vftbl_t, interfacetable[0]) -
599                                         c->index * sizeof(methodptr*));
600
601                         break;
602
603                 case REG_ITMP2:
604                         /* First M_ALD is into ITMP2 */
605                         /* CHECKCAST code */
606
607                         *(u4 *)(ra + SZ_L + SZ_L) |= (u2)(s2)(- c->index);
608                         *(u4 *)(ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC + SZ_ILL) |=
609                                 (u2)(s2)(OFFSET(vftbl_t, interfacetable[0]) -
610                                         c->index * sizeof(methodptr*));
611
612                         break;
613
614                 default:
615                         assert(0);
616                         break;
617         }
618
619         return true;
620 }
621
622 /* patcher_clinit **************************************************************
623
624    May be used for GET/PUTSTATIC and in native stub.
625
626    Machine code:
627
628 *******************************************************************************/
629
630 __PORTED__ bool patcher_clinit(u1 *sp)
631 {
632         u1        *ra;
633         u4         mcode;
634         classinfo *c;
635
636         /* get stuff from the stack */
637
638         ra    = (u1 *)        *((ptrint *) (sp + 5 * 4));
639         mcode =               *((u4 *)     (sp + 3 * 4));
640         c     = (classinfo *) *((ptrint *) (sp + 2 * 4));
641
642         /* check if the class is initialized */
643
644         if (!(c->state & CLASS_INITIALIZED))
645                 if (!initialize_class(c))
646                         return false;
647
648         /* patch back original code */
649
650         *((u4 *) ra) = mcode;
651
652         return true;
653 }
654
655
656 /* patcher_athrow_areturn ******************************************************
657
658    Machine code:
659
660    <patched call position>
661
662 *******************************************************************************/
663
664 #ifdef ENABLE_VERIFIER
665 __PORTED__ bool patcher_athrow_areturn(u1 *sp)
666 {
667         u1               *ra;
668         u4                mcode;
669         unresolved_class *uc;
670
671         /* get stuff from the stack */
672
673         ra    = (u1 *)               *((ptrint *) (sp + 5 * 4));
674         mcode =                      *((u4 *)     (sp + 3 * 4));
675         uc    = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
676
677         /* resolve the class and check subtype constraints */
678
679         if (!resolve_class_eager_no_access_check(uc))
680                 return false;
681
682         /* patch back original code */
683
684         *((u4 *) ra) = mcode;
685
686         return true;
687 }
688 #endif /* ENABLE_VERIFIER */
689
690
691 /* patcher_resolve_native ******************************************************
692
693 *******************************************************************************/
694
695 #if !defined(WITH_STATIC_CLASSPATH)
696 __PORTED__ bool patcher_resolve_native(u1 *sp)
697 {
698         u1          *ra;
699         u4           mcode;
700         methodinfo  *m;
701         functionptr  f;
702         s4           disp;
703         u1          *pv;
704
705         /* get stuff from the stack */
706
707         ra    = (u1 *)         *((ptrint *) (sp + 5 * 4));
708         mcode =                *((u4 *)     (sp + 3 * 4));
709         disp  =                *((s4 *)     (sp + 1 * 4));
710         m     = (methodinfo *) *((ptrint *) (sp + 2 * 4));
711         pv    = (u1 *)         *((ptrint *) (sp + 0 * 4));
712
713         /* resolve native function */
714
715         if (!(f = native_resolve_function(m)))
716                 return false;
717
718         /* patch native function pointer */
719
720         *((ptrint *) (pv + disp)) = (ptrint) f;
721
722         /* patch back original code */
723
724         *((u4 *) ra) = mcode;
725
726         return true;
727 }
728 #endif /* !defined(WITH_STATIC_CLASSPATH) */
729
730
731 /*
732  * These are local overrides for various environment variables in Emacs.
733  * Please do not remove this and leave it at the end of the file, where
734  * Emacs will automagically detect them.
735  * ---------------------------------------------------------------------
736  * Local variables:
737  * mode: c
738  * indent-tabs-mode: t
739  * c-basic-offset: 4
740  * tab-width: 4
741  * End:
742  * vim:noexpandtab:sw=4:ts=4:
743  */