* src/vm/jit/patcher-common.h: Added __MIPS__ for new patcher
[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, 2007 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    $Id: patcher.c 8264 2007-08-06 16:02:28Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "vm/jit/mips/codegen.h"
37
38 #include "mm/memory.h"
39
40 #include "native/native.h"
41
42 #include "vm/builtin.h"
43 #include "vm/exceptions.h"
44 #include "vm/initialize.h"
45
46 #include "vm/jit/asmpart.h"
47 #include "vm/jit/md.h"
48 #include "vm/jit/patcher-common.h"
49
50 #include "vmcore/class.h"
51 #include "vmcore/field.h"
52 #include "vmcore/options.h"
53 #include "vm/resolve.h"
54 #include "vmcore/references.h"
55
56
57 #define PATCH_BACK_ORIGINAL_MCODE \
58         *((u4 *) pr->mpc) = (u4) pr->mcode; \
59         md_icacheflush((u1 *) pr->mpc, PATCHER_CALL_SIZE);
60
61
62 /* patcher_initialize_class ****************************************************
63
64    Initalizes a given classinfo pointer.  This function does not patch
65    any data.
66
67 *******************************************************************************/
68
69 bool patcher_initialize_class(patchref_t *pr)
70 {
71         classinfo *c;
72
73         /* get stuff from the stack */
74
75         c = (classinfo *) pr->ref;
76
77         /* check if the class is initialized */
78
79         if (!(c->state & CLASS_INITIALIZED))
80                 if (!initialize_class(c))
81                         return false;
82
83         PATCH_BACK_ORIGINAL_MCODE;
84
85         return true;
86 }
87
88
89 /* patcher_resolve_class *****************************************************
90
91    Initalizes a given classinfo pointer.  This function does not patch
92    any data.
93
94 *******************************************************************************/
95
96 #ifdef ENABLE_VERIFIER
97 bool patcher_resolve_class(patchref_t *pr)
98 {
99         unresolved_class *uc;
100
101         /* get stuff from the stack */
102
103         uc = (unresolved_class *) pr->ref;
104
105         /* resolve the class and check subtype constraints */
106
107         if (!resolve_class_eager_no_access_check(uc))
108                 return false;
109
110         PATCH_BACK_ORIGINAL_MCODE;
111
112         return true;
113 }
114 #endif /* ENABLE_VERIFIER */
115
116
117 /* patcher_get_putstatic *******************************************************
118
119    Machine code:
120
121    <patched call position>
122    dfc1ffb8    ld       at,-72(s8)
123    fc250000    sd       a1,0(at)
124
125 *******************************************************************************/
126
127 bool patcher_get_putstatic(patchref_t *pr)
128 {
129         unresolved_field *uf;
130         u1               *datap;
131         fieldinfo        *fi;
132
133         /* get stuff from the stack */
134
135         uf    = (unresolved_field *) pr->ref;
136         datap = (u1 *)               pr->datap;
137
138         /* get the fieldinfo */
139
140         if (!(fi = resolve_field_eager(uf)))
141                 return false;
142
143         /* check if the field's class is initialized */
144
145         if (!(fi->class->state & CLASS_INITIALIZED))
146                 if (!initialize_class(fi->class))
147                         return false;
148
149         PATCH_BACK_ORIGINAL_MCODE;
150
151         /* patch the field value's address */
152
153         *((ptrint *) datap) = (ptrint) &(fi->value);
154
155         /* synchronize data cache */
156
157         md_dcacheflush(datap, SIZEOF_VOID_P);
158
159         return true;
160 }
161
162
163 /* patcher_get_putfield ********************************************************
164
165    Machine code:
166
167    <patched call position>
168    8ee90020    lw       a5,32(s7)
169
170 *******************************************************************************/
171
172 bool patcher_get_putfield(patchref_t *pr)
173 {
174         u1               *ra;
175         unresolved_field *uf;
176         fieldinfo        *fi;
177
178         /* get stuff from the stack */
179
180         ra = (u1 *)               pr->mpc;
181         uf = (unresolved_field *) pr->ref;
182
183         /* get the fieldinfo */
184
185         if (!(fi = resolve_field_eager(uf)))
186                 return false;
187
188         PATCH_BACK_ORIGINAL_MCODE;
189
190         /* if we show disassembly, we have to skip the nop's */
191
192         if (opt_shownops)
193                 ra = ra + PATCHER_CALL_SIZE;
194
195 #if SIZEOF_VOID_P == 4
196         if (IS_LNG_TYPE(fi->type)) {
197 # if WORDS_BIGENDIAN == 1
198                 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
199                 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
200                 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
201 # else
202                 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
203                 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
204                 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
205 # endif
206         }
207         else
208 #endif
209                 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
210
211         /* synchronize instruction cache */
212
213         md_icacheflush(ra, 2 * 4);
214
215         return true;
216 }
217
218
219 /* patcher_resolve_classref_to_classinfo ***************************************
220
221    ACONST:
222
223    <patched call postition>
224    dfc4ff98    ld       a0,-104(s8)
225
226    MULTIANEWARRAY:
227
228    <patched call position>
229    dfc5ff90    ld       a1,-112(s8)
230    03a03025    move     a2,sp
231    dfd9ff88    ld       t9,-120(s8)
232    0320f809    jalr     t9
233    00000000    nop
234
235    ARRAYCHECKCAST:
236
237    <patched call position>
238    dfc5ffc0    ld       a1,-64(s8)
239    dfd9ffb8    ld       t9,-72(s8)
240    0320f809    jalr     t9
241    00000000    nop
242
243 *******************************************************************************/
244
245 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
246 {
247         constant_classref *cr;
248         u1                *datap;
249         classinfo         *c;
250
251         /* get stuff from the stack */
252
253         cr    = (constant_classref *) pr->ref;
254         datap = (u1 *)                pr->datap;
255
256         /* get the classinfo */
257
258         if (!(c = resolve_classref_eager(cr)))
259                 return false;
260
261         PATCH_BACK_ORIGINAL_MCODE;
262
263         /* patch the classinfo pointer */
264
265         *((intptr_t *) datap) = (intptr_t) c;
266
267         /* synchronize data cache */
268
269         md_dcacheflush(datap, SIZEOF_VOID_P);
270
271         return true;
272 }
273
274
275 /* patcher_resolve_classref_to_vftbl *******************************************
276
277    CHECKCAST (class):
278    INSTANCEOF (class):
279
280    <patched call position>
281    dd030000    ld       v1,0(a4)
282    dfd9ff18    ld       t9,-232(s8)
283
284 *******************************************************************************/
285
286 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
287 {
288         constant_classref *cr;
289         u1                *datap;
290         classinfo         *c;
291
292         /* get stuff from the stack */
293
294         cr    = (constant_classref *) pr->ref;
295         datap = (u1 *)                pr->datap;
296
297         /* get the fieldinfo */
298
299         if (!(c = resolve_classref_eager(cr)))
300                 return false;
301
302         PATCH_BACK_ORIGINAL_MCODE;
303
304         /* patch super class' vftbl */
305
306         *((intptr_t *) datap) = (intptr_t) c->vftbl;
307
308         /* synchronize data cache */
309
310         md_dcacheflush(datap, SIZEOF_VOID_P);
311
312         return true;
313 }
314
315
316 /* patcher_resolve_classref_to_flags *******************************************
317
318    CHECKCAST/INSTANCEOF:
319
320    <patched call position>
321    8fc3ff24    lw       v1,-220(s8)
322    30630200    andi     v1,v1,512
323    1060000d    beq      v1,zero,0x000000001051824c
324    00000000    nop
325
326 *******************************************************************************/
327
328 bool patcher_resolve_classref_to_flags(patchref_t *pr)
329 {
330         constant_classref *cr;
331         u1                *datap;
332         classinfo         *c;
333
334         /* get stuff from the stack */
335
336         cr    = (constant_classref *) pr->ref;
337         datap = (u1 *)                pr->datap;
338
339         /* get the fieldinfo */
340
341         if (!(c = resolve_classref_eager(cr)))
342                 return false;
343
344         PATCH_BACK_ORIGINAL_MCODE;
345
346         /* patch class flags */
347
348         *((int32_t *) datap) = (int32_t) c->flags;
349
350         /* synchronize data cache */
351
352         md_dcacheflush(datap, sizeof(int32_t));
353
354         return true;
355 }
356
357
358 /* patcher_resolve_native ******************************************************
359
360    XXX
361
362 *******************************************************************************/
363
364 #if !defined(WITH_STATIC_CLASSPATH)
365 bool patcher_resolve_native_function(patchref_t *pr)
366 {
367         methodinfo  *m;
368         u1          *datap;
369         functionptr  f;
370
371         /* get stuff from the stack */
372
373         m     = (methodinfo *) pr->ref;
374         datap = (u1 *)         pr->datap;
375
376         /* resolve native function */
377
378         if (!(f = native_resolve_function(m)))
379                 return false;
380
381         PATCH_BACK_ORIGINAL_MCODE;
382
383         /* patch native function pointer */
384
385         *((ptrint *) datap) = (ptrint) f;
386
387         /* synchronize data cache */
388
389         md_dcacheflush(datap, SIZEOF_VOID_P);
390
391         return true;
392 }
393 #endif /* !defined(WITH_STATIC_CLASSPATH) */
394
395
396 /* patcher_invokestatic_special ************************************************
397
398    Machine code:
399
400    <patched call position>
401    dfdeffc0    ld       s8,-64(s8)
402    03c0f809    jalr     s8
403    00000000    nop
404
405 ******************************************************************************/
406
407 bool patcher_invokestatic_special(patchref_t *pr)
408 {
409         unresolved_method *um;
410         u1                *datap;
411         methodinfo        *m;
412
413         /* get stuff from the stack */
414
415         um    = (unresolved_method *) pr->ref;
416         datap = (u1 *)                pr->datap;
417
418         /* get the fieldinfo */
419
420         if (!(m = resolve_method_eager(um)))
421                 return false;
422
423         PATCH_BACK_ORIGINAL_MCODE;
424
425         /* patch stubroutine */
426
427         *((ptrint *) datap) = (ptrint) m->stubroutine;
428
429         /* synchronize data cache */
430
431         md_dcacheflush(datap, SIZEOF_VOID_P);
432
433         return true;
434 }
435
436
437 /* patcher_invokevirtual *******************************************************
438
439    Machine code:
440
441    <patched call position>
442    dc990000    ld       t9,0(a0)
443    df3e0040    ld       s8,64(t9)
444    03c0f809    jalr     s8
445    00000000    nop
446
447 *******************************************************************************/
448
449 bool patcher_invokevirtual(patchref_t *pr)
450 {
451         u1                *ra;
452         unresolved_method *um;
453         methodinfo        *m;
454
455         /* get stuff from the stack */
456
457         ra = (u1 *)                pr->mpc;
458         um = (unresolved_method *) pr->ref;
459
460         /* get the fieldinfo */
461
462         if (!(m = resolve_method_eager(um)))
463                 return false;
464
465         PATCH_BACK_ORIGINAL_MCODE;
466
467         /* if we show disassembly, we have to skip the nop's */
468
469         if (opt_shownops)
470                 ra = ra + PATCHER_CALL_SIZE;
471
472         /* patch vftbl index */
473
474         *((s4 *) (ra + 1 * 4)) |=
475                 (s4) ((OFFSET(vftbl_t, table[0]) +
476                            sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
477
478         /* synchronize instruction cache */
479
480         md_icacheflush(ra + 1 * 4, 1 * 4);
481
482         return true;
483 }
484
485
486 /* patcher_invokeinterface *****************************************************
487
488    Machine code:
489
490    <patched call position>
491    dc990000    ld       t9,0(a0)
492    df39ffa0    ld       t9,-96(t9)
493    df3e0018    ld       s8,24(t9)
494    03c0f809    jalr     s8
495    00000000    nop
496
497 *******************************************************************************/
498
499 bool patcher_invokeinterface(patchref_t *pr)
500 {
501         u1                *ra;
502         unresolved_method *um;
503         methodinfo        *m;
504
505         /* get stuff from the stack */
506
507         ra = (u1 *)                pr->mpc;
508         um = (unresolved_method *) pr->ref;
509
510         /* get the fieldinfo */
511
512         if (!(m = resolve_method_eager(um)))
513                 return false;
514
515         PATCH_BACK_ORIGINAL_MCODE;
516
517         /* if we show disassembly, we have to skip the nop's */
518
519         if (opt_shownops)
520                 ra = ra + PATCHER_CALL_SIZE;
521
522         /* patch interfacetable index */
523
524         *((s4 *) (ra + 1 * 4)) |=
525                 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
526                            sizeof(methodptr*) * m->class->index) & 0x0000ffff);
527
528         /* patch method offset */
529
530         *((s4 *) (ra + 2 * 4)) |=
531                 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
532
533         /* synchronize instruction cache */
534
535         md_icacheflush(ra + 1 * 4, 2 * 4);
536
537         return true;
538 }
539
540
541 /* patcher_checkcast_interface *************************************************
542
543    Machine code:
544
545    <patched call position>
546    dd030000    ld       v1,0(a4)
547    8c79001c    lw       t9,28(v1)
548    27390000    addiu    t9,t9,0
549    1b200082    blez     t9,zero,0x000000001051843c
550    00000000    nop
551    dc790000    ld       t9,0(v1)
552
553 *******************************************************************************/
554
555 bool patcher_checkcast_interface(patchref_t *pr)
556 {
557         u1                *ra;
558         constant_classref *cr;
559         classinfo         *c;
560
561         /* get stuff from the stack */
562
563         ra = (u1 *)                pr->mpc;
564         cr = (constant_classref *) pr->ref;
565
566         /* get the fieldinfo */
567
568         if (!(c = resolve_classref_eager(cr)))
569                 return false;
570
571         PATCH_BACK_ORIGINAL_MCODE;
572
573         /* if we show disassembly, we have to skip the nop's */
574
575         if (opt_shownops)
576                 ra = ra + PATCHER_CALL_SIZE;
577
578         /* patch super class index */
579
580         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
581         /*      *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
582         /*                                                                       c->index * sizeof(methodptr*)) & 0x0000ffff); */
583         *((s4 *) (ra + 6 * 4)) |=
584                 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
585                            c->index * sizeof(methodptr*)) & 0x0000ffff);
586
587         /* synchronize instruction cache */
588
589         md_icacheflush(ra + 2 * 4, 5 * 4);
590
591         return true;
592 }
593
594
595 /* patcher_instanceof_interface ************************************************
596
597    Machine code:
598
599    <patched call position>
600    dd030000    ld       v1,0(a4)
601    8c79001c    lw       t9,28(v1)
602    27390000    addiu    t9,t9,0
603    1b200082    blez     t9,zero,0x000000001051843c
604    00000000    nop
605    dc790000    ld       t9,0(v1)
606
607 *******************************************************************************/
608
609 bool patcher_instanceof_interface(patchref_t *pr)
610 {
611         u1                *ra;
612         constant_classref *cr;
613         classinfo         *c;
614
615         /* get stuff from the stack */
616
617         ra = (u1 *)                pr->mpc;
618         cr = (constant_classref *) pr->ref;
619
620         /* get the fieldinfo */
621
622         if (!(c = resolve_classref_eager(cr)))
623                 return false;
624
625         PATCH_BACK_ORIGINAL_MCODE;
626
627         /* if we show disassembly, we have to skip the nop's */
628
629         if (opt_shownops)
630                 ra = ra + PATCHER_CALL_SIZE;
631
632         /* patch super class index */
633
634         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
635         *((s4 *) (ra + 5 * 4)) |=
636                 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
637                            c->index * sizeof(methodptr*)) & 0x0000ffff);
638
639         /* synchronize instruction cache */
640
641         md_icacheflush(ra + 2 * 4, 4 * 4);
642
643         return true;
644 }
645
646
647 /*
648  * These are local overrides for various environment variables in Emacs.
649  * Please do not remove this and leave it at the end of the file, where
650  * Emacs will automagically detect them.
651  * ---------------------------------------------------------------------
652  * Local variables:
653  * mode: c
654  * indent-tabs-mode: t
655  * c-basic-offset: 4
656  * tab-width: 4
657  * End:
658  * vim:noexpandtab:sw=4:ts=4:
659  */