1 /* src/vm/jit/arm/patcher.c - ARM code patching functions
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 Copyright (C) 2008 Theobroma Systems Ltd.
7 This file is part of CACAO.
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2, or (at
12 your option) any later version.
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "vm/jit/arm/md.h"
36 #include "mm/memory.h"
38 #include "native/native.hpp"
40 #include "vm/jit/builtin.hpp"
42 #include "vm/field.hpp"
43 #include "vm/initialize.h"
44 #include "vm/options.h"
45 #include "vm/references.h"
46 #include "vm/resolve.h"
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/patcher-common.hpp"
52 #define gen_resolveload(inst,offset) \
53 assert((offset) >= -0x0fff && (offset) <= 0x0fff); \
54 assert(!((inst) & 0x0fff)); \
56 (inst) = ((inst) & 0xff7ff000) | ((-(offset)) & 0x0fff); \
57 /*(inst) &= ~(1 << 23);*/ \
59 (inst) = ((inst) & 0xfffff000) | ((offset) & 0x0fff); \
60 /*(inst) |= (1 << 23);*/ \
63 /* This is the same as gen_resolveload but does not check whether the opcode
64 * is 'clean' (= current offset is zero).
66 #define gen_resolveload_unchecked(inst,offset) \
67 assert((offset) >= -0x0fff && (offset) <= 0x0fff); \
69 (inst) = ((inst) & 0xff7ff000) | ((-(offset)) & 0x0fff); \
70 /*(inst) &= ~(1 << 23);*/ \
72 (inst) = ((inst) & 0xfffff000) | ((offset) & 0x0fff); \
73 /*(inst) |= (1 << 23);*/ \
76 /* patch_md ********************************************************************
78 Patch back address in a machine dependent way
80 *******************************************************************************/
81 void patch_md(s4 md_patch, ptrint dest, void* ref)
83 gen_resolveload_unchecked(*((s4 *) dest), (s4) ref);
86 /* patcher_patch_code **********************************************************
88 Just patches back the original machine code.
90 *******************************************************************************/
92 void patcher_patch_code(patchref_t *pr)
94 *((uint32_t*) pr->mpc) = (uint32_t) pr->mcode;
95 md_icacheflush((void*) pr->mpc, 1 * 4);
100 * Check if the trap instruction at the given PC is valid.
102 * @param pc Program counter.
104 * @return true if valid, false otherwise.
106 bool patcher_is_valid_trap_instruction_at(void* pc)
108 uint32_t mcode = *((uint32_t*) pc);
110 // Check for the undefined instruction we use.
111 if ((mcode & 0x0ff000f0) != 0x07f000f0) {
119 /* patcher_get_putstatic *******************************************************
123 <patched call position>
124 e51c103c ldr r1, [ip, #-60]
126 *******************************************************************************/
128 bool patcher_get_putstatic(patchref_t *pr)
130 unresolved_field* uf = (unresolved_field *) pr->ref;
131 uintptr_t* datap = (uintptr_t*) pr->datap;
133 // Resolve the field.
134 fieldinfo* fi = resolve_field_eager(uf);
139 // Check if the field's class is initialized.
140 if (!(fi->clazz->state & CLASS_INITIALIZED))
141 if (!initialize_class(fi->clazz))
144 // Patch the field value's address.
145 *datap = (uintptr_t) fi->value;
147 // Patch back the original code.
148 patcher_patch_code(pr);
154 /* patcher_get_putfield ********************************************************
158 <patched call position>
159 e58a8000 str r8, [sl, #__]
161 *******************************************************************************/
163 bool patcher_get_putfield(patchref_t *pr)
165 uint32_t* pc = (uint32_t*) pr->mpc;
166 unresolved_field* uf = (unresolved_field*) pr->ref;
168 // Resolve the field.
169 fieldinfo* fi = resolve_field_eager(uf);
174 // Patch the field's offset into the instruction.
179 #if defined(ENABLE_SOFTFLOAT)
182 assert(fi->offset <= 0x0fff);
183 pr->mcode |= (fi->offset & 0x0fff);
187 #if defined(ENABLE_SOFTFLOAT)
190 assert((fi->offset + 4) <= 0x0fff);
191 pr->mcode |= ((fi->offset + 0) & 0x0fff);
193 pc[1] |= ((fi->offset + 4) & 0x0fff);
196 #if !defined(ENABLE_SOFTFLOAT)
199 assert(fi->offset <= 0x03ff);
200 pr->mcode |= ((fi->offset >> 2) & 0x00ff);
205 // Synchronize instruction cache.
206 md_icacheflush(pc, 2 * 4);
208 // Patch back the original code.
209 patcher_patch_code(pr);
215 /* patcher_resolve_classref_to_classinfo ***************************************
217 ACONST - Machine code:
219 <patched call postition>
220 e51cc030 ldr r0, [ip, #-48]
222 MULTIANEWARRAY - Machine code:
224 <patched call position>
225 e3a00002 mov r0, #2 ; 0x2
226 e51c1064 ldr r1, [ip, #-100]
229 e51cf068 ldr pc, [ip, #-104]
231 ARRAYCHECKCAST - Machine code:
233 <patched call position>
234 e51c1120 ldr r1, [ip, #-288]
236 e51cf124 ldr pc, [ip, #-292]
238 *******************************************************************************/
240 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
242 constant_classref* cr = (constant_classref *) pr->ref;
243 uintptr_t* datap = (uintptr_t*) pr->datap;
245 // Resolve the class.
246 classinfo* c = resolve_classref_eager(cr);
251 // Patch the classinfo pointer.
252 *datap = (uintptr_t) c;
254 // Patch back the original code.
255 patcher_patch_code(pr);
261 /* patcher_invokestatic_special ************************************************
265 <patched call position>
266 e51cc02c ldr ip, [ip, #-44]
270 ******************************************************************************/
272 bool patcher_invokestatic_special(patchref_t *pr)
274 unresolved_method* um = (unresolved_method*) pr->ref;
275 uintptr_t* datap = (uintptr_t*) pr->datap;
277 // Reolve the method.
278 methodinfo* m = resolve_method_eager(um);
283 // Patch stubroutine.
284 *datap = (uintptr_t) m->stubroutine;
286 // Patch back the original code.
287 patcher_patch_code(pr);
293 /* patcher_invokevirtual *******************************************************
297 <patched call position>
298 e590b000 ldr fp, [r0]
299 e59bc000 ldr ip, [fp, #__]
303 *******************************************************************************/
305 bool patcher_invokevirtual(patchref_t *pr)
307 uint32_t* pc = (uint32_t*) pr->mpc;
308 unresolved_method* um = (unresolved_method *) pr->ref;
310 // Resolve the method.
311 methodinfo* m = resolve_method_eager(um);
316 // Patch vftbl index.
317 gen_resolveload(pc[1], (int32_t) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
319 // Synchronize instruction cache.
320 md_icacheflush(pc + 1, 1 * 4);
322 // Patch back the original code.
323 patcher_patch_code(pr);
329 /* patcher_invokeinterface *****************************************************
333 <patched call position>
334 e590b000 ldr fp, [r0]
335 e59bb000 ldr fp, [fp, #__]
336 e59bc000 ldr ip, [fp, #__]
341 *******************************************************************************/
343 bool patcher_invokeinterface(patchref_t *pr)
345 uint32_t* pc = (uint32_t*) pr->mpc;
346 unresolved_method* um = (unresolved_method *) pr->ref;
348 // Resolve the method.
349 methodinfo* m = resolve_method_eager(um);
354 // Patch interfacetable index.
355 gen_resolveload(pc[1], (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index));
357 // Patch method offset.
358 gen_resolveload(pc[2], (int32_t) (sizeof(methodptr) * (m - m->clazz->methods)));
360 // Synchronize instruction cache.
361 md_icacheflush(pc + 1, 2 * 4);
363 // Patch back the original code.
364 patcher_patch_code(pr);
370 /* patcher_checkcast_instanceof_flags ******************************************
374 <patched call position>
376 *******************************************************************************/
378 bool patcher_resolve_classref_to_flags(patchref_t *pr)
380 constant_classref* cr = (constant_classref*) pr->ref;
381 int32_t* datap = (int32_t*) pr->datap;
383 // Resolve the class.
384 classinfo* c = resolve_classref_eager(cr);
389 // Patch class flags.
390 *datap = (int32_t) c->flags;
392 // Patch back the original code.
393 patcher_patch_code(pr);
399 /* patcher_resolve_classref_to_index *******************************************
403 <patched call position>
405 *******************************************************************************/
407 bool patcher_resolve_classref_to_index(patchref_t *pr)
409 constant_classref* cr = (constant_classref*) pr->ref;
410 int32_t* datap = (int32_t*) pr->datap;
412 // Resolve the class.
413 classinfo* c = resolve_classref_eager(cr);
418 // Patch super class index.
419 *datap = (int32_t) c->index;
421 // Patch back the original code.
422 patcher_patch_code(pr);
428 /* patcher_resolve_classref_to_vftbl *******************************************
432 <patched call position>
434 *******************************************************************************/
436 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
438 constant_classref* cr = (constant_classref*) pr->ref;
439 uintptr_t* datap = (uintptr_t*) pr->datap;
441 // Resolve the class.
443 classinfo* c = resolve_classref_eager(cr);
448 // Patch super class' vftbl.
449 *datap = (uintptr_t) c->vftbl;
451 // Patch back the original code.
452 patcher_patch_code(pr);
459 * These are local overrides for various environment variables in Emacs.
460 * Please do not remove this and leave it at the end of the file, where
461 * Emacs will automagically detect them.
462 * ---------------------------------------------------------------------
465 * indent-tabs-mode: t
469 * vim:noexpandtab:sw=4:ts=4: