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.hpp"
38 #include "native/native.hpp"
40 #include "vm/jit/builtin.hpp"
41 #include "vm/class.hpp"
42 #include "vm/field.hpp"
43 #include "vm/initialize.hpp"
44 #include "vm/options.h"
45 #include "vm/references.h"
46 #include "vm/resolve.hpp"
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/patcher-common.hpp"
52 /* patcher_patch_code **********************************************************
54 Just patches back the original machine code.
56 *******************************************************************************/
58 void patcher_patch_code(patchref_t *pr)
60 *((uint32_t*) pr->mpc) = (uint32_t) pr->mcode;
61 md_icacheflush((void*) pr->mpc, 1 * 4);
66 * Check if the trap instruction at the given PC is valid.
68 * @param pc Program counter.
70 * @return true if valid, false otherwise.
72 bool patcher_is_valid_trap_instruction_at(void* pc)
74 uint32_t mcode = *((uint32_t*) pc);
76 // Check for the undefined instruction we use.
77 if ((mcode & 0x0ff000f0) != 0x07f000f0) {
85 /* patcher_get_putstatic *******************************************************
89 <patched call position>
90 e51c103c ldr r1, [ip, #-60]
92 *******************************************************************************/
94 bool patcher_get_putstatic(patchref_t *pr)
96 unresolved_field* uf = (unresolved_field *) pr->ref;
97 uintptr_t* datap = (uintptr_t*) pr->datap;
100 fieldinfo* fi = resolve_field_eager(uf);
105 // Check if the field's class is initialized.
106 if (!(fi->clazz->state & CLASS_INITIALIZED))
107 if (!initialize_class(fi->clazz))
110 // Patch the field value's address.
111 *datap = (uintptr_t) fi->value;
113 // Patch back the original code.
114 patcher_patch_code(pr);
120 /* patcher_get_putfield ********************************************************
124 <patched call position>
125 e58a8000 str r8, [sl, #__]
127 *******************************************************************************/
129 bool patcher_get_putfield(patchref_t *pr)
131 uint32_t* pc = (uint32_t*) pr->mpc;
132 unresolved_field* uf = (unresolved_field*) pr->ref;
134 // Resolve the field.
135 fieldinfo* fi = resolve_field_eager(uf);
140 // Patch the field's offset into the instruction.
145 #if defined(ENABLE_SOFTFLOAT)
148 assert(fi->offset <= 0x0fff);
149 pr->mcode |= (fi->offset & 0x0fff);
153 #if defined(ENABLE_SOFTFLOAT)
156 assert((fi->offset + 4) <= 0x0fff);
157 pr->mcode |= ((fi->offset + 0) & 0x0fff);
159 pc[1] |= ((fi->offset + 4) & 0x0fff);
162 #if !defined(ENABLE_SOFTFLOAT)
165 assert(fi->offset <= 0x03ff);
166 pr->mcode |= ((fi->offset >> 2) & 0x00ff);
171 // Synchronize instruction cache.
172 md_icacheflush(pc, 2 * 4);
174 // Patch back the original code.
175 patcher_patch_code(pr);
181 /* patcher_resolve_classref_to_classinfo ***************************************
183 ACONST - Machine code:
185 <patched call postition>
186 e51cc030 ldr r0, [ip, #-48]
188 MULTIANEWARRAY - Machine code:
190 <patched call position>
191 e3a00002 mov r0, #2 ; 0x2
192 e51c1064 ldr r1, [ip, #-100]
195 e51cf068 ldr pc, [ip, #-104]
197 ARRAYCHECKCAST - Machine code:
199 <patched call position>
200 e51c1120 ldr r1, [ip, #-288]
202 e51cf124 ldr pc, [ip, #-292]
204 *******************************************************************************/
206 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
208 constant_classref* cr = (constant_classref *) pr->ref;
209 uintptr_t* datap = (uintptr_t*) pr->datap;
211 // Resolve the class.
212 classinfo* c = resolve_classref_eager(cr);
217 // Patch the classinfo pointer.
218 *datap = (uintptr_t) c;
220 // Patch back the original code.
221 patcher_patch_code(pr);
227 /* patcher_invokestatic_special ************************************************
231 <patched call position>
232 e51cc02c ldr ip, [ip, #-44]
236 ******************************************************************************/
238 bool patcher_invokestatic_special(patchref_t *pr)
240 unresolved_method* um = (unresolved_method*) pr->ref;
241 uintptr_t* datap = (uintptr_t*) pr->datap;
243 // Reolve the method.
244 methodinfo* m = resolve_method_eager(um);
249 // Patch stubroutine.
250 *datap = (uintptr_t) m->stubroutine;
252 // Patch back the original code.
253 patcher_patch_code(pr);
259 /* patcher_invokevirtual *******************************************************
263 <patched call position>
264 e590b000 ldr fp, [r0]
265 e59bc000 ldr ip, [fp, #__]
269 *******************************************************************************/
271 bool patcher_invokevirtual(patchref_t *pr)
273 unresolved_method* um = (unresolved_method*) pr->ref;
274 int32_t* datap = (int32_t*) pr->datap;
276 // Resolve the method.
277 methodinfo* m = resolve_method_eager(um);
282 // Patch vftbl index.
283 int32_t disp = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex;
286 // Patch back the original code.
287 patcher_patch_code(pr);
293 /* patcher_invokeinterface *****************************************************
297 <patched call position>
298 e590b000 ldr fp, [r0]
299 e59bb000 ldr fp, [fp, #__]
300 e59bc000 ldr ip, [fp, #__]
304 *******************************************************************************/
306 bool patcher_invokeinterface(patchref_t *pr)
308 unresolved_method* um = (unresolved_method*) pr->ref;
309 int32_t* datap = (int32_t*) pr->datap;
311 // Resolve the method.
312 methodinfo* m = resolve_method_eager(um);
317 // Patch interfacetable index.
318 int32_t disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index;
321 // HACK The next data segment entry is one below.
324 // Patch method offset.
325 disp = sizeof(methodptr) * (m - m->clazz->methods);
328 // Patch back the original code.
329 patcher_patch_code(pr);
335 /* patcher_checkcast_instanceof_flags ******************************************
339 <patched call position>
341 *******************************************************************************/
343 bool patcher_resolve_classref_to_flags(patchref_t *pr)
345 constant_classref* cr = (constant_classref*) pr->ref;
346 int32_t* datap = (int32_t*) pr->datap;
348 // Resolve the class.
349 classinfo* c = resolve_classref_eager(cr);
354 // Patch class flags.
355 *datap = (int32_t) c->flags;
357 // Patch back the original code.
358 patcher_patch_code(pr);
364 /* patcher_resolve_classref_to_index *******************************************
368 <patched call position>
370 *******************************************************************************/
372 bool patcher_resolve_classref_to_index(patchref_t *pr)
374 constant_classref* cr = (constant_classref*) pr->ref;
375 int32_t* datap = (int32_t*) pr->datap;
377 // Resolve the class.
378 classinfo* c = resolve_classref_eager(cr);
383 // Patch super class index.
384 *datap = (int32_t) c->index;
386 // Patch back the original code.
387 patcher_patch_code(pr);
393 /* patcher_resolve_classref_to_vftbl *******************************************
397 <patched call position>
399 *******************************************************************************/
401 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
403 constant_classref* cr = (constant_classref*) pr->ref;
404 uintptr_t* datap = (uintptr_t*) pr->datap;
406 // Resolve the class.
408 classinfo* c = resolve_classref_eager(cr);
413 // Patch super class' vftbl.
414 *datap = (uintptr_t) c->vftbl;
416 // Patch back the original code.
417 patcher_patch_code(pr);
424 * These are local overrides for various environment variables in Emacs.
425 * Please do not remove this and leave it at the end of the file, where
426 * Emacs will automagically detect them.
427 * ---------------------------------------------------------------------
430 * indent-tabs-mode: t
434 * vim:noexpandtab:sw=4:ts=4: