* src/vm/jit/arm/codegen.c (codegen_emit_stub_native): Removed
[cacao.git] / src / vm / jit / arm / patcher.c
1 /* src/vm/jit/arm/patcher.c - ARM 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 "mm/memory.h"
36
37 #include "native/native.h"
38
39 #include "vm/builtin.h"
40 #include "vm/exceptions.h"
41 #include "vm/initialize.h"
42
43 #include "vm/jit/asmpart.h"
44 #include "vm/jit/md.h"
45 #include "vm/jit/patcher-common.h"
46
47 #include "vmcore/field.h"
48 #include "vmcore/options.h"
49 #include "vmcore/references.h"
50 #include "vm/resolve.h"
51
52
53 #define PATCH_BACK_ORIGINAL_MCODE \
54     *((u4 *) pr->mpc) = (u4) pr->mcode; \
55     md_icacheflush((u1 *) pr->mpc, 1 * 4);
56
57 #define gen_resolveload(inst,offset) \
58         assert((offset) >= -0x0fff && (offset) <= 0x0fff); \
59         assert(!((inst) & 0x0fff)); \
60         if ((offset) <  0) { \
61                 (inst) = ((inst) & 0xff7ff000) | ((-(offset)) & 0x0fff); \
62                 /*(inst) &= ~(1 << 23);*/ \
63         } else { \
64                 (inst) = ((inst) & 0xfffff000) | ((offset) & 0x0fff); \
65                 /*(inst) |= (1 << 23);*/ \
66         }
67
68
69 /* patcher_patch_code **********************************************************
70
71    Just patches back the original machine code.
72
73 *******************************************************************************/
74
75 void patcher_patch_code(patchref_t *pr)
76 {
77         PATCH_BACK_ORIGINAL_MCODE;
78 }
79
80
81 /* patcher_get_putstatic *******************************************************
82
83    Machine code:
84
85    <patched call position>
86    e51c103c    ldr   r1, [ip, #-60]
87
88 *******************************************************************************/
89
90 bool patcher_get_putstatic(patchref_t *pr)
91 {
92         unresolved_field *uf;
93         u1               *datap;
94         fieldinfo        *fi;
95
96         /* get stuff from the stack */
97
98         uf    = (unresolved_field *) pr->ref;
99         datap = (u1 *)               pr->datap;
100
101         /* get the fieldinfo */
102
103         if (!(fi = resolve_field_eager(uf)))
104                 return false;
105
106         /* check if the field's class is initialized */
107
108         if (!(fi->class->state & CLASS_INITIALIZED))
109                 if (!initialize_class(fi->class))
110                         return false;
111
112         PATCH_BACK_ORIGINAL_MCODE;
113
114         /* patch the field value's address */
115
116         *((intptr_t *) datap) = (intptr_t) fi->value;
117
118         return true;
119 }
120
121
122 /* patcher_get_putfield ********************************************************
123
124    Machine code:
125
126    <patched call position>
127    e58a8000    str   r8, [sl, #__]
128
129 *******************************************************************************/
130
131 bool patcher_get_putfield(patchref_t *pr)
132 {
133         u1                *ra;
134         u4                 mcode;
135         unresolved_field  *uf;
136         fieldinfo         *fi;
137
138         /* get stuff from the stack */
139         ra    = (u1*)                 pr->mpc;
140         mcode =                       pr->mcode;
141         uf    = (unresolved_field*)   pr->ref;
142
143         /* get the fieldinfo */
144
145         if (!(fi = resolve_field_eager(uf)))
146                 return false;
147
148         PATCH_BACK_ORIGINAL_MCODE;
149
150         /* if we show disassembly, we have to skip the nop */
151
152         if (opt_shownops)
153                 ra = ra + 1 * 4;
154
155         /* patch the field's offset into the instruction */
156
157         switch(fi->type) {
158         case TYPE_ADR:
159         case TYPE_INT:
160 #if defined(ENABLE_SOFTFLOAT)
161         case TYPE_FLT:
162 #endif
163                 assert(fi->offset <= 0x0fff);
164                 *((u4 *) (ra + 0 * 4)) |= (fi->offset & 0x0fff);
165                 break;
166
167         case TYPE_LNG:
168 #if defined(ENABLE_SOFTFLOAT)
169         case TYPE_DBL:
170 #endif
171                 assert((fi->offset + 4) <= 0x0fff);
172                 *((u4 *) (ra + 0 * 4)) |= ((fi->offset + 0) & 0x0fff);
173                 *((u4 *) (ra + 1 * 4)) &= 0xfffff000;
174                 *((u4 *) (ra + 1 * 4)) |= ((fi->offset + 4) & 0x0fff);
175                 break;
176
177 #if !defined(ENABLE_SOFTFLOAT)
178         case TYPE_FLT:
179         case TYPE_DBL:
180                 assert(fi->offset <= 0x03ff);
181                 *((u4 *) (ra + 0 * 4)) |= ((fi->offset >> 2) & 0x00ff);
182                 break;
183 #endif
184         }
185
186         /* synchronize instruction cache */
187
188         md_icacheflush(ra, 2 * 4);
189
190         return true;
191 }
192
193
194 /* patcher_resolve_classref_to_classinfo ***************************************
195
196    ACONST - Machine code:
197
198    <patched call postition>
199    e51cc030    ldr   r0, [ip, #-48]
200
201    MULTIANEWARRAY - Machine code:
202     
203    <patched call position>
204    e3a00002    mov   r0, #2  ; 0x2
205    e51c1064    ldr   r1, [ip, #-100]
206    e1a0200d    mov   r2, sp
207    e1a0e00f    mov   lr, pc
208    e51cf068    ldr   pc, [ip, #-104]
209
210    ARRAYCHECKCAST - Machine code:
211
212    <patched call position>
213    e51c1120    ldr   r1, [ip, #-288]
214    e1a0e00f    mov   lr, pc
215    e51cf124    ldr   pc, [ip, #-292]
216
217 *******************************************************************************/
218
219 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
220 {
221         constant_classref *cr;
222         u1                *datap;
223         classinfo         *c;
224
225         /* get stuff from the stack */
226
227         cr    = (constant_classref *) pr->ref;
228         datap = (u1 *)                pr->datap;
229
230         /* get the classinfo */
231
232         if (!(c = resolve_classref_eager(cr)))
233                 return false;
234
235         PATCH_BACK_ORIGINAL_MCODE;
236
237         /* patch the classinfo pointer */
238
239         *((ptrint *) datap) = (ptrint) c;
240
241         return true;
242 }
243
244
245 /* patcher_invokestatic_special ************************************************
246
247    Machine code:
248
249    <patched call position>
250    e51cc02c    ldr   ip, [ip, #-44]
251    e1a0e00f    mov   lr, pc
252    e1a0f00c    mov   pc, ip
253
254 ******************************************************************************/
255
256 bool patcher_invokestatic_special(patchref_t *pr)
257 {
258         unresolved_method *um;
259         u1                *datap;
260         methodinfo        *m;
261
262         /* get stuff from the stack */
263
264         um    = (unresolved_method*) pr->ref;
265         datap = (u1 *)               pr->datap;
266
267         /* get the methodinfo */
268
269         if (!(m = resolve_method_eager(um)))
270                 return false;
271
272         PATCH_BACK_ORIGINAL_MCODE;
273
274         /* patch stubroutine */
275
276         *((ptrint *) datap) = (ptrint) m->stubroutine;
277
278         return true;
279 }
280
281
282 /* patcher_invokevirtual *******************************************************
283
284    Machine code:
285
286    <patched call position>
287    e590b000    ldr   fp, [r0]
288    e59bc000    ldr   ip, [fp, #__]
289    e1a0e00f    mov   lr, pc
290    e1a0f00c    mov   pc, ip
291
292 *******************************************************************************/
293
294 bool patcher_invokevirtual(patchref_t *pr)
295 {
296         u1                *ra;
297         unresolved_method *um;
298         methodinfo        *m;
299
300         /* get stuff from the stack */
301
302         ra = (u1 *)                pr->mpc;
303         um = (unresolved_method *) pr->ref;
304
305         /* get the methodinfo */
306
307         if (!(m = resolve_method_eager(um)))
308                 return false;
309
310         PATCH_BACK_ORIGINAL_MCODE;
311
312         /* if we show disassembly, we have to skip the nop */
313
314         if (opt_shownops)
315                 ra = ra + 1 * 4;
316
317         /* patch vftbl index */
318
319         gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
320
321         /* synchronize instruction cache */
322
323         md_icacheflush(ra + 1 * 4, 1 * 4);
324
325         return true;
326 }
327
328
329 /* patcher_invokeinterface *****************************************************
330
331    Machine code:
332
333    <patched call position>
334    e590b000    ldr   fp, [r0]
335    e59bb000    ldr   fp, [fp, #__]
336    e59bc000    ldr   ip, [fp, #__]
337    e1a0e00f    mov   lr, pc
338    e1a0f00c    mov   pc, ip
339
340
341 *******************************************************************************/
342
343 bool patcher_invokeinterface(patchref_t *pr)
344 {
345         u1                *ra;
346         unresolved_method *um;
347         methodinfo        *m;
348
349         /* get stuff from the stack */
350
351         ra = (u1 *)                pr->mpc;
352         um = (unresolved_method *) pr->ref;
353
354         /* get the methodinfo */
355
356         if (!(m = resolve_method_eager(um)))
357                 return false;
358
359         PATCH_BACK_ORIGINAL_MCODE;
360
361         /* if we show disassembly, we have to skip the nop */
362
363         if (opt_shownops)
364                 ra = ra + 1 * 4;
365
366         /* patch interfacetable index */
367
368         gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index));
369
370         /* patch method offset */
371
372         gen_resolveload(*((s4 *) (ra + 2 * 4)), (s4) (sizeof(methodptr) * (m - m->class->methods)));
373
374         /* synchronize instruction cache */
375
376         md_icacheflush(ra + 1 * 4, 2 * 4);
377
378         return true;
379 }
380
381
382 /* patcher_checkcast_instanceof_flags ******************************************
383
384    Machine code:
385
386    <patched call position>
387
388 *******************************************************************************/
389
390 bool patcher_resolve_classref_to_flags(patchref_t *pr)
391 {
392         constant_classref *cr;
393         u1                *datap;
394         classinfo         *c;
395
396         /* get stuff from the stack */
397
398         cr    = (constant_classref *) pr->ref;
399         datap = (u1 *)                pr->datap;
400
401         /* get the classinfo */
402
403         if (!(c = resolve_classref_eager(cr)))
404                 return false;
405
406         PATCH_BACK_ORIGINAL_MCODE;
407
408         /* patch class flags */
409
410         *((s4 *) datap) = (s4) c->flags;
411
412         return true;
413 }
414
415
416 /* patcher_resolve_classref_to_index *******************************************
417
418    Machine code:
419
420    <patched call position>
421
422 *******************************************************************************/
423
424 bool patcher_resolve_classref_to_index(patchref_t *pr)
425 {
426         constant_classref *cr;
427         u1                *datap;
428         classinfo         *c;
429
430         /* get stuff from the stack */
431
432         cr    = (constant_classref *) pr->ref;
433         datap = (u1 *)                pr->datap;
434
435         /* get the classinfo */
436
437         if (!(c = resolve_classref_eager(cr)))
438                 return false;
439
440         PATCH_BACK_ORIGINAL_MCODE;
441
442         /* patch super class index */
443
444         *((s4 *) datap) = (s4) c->index;
445
446         return true;
447 }
448
449
450 /* patcher_resolve_classref_to_vftbl *******************************************
451
452    Machine code:
453
454    <patched call position>
455
456 *******************************************************************************/
457
458 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
459 {
460         constant_classref *cr;
461         u1                *datap;
462         classinfo         *c;
463
464         /* get stuff from the stack */
465
466         cr    = (constant_classref *) pr->ref;
467         datap = (u1 *)                pr->datap;
468
469         /* get the classinfo */
470
471         if (!(c = resolve_classref_eager(cr)))
472                 return false;
473
474         PATCH_BACK_ORIGINAL_MCODE;
475
476         /* patch super class' vftbl */
477
478         *((ptrint *) datap) = (ptrint) c->vftbl;
479
480         return true;
481 }
482
483
484 /*
485  * These are local overrides for various environment variables in Emacs.
486  * Please do not remove this and leave it at the end of the file, where
487  * Emacs will automagically detect them.
488  * ---------------------------------------------------------------------
489  * Local variables:
490  * mode: c
491  * indent-tabs-mode: t
492  * c-basic-offset: 4
493  * tab-width: 4
494  * End:
495  * vim:noexpandtab:sw=4:ts=4:
496  */