1 /* src/vm/jit/mips/patcher.c - MIPS code patching functions
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31 #include "vm/jit/mips/codegen.h"
32 #include "vm/jit/mips/md.h"
34 #include "mm/memory.h"
36 #include "native/native.hpp"
38 #include "vm/jit/builtin.hpp"
39 #include "vm/class.hpp"
40 #include "vm/field.hpp"
41 #include "vm/initialize.hpp"
42 #include "vm/options.h"
43 #include "vm/references.h"
44 #include "vm/resolve.hpp"
46 #include "vm/jit/asmpart.h"
47 #include "vm/jit/patcher-common.hpp"
50 /* patcher_patch_code **********************************************************
52 Just patches back the original machine code.
54 *******************************************************************************/
56 void patcher_patch_code(patchref_t *pr)
58 *((uint32_t*) pr->mpc) = (uint32_t) pr->mcode;
59 md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE);
63 /* patcher_get_putstatic *******************************************************
67 <patched call position>
68 dfc1ffb8 ld at,-72(s8)
71 *******************************************************************************/
73 bool patcher_get_putstatic(patchref_t *pr)
75 unresolved_field* uf = (unresolved_field *) pr->ref;
76 uintptr_t* datap = (uintptr_t*) pr->datap;
79 fieldinfo* fi = resolve_field_eager(uf);
84 // Check if the field's class is initialized.
85 if (!(fi->clazz->state & CLASS_INITIALIZED))
86 if (!initialize_class(fi->clazz))
89 // Patch the field value's address.
90 *datap = (uintptr_t) fi->value;
92 // Synchronize data cache.
93 md_dcacheflush(datap, SIZEOF_VOID_P);
95 // Patch back the original code.
96 patcher_patch_code(pr);
102 /* patcher_get_putfield ********************************************************
106 <patched call position>
107 8ee90020 lw a5,32(s7)
109 *******************************************************************************/
111 bool patcher_get_putfield(patchref_t *pr)
113 uint32_t* pc = (uint32_t*) pr->mpc;
114 unresolved_field* uf = (unresolved_field*) pr->ref;
116 // Resolve the field.
117 fieldinfo* fi = resolve_field_eager(uf);
122 #if SIZEOF_VOID_P == 4
123 if (IS_LNG_TYPE(fi->type)) {
124 # if WORDS_BIGENDIAN == 1
125 // ATTENTION: order of these instructions depend on M_LLD_INTERN.
126 // The first instruction is patched back later.
127 pr->mcode |= (int16_t) ((fi->offset + 0) & 0x0000ffff);
128 pc[1] |= (int16_t) ((fi->offset + 4) & 0x0000ffff);
130 // ATTENTION: order of these instructions depend on M_LLD_INTERN.
131 // The first instruction is patched back later.
132 pr->mcode |= (int16_t) ((fi->offset + 4) & 0x0000ffff);
133 pc[1] |= (int16_t) ((fi->offset + 0) & 0x0000ffff);
139 // The instruction is patched back later.
140 pr->mcode |= (int16_t) (fi->offset & 0x0000ffff);
143 // Synchronize instruction cache.
144 md_icacheflush(pc, 2 * 4);
146 // Patch back the original code.
147 patcher_patch_code(pr);
153 /* patcher_resolve_classref_to_classinfo ***************************************
157 <patched call postition>
158 dfc4ff98 ld a0,-104(s8)
162 <patched call position>
163 dfc5ff90 ld a1,-112(s8)
165 dfd9ff88 ld t9,-120(s8)
171 <patched call position>
172 dfc5ffc0 ld a1,-64(s8)
173 dfd9ffb8 ld t9,-72(s8)
177 *******************************************************************************/
179 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
181 constant_classref* cr = (constant_classref*) pr->ref;
182 uintptr_t* datap = (uintptr_t*) pr->datap;
184 // Resolve the class.
185 classinfo* c = resolve_classref_eager(cr);
191 *datap = (uintptr_t) c;
193 // Synchronize data cache.
194 md_dcacheflush(datap, SIZEOF_VOID_P);
196 // Patch back the original code.
197 patcher_patch_code(pr);
203 /* patcher_resolve_classref_to_vftbl *******************************************
208 <patched call position>
210 dfd9ff18 ld t9,-232(s8)
212 *******************************************************************************/
214 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
216 constant_classref* cr = (constant_classref *) pr->ref;
217 uintptr_t* datap = (uintptr_t*) pr->datap;
219 // Resolve the field.
220 classinfo* c = resolve_classref_eager(cr);
225 // Patch super class' vftbl.
226 *datap = (uintptr_t) c->vftbl;
228 // Synchronize data cache.
229 md_dcacheflush(datap, SIZEOF_VOID_P);
231 // Patch back the original code.
232 patcher_patch_code(pr);
238 /* patcher_resolve_classref_to_flags *******************************************
240 CHECKCAST/INSTANCEOF:
242 <patched call position>
243 8fc3ff24 lw v1,-220(s8)
244 30630200 andi v1,v1,512
245 1060000d beq v1,zero,0x000000001051824c
248 *******************************************************************************/
250 bool patcher_resolve_classref_to_flags(patchref_t *pr)
252 constant_classref* cr = (constant_classref*) pr->ref;
253 int32_t* datap = (int32_t*) pr->datap;
255 // Resolve the class.
256 classinfo* c = resolve_classref_eager(cr);
261 // Patch class flags.
262 *datap = (int32_t) c->flags;
264 // Synchronize data cache.
265 md_dcacheflush(datap, sizeof(int32_t));
267 // Patch back the original code.
268 patcher_patch_code(pr);
274 /* patcher_invokestatic_special ************************************************
278 <patched call position>
279 dfdeffc0 ld s8,-64(s8)
283 ******************************************************************************/
285 bool patcher_invokestatic_special(patchref_t *pr)
287 unresolved_method* um = (unresolved_method*) pr->ref;
288 void** datap = (void*) pr->datap;
290 // Resolve the method.
291 methodinfo* m = resolve_method_eager(um);
296 // Patch stubroutine.
297 *datap = (void*) m->stubroutine;
299 // Synchronize data cache.
300 md_dcacheflush(datap, SIZEOF_VOID_P);
302 // Patch back the original code.
303 patcher_patch_code(pr);
309 /* patcher_invokevirtual *******************************************************
313 <patched call position>
315 df3e0040 ld s8,64(t9)
319 *******************************************************************************/
321 bool patcher_invokevirtual(patchref_t *pr)
323 uint32_t* pc = (uint32_t*) pr->mpc;
324 unresolved_method* um = (unresolved_method*) pr->ref;
326 // Resolve the method.
327 methodinfo* m = resolve_method_eager(um);
332 // Patch vftbl index.
333 pc[1] |= (int32_t) ((OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
335 // Synchronize instruction cache.
336 md_icacheflush(pc + 1, 1 * 4);
338 // Patch back the original code.
339 patcher_patch_code(pr);
345 /* patcher_invokeinterface *****************************************************
349 <patched call position>
351 df39ffa0 ld t9,-96(t9)
352 df3e0018 ld s8,24(t9)
356 *******************************************************************************/
358 bool patcher_invokeinterface(patchref_t *pr)
360 uint32_t* pc = (uint32_t*) pr->mpc;
361 unresolved_method* um = (unresolved_method*) pr->ref;
363 // Resovlve the method.
364 methodinfo* m = resolve_method_eager(um);
369 // Patch interfacetable index.
370 pc[1] |= (int32_t) ((OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index) & 0x0000ffff);
372 // Patch method offset.
373 pc[2] |= (int32_t) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x0000ffff);
375 // Synchronize instruction cache.
376 md_icacheflush(pc + 1, 2 * 4);
378 // Patch back the original code.
379 patcher_patch_code(pr);
385 /* patcher_checkcast_interface *************************************************
389 <patched call position>
391 8c79001c lw t9,28(v1)
392 27390000 addiu t9,t9,0
393 1b200082 blez t9,zero,0x000000001051843c
397 *******************************************************************************/
399 bool patcher_checkcast_interface(patchref_t *pr)
401 uint32_t* pc = (uint32_t*) pr->mpc;
402 constant_classref* cr = (constant_classref*) pr->ref;
404 // Resolve the class.
405 classinfo* c = resolve_classref_eager(cr);
410 // Patch super class index.
411 pc[2] |= (int32_t) (-(c->index) & 0x0000ffff);
412 pc[6] |= (int32_t) ((OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)) & 0x0000ffff);
414 // Synchronize instruction cache.
415 md_icacheflush(pc + 2, 5 * 4);
417 // Patch back the original code.
418 patcher_patch_code(pr);
424 /* patcher_instanceof_interface ************************************************
428 <patched call position>
430 8c79001c lw t9,28(v1)
431 27390000 addiu t9,t9,0
432 1b200082 blez t9,zero,0x000000001051843c
436 *******************************************************************************/
438 bool patcher_instanceof_interface(patchref_t *pr)
440 uint32_t* pc = (uint32_t*) pr->mpc;
441 constant_classref* cr = (constant_classref*) pr->ref;
443 // Resolve the method.
444 classinfo* c = resolve_classref_eager(cr);
449 // Patch super class index.
450 pc[2] |= (int32_t) (-(c->index) & 0x0000ffff);
451 pc[5] |= (int32_t) ((OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)) & 0x0000ffff);
453 // Synchronize instruction cache.
454 md_icacheflush(pc + 2, 4 * 4);
456 // Patch back the original code.
457 patcher_patch_code(pr);
464 * These are local overrides for various environment variables in Emacs.
465 * Please do not remove this and leave it at the end of the file, where
466 * Emacs will automagically detect them.
467 * ---------------------------------------------------------------------
470 * indent-tabs-mode: t
474 * vim:noexpandtab:sw=4:ts=4: