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