* src/vmcore/field.h (fieldinfo): Renamed class to clazz.
[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, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30
31 #include "vm/types.h"
32
33 #include "vm/jit/mips/codegen.h"
34 #include "vm/jit/mips/md.h"
35
36 #include "mm/memory.h"
37
38 #include "native/native.h"
39
40 #include "vm/builtin.h"
41 #include "vm/exceptions.h"
42 #include "vm/initialize.h"
43
44 #include "vm/jit/asmpart.h"
45 #include "vm/jit/patcher-common.h"
46
47 #include "vmcore/class.h"
48 #include "vmcore/field.h"
49 #include "vmcore/options.h"
50 #include "vm/resolve.h"
51 #include "vmcore/references.h"
52
53
54 #define PATCH_BACK_ORIGINAL_MCODE \
55         *((u4 *) pr->mpc) = (u4) pr->mcode; \
56         md_icacheflush((u1 *) pr->mpc, PATCHER_CALL_SIZE);
57
58
59 /* patcher_patch_code **********************************************************
60
61    Just patches back the original machine code.
62
63 *******************************************************************************/
64
65 void patcher_patch_code(patchref_t *pr)
66 {
67         PATCH_BACK_ORIGINAL_MCODE;
68 }
69
70
71 /* patcher_get_putstatic *******************************************************
72
73    Machine code:
74
75    <patched call position>
76    dfc1ffb8    ld       at,-72(s8)
77    fc250000    sd       a1,0(at)
78
79 *******************************************************************************/
80
81 bool patcher_get_putstatic(patchref_t *pr)
82 {
83         unresolved_field *uf;
84         u1               *datap;
85         fieldinfo        *fi;
86
87         /* get stuff from the stack */
88
89         uf    = (unresolved_field *) pr->ref;
90         datap = (u1 *)               pr->datap;
91
92         /* get the fieldinfo */
93
94         if (!(fi = resolve_field_eager(uf)))
95                 return false;
96
97         /* check if the field's class is initialized */
98
99         if (!(fi->clazz->state & CLASS_INITIALIZED))
100                 if (!initialize_class(fi->clazz))
101                         return false;
102
103         PATCH_BACK_ORIGINAL_MCODE;
104
105         /* patch the field value's address */
106
107         *((intptr_t *) datap) = (intptr_t) fi->value;
108
109         /* synchronize data cache */
110
111         md_dcacheflush(datap, SIZEOF_VOID_P);
112
113         return true;
114 }
115
116
117 /* patcher_get_putfield ********************************************************
118
119    Machine code:
120
121    <patched call position>
122    8ee90020    lw       a5,32(s7)
123
124 *******************************************************************************/
125
126 bool patcher_get_putfield(patchref_t *pr)
127 {
128         u1               *ra;
129         unresolved_field *uf;
130         fieldinfo        *fi;
131
132         /* get stuff from the stack */
133
134         ra = (u1 *)               pr->mpc;
135         uf = (unresolved_field *) pr->ref;
136
137         /* get the fieldinfo */
138
139         if (!(fi = resolve_field_eager(uf)))
140                 return false;
141
142         PATCH_BACK_ORIGINAL_MCODE;
143
144         /* if we show disassembly, we have to skip the nop's */
145
146         if (opt_shownops)
147                 ra = ra + PATCHER_CALL_SIZE;
148
149 #if SIZEOF_VOID_P == 4
150         if (IS_LNG_TYPE(fi->type)) {
151 # if WORDS_BIGENDIAN == 1
152                 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
153                 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
154                 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
155 # else
156                 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
157                 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
158                 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
159 # endif
160         }
161         else
162 #endif
163                 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
164
165         /* synchronize instruction cache */
166
167         md_icacheflush(ra, 2 * 4);
168
169         return true;
170 }
171
172
173 /* patcher_resolve_classref_to_classinfo ***************************************
174
175    ACONST:
176
177    <patched call postition>
178    dfc4ff98    ld       a0,-104(s8)
179
180    MULTIANEWARRAY:
181
182    <patched call position>
183    dfc5ff90    ld       a1,-112(s8)
184    03a03025    move     a2,sp
185    dfd9ff88    ld       t9,-120(s8)
186    0320f809    jalr     t9
187    00000000    nop
188
189    ARRAYCHECKCAST:
190
191    <patched call position>
192    dfc5ffc0    ld       a1,-64(s8)
193    dfd9ffb8    ld       t9,-72(s8)
194    0320f809    jalr     t9
195    00000000    nop
196
197 *******************************************************************************/
198
199 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
200 {
201         constant_classref *cr;
202         u1                *datap;
203         classinfo         *c;
204
205         /* get stuff from the stack */
206
207         cr    = (constant_classref *) pr->ref;
208         datap = (u1 *)                pr->datap;
209
210         /* get the classinfo */
211
212         if (!(c = resolve_classref_eager(cr)))
213                 return false;
214
215         PATCH_BACK_ORIGINAL_MCODE;
216
217         /* patch the classinfo pointer */
218
219         *((intptr_t *) datap) = (intptr_t) c;
220
221         /* synchronize data cache */
222
223         md_dcacheflush(datap, SIZEOF_VOID_P);
224
225         return true;
226 }
227
228
229 /* patcher_resolve_classref_to_vftbl *******************************************
230
231    CHECKCAST (class):
232    INSTANCEOF (class):
233
234    <patched call position>
235    dd030000    ld       v1,0(a4)
236    dfd9ff18    ld       t9,-232(s8)
237
238 *******************************************************************************/
239
240 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
241 {
242         constant_classref *cr;
243         u1                *datap;
244         classinfo         *c;
245
246         /* get stuff from the stack */
247
248         cr    = (constant_classref *) pr->ref;
249         datap = (u1 *)                pr->datap;
250
251         /* get the fieldinfo */
252
253         if (!(c = resolve_classref_eager(cr)))
254                 return false;
255
256         PATCH_BACK_ORIGINAL_MCODE;
257
258         /* patch super class' vftbl */
259
260         *((intptr_t *) datap) = (intptr_t) c->vftbl;
261
262         /* synchronize data cache */
263
264         md_dcacheflush(datap, SIZEOF_VOID_P);
265
266         return true;
267 }
268
269
270 /* patcher_resolve_classref_to_flags *******************************************
271
272    CHECKCAST/INSTANCEOF:
273
274    <patched call position>
275    8fc3ff24    lw       v1,-220(s8)
276    30630200    andi     v1,v1,512
277    1060000d    beq      v1,zero,0x000000001051824c
278    00000000    nop
279
280 *******************************************************************************/
281
282 bool patcher_resolve_classref_to_flags(patchref_t *pr)
283 {
284         constant_classref *cr;
285         u1                *datap;
286         classinfo         *c;
287
288         /* get stuff from the stack */
289
290         cr    = (constant_classref *) pr->ref;
291         datap = (u1 *)                pr->datap;
292
293         /* get the fieldinfo */
294
295         if (!(c = resolve_classref_eager(cr)))
296                 return false;
297
298         PATCH_BACK_ORIGINAL_MCODE;
299
300         /* patch class flags */
301
302         *((int32_t *) datap) = (int32_t) c->flags;
303
304         /* synchronize data cache */
305
306         md_dcacheflush(datap, sizeof(int32_t));
307
308         return true;
309 }
310
311
312 /* patcher_invokestatic_special ************************************************
313
314    Machine code:
315
316    <patched call position>
317    dfdeffc0    ld       s8,-64(s8)
318    03c0f809    jalr     s8
319    00000000    nop
320
321 ******************************************************************************/
322
323 bool patcher_invokestatic_special(patchref_t *pr)
324 {
325         unresolved_method *um;
326         u1                *datap;
327         methodinfo        *m;
328
329         /* get stuff from the stack */
330
331         um    = (unresolved_method *) pr->ref;
332         datap = (u1 *)                pr->datap;
333
334         /* get the fieldinfo */
335
336         if (!(m = resolve_method_eager(um)))
337                 return false;
338
339         PATCH_BACK_ORIGINAL_MCODE;
340
341         /* patch stubroutine */
342
343         *((ptrint *) datap) = (ptrint) m->stubroutine;
344
345         /* synchronize data cache */
346
347         md_dcacheflush(datap, SIZEOF_VOID_P);
348
349         return true;
350 }
351
352
353 /* patcher_invokevirtual *******************************************************
354
355    Machine code:
356
357    <patched call position>
358    dc990000    ld       t9,0(a0)
359    df3e0040    ld       s8,64(t9)
360    03c0f809    jalr     s8
361    00000000    nop
362
363 *******************************************************************************/
364
365 bool patcher_invokevirtual(patchref_t *pr)
366 {
367         u1                *ra;
368         unresolved_method *um;
369         methodinfo        *m;
370
371         /* get stuff from the stack */
372
373         ra = (u1 *)                pr->mpc;
374         um = (unresolved_method *) pr->ref;
375
376         /* get the fieldinfo */
377
378         if (!(m = resolve_method_eager(um)))
379                 return false;
380
381         PATCH_BACK_ORIGINAL_MCODE;
382
383         /* if we show disassembly, we have to skip the nop's */
384
385         if (opt_shownops)
386                 ra = ra + PATCHER_CALL_SIZE;
387
388         /* patch vftbl index */
389
390         *((s4 *) (ra + 1 * 4)) |=
391                 (s4) ((OFFSET(vftbl_t, table[0]) +
392                            sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
393
394         /* synchronize instruction cache */
395
396         md_icacheflush(ra + 1 * 4, 1 * 4);
397
398         return true;
399 }
400
401
402 /* patcher_invokeinterface *****************************************************
403
404    Machine code:
405
406    <patched call position>
407    dc990000    ld       t9,0(a0)
408    df39ffa0    ld       t9,-96(t9)
409    df3e0018    ld       s8,24(t9)
410    03c0f809    jalr     s8
411    00000000    nop
412
413 *******************************************************************************/
414
415 bool patcher_invokeinterface(patchref_t *pr)
416 {
417         u1                *ra;
418         unresolved_method *um;
419         methodinfo        *m;
420
421         /* get stuff from the stack */
422
423         ra = (u1 *)                pr->mpc;
424         um = (unresolved_method *) pr->ref;
425
426         /* get the fieldinfo */
427
428         if (!(m = resolve_method_eager(um)))
429                 return false;
430
431         PATCH_BACK_ORIGINAL_MCODE;
432
433         /* if we show disassembly, we have to skip the nop's */
434
435         if (opt_shownops)
436                 ra = ra + PATCHER_CALL_SIZE;
437
438         /* patch interfacetable index */
439
440         *((s4 *) (ra + 1 * 4)) |=
441                 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
442                            sizeof(methodptr*) * m->clazz->index) & 0x0000ffff);
443
444         /* patch method offset */
445
446         *((s4 *) (ra + 2 * 4)) |=
447                 (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x0000ffff);
448
449         /* synchronize instruction cache */
450
451         md_icacheflush(ra + 1 * 4, 2 * 4);
452
453         return true;
454 }
455
456
457 /* patcher_checkcast_interface *************************************************
458
459    Machine code:
460
461    <patched call position>
462    dd030000    ld       v1,0(a4)
463    8c79001c    lw       t9,28(v1)
464    27390000    addiu    t9,t9,0
465    1b200082    blez     t9,zero,0x000000001051843c
466    00000000    nop
467    dc790000    ld       t9,0(v1)
468
469 *******************************************************************************/
470
471 bool patcher_checkcast_interface(patchref_t *pr)
472 {
473         u1                *ra;
474         constant_classref *cr;
475         classinfo         *c;
476
477         /* get stuff from the stack */
478
479         ra = (u1 *)                pr->mpc;
480         cr = (constant_classref *) pr->ref;
481
482         /* get the fieldinfo */
483
484         if (!(c = resolve_classref_eager(cr)))
485                 return false;
486
487         PATCH_BACK_ORIGINAL_MCODE;
488
489         /* if we show disassembly, we have to skip the nop's */
490
491         if (opt_shownops)
492                 ra = ra + PATCHER_CALL_SIZE;
493
494         /* patch super class index */
495
496         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
497         /*      *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
498         /*                                                                       c->index * sizeof(methodptr*)) & 0x0000ffff); */
499         *((s4 *) (ra + 6 * 4)) |=
500                 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
501                            c->index * sizeof(methodptr*)) & 0x0000ffff);
502
503         /* synchronize instruction cache */
504
505         md_icacheflush(ra + 2 * 4, 5 * 4);
506
507         return true;
508 }
509
510
511 /* patcher_instanceof_interface ************************************************
512
513    Machine code:
514
515    <patched call position>
516    dd030000    ld       v1,0(a4)
517    8c79001c    lw       t9,28(v1)
518    27390000    addiu    t9,t9,0
519    1b200082    blez     t9,zero,0x000000001051843c
520    00000000    nop
521    dc790000    ld       t9,0(v1)
522
523 *******************************************************************************/
524
525 bool patcher_instanceof_interface(patchref_t *pr)
526 {
527         u1                *ra;
528         constant_classref *cr;
529         classinfo         *c;
530
531         /* get stuff from the stack */
532
533         ra = (u1 *)                pr->mpc;
534         cr = (constant_classref *) pr->ref;
535
536         /* get the fieldinfo */
537
538         if (!(c = resolve_classref_eager(cr)))
539                 return false;
540
541         PATCH_BACK_ORIGINAL_MCODE;
542
543         /* if we show disassembly, we have to skip the nop's */
544
545         if (opt_shownops)
546                 ra = ra + PATCHER_CALL_SIZE;
547
548         /* patch super class index */
549
550         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
551         *((s4 *) (ra + 5 * 4)) |=
552                 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
553                            c->index * sizeof(methodptr*)) & 0x0000ffff);
554
555         /* synchronize instruction cache */
556
557         md_icacheflush(ra + 2 * 4, 4 * 4);
558
559         return true;
560 }
561
562
563 /*
564  * These are local overrides for various environment variables in Emacs.
565  * Please do not remove this and leave it at the end of the file, where
566  * Emacs will automagically detect them.
567  * ---------------------------------------------------------------------
568  * Local variables:
569  * mode: c
570  * indent-tabs-mode: t
571  * c-basic-offset: 4
572  * tab-width: 4
573  * End:
574  * vim:noexpandtab:sw=4:ts=4:
575  */