* src/mm/cacao-gc/gc.c (gc_reference_unregister): Added.
[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 8027 2007-06-07 10:30:33Z michi $
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
279 /* patcher_putfieldconst *******************************************************
280
281    Machine code:
282
283    <patched call position>
284    41 c7 85 00 00 00 00 7b 00 00 00    movl   $0x7b,0x0(%r13)
285
286 *******************************************************************************/
287
288 bool patcher_putfieldconst(u1 *sp)
289 {
290         OOPS();
291         u1               *ra;
292         u8                mcode;
293         unresolved_field *uf;
294         fieldinfo        *fi;
295
296         /* get stuff from the stack */
297
298         ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
299         mcode =                      *((u8 *)     (sp + 3 * 8));
300         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
301
302         /* get the fieldinfo */
303
304         if (!(fi = resolve_field_eager(uf)))
305                 return false;
306
307         /* patch back original code */
308
309         *((u8 *) ra) = mcode;
310
311         /* if we show disassembly, we have to skip the nop's */
312
313         if (opt_shownops)
314                 ra = ra + 5;
315
316         /* patch the field's offset */
317
318         if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
319                 /* handle special case when the base register is %r12 */
320
321                 if (*(ra + 2) == 0x84) {
322                         *((u4 *) (ra + 4))      = (u4) (fi->offset);
323                         *((u4 *) (ra + 12 + 4)) = (u4) (fi->offset + 4);
324                 }
325                 else {
326                         *((u4 *) (ra + 3))      = (u4) (fi->offset);
327                         *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
328                 }
329         }
330         else {
331                 /* handle special case when the base register is %r12 */
332
333                 if (*(ra + 2) == 0x84)
334                         *((u4 *) (ra + 4)) = (u4) (fi->offset);
335                 else
336                         *((u4 *) (ra + 3)) = (u4) (fi->offset);
337         }
338
339         return true;
340 }
341
342
343 /* patcher_aconst **************************************************************
344
345    Machine code:
346
347    <patched call position>
348    48 bf a0 f0 92 00 00 00 00 00    mov    $0x92f0a0,%rdi
349
350 *******************************************************************************/
351
352 bool patcher_aconst(u1 *sp)
353 {
354         OOPS();
355         u1                *ra;
356         u8                 mcode;
357         constant_classref *cr;
358         classinfo         *c;
359
360         /* get stuff from the stack */
361
362         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
363         mcode =                       *((u8 *)     (sp + 3 * 8));
364         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
365
366         /* get the classinfo */
367
368         if (!(c = resolve_classref_eager(cr)))
369                 return false;
370
371         /* patch back original code */
372
373         *((u8 *) ra) = mcode;
374
375         /* if we show disassembly, we have to skip the nop's */
376
377         if (opt_shownops)
378                 ra = ra + 5;
379
380         /* patch the classinfo pointer */
381
382         *((ptrint *) (ra + 2)) = (ptrint) c;
383
384         return true;
385 }
386
387
388 /* patcher_builtin_multianewarray **********************************************
389
390    Machine code:
391
392    <patched call position>
393    48 bf 02 00 00 00 00 00 00 00    mov    $0x2,%rdi
394    48 be 30 40 b2 00 00 00 00 00    mov    $0xb24030,%rsi
395    48 89 e2                         mov    %rsp,%rdx
396    48 b8 7c 96 4b 00 00 00 00 00    mov    $0x4b967c,%rax
397    48 ff d0                         callq  *%rax
398
399 *******************************************************************************/
400
401 bool patcher_builtin_multianewarray(u1 *sp)
402 {
403         OOPS();
404         u1                *ra;
405         u8                 mcode;
406         constant_classref *cr;
407         classinfo         *c;
408
409         /* get stuff from the stack */
410
411         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
412         mcode =                       *((u8 *)     (sp + 3 * 8));
413         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
414
415         /* get the classinfo */
416
417         if (!(c = resolve_classref_eager(cr)))
418                 return false;
419
420         /* patch back original code */
421
422         *((u8 *) ra) = mcode;
423
424         /* if we show disassembly, we have to skip the nop's */
425
426         if (opt_shownops)
427                 ra = ra + 5;
428
429         /* patch the classinfo pointer */
430
431         *((ptrint *) (ra + 10 + 2)) = (ptrint) c;
432
433         return true;
434 }
435
436
437 /* patcher_builtin_arraycheckcast **********************************************
438
439    Machine code:
440
441    <patched call position>
442    48 be b8 3f b2 00 00 00 00 00    mov    $0xb23fb8,%rsi
443    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
444    48 ff d0                         callq  *%rax
445
446 *******************************************************************************/
447
448 bool patcher_builtin_arraycheckcast(u1 *sp)
449 {
450         OOPS();
451         u1                *ra;
452         u8                 mcode;
453         constant_classref *cr;
454         classinfo         *c;
455
456         /* get stuff from the stack */
457
458         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
459         mcode =                       *((u8 *)     (sp + 3 * 8));
460         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
461
462         /* get the classinfo */
463
464         if (!(c = resolve_classref_eager(cr)))
465                 return false;
466
467         /* patch back original code */
468
469         *((u8 *) ra) = mcode;
470
471         /* if we show disassembly, we have to skip the nop's */
472
473         if (opt_shownops)
474                 ra = ra + 5;
475
476         /* patch the classinfo pointer */
477
478         *((ptrint *) (ra + 2)) = (ptrint) c;
479
480         return true;
481 }
482
483
484 /* patcher_invokestatic_special ************************************************
485
486    Machine code:
487
488 *******************************************************************************/
489
490 __PORTED__ bool patcher_invokestatic_special(u1 *sp)
491 {
492         u1                *ra;
493         u4                 mcode;
494         unresolved_method *um;
495         s4                 disp;
496         u1                *pv;
497         methodinfo        *m;
498
499         /* get stuff from the stack */
500
501         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
502         mcode =                       *((u4 *)     (sp + 3 * 4));
503         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
504         disp  =                       *((s4 *)     (sp + 1 * 4));
505         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
506
507         /* get the fieldinfo */
508
509         if (!(m = resolve_method_eager(um)))
510                 return false;
511
512         *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
513
514         /* patch back original code */
515
516         *((u4 *) ra) = mcode;
517
518         /* patch stubroutine */
519
520         return true;
521 }
522
523
524 /* patcher_invokevirtual *******************************************************
525
526    Machine code:
527
528 *******************************************************************************/
529
530 bool patcher_invokevirtual(u1 *sp)
531 {
532         u1                *ra;
533         u4                 mcode, brcode;
534         unresolved_method *um;
535         methodinfo        *m;
536         s4                off;
537
538         /* get stuff from the stack */
539
540         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
541         mcode =                       *((u4 *)     (sp + 3 * 4));
542         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
543
544         /* get the fieldinfo */
545
546         if (!(m = resolve_method_eager(um)))
547                 return false;
548
549         /* patch back original code */
550
551         brcode = *((u4 *) ra);
552         *((u4 *) ra) = mcode;
553
554         /* If NOPs are generated, skip them */
555
556         if (! PATCHER_IS_SHORTBRANCH(brcode))
557                 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
558         else if (opt_shownops)
559                 ra += PATCHER_NOPS_SKIP;
560
561         /* patch vftbl index */
562
563
564         off = (s4) (OFFSET(vftbl_t, table[0]) +
565                                                                    sizeof(methodptr) * m->vftblindex);
566
567         assert(N_VALID_DISP(off));
568
569         *((s4 *)(ra + 4)) |= off;
570
571         return true;
572 }
573
574
575 /* patcher_invokeinterface *****************************************************
576
577    Machine code:
578
579 *******************************************************************************/
580
581 bool patcher_invokeinterface(u1 *sp)
582 {
583         u1                *ra;
584         u4                 mcode, brcode;
585         unresolved_method *um;
586         methodinfo        *m;
587         s4                 idx, off;
588
589         /* get stuff from the stack */
590
591         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
592         mcode =                       *((u4 *)     (sp + 3 * 4));
593         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
594
595         /* get the fieldinfo */
596
597         if (!(m = resolve_method_eager(um)))
598                 return false;
599
600         /* patch back original code */
601
602         brcode = *((u4 *) ra);
603         *((u4 *) ra) = mcode;
604
605         /* If NOPs are generated, skip them */
606
607         if (! PATCHER_IS_SHORTBRANCH(brcode))
608                 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
609         else if (opt_shownops)
610                 ra += PATCHER_NOPS_SKIP;
611
612         /* get interfacetable index */
613
614         idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
615                 sizeof(methodptr) * m->class->index) + 
616                 N_DISP_MAX;
617
618         ASSERT_VALID_DISP(idx);
619
620         /* get method offset */
621
622         off =
623                 (s4) (sizeof(methodptr) * (m - m->class->methods));
624         ASSERT_VALID_DISP(off);
625
626         /* patch them */
627
628         *((s4 *)(ra + 4)) |= idx;
629         *((s4 *)(ra + 4 + 4)) |= off;
630
631         return true;
632 }
633
634
635 /* patcher_resolve_classref_to_flags *******************************************
636
637    CHECKCAST/INSTANCEOF:
638
639    <patched call position>
640
641 *******************************************************************************/
642
643 __PORTED__ bool patcher_resolve_classref_to_flags(u1 *sp)
644 {
645         constant_classref *cr;
646         s4                 disp;
647         u1                *pv;
648         classinfo         *c;
649         u4                 mcode;
650         u1                *ra;
651
652         /* get stuff from the stack */
653
654         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
655         mcode =                       *((u4 *)     (sp + 3 * 4));
656         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
657         disp  =                       *((s4 *)     (sp + 1 * 4));
658         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
659
660         /* get the fieldinfo */
661
662         if (!(c = resolve_classref_eager(cr)))
663                 return false;
664
665         /* patch class flags */
666
667         *((s4 *) (pv + disp)) = (s4) c->flags;
668
669         /* patch back original code */
670
671         *((u4 *) ra) = mcode;
672
673         return true;
674 }
675
676 /* patcher_resolve_classref_to_classinfo ***************************************
677
678    ACONST:
679    MULTIANEWARRAY:
680    ARRAYCHECKCAST:
681
682 *******************************************************************************/
683
684 __PORTED__ bool patcher_resolve_classref_to_classinfo(u1 *sp)
685 {
686         constant_classref *cr;
687         s4                 disp;
688         u1                *pv;
689         classinfo         *c;
690         u4                 mcode;
691         u1                *ra;
692
693         /* get stuff from the stack */
694
695         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
696         mcode =                       *((u4 *)     (sp + 3 * 4));
697         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
698         disp  =                       *((s4 *)     (sp + 1 * 4));
699         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
700
701         /* get the classinfo */
702
703         if (!(c = resolve_classref_eager(cr)))
704                 return false;
705
706         /* patch the classinfo pointer */
707
708         *((ptrint *) (pv + disp)) = (ptrint) c;
709
710         /* patch back original code */
711
712         *((u4 *) ra) = mcode;
713
714         return true;
715 }
716
717 /* patcher_resolve_classref_to_vftbl *******************************************
718
719    CHECKCAST (class):
720    INSTANCEOF (class):
721
722 *******************************************************************************/
723
724 bool patcher_resolve_classref_to_vftbl(u1 *sp)
725 {
726         constant_classref *cr;
727         s4                 disp;
728         u1                *pv;
729         classinfo         *c;
730         u4                 mcode;
731         u1                *ra;
732
733         /* get stuff from the stack */
734
735         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
736         mcode =                       *((u4 *)     (sp + 3 * 4));
737         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
738         disp  =                       *((s4 *)     (sp + 1 * 4));
739         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
740
741         /* get the fieldinfo */
742
743         if (!(c = resolve_classref_eager(cr)))
744                 return false;
745
746         /* patch super class' vftbl */
747
748         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
749
750         /* patch back original code */
751
752         *((u4 *) ra) = mcode;
753
754         return true;
755 }
756
757 /* patcher_checkcast_instanceof_interface **************************************
758
759    Machine code:
760
761 *******************************************************************************/
762
763 bool patcher_checkcast_instanceof_interface(u1 *sp)
764 {
765         u1                *ra;
766         u4                 mcode, brcode;
767         constant_classref *cr;
768         classinfo         *c;
769
770         /* get stuff from the stack */
771
772         ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
773         mcode =                       *((u4 *)     (sp + 3 * 4));
774         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
775
776         /* get the fieldinfo */
777
778         if (!(c = resolve_classref_eager(cr)))
779                 return false;
780
781         /* patch back original code */
782
783         brcode = *((u4 *) ra);
784         *((u4 *) ra) = mcode;
785
786         /* If NOPs are generated, skip them */
787
788         if (! PATCHER_IS_SHORTBRANCH(brcode))
789                 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
790         else if (opt_shownops)
791                 ra += PATCHER_NOPS_SKIP;
792
793         /* patch super class index */
794
795         /* From here, split your editor and open codegen.c */
796
797         switch (*(ra + 1) >> 4) {
798                 case REG_ITMP1: 
799                         /* First M_ALD is into ITMP1 */
800                         /* INSTANCEOF code */
801
802                         *(u4 *)(ra + SZ_L + SZ_L) |= (u2)(s2)(- c->index);
803                         *(u4 *)(ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC) |=
804                                 (u2)(s2)(OFFSET(vftbl_t, interfacetable[0]) -
805                                         c->index * sizeof(methodptr*));
806
807                         break;
808
809                 case REG_ITMP2:
810                         /* First M_ALD is into ITMP2 */
811                         /* CHECKCAST code */
812
813                         *(u4 *)(ra + SZ_L + SZ_L) |= (u2)(s2)(- c->index);
814                         *(u4 *)(ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC + SZ_ILL) |=
815                                 (u2)(s2)(OFFSET(vftbl_t, interfacetable[0]) -
816                                         c->index * sizeof(methodptr*));
817
818                         break;
819
820                 default:
821                         assert(0);
822                         break;
823         }
824
825         return true;
826 }
827
828
829 /* patcher_checkcast_class *****************************************************
830
831    Machine code:
832
833    <patched call position>
834    49 bb 00 00 00 00 00 00 00 00    mov    $0x0,%r11
835    45 8b 92 20 00 00 00             mov    0x20(%r10),%r10d
836    45 8b 9b 20 00 00 00             mov    0x20(%r11),%r11d
837    4d 29 da                         sub    %r11,%r10
838    49 bb 00 00 00 00 00 00 00 00    mov    $0x0,%r11
839
840 *******************************************************************************/
841
842 bool patcher_checkcast_class(u1 *sp)
843 {
844         OOPS();
845         u1                *ra;
846         u8                 mcode;
847         constant_classref *cr;
848         classinfo         *c;
849
850         /* get stuff from the stack */
851
852         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
853         mcode =                       *((u8 *)     (sp + 3 * 8));
854         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
855
856         /* get the fieldinfo */
857
858         if (!(c = resolve_classref_eager(cr)))
859                 return false;
860
861         /* patch back original code */
862
863         *((u8 *) ra) = mcode;
864
865         /* if we show disassembly, we have to skip the nop's */
866
867         if (opt_shownops)
868                 ra = ra + 5;
869
870         /* patch super class' vftbl */
871
872         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
873         *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
874
875         return true;
876 }
877
878
879 /* patcher_instanceof_class ****************************************************
880
881    Machine code:
882
883    <patched call position>
884    49 ba 00 00 00 00 00 00 00 00    mov    $0x0,%r10
885
886 *******************************************************************************/
887
888 bool patcher_instanceof_class(u1 *sp)
889 {
890         OOPS();
891         u1                *ra;
892         u8                 mcode;
893         constant_classref *cr;
894         classinfo         *c;
895
896         /* get stuff from the stack */
897
898         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
899         mcode =                       *((u8 *)     (sp + 3 * 8));
900         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
901
902         /* get the fieldinfo */
903
904         if (!(c = resolve_classref_eager(cr)))
905                 return false;
906
907         /* patch back original code */
908
909         *((u8 *) ra) = mcode;
910
911         /* if we show disassembly, we have to skip the nop's */
912
913         if (opt_shownops)
914                 ra = ra + 5;
915
916         /* patch super class' vftbl */
917
918         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
919
920         return true;
921 }
922
923
924 /* patcher_clinit **************************************************************
925
926    May be used for GET/PUTSTATIC and in native stub.
927
928    Machine code:
929
930 *******************************************************************************/
931
932 __PORTED__ bool patcher_clinit(u1 *sp)
933 {
934         u1        *ra;
935         u4         mcode;
936         classinfo *c;
937
938         /* get stuff from the stack */
939
940         ra    = (u1 *)        *((ptrint *) (sp + 5 * 4));
941         mcode =               *((u4 *)     (sp + 3 * 4));
942         c     = (classinfo *) *((ptrint *) (sp + 2 * 4));
943
944         /* check if the class is initialized */
945
946         if (!(c->state & CLASS_INITIALIZED))
947                 if (!initialize_class(c))
948                         return false;
949
950         /* patch back original code */
951
952         *((u4 *) ra) = mcode;
953
954         return true;
955 }
956
957
958 /* patcher_athrow_areturn ******************************************************
959
960    Machine code:
961
962    <patched call position>
963
964 *******************************************************************************/
965
966 #ifdef ENABLE_VERIFIER
967 __PORTED__ bool patcher_athrow_areturn(u1 *sp)
968 {
969         u1               *ra;
970         u4                mcode;
971         unresolved_class *uc;
972
973         /* get stuff from the stack */
974
975         ra    = (u1 *)               *((ptrint *) (sp + 5 * 4));
976         mcode =                      *((u4 *)     (sp + 3 * 4));
977         uc    = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
978
979         /* resolve the class and check subtype constraints */
980
981         if (!resolve_class_eager_no_access_check(uc))
982                 return false;
983
984         /* patch back original code */
985
986         *((u4 *) ra) = mcode;
987
988         return true;
989 }
990 #endif /* ENABLE_VERIFIER */
991
992
993 /* patcher_resolve_native ******************************************************
994
995 *******************************************************************************/
996
997 #if !defined(WITH_STATIC_CLASSPATH)
998 __PORTED__ bool patcher_resolve_native(u1 *sp)
999 {
1000         u1          *ra;
1001         u4           mcode;
1002         methodinfo  *m;
1003         functionptr  f;
1004         s4           disp;
1005         u1          *pv;
1006
1007         /* get stuff from the stack */
1008
1009         ra    = (u1 *)         *((ptrint *) (sp + 5 * 4));
1010         mcode =                *((u4 *)     (sp + 3 * 4));
1011         disp  =                *((s4 *)     (sp + 1 * 4));
1012         m     = (methodinfo *) *((ptrint *) (sp + 2 * 4));
1013         pv    = (u1 *)         *((ptrint *) (sp + 0 * 4));
1014
1015         /* resolve native function */
1016
1017         if (!(f = native_resolve_function(m)))
1018                 return false;
1019
1020         /* patch native function pointer */
1021
1022         *((ptrint *) (pv + disp)) = (ptrint) f;
1023
1024         /* patch back original code */
1025
1026         *((u4 *) ra) = mcode;
1027
1028         return true;
1029 }
1030 #endif /* !defined(WITH_STATIC_CLASSPATH) */
1031
1032
1033 /*
1034  * These are local overrides for various environment variables in Emacs.
1035  * Please do not remove this and leave it at the end of the file, where
1036  * Emacs will automagically detect them.
1037  * ---------------------------------------------------------------------
1038  * Local variables:
1039  * mode: c
1040  * indent-tabs-mode: t
1041  * c-basic-offset: 4
1042  * tab-width: 4
1043  * End:
1044  * vim:noexpandtab:sw=4:ts=4:
1045  */