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