313620b9541d78890c4ed6fbeb9581d41bc4a354
[cacao.git] / src / vm / jit / mips / patcher.c
1 /* src/vm/jit/mips/patcher.c - MIPS 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 5164 2006-07-19 15:54:01Z twisti $
32
33 */
34
35
36 #include "config.h"
37
38 #include <assert.h>
39
40 #include "vm/types.h"
41
42 #include "mm/memory.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
45 #include "vm/class.h"
46 #include "vm/exceptions.h"
47 #include "vm/field.h"
48 #include "vm/initialize.h"
49 #include "vm/options.h"
50 #include "vm/resolve.h"
51 #include "vm/references.h"
52 #include "vm/jit/asmpart.h"
53 #include "vm/jit/patcher.h"
54
55
56 /* patcher_wrapper *************************************************************
57
58    Wrapper for all patchers.  It also creates the stackframe info
59    structure.
60
61    If the return value of the patcher function is false, it gets the
62    exception object, clears the exception pointer and returns the
63    exception.
64
65 *******************************************************************************/
66
67 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
68 {
69         stackframeinfo     sfi;
70         u1                *xpc;
71         java_objectheader *o;
72         functionptr        f;
73         bool               result;
74         java_objectheader *e;
75
76         /* define the patcher function */
77
78         bool (*patcher_function)(u1 *);
79
80         assert(pv != NULL);
81
82         /* get stuff from the stack */
83
84         xpc = (u1 *)                *((ptrint *) (sp + 5 * 8));
85         o   = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
86         f   = (functionptr)         *((ptrint *) (sp + 0 * 8));
87
88         /* store PV into the patcher function position */
89
90         *((ptrint *) (sp + 0 * 8)) = (ptrint) pv;
91
92         /* cast the passed function to a patcher function */
93
94         patcher_function = (bool (*)(u1 *)) (ptrint) f;
95
96         /* enter a monitor on the patching position */
97
98         PATCHER_MONITORENTER;
99
100         /* create the stackframeinfo */
101
102         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 6 * 8, ra, xpc);
103
104         /* call the proper patcher function */
105
106         result = (patcher_function)(sp);
107
108         /* remove the stackframeinfo */
109
110         stacktrace_remove_stackframeinfo(&sfi);
111
112         /* check for return value and exit accordingly */
113
114         if (result == false) {
115                 e = exceptions_get_and_clear_exception();
116
117                 PATCHER_MONITOREXIT;
118
119                 return e;
120         }
121
122         PATCHER_MARK_PATCHED_MONITOREXIT;
123
124         return NULL;
125 }
126
127
128 /* patcher_get_putstatic *******************************************************
129
130    Machine code:
131
132    <patched call position>
133    dfc1ffb8    ld       at,-72(s8)
134    fc250000    sd       a1,0(at)
135
136 *******************************************************************************/
137
138 bool patcher_get_putstatic(u1 *sp)
139 {
140         u1               *ra;
141 #if SIZEOF_VOID_P == 8
142         u8                mcode;
143 #else
144         u4                mcode[2];
145 #endif
146         unresolved_field *uf;
147         s4                disp;
148         u1               *pv;
149         fieldinfo        *fi;
150
151         /* get stuff from the stack */
152
153         ra       = (u1 *)               *((ptrint *) (sp + 5 * 8));
154 #if SIZEOF_VOID_P == 8
155         mcode    =                      *((u8 *)     (sp + 3 * 8));
156 #else
157         mcode[0] =                      *((u4 *)     (sp + 3 * 8));
158         mcode[1] =                      *((u4 *)     (sp + 3 * 8 + 4));
159 #endif
160         uf       = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
161         disp     =                      *((s4 *)     (sp + 1 * 8));
162         pv       = (u1 *)               *((ptrint *) (sp + 0 * 8));
163
164         /* get the fieldinfo */
165
166         if (!(fi = resolve_field_eager(uf)))
167                 return false;
168
169         /* check if the field's class is initialized */
170
171         if (!(fi->class->state & CLASS_INITIALIZED))
172                 if (!initialize_class(fi->class))
173                         return false;
174
175         /* patch back original code */
176
177 #if SIZEOF_VOID_P == 8
178         *((u4 *) (ra + 0 * 4)) = mcode;
179         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
180 #else
181         *((u4 *) (ra + 0 * 4)) = mcode[0];
182         *((u4 *) (ra + 1 * 4)) = mcode[1];
183 #endif
184
185         /* synchronize instruction cache */
186
187         md_icacheflush(ra, 2 * 4);
188
189         /* patch the field value's address */
190
191         *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
192
193         /* synchronize data cache */
194
195         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
196
197         return true;
198 }
199
200
201 /* patcher_get_putfield ********************************************************
202
203    Machine code:
204
205    <patched call position>
206    8ee90020    lw       a5,32(s7)
207
208 *******************************************************************************/
209
210 bool patcher_get_putfield(u1 *sp)
211 {
212         u1               *ra;
213 #if SIZEOF_VOID_P == 8
214         u8                mcode;
215 #else
216         u4                mcode[2];
217 #endif
218         unresolved_field *uf;
219         fieldinfo        *fi;
220
221         ra       = (u1 *)               *((ptrint *) (sp + 5 * 8));
222 #if SIZEOF_VOID_P == 8
223         mcode    =                      *((u8 *)     (sp + 3 * 8));
224 #else
225         mcode[0] =                      *((u4 *)     (sp + 3 * 8));
226         mcode[1] =                      *((u4 *)     (sp + 3 * 8 + 4));
227 #endif
228         uf       = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
229
230         /* get the fieldinfo */
231
232         if (!(fi = resolve_field_eager(uf)))
233                 return false;
234
235         /* patch back original code */
236
237 #if SIZEOF_VOID_P == 8
238         *((u4 *) (ra + 0 * 4)) = mcode;
239         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
240 #else
241         *((u4 *) (ra + 0 * 4)) = mcode[0];
242         *((u4 *) (ra + 1 * 4)) = mcode[1];
243 #endif
244
245         /* if we show disassembly, we have to skip the nop's */
246
247         if (opt_showdisassemble)
248                 ra = ra + 2 * 4;
249
250         /* patch the field's offset */
251
252 #if SIZEOF_VOID_P == 4
253         if (fi->type == TYPE_LNG) {
254 # if WORDS_BIGENDIAN == 1
255                 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
256                 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
257                 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
258 # else
259                 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
260                 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
261                 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
262 # endif
263         } else
264 #endif
265                 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
266
267         /* synchronize instruction cache */
268
269         if (opt_showdisassemble) {
270 #if SIZEOF_VOID_P == 4
271                 if (fi->type == TYPE_LNG)
272                         md_icacheflush(ra - 2 * 4, 4 * 4);
273                 else
274 #endif
275                         md_icacheflush(ra - 2 * 4, 3 * 4);
276         }
277         else {
278                 md_icacheflush(ra, 2 * 4);
279         }
280
281         return true;
282 }
283
284
285 /* patcher_aconst **************************************************************
286
287    Machine code:
288
289    <patched call postition>
290    dfc4ff98    ld       a0,-104(s8)
291
292 *******************************************************************************/
293
294 bool patcher_aconst(u1 *sp)
295 {
296         u1                *ra;
297 #if SIZEOF_VOID_P == 8
298         u8                 mcode;
299 #else
300         u4                 mcode[2];
301 #endif
302         constant_classref *cr;
303         s4                 disp;
304         u1                *pv;
305         classinfo         *c;
306
307         /* get stuff from the stack */
308
309         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
310 #if SIZEOF_VOID_P == 8
311         mcode    =                       *((u8 *)     (sp + 3 * 8));
312 #else
313         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
314         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
315 #endif
316         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
317         disp     =                       *((s4 *)     (sp + 1 * 8));
318         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
319
320         /* get the classinfo */
321
322         if (!(c = resolve_classref_eager(cr)))
323                 return false;
324
325         /* patch back original code */
326
327 #if SIZEOF_VOID_P == 8
328         *((u4 *) (ra + 0 * 4)) = mcode;
329         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
330 #else
331         *((u4 *) (ra + 0 * 4)) = mcode[0];
332         *((u4 *) (ra + 1 * 4)) = mcode[1];
333 #endif
334
335         /* synchronize instruction cache */
336
337         md_icacheflush(ra, 2 * 4);
338
339         /* patch the classinfo pointer */
340
341         *((ptrint *) (pv + disp)) = (ptrint) c;
342
343         /* synchronize data cache */
344
345         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
346
347         return true;
348 }
349
350
351 /* patcher_builtin_multianewarray **********************************************
352
353    Machine code:
354
355    <patched call position>
356    dfc5ff90    ld       a1,-112(s8)
357    03a03025    move     a2,sp
358    dfd9ff88    ld       t9,-120(s8)
359    0320f809    jalr     t9
360    00000000    nop
361
362 *******************************************************************************/
363
364 bool patcher_builtin_multianewarray(u1 *sp)
365 {
366         u1                *ra;
367 #if SIZEOF_VOID_P == 8
368         u8                 mcode;
369 #else   
370         u4                 mcode[2];
371 #endif
372         constant_classref *cr;
373         s4                 disp;
374         u1                *pv;
375         classinfo         *c;
376
377         /* get stuff from the stack */
378
379         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
380 #if SIZEOF_VOID_P == 8
381         mcode    =                       *((u8 *)     (sp + 3 * 8));
382 #else
383         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
384         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
385 #endif
386         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
387         disp     =                       *((s4 *)     (sp + 1 * 8));
388         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
389
390         /* get the classinfo */
391
392         if (!(c = resolve_classref_eager(cr)))
393                 return false;
394
395         /* patch back original code */
396
397 #if SIZEOF_VOID_P == 8
398         *((u4 *) (ra + 0 * 4)) = mcode;
399         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
400 #else
401         *((u4 *) (ra + 0 * 4)) = mcode[0];
402         *((u4 *) (ra + 1 * 4)) = mcode[1];
403 #endif
404
405         /* synchronize instruction cache */
406
407         md_icacheflush(ra, 2 * 4);
408
409         /* patch the classinfo pointer */
410
411         *((ptrint *) (pv + disp)) = (ptrint) c;
412
413         /* synchronize data cache */
414
415         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
416
417         return true;
418 }
419
420
421 /* patcher_builtin_arraycheckcast **********************************************
422
423    Machine code:
424
425    <patched call position>
426    dfc5ffc0    ld       a1,-64(s8)
427    dfd9ffb8    ld       t9,-72(s8)
428    0320f809    jalr     t9
429    00000000    nop
430
431 *******************************************************************************/
432
433 bool patcher_builtin_arraycheckcast(u1 *sp)
434 {
435         u1                *ra;
436 #if SIZEOF_VOID_P == 8
437         u8                 mcode;
438 #else
439         u4                 mcode[2];
440 #endif
441         constant_classref *cr;
442         s4                 disp;
443         u1                *pv;
444         classinfo         *c;
445
446         /* get stuff from the stack */
447
448         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
449 #if SIZEOF_VOID_P == 8
450         mcode    =                       *((u8 *)     (sp + 3 * 8));
451 #else
452         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
453         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
454 #endif
455         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
456         disp     =                       *((s4 *)     (sp + 1 * 8));
457         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
458
459         /* get the classinfo */
460
461         if (!(c = resolve_classref_eager(cr)))
462                 return false;
463
464         /* patch back original code */
465
466 #if SIZEOF_VOID_P == 8
467         *((u4 *) (ra + 0 * 4)) = mcode;
468         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
469 #else
470         *((u4 *) (ra + 0 * 4)) = mcode[0];
471         *((u4 *) (ra + 1 * 4)) = mcode[1];
472 #endif
473
474         /* synchronize instruction cache */
475
476         md_icacheflush(ra, 2 * 4);
477
478         /* patch the classinfo pointer */
479
480         *((ptrint *) (pv + disp)) = (ptrint) c;
481
482         /* synchronize data cache */
483
484         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
485
486         return true;
487 }
488
489
490 /* patcher_invokestatic_special ************************************************
491
492    Machine code:
493
494    <patched call position>
495    dfdeffc0    ld       s8,-64(s8)
496    03c0f809    jalr     s8
497    00000000    nop
498
499 ******************************************************************************/
500
501 bool patcher_invokestatic_special(u1 *sp)
502 {
503         u1                *ra;
504 #if SIZEOF_VOID_P == 8
505         u8                 mcode;
506 #else
507         u4                 mcode[2];
508 #endif
509         unresolved_method *um;
510         s4                 disp;
511         u1                *pv;
512         methodinfo        *m;
513
514         /* get stuff from the stack */
515
516         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
517 #if SIZEOF_VOID_P == 8
518         mcode    =                       *((u8 *)     (sp + 3 * 8));
519 #else
520         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
521         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
522 #endif
523         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
524         disp     =                       *((s4 *)     (sp + 1 * 8));
525         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
526
527         /* get the fieldinfo */
528
529         if (!(m = resolve_method_eager(um)))
530                 return false;
531
532         /* patch back original code */
533
534 #if SIZEOF_VOID_P == 8
535         *((u4 *) (ra + 0 * 4)) = mcode;
536         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
537 #else
538         *((u4 *) (ra + 0 * 4)) = mcode[0];
539         *((u4 *) (ra + 1 * 4)) = mcode[1];
540 #endif
541
542         /* synchronize instruction cache */
543
544         md_icacheflush(ra, 2 * 4);
545
546         /* patch stubroutine */
547
548         *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
549
550         /* synchronize data cache */
551
552         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
553
554         return true;
555 }
556
557
558 /* patcher_invokevirtual *******************************************************
559
560    Machine code:
561
562    <patched call position>
563    dc990000    ld       t9,0(a0)
564    df3e0040    ld       s8,64(t9)
565    03c0f809    jalr     s8
566    00000000    nop
567
568 *******************************************************************************/
569
570 bool patcher_invokevirtual(u1 *sp)
571 {
572         u1                *ra;
573 #if SIZEOF_VOID_P == 8
574         u8                 mcode;
575 #else
576         u4                 mcode[2];
577 #endif
578         unresolved_method *um;
579         methodinfo        *m;
580
581         /* get stuff from the stack */
582
583         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
584 #if SIZEOF_VOID_P == 8
585         mcode    =                       *((u8 *)     (sp + 3 * 8));
586 #else
587         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
588         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
589 #endif
590         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
591
592         /* get the fieldinfo */
593
594         if (!(m = resolve_method_eager(um)))
595                 return false;
596
597         /* patch back original code */
598
599 #if SIZEOF_VOID_P == 8
600         *((u4 *) (ra + 0 * 4)) = mcode;
601         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
602 #else
603         *((u4 *) (ra + 0 * 4)) = mcode[0];
604         *((u4 *) (ra + 1 * 4)) = mcode[1];
605 #endif
606
607         /* if we show disassembly, we have to skip the nop's */
608
609         if (opt_showdisassemble)
610                 ra = ra + 2 * 4;
611
612         /* patch vftbl index */
613
614         *((s4 *) (ra + 1 * 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
615                                                                          sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
616
617         /* synchronize instruction cache */
618
619         if (opt_showdisassemble)
620                 md_icacheflush(ra - 2 * 4, 4 * 4);
621         else
622                 md_icacheflush(ra, 2 * 4);
623
624         return true;
625 }
626
627
628 /* patcher_invokeinterface *****************************************************
629
630    Machine code:
631
632    <patched call position>
633    dc990000    ld       t9,0(a0)
634    df39ffa0    ld       t9,-96(t9)
635    df3e0018    ld       s8,24(t9)
636    03c0f809    jalr     s8
637    00000000    nop
638
639 *******************************************************************************/
640
641 bool patcher_invokeinterface(u1 *sp)
642 {
643         u1                *ra;
644 #if SIZEOF_VOID_P == 8
645         u8                 mcode;
646 #else
647         u4                 mcode[2];
648 #endif
649         unresolved_method *um;
650         methodinfo        *m;
651
652         /* get stuff from the stack */
653
654         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
655 #if SIZEOF_VOID_P == 8
656         mcode    =                       *((u8 *)     (sp + 3 * 8));
657 #else
658         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
659         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
660 #endif
661         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
662
663         /* get the fieldinfo */
664
665         if (!(m = resolve_method_eager(um)))
666                 return false;
667
668         /* patch back original code */
669
670 #if SIZEOF_VOID_P == 8
671         *((u4 *) (ra + 0 * 4)) = mcode;
672         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
673 #else
674         *((u4 *) (ra + 0 * 4)) = mcode[0];
675         *((u4 *) (ra + 1 * 4)) = mcode[1];
676 #endif
677
678         /* if we show disassembly, we have to skip the nop's */
679
680         if (opt_showdisassemble)
681                 ra = ra + 2 * 4;
682
683         /* patch interfacetable index */
684
685         *((s4 *) (ra + 1 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
686                                                                          sizeof(methodptr*) * m->class->index) & 0x0000ffff);
687
688         /* patch method offset */
689
690         *((s4 *) (ra + 2 * 4)) |=
691                 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
692
693         /* synchronize instruction cache */
694
695         if (opt_showdisassemble)
696                 md_icacheflush(ra - 2 * 4, 5 * 4);
697         else
698                 md_icacheflush(ra, 3 * 4);
699
700         return true;
701 }
702
703
704 /* patcher_checkcast_instanceof_flags ******************************************
705
706    Machine code:
707
708    <patched call position>
709    8fc3ff24    lw       v1,-220(s8)
710    30630200    andi     v1,v1,512
711    1060000d    beq      v1,zero,0x000000001051824c
712    00000000    nop
713
714 *******************************************************************************/
715
716 bool patcher_checkcast_instanceof_flags(u1 *sp)
717 {
718         u1                *ra;
719 #if SIZEOF_VOID_P == 8
720         u8                 mcode;
721 #else
722         u4                 mcode[2];
723 #endif
724         constant_classref *cr;
725         s4                 disp;
726         u1                *pv;
727         classinfo         *c;
728
729         /* get stuff from the stack */
730
731         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
732 #if SIZEOF_VOID_P == 8
733         mcode    =                       *((u8 *)     (sp + 3 * 8));
734 #else
735         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
736         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
737 #endif
738         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
739         disp     =                       *((s4 *)     (sp + 1 * 8));
740         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
741
742         /* get the fieldinfo */
743
744         if (!(c = resolve_classref_eager(cr)))
745                 return false;
746
747         /* patch back original code */
748
749 #if SIZEOF_VOID_P == 8
750         *((u4 *) (ra + 0 * 4)) = mcode;
751         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
752 #else
753         *((u4 *) (ra + 0 * 4)) = mcode[0];
754         *((u4 *) (ra + 1 * 4)) = mcode[1];
755 #endif
756
757         /* synchronize instruction cache */
758
759         md_icacheflush(ra, 2 * 4);
760
761         /* patch class flags */
762
763         *((s4 *) (pv + disp)) = (s4) c->flags;
764
765         /* synchronize data cache */
766
767         md_dcacheflush(pv + disp, sizeof(s4));
768
769         return true;
770 }
771
772
773 /* patcher_checkcast_instanceof_interface **************************************
774
775    Machine code:
776
777    <patched call position>
778    dd030000    ld       v1,0(a4)
779    8c79001c    lw       t9,28(v1)
780    27390000    addiu    t9,t9,0
781    1b200082    blez     t9,zero,0x000000001051843c
782    00000000    nop
783    dc790000    ld       t9,0(v1)
784
785 *******************************************************************************/
786
787 bool patcher_checkcast_instanceof_interface(u1 *sp)
788 {
789         u1                *ra;
790 #if SIZEOF_VOID_P == 8
791         u8                 mcode;
792 #else
793         u4                 mcode[2];
794 #endif
795         constant_classref *cr;
796         classinfo         *c;
797
798         /* get stuff from the stack */
799
800         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
801 #if SIZEOF_VOID_P == 8
802         mcode    =                       *((u8 *)     (sp + 3 * 8));
803 #else
804         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
805         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
806 #endif
807         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
808
809         /* get the fieldinfo */
810
811         if (!(c = resolve_classref_eager(cr)))
812                 return false;
813
814         /* patch back original code */
815
816 #if SIZEOF_VOID_P == 8
817         *((u4 *) (ra + 0 * 4)) = mcode;
818         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
819 #else
820         *((u4 *) (ra + 0 * 4)) = mcode[0];
821         *((u4 *) (ra + 1 * 4)) = mcode[1];
822 #endif
823
824         /* if we show disassembly, we have to skip the nop's */
825
826         if (opt_showdisassemble)
827                 ra = ra + 2 * 4;
828
829         /* patch super class index */
830
831         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
832
833         *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
834                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
835
836         /* synchronize instruction cache */
837
838         if (opt_showdisassemble)
839                 md_icacheflush(ra - 2 * 4, 8 * 4);
840         else
841                 md_icacheflush(ra, 6 * 4);
842
843         return true;
844 }
845
846
847 /* patcher_checkcast_instanceof_class ******************************************
848
849    Machine code:
850
851    <patched call position>
852    dd030000    ld       v1,0(a4)
853    dfd9ff18    ld       t9,-232(s8)
854
855 *******************************************************************************/
856
857 bool patcher_checkcast_instanceof_class(u1 *sp)
858 {
859         u1                *ra;
860 #if SIZEOF_VOID_P == 8
861         u8                 mcode;
862 #else
863         u4                 mcode[2];
864 #endif
865         constant_classref *cr;
866         s4                 disp;
867         u1                *pv;
868         classinfo         *c;
869
870         /* get stuff from the stack */
871
872         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
873 #if SIZEOF_VOID_P == 8
874         mcode    =                       *((u8 *)     (sp + 3 * 8));
875 #else
876         mcode[0] =                       *((u4 *)     (sp + 3 * 8));
877         mcode[1] =                       *((u4 *)     (sp + 3 * 8 + 4));
878 #endif
879         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
880         disp     =                       *((s4 *)     (sp + 1 * 8));
881         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
882
883         /* get the fieldinfo */
884
885         if (!(c = resolve_classref_eager(cr)))
886                 return false;
887
888         /* patch back original code */
889
890 #if SIZEOF_VOID_P == 8
891         *((u4 *) (ra + 0 * 4)) = mcode;
892         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
893 #else
894         *((u4 *) (ra + 0 * 4)) = mcode[0];
895         *((u4 *) (ra + 1 * 4)) = mcode[1];
896 #endif
897
898         /* synchronize instruction cache */
899
900         md_icacheflush(ra, 2 * 4);
901
902         /* patch super class' vftbl */
903
904         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
905
906         /* synchronize data cache */
907
908         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
909
910         return true;
911 }
912
913
914 /* patcher_clinit **************************************************************
915
916    No special machine code.
917
918 *******************************************************************************/
919
920 bool patcher_clinit(u1 *sp)
921 {
922         u1        *ra;
923 #if SIZEOF_VOID_P == 8
924         u8         mcode;
925 #else
926         u4         mcode[2];
927 #endif
928         classinfo *c;
929
930         /* get stuff from the stack */
931
932         ra       = (u1 *)        *((ptrint *) (sp + 5 * 8));
933 #if SIZEOF_VOID_P == 8
934         mcode    =               *((u8 *)     (sp + 3 * 8));
935 #else
936         mcode[0] =               *((u4 *)     (sp + 3 * 8));
937         mcode[1] =               *((u4 *)     (sp + 3 * 8 + 4));
938 #endif
939         c        = (classinfo *) *((ptrint *) (sp + 2 * 8));
940
941         /* check if the class is initialized */
942
943         if (!(c->state & CLASS_INITIALIZED))
944                 if (!initialize_class(c))
945                         return false;
946
947         /* patch back original code */
948
949 #if SIZEOF_VOID_P == 8
950         *((u4 *) (ra + 0 * 4)) = mcode;
951         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
952 #else
953         *((u4 *) (ra + 0 * 4)) = mcode[0];
954         *((u4 *) (ra + 1 * 4)) = mcode[1];
955 #endif
956
957         /* synchronize instruction cache */
958
959         md_icacheflush(ra, 2 * 4);
960
961         return true;
962 }
963
964
965 /* patcher_athrow_areturn ******************************************************
966
967    Machine code:
968
969    <patched call position>
970
971 *******************************************************************************/
972
973 #ifdef ENABLE_VERIFIER
974 bool patcher_athrow_areturn(u1 *sp)
975 {
976         u1               *ra;
977 #if SIZEOF_VOID_P == 8
978         u8                mcode;
979 #else
980         u4                mcode[2];
981 #endif
982         unresolved_class *uc;
983         classinfo        *c;
984
985         /* get stuff from the stack */
986
987         ra       = (u1 *)               *((ptrint *) (sp + 5 * 8));
988 #if SIZEOF_VOID_P == 8
989         mcode    =                      *((u8 *)     (sp + 3 * 8));
990 #else
991         mcode[0] =                      *((u4 *)     (sp + 3 * 8));
992         mcode[1] =                      *((u4 *)     (sp + 3 * 8 + 4));
993 #endif
994         uc       = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
995
996         /* resolve the class */
997
998         if (!resolve_class(uc, resolveEager, false, &c))
999                 return false;
1000
1001         /* patch back original code */
1002
1003 #if SIZEOF_VOID_P == 8
1004         *((u4 *) (ra + 0 * 4)) = mcode;
1005         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
1006 #else
1007         *((u4 *) (ra + 0 * 4)) = mcode[0];
1008         *((u4 *) (ra + 1 * 4)) = mcode[1];
1009 #endif
1010
1011         /* synchronize instruction cache */
1012
1013         md_icacheflush(ra, 2 * 4);
1014
1015         return true;
1016 }
1017 #endif /* ENABLE_VERIFIER */
1018
1019
1020 /* patcher_resolve_native ******************************************************
1021
1022    XXX
1023
1024 *******************************************************************************/
1025
1026 #if !defined(WITH_STATIC_CLASSPATH)
1027 bool patcher_resolve_native(u1 *sp)
1028 {
1029         u1          *ra;
1030 #if SIZEOF_VOID_P == 8
1031         u8           mcode;
1032 #else
1033         u4           mcode[2];
1034 #endif
1035         methodinfo  *m;
1036         s4           disp;
1037         u1          *pv;
1038         functionptr  f;
1039
1040         /* get stuff from the stack */
1041
1042         ra       = (u1 *)         *((ptrint *) (sp + 5 * 8));
1043 #if SIZEOF_VOID_P == 8
1044         mcode    =                *((u8 *)     (sp + 3 * 8));
1045 #else
1046         mcode[0] =                *((u4 *)     (sp + 3 * 8));
1047         mcode[1] =                *((u4 *)     (sp + 3 * 8 + 4));
1048 #endif
1049         m        = (methodinfo *) *((ptrint *) (sp + 2 * 8));
1050         disp     =                *((s4 *)     (sp + 1 * 8));
1051         pv       = (u1 *)         *((ptrint *) (sp + 0 * 8));
1052
1053         /* calculate and set the new return address */
1054
1055         ra = ra - 2 * 4;
1056         *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
1057
1058         /* resolve native function */
1059
1060         if (!(f = native_resolve_function(m)))
1061                 return false;
1062
1063         /* patch back original code */
1064
1065 #if SIZEOF_VOID_P == 8
1066         *((u4 *) (ra + 0 * 4)) = mcode;
1067         *((u4 *) (ra + 1 * 4)) = mcode >> 32;
1068 #else
1069         *((u4 *) (ra + 0 * 4)) = mcode[0];
1070         *((u4 *) (ra + 1 * 4)) = mcode[1];
1071 #endif
1072
1073         /* synchronize instruction cache */
1074
1075         md_icacheflush(ra, 2 * 4);
1076
1077         /* patch native function pointer */
1078
1079         *((ptrint *) (pv + disp)) = (ptrint) f;
1080
1081         /* synchronize data cache */
1082
1083         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
1084
1085         return true;
1086 }
1087 #endif /* !defined(WITH_STATIC_CLASSPATH) */
1088
1089
1090 /*
1091  * These are local overrides for various environment variables in Emacs.
1092  * Please do not remove this and leave it at the end of the file, where
1093  * Emacs will automagically detect them.
1094  * ---------------------------------------------------------------------
1095  * Local variables:
1096  * mode: c
1097  * indent-tabs-mode: t
1098  * c-basic-offset: 4
1099  * tab-width: 4
1100  * End:
1101  * vim:noexpandtab:sw=4:ts=4:
1102  */