74a38211837300af907f4b979ab55ce1a45775c2
[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 7581 2007-03-26 07:23:16Z pm $
32
33 */
34
35
36 #include "config.h"
37 #include "vm/types.h"
38
39 #include "vm/jit/s390/codegen.h"
40 #include "vm/jit/s390/md-abi.h"
41
42 #include "mm/memory.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
45 #include "vmcore/class.h"
46 #include "vm/exceptions.h"
47 #include "vmcore/field.h"
48 #include "vm/initialize.h"
49 #include "vmcore/options.h"
50 #include "vmcore/references.h"
51 #include "vm/resolve.h"
52 #include "vm/jit/patcher.h"
53 #include "vm/jit/stacktrace.h"
54
55 #include <assert.h>
56 #define OOPS() assert(0);
57 #define __PORTED__
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_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
71 {
72 #if 1
73         stackframeinfo     sfi;
74         u1                *xpc;
75         java_objectheader *o;
76         functionptr        f;
77         bool               result;
78         java_objectheader *e;
79
80         /* define the patcher function */
81
82         bool (*patcher_function)(u1 *);
83
84         /* get stuff from the stack */
85
86         xpc = (u1 *)                *((ptrint *) (sp + 5 * 4));
87         o   = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
88         f   = (functionptr)         *((ptrint *) (sp + 0 * 4));
89         
90         xpc = xpc - 4; /* the patch position is 4 bytes before the RA */
91
92         *((ptrint *) (sp + 5 * 4)) = (ptrint) xpc;
93
94         /* store PV into the patcher function position */
95
96         *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
97
98         /* cast the passed function to a patcher function */
99
100         patcher_function = (bool (*)(u1 *)) (ptrint) f;
101
102         /* enter a monitor on the patching position */
103
104         PATCHER_MONITORENTER;
105
106         /* create the stackframeinfo */
107
108         /* RA is passed as NULL, but the XPC is correct and can be used in
109            stacktrace_create_extern_stackframeinfo for
110            md_codegen_get_pv_from_pc. */
111
112         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + (6 * 4), ra, xpc);
113
114         /* call the proper patcher function */
115
116         result = (patcher_function)(sp);
117
118         /* remove the stackframeinfo */
119
120         stacktrace_remove_stackframeinfo(&sfi);
121
122         /* check for return value and exit accordingly */
123
124         if (result == false) {
125                 e = exceptions_get_and_clear_exception();
126
127                 PATCHER_MONITOREXIT;
128
129                 return e;
130         }
131
132         PATCHER_MARK_PATCHED_MONITOREXIT;
133
134         return NULL;
135 #else
136
137         stackframeinfo     sfi;
138         u1                *xpc;
139         java_objectheader *o;
140         u4                 mcode;
141         functionptr        f;
142         bool               result;
143         java_objectheader *e;
144
145         /* define the patcher function */
146
147         bool (*patcher_function)(u1 *);
148
149         assert(pv != NULL);
150
151         /* get stuff from the stack */
152
153         xpc = (u1 *)                *((ptrint *) (sp + 5 * 4));
154         o   = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
155         f   = (functionptr)         *((ptrint *) (sp + 0 * 4));
156
157         /* Correct RA is calculated in codegen.c and stored in the patcher
158            stub stack.  There's no need to adjust xpc. */
159
160         /* store PV into the patcher function position */
161
162         *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
163
164         /* cast the passed function to a patcher function */
165
166         patcher_function = (bool (*)(u1 *)) (ptrint) f;
167
168         /* enter a monitor on the patching position */
169
170         PATCHER_MONITORENTER;
171
172         /* create the stackframeinfo */
173
174         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 8 * 4, ra, xpc);
175
176         /* call the proper patcher function */
177
178         result = (patcher_function)(sp);
179
180         /* remove the stackframeinfo */
181
182         stacktrace_remove_stackframeinfo(&sfi);
183
184         /* check for return value and exit accordingly */
185
186         if (result == false) {
187                 e = exceptions_get_and_clear_exception();
188
189                 PATCHER_MONITOREXIT;
190
191                 return e;
192         }
193
194         PATCHER_MARK_PATCHED_MONITOREXIT;
195
196         return NULL;
197 #endif
198 }
199
200
201 /* patcher_get_putstatic *******************************************************
202
203    Machine code:
204
205 *******************************************************************************/
206
207 bool patcher_get_putstatic(u1 *sp)
208 {
209         u1               *ra;
210         u4                mcode;
211         unresolved_field *uf;
212         s4                disp;
213         fieldinfo        *fi;
214         u1               *pv;
215
216         /* get stuff from the stack */
217
218         ra    = (u1 *)               *((ptrint *) (sp + 5 * 4));
219         mcode =                      *((u4 *)     (sp + 3 * 4));
220         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
221         disp  =                      *((s4 *)     (sp + 1 * 4));
222         pv    = (u1 *)               *((ptrint *) (sp + 0 * 4));
223
224         /* get the fieldinfo */
225
226         if (!(fi = resolve_field_eager(uf)))
227                 return false;
228
229         /* check if the field's class is initialized */
230
231         if (!(fi->class->state & CLASS_INITIALIZED))
232                 if (!initialize_class(fi->class))
233                         return false;
234
235         *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
236
237         /* patch back original code */
238
239         *((u4 *) ra) = mcode;
240
241         return true;
242 }
243
244
245 /* patcher_get_putfield ********************************************************
246
247    Machine code:
248
249 *******************************************************************************/
250
251 bool patcher_get_putfield(u1 *sp)
252 {
253         u1               *ra;
254         u4                mcode;
255         unresolved_field *uf;
256         fieldinfo        *fi;
257         u1                byte;
258
259         /* get stuff from the stack */
260
261         ra    = (u1 *)               *((ptrint *) (sp + 5 * 4));
262         mcode =                      *((u4 *)     (sp + 3 * 4));
263         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
264
265         /* get the fieldinfo */
266
267         if (!(fi = resolve_field_eager(uf)))
268                 return false;
269
270         /* patch back original code */
271
272         *((u4 *) ra) = mcode;
273
274         /* If NOPs are generated, skip them */
275
276         if (opt_shownops)
277                 ra += PATCHER_NOPS_SKIP;
278
279         /* patch correct offset */
280
281         if (fi->type == TYPE_LNG) {
282                 assert(N_VALID_DISP(fi->offset + 4));
283                 /* 2 RX operations, for 2 words; each already contains a 0 or 4 offset. */
284                 *((u4 *) ra ) |= (fi->offset + (*((u4 *) ra) & 0xF));
285                 ra += 4;
286                 *((u4 *) ra ) |= (fi->offset + (*((u4 *) ra) & 0xF));
287         } else {
288                 assert(N_VALID_DISP(fi->offset));
289                 /* 1 RX operation */
290                 *((u4 *) ra) |= fi->offset;
291         }
292
293         return true;
294 }
295
296
297 /* patcher_putfieldconst *******************************************************
298
299    Machine code:
300
301    <patched call position>
302    41 c7 85 00 00 00 00 7b 00 00 00    movl   $0x7b,0x0(%r13)
303
304 *******************************************************************************/
305
306 bool patcher_putfieldconst(u1 *sp)
307 {
308         OOPS();
309         u1               *ra;
310         u8                mcode;
311         unresolved_field *uf;
312         fieldinfo        *fi;
313
314         /* get stuff from the stack */
315
316         ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
317         mcode =                      *((u8 *)     (sp + 3 * 8));
318         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
319
320         /* get the fieldinfo */
321
322         if (!(fi = resolve_field_eager(uf)))
323                 return false;
324
325         /* patch back original code */
326
327         *((u8 *) ra) = mcode;
328
329         /* if we show disassembly, we have to skip the nop's */
330
331         if (opt_shownops)
332                 ra = ra + 5;
333
334         /* patch the field's offset */
335
336         if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
337                 /* handle special case when the base register is %r12 */
338
339                 if (*(ra + 2) == 0x84) {
340                         *((u4 *) (ra + 4))      = (u4) (fi->offset);
341                         *((u4 *) (ra + 12 + 4)) = (u4) (fi->offset + 4);
342                 }
343                 else {
344                         *((u4 *) (ra + 3))      = (u4) (fi->offset);
345                         *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
346                 }
347         }
348         else {
349                 /* handle special case when the base register is %r12 */
350
351                 if (*(ra + 2) == 0x84)
352                         *((u4 *) (ra + 4)) = (u4) (fi->offset);
353                 else
354                         *((u4 *) (ra + 3)) = (u4) (fi->offset);
355         }
356
357         return true;
358 }
359
360
361 /* patcher_aconst **************************************************************
362
363    Machine code:
364
365    <patched call position>
366    48 bf a0 f0 92 00 00 00 00 00    mov    $0x92f0a0,%rdi
367
368 *******************************************************************************/
369
370 bool patcher_aconst(u1 *sp)
371 {
372         OOPS();
373         u1                *ra;
374         u8                 mcode;
375         constant_classref *cr;
376         classinfo         *c;
377
378         /* get stuff from the stack */
379
380         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
381         mcode =                       *((u8 *)     (sp + 3 * 8));
382         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
383
384         /* get the classinfo */
385
386         if (!(c = resolve_classref_eager(cr)))
387                 return false;
388
389         /* patch back original code */
390
391         *((u8 *) ra) = mcode;
392
393         /* if we show disassembly, we have to skip the nop's */
394
395         if (opt_shownops)
396                 ra = ra + 5;
397
398         /* patch the classinfo pointer */
399
400         *((ptrint *) (ra + 2)) = (ptrint) c;
401
402         return true;
403 }
404
405
406 /* patcher_builtin_multianewarray **********************************************
407
408    Machine code:
409
410    <patched call position>
411    48 bf 02 00 00 00 00 00 00 00    mov    $0x2,%rdi
412    48 be 30 40 b2 00 00 00 00 00    mov    $0xb24030,%rsi
413    48 89 e2                         mov    %rsp,%rdx
414    48 b8 7c 96 4b 00 00 00 00 00    mov    $0x4b967c,%rax
415    48 ff d0                         callq  *%rax
416
417 *******************************************************************************/
418
419 bool patcher_builtin_multianewarray(u1 *sp)
420 {
421         OOPS();
422         u1                *ra;
423         u8                 mcode;
424         constant_classref *cr;
425         classinfo         *c;
426
427         /* get stuff from the stack */
428
429         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
430         mcode =                       *((u8 *)     (sp + 3 * 8));
431         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
432
433         /* get the classinfo */
434
435         if (!(c = resolve_classref_eager(cr)))
436                 return false;
437
438         /* patch back original code */
439
440         *((u8 *) ra) = mcode;
441
442         /* if we show disassembly, we have to skip the nop's */
443
444         if (opt_shownops)
445                 ra = ra + 5;
446
447         /* patch the classinfo pointer */
448
449         *((ptrint *) (ra + 10 + 2)) = (ptrint) c;
450
451         return true;
452 }
453
454
455 /* patcher_builtin_arraycheckcast **********************************************
456
457    Machine code:
458
459    <patched call position>
460    48 be b8 3f b2 00 00 00 00 00    mov    $0xb23fb8,%rsi
461    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
462    48 ff d0                         callq  *%rax
463
464 *******************************************************************************/
465
466 bool patcher_builtin_arraycheckcast(u1 *sp)
467 {
468         OOPS();
469         u1                *ra;
470         u8                 mcode;
471         constant_classref *cr;
472         classinfo         *c;
473
474         /* get stuff from the stack */
475
476         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
477         mcode =                       *((u8 *)     (sp + 3 * 8));
478         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
479
480         /* get the classinfo */
481
482         if (!(c = resolve_classref_eager(cr)))
483                 return false;
484
485         /* patch back original code */
486
487         *((u8 *) ra) = mcode;
488
489         /* if we show disassembly, we have to skip the nop's */
490
491         if (opt_shownops)
492                 ra = ra + 5;
493
494         /* patch the classinfo pointer */
495
496         *((ptrint *) (ra + 2)) = (ptrint) c;
497
498         return true;
499 }
500
501
502 /* patcher_invokestatic_special ************************************************
503
504    Machine code:
505
506 *******************************************************************************/
507
508 __PORTED__ bool patcher_invokestatic_special(u1 *sp)
509 {
510         u1                *ra;
511         u4                 mcode;
512         unresolved_method *um;
513         s4                 disp;
514         u1                *pv;
515         methodinfo        *m;
516
517         /* get stuff from the stack */
518
519         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
520         mcode =                       *((u4 *)     (sp + 3 * 4));
521         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
522         disp  =                       *((s4 *)     (sp + 1 * 4));
523         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
524
525         /* get the fieldinfo */
526
527         if (!(m = resolve_method_eager(um)))
528                 return false;
529
530         *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
531
532         /* patch back original code */
533
534         *((u4 *) ra) = mcode;
535
536         /* patch stubroutine */
537
538         return true;
539 }
540
541
542 /* patcher_invokevirtual *******************************************************
543
544    Machine code:
545
546 *******************************************************************************/
547
548 bool patcher_invokevirtual(u1 *sp)
549 {
550         u1                *ra;
551         u4                 mcode;
552         unresolved_method *um;
553         methodinfo        *m;
554         s4                off;
555
556         /* get stuff from the stack */
557
558         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
559         mcode =                       *((u4 *)     (sp + 3 * 4));
560         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
561
562         /* get the fieldinfo */
563
564         if (!(m = resolve_method_eager(um)))
565                 return false;
566
567         /* patch back original code */
568
569         *((u4 *) ra) = mcode;
570
571         /* If NOPs are generated, skip them */
572
573         if (opt_shownops)
574                 ra += PATCHER_NOPS_SKIP;
575
576         /* patch vftbl index */
577
578
579         off = (s4) (OFFSET(vftbl_t, table[0]) +
580                                                                    sizeof(methodptr) * m->vftblindex);
581
582         assert(N_VALID_DISP(off));
583
584         *((s4 *)(ra + 4)) |= off;
585
586         return true;
587 }
588
589
590 /* patcher_invokeinterface *****************************************************
591
592    Machine code:
593
594 *******************************************************************************/
595
596 bool patcher_invokeinterface(u1 *sp)
597 {
598         u1                *ra;
599         u4                 mcode;
600         unresolved_method *um;
601         methodinfo        *m;
602         s4                 idx, off;
603
604         /* get stuff from the stack */
605
606         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
607         mcode =                       *((u4 *)     (sp + 3 * 4));
608         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
609
610         /* get the fieldinfo */
611
612         if (!(m = resolve_method_eager(um)))
613                 return false;
614
615         /* patch back original code */
616
617         *((u4 *) ra) = mcode;
618
619         /* If NOPs are generated, skip them */
620
621         if (opt_shownops)
622                 ra += PATCHER_NOPS_SKIP;
623
624         /* get interfacetable index */
625
626         idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
627                 sizeof(methodptr) * m->class->index) + 
628                 N_DISP_MAX;
629
630         ASSERT_VALID_DISP(idx);
631
632         /* get method offset */
633
634         off =
635                 (s4) (sizeof(methodptr) * (m - m->class->methods));
636         ASSERT_VALID_DISP(off);
637
638         /* patch them */
639
640         *((s4 *)(ra + 4)) |= idx;
641         *((s4 *)(ra + 4 + 4)) |= off;
642
643         return true;
644 }
645
646
647 /* patcher_resolve_classref_to_flags *******************************************
648
649    CHECKCAST/INSTANCEOF:
650
651    <patched call position>
652
653 *******************************************************************************/
654
655 __PORTED__ bool patcher_resolve_classref_to_flags(u1 *sp)
656 {
657         constant_classref *cr;
658         s4                 disp;
659         u1                *pv;
660         classinfo         *c;
661         u4                 mcode;
662         u1                *ra;
663
664         /* get stuff from the stack */
665
666         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
667         mcode =                       *((u4 *)     (sp + 3 * 4));
668         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
669         disp  =                       *((s4 *)     (sp + 1 * 4));
670         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
671
672         /* get the fieldinfo */
673
674         if (!(c = resolve_classref_eager(cr)))
675                 return false;
676
677         /* patch class flags */
678
679         *((s4 *) (pv + disp)) = (s4) c->flags;
680
681         /* patch back original code */
682
683         *((u4 *) ra) = mcode;
684
685         return true;
686 }
687
688 /* patcher_resolve_classref_to_classinfo ***************************************
689
690    ACONST:
691    MULTIANEWARRAY:
692    ARRAYCHECKCAST:
693
694 *******************************************************************************/
695
696 __PORTED__ bool patcher_resolve_classref_to_classinfo(u1 *sp)
697 {
698         constant_classref *cr;
699         s4                 disp;
700         u1                *pv;
701         classinfo         *c;
702         u4                 mcode;
703         u1                *ra;
704
705         /* get stuff from the stack */
706
707         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
708         mcode =                       *((u4 *)     (sp + 3 * 4));
709         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
710         disp  =                       *((s4 *)     (sp + 1 * 4));
711         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
712
713         /* get the classinfo */
714
715         if (!(c = resolve_classref_eager(cr)))
716                 return false;
717
718         /* patch the classinfo pointer */
719
720         *((ptrint *) (pv + disp)) = (ptrint) c;
721
722         /* patch back original code */
723
724         *((u4 *) ra) = mcode;
725
726         return true;
727 }
728
729 /* patcher_resolve_classref_to_vftbl *******************************************
730
731    CHECKCAST (class):
732    INSTANCEOF (class):
733
734 *******************************************************************************/
735
736 bool patcher_resolve_classref_to_vftbl(u1 *sp)
737 {
738         constant_classref *cr;
739         s4                 disp;
740         u1                *pv;
741         classinfo         *c;
742         u4                 mcode;
743         u1                *ra;
744
745         /* get stuff from the stack */
746
747         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
748         mcode =                       *((u4 *)     (sp + 3 * 4));
749         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
750         disp  =                       *((s4 *)     (sp + 1 * 4));
751         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
752
753         /* get the fieldinfo */
754
755         if (!(c = resolve_classref_eager(cr)))
756                 return false;
757
758         /* patch super class' vftbl */
759
760         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
761
762         /* patch back original code */
763
764         *((u4 *) ra) = mcode;
765
766         return true;
767 }
768
769 /* patcher_checkcast_instanceof_interface **************************************
770
771    Machine code:
772
773 *******************************************************************************/
774
775 bool patcher_checkcast_instanceof_interface(u1 *sp)
776 {
777         u1                *ra;
778         u4                 mcode;
779         constant_classref *cr;
780         classinfo         *c;
781
782         /* get stuff from the stack */
783
784         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
785         mcode =                       *((u4 *)     (sp + 3 * 4));
786         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
787
788         /* get the fieldinfo */
789
790         if (!(c = resolve_classref_eager(cr)))
791                 return false;
792
793         /* patch back original code */
794
795         *((u4 *) ra) = mcode;
796
797         /* If NOPs are generated, skip them */
798
799         if (opt_shownops)
800                 ra += PATCHER_NOPS_SKIP;
801
802         /* patch super class index */
803
804         /* From here, split your editor and open codegen.c */
805
806         switch (*(ra + 1) >> 4) {
807                 case REG_ITMP1: 
808                         /* First M_ALD is into ITMP1 */
809                         /* INSTANCEOF code */
810                 case REG_ITMP2:
811                         /* First M_ALD is into ITMP1 */
812                         /* CHECKCAST code */
813
814                         *(u4 *)(ra + SZ_L + SZ_L) |= (u2)(s2)(- c->index);
815                         *(u4 *)(ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC) |=
816                                 (u2)(s2)(OFFSET(vftbl_t, interfacetable[0]) -
817                                         c->index * sizeof(methodptr*));
818
819                         break;
820
821                 default:
822                         assert(0);
823                         break;
824         }
825
826         return true;
827 }
828
829
830 /* patcher_checkcast_class *****************************************************
831
832    Machine code:
833
834    <patched call position>
835    49 bb 00 00 00 00 00 00 00 00    mov    $0x0,%r11
836    45 8b 92 20 00 00 00             mov    0x20(%r10),%r10d
837    45 8b 9b 20 00 00 00             mov    0x20(%r11),%r11d
838    4d 29 da                         sub    %r11,%r10
839    49 bb 00 00 00 00 00 00 00 00    mov    $0x0,%r11
840
841 *******************************************************************************/
842
843 bool patcher_checkcast_class(u1 *sp)
844 {
845         OOPS();
846         u1                *ra;
847         u8                 mcode;
848         constant_classref *cr;
849         classinfo         *c;
850
851         /* get stuff from the stack */
852
853         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
854         mcode =                       *((u8 *)     (sp + 3 * 8));
855         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
856
857         /* get the fieldinfo */
858
859         if (!(c = resolve_classref_eager(cr)))
860                 return false;
861
862         /* patch back original code */
863
864         *((u8 *) ra) = mcode;
865
866         /* if we show disassembly, we have to skip the nop's */
867
868         if (opt_shownops)
869                 ra = ra + 5;
870
871         /* patch super class' vftbl */
872
873         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
874         *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
875
876         return true;
877 }
878
879
880 /* patcher_instanceof_class ****************************************************
881
882    Machine code:
883
884    <patched call position>
885    49 ba 00 00 00 00 00 00 00 00    mov    $0x0,%r10
886
887 *******************************************************************************/
888
889 bool patcher_instanceof_class(u1 *sp)
890 {
891         OOPS();
892         u1                *ra;
893         u8                 mcode;
894         constant_classref *cr;
895         classinfo         *c;
896
897         /* get stuff from the stack */
898
899         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
900         mcode =                       *((u8 *)     (sp + 3 * 8));
901         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
902
903         /* get the fieldinfo */
904
905         if (!(c = resolve_classref_eager(cr)))
906                 return false;
907
908         /* patch back original code */
909
910         *((u8 *) ra) = mcode;
911
912         /* if we show disassembly, we have to skip the nop's */
913
914         if (opt_shownops)
915                 ra = ra + 5;
916
917         /* patch super class' vftbl */
918
919         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
920
921         return true;
922 }
923
924
925 /* patcher_clinit **************************************************************
926
927    May be used for GET/PUTSTATIC and in native stub.
928
929    Machine code:
930
931 *******************************************************************************/
932
933 __PORTED__ bool patcher_clinit(u1 *sp)
934 {
935         u1        *ra;
936         u4         mcode;
937         classinfo *c;
938
939         /* get stuff from the stack */
940
941         ra    = (u1 *)        *((ptrint *) (sp + 5 * 4));
942         mcode =               *((u4 *)     (sp + 3 * 4));
943         c     = (classinfo *) *((ptrint *) (sp + 2 * 4));
944
945         /* check if the class is initialized */
946
947         if (!(c->state & CLASS_INITIALIZED))
948                 if (!initialize_class(c))
949                         return false;
950
951         /* patch back original code */
952
953         *((u4 *) ra) = mcode;
954
955         return true;
956 }
957
958
959 /* patcher_athrow_areturn ******************************************************
960
961    Machine code:
962
963    <patched call position>
964
965 *******************************************************************************/
966
967 #ifdef ENABLE_VERIFIER
968 __PORTED__ bool patcher_athrow_areturn(u1 *sp)
969 {
970         u1               *ra;
971         u4                mcode;
972         unresolved_class *uc;
973
974         /* get stuff from the stack */
975
976         ra    = (u1 *)               *((ptrint *) (sp + 5 * 4));
977         mcode =                      *((u4 *)     (sp + 3 * 4));
978         uc    = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
979
980         /* resolve the class and check subtype constraints */
981
982         if (!resolve_class_eager_no_access_check(uc))
983                 return false;
984
985         /* patch back original code */
986
987         *((u4 *) ra) = mcode;
988
989         return true;
990 }
991 #endif /* ENABLE_VERIFIER */
992
993
994 /* patcher_resolve_native ******************************************************
995
996 *******************************************************************************/
997
998 #if !defined(WITH_STATIC_CLASSPATH)
999 __PORTED__ bool patcher_resolve_native(u1 *sp)
1000 {
1001         u1          *ra;
1002         u4           mcode;
1003         methodinfo  *m;
1004         functionptr  f;
1005         s4           disp;
1006         u1          *pv;
1007
1008         /* get stuff from the stack */
1009
1010         ra    = (u1 *)         *((ptrint *) (sp + 5 * 4));
1011         mcode =                *((u4 *)     (sp + 3 * 4));
1012         disp  =                *((s4 *)     (sp + 1 * 4));
1013         m     = (methodinfo *) *((ptrint *) (sp + 2 * 4));
1014         pv    = (u1 *)         *((ptrint *) (sp + 0 * 4));
1015
1016         /* resolve native function */
1017
1018         if (!(f = native_resolve_function(m)))
1019                 return false;
1020
1021         /* patch native function pointer */
1022
1023         *((ptrint *) (pv + disp)) = (ptrint) f;
1024
1025         /* patch back original code */
1026
1027         *((u4 *) ra) = mcode;
1028
1029         return true;
1030 }
1031 #endif /* !defined(WITH_STATIC_CLASSPATH) */
1032
1033
1034 /*
1035  * These are local overrides for various environment variables in Emacs.
1036  * Please do not remove this and leave it at the end of the file, where
1037  * Emacs will automagically detect them.
1038  * ---------------------------------------------------------------------
1039  * Local variables:
1040  * mode: c
1041  * indent-tabs-mode: t
1042  * c-basic-offset: 4
1043  * tab-width: 4
1044  * End:
1045  * vim:noexpandtab:sw=4:ts=4:
1046  */