* src/vm/jit/patcher-common.h (patcher_patch_code): Added prototype.
[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_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_resolve_native ******************************************************
315
316    XXX
317
318 *******************************************************************************/
319
320 bool patcher_resolve_native_function(patchref_t *pr)
321 {
322         methodinfo  *m;
323         u1          *datap;
324         functionptr  f;
325
326         /* get stuff from the stack */
327
328         m     = (methodinfo *) pr->ref;
329         datap = (u1 *)         pr->datap;
330
331         /* resolve native function */
332
333         if (!(f = native_resolve_function(m)))
334                 return false;
335
336         PATCH_BACK_ORIGINAL_MCODE;
337
338         /* patch native function pointer */
339
340         *((ptrint *) datap) = (ptrint) f;
341
342         /* synchronize data cache */
343
344         md_dcacheflush(datap, SIZEOF_VOID_P);
345
346         return true;
347 }
348
349
350 /* patcher_invokestatic_special ************************************************
351
352    Machine code:
353
354    <patched call position>
355    dfdeffc0    ld       s8,-64(s8)
356    03c0f809    jalr     s8
357    00000000    nop
358
359 ******************************************************************************/
360
361 bool patcher_invokestatic_special(patchref_t *pr)
362 {
363         unresolved_method *um;
364         u1                *datap;
365         methodinfo        *m;
366
367         /* get stuff from the stack */
368
369         um    = (unresolved_method *) pr->ref;
370         datap = (u1 *)                pr->datap;
371
372         /* get the fieldinfo */
373
374         if (!(m = resolve_method_eager(um)))
375                 return false;
376
377         PATCH_BACK_ORIGINAL_MCODE;
378
379         /* patch stubroutine */
380
381         *((ptrint *) datap) = (ptrint) m->stubroutine;
382
383         /* synchronize data cache */
384
385         md_dcacheflush(datap, SIZEOF_VOID_P);
386
387         return true;
388 }
389
390
391 /* patcher_invokevirtual *******************************************************
392
393    Machine code:
394
395    <patched call position>
396    dc990000    ld       t9,0(a0)
397    df3e0040    ld       s8,64(t9)
398    03c0f809    jalr     s8
399    00000000    nop
400
401 *******************************************************************************/
402
403 bool patcher_invokevirtual(patchref_t *pr)
404 {
405         u1                *ra;
406         unresolved_method *um;
407         methodinfo        *m;
408
409         /* get stuff from the stack */
410
411         ra = (u1 *)                pr->mpc;
412         um = (unresolved_method *) pr->ref;
413
414         /* get the fieldinfo */
415
416         if (!(m = resolve_method_eager(um)))
417                 return false;
418
419         PATCH_BACK_ORIGINAL_MCODE;
420
421         /* if we show disassembly, we have to skip the nop's */
422
423         if (opt_shownops)
424                 ra = ra + PATCHER_CALL_SIZE;
425
426         /* patch vftbl index */
427
428         *((s4 *) (ra + 1 * 4)) |=
429                 (s4) ((OFFSET(vftbl_t, table[0]) +
430                            sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
431
432         /* synchronize instruction cache */
433
434         md_icacheflush(ra + 1 * 4, 1 * 4);
435
436         return true;
437 }
438
439
440 /* patcher_invokeinterface *****************************************************
441
442    Machine code:
443
444    <patched call position>
445    dc990000    ld       t9,0(a0)
446    df39ffa0    ld       t9,-96(t9)
447    df3e0018    ld       s8,24(t9)
448    03c0f809    jalr     s8
449    00000000    nop
450
451 *******************************************************************************/
452
453 bool patcher_invokeinterface(patchref_t *pr)
454 {
455         u1                *ra;
456         unresolved_method *um;
457         methodinfo        *m;
458
459         /* get stuff from the stack */
460
461         ra = (u1 *)                pr->mpc;
462         um = (unresolved_method *) pr->ref;
463
464         /* get the fieldinfo */
465
466         if (!(m = resolve_method_eager(um)))
467                 return false;
468
469         PATCH_BACK_ORIGINAL_MCODE;
470
471         /* if we show disassembly, we have to skip the nop's */
472
473         if (opt_shownops)
474                 ra = ra + PATCHER_CALL_SIZE;
475
476         /* patch interfacetable index */
477
478         *((s4 *) (ra + 1 * 4)) |=
479                 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
480                            sizeof(methodptr*) * m->class->index) & 0x0000ffff);
481
482         /* patch method offset */
483
484         *((s4 *) (ra + 2 * 4)) |=
485                 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
486
487         /* synchronize instruction cache */
488
489         md_icacheflush(ra + 1 * 4, 2 * 4);
490
491         return true;
492 }
493
494
495 /* patcher_checkcast_interface *************************************************
496
497    Machine code:
498
499    <patched call position>
500    dd030000    ld       v1,0(a4)
501    8c79001c    lw       t9,28(v1)
502    27390000    addiu    t9,t9,0
503    1b200082    blez     t9,zero,0x000000001051843c
504    00000000    nop
505    dc790000    ld       t9,0(v1)
506
507 *******************************************************************************/
508
509 bool patcher_checkcast_interface(patchref_t *pr)
510 {
511         u1                *ra;
512         constant_classref *cr;
513         classinfo         *c;
514
515         /* get stuff from the stack */
516
517         ra = (u1 *)                pr->mpc;
518         cr = (constant_classref *) pr->ref;
519
520         /* get the fieldinfo */
521
522         if (!(c = resolve_classref_eager(cr)))
523                 return false;
524
525         PATCH_BACK_ORIGINAL_MCODE;
526
527         /* if we show disassembly, we have to skip the nop's */
528
529         if (opt_shownops)
530                 ra = ra + PATCHER_CALL_SIZE;
531
532         /* patch super class index */
533
534         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
535         /*      *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
536         /*                                                                       c->index * sizeof(methodptr*)) & 0x0000ffff); */
537         *((s4 *) (ra + 6 * 4)) |=
538                 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
539                            c->index * sizeof(methodptr*)) & 0x0000ffff);
540
541         /* synchronize instruction cache */
542
543         md_icacheflush(ra + 2 * 4, 5 * 4);
544
545         return true;
546 }
547
548
549 /* patcher_instanceof_interface ************************************************
550
551    Machine code:
552
553    <patched call position>
554    dd030000    ld       v1,0(a4)
555    8c79001c    lw       t9,28(v1)
556    27390000    addiu    t9,t9,0
557    1b200082    blez     t9,zero,0x000000001051843c
558    00000000    nop
559    dc790000    ld       t9,0(v1)
560
561 *******************************************************************************/
562
563 bool patcher_instanceof_interface(patchref_t *pr)
564 {
565         u1                *ra;
566         constant_classref *cr;
567         classinfo         *c;
568
569         /* get stuff from the stack */
570
571         ra = (u1 *)                pr->mpc;
572         cr = (constant_classref *) pr->ref;
573
574         /* get the fieldinfo */
575
576         if (!(c = resolve_classref_eager(cr)))
577                 return false;
578
579         PATCH_BACK_ORIGINAL_MCODE;
580
581         /* if we show disassembly, we have to skip the nop's */
582
583         if (opt_shownops)
584                 ra = ra + PATCHER_CALL_SIZE;
585
586         /* patch super class index */
587
588         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
589         *((s4 *) (ra + 5 * 4)) |=
590                 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
591                            c->index * sizeof(methodptr*)) & 0x0000ffff);
592
593         /* synchronize instruction cache */
594
595         md_icacheflush(ra + 2 * 4, 4 * 4);
596
597         return true;
598 }
599
600
601 /*
602  * These are local overrides for various environment variables in Emacs.
603  * Please do not remove this and leave it at the end of the file, where
604  * Emacs will automagically detect them.
605  * ---------------------------------------------------------------------
606  * Local variables:
607  * mode: c
608  * indent-tabs-mode: t
609  * c-basic-offset: 4
610  * tab-width: 4
611  * End:
612  * vim:noexpandtab:sw=4:ts=4:
613  */