1 /* src/vm/jit/s390/patcher.c - s390 code patching functions
3 Copyright (C) 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 "mm/memory.h"
32 #include "native/native.h"
33 #include "vm/builtin.h"
34 #include "vm/exceptions.h"
35 #include "vm/initialize.h"
36 #include "vm/jit/patcher-common.h"
37 #include "vm/jit/s390/codegen.h"
38 #include "vm/jit/s390/md-abi.h"
39 #include "vm/jit/stacktrace.h"
40 #include "vm/resolve.h"
42 #include "vmcore/class.h"
43 #include "vmcore/field.h"
44 #include "vmcore/options.h"
45 #include "vmcore/references.h"
47 #define PATCH_BACK_ORIGINAL_MCODE \
48 *((u2 *) pr->mpc) = (u2) pr->mcode;
53 /* patcher_patch_code **********************************************************
55 Just patches back the original machine code.
57 *******************************************************************************/
59 void patcher_patch_code(patchref_t *pr)
61 PATCH_BACK_ORIGINAL_MCODE;
65 /* patcher_get_putstatic *******************************************************
69 *******************************************************************************/
71 bool patcher_get_putstatic(patchref_t *pr)
79 /* get stuff from the stack */
81 uf = (unresolved_field *) pr->ref;
82 datap = (u1 *) pr->datap;
84 /* get the fieldinfo */
86 if (!(fi = resolve_field_eager(uf)))
89 /* check if the field's class is initialized */
91 if (!(fi->class->state & CLASS_INITIALIZED))
92 if (!initialize_class(fi->class))
95 PATCH_BACK_ORIGINAL_MCODE;
97 /* patch the field value's address */
99 *((intptr_t *) datap) = (intptr_t) fi->value;
105 /* patcher_get_putfield ********************************************************
109 *******************************************************************************/
111 bool patcher_get_putfield(patchref_t *pr)
114 unresolved_field *uf;
120 /* get stuff from the stack */
123 uf = (unresolved_field *) pr->ref;
126 /* get the fieldinfo */
128 if (!(fi = resolve_field_eager(uf)))
131 PATCH_BACK_ORIGINAL_MCODE;
133 /* If NOPs are generated, skip them */
136 ra += PATCHER_NOPS_SKIP;
138 /* If there is an operand load before, skip the load size passed in disp (see ICMD_PUTFIELD) */
142 /* patch correct offset */
144 if (fi->type == TYPE_LNG) {
145 ASSERT_VALID_DISP(fi->offset + 4);
146 /* 2 RX operations, for 2 words; each already contains a 0 or 4 offset. */
147 N_RX_SET_DISP(ra, fi->offset + N_RX_GET_DISP(ra));
149 N_RX_SET_DISP(ra, fi->offset + N_RX_GET_DISP(ra));
151 ASSERT_VALID_DISP(fi->offset);
153 N_RX_SET_DISP(ra, fi->offset);
159 /* patcher_invokestatic_special ************************************************
163 *******************************************************************************/
165 bool patcher_invokestatic_special(patchref_t *pr)
167 unresolved_method *um;
173 /* get stuff from the stack */
175 um = (unresolved_method *) pr->ref;
176 datap = (u1 *) pr->datap;
178 /* get the fieldinfo */
180 if (!(m = resolve_method_eager(um)))
183 PATCH_BACK_ORIGINAL_MCODE;
185 /* patch stubroutine */
187 *((ptrint *) datap) = (ptrint) m->stubroutine;
192 /* patcher_invokevirtual *******************************************************
196 *******************************************************************************/
198 bool patcher_invokevirtual(patchref_t *pr)
201 unresolved_method *um;
207 /* get stuff from the stack */
210 um = (unresolved_method *) pr->ref;
212 /* get the fieldinfo */
214 if (!(m = resolve_method_eager(um)))
217 /* patch back original code */
219 PATCH_BACK_ORIGINAL_MCODE;
221 /* If NOPs are generated, skip them */
224 ra += PATCHER_NOPS_SKIP;
226 /* patch vftbl index */
229 off = (s4) (OFFSET(vftbl_t, table[0]) +
230 sizeof(methodptr) * m->vftblindex);
232 ASSERT_VALID_DISP(off);
234 N_RX_SET_DISP(ra + SZ_RX, off);
240 /* patcher_invokeinterface *****************************************************
244 *******************************************************************************/
246 bool patcher_invokeinterface(patchref_t *pr)
249 unresolved_method *um;
255 /* get stuff from the stack */
258 um = (unresolved_method *) pr->ref;
260 /* get the fieldinfo */
262 if (!(m = resolve_method_eager(um)))
265 /* patch back original code */
267 PATCH_BACK_ORIGINAL_MCODE;
269 /* If NOPs are generated, skip them */
272 ra += PATCHER_NOPS_SKIP;
274 /* get interfacetable index */
276 idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
277 sizeof(methodptr) * m->clazz->index);
279 ASSERT_VALID_IMM(idx);
281 /* get method offset */
284 (s4) (sizeof(methodptr) * (m - m->clazz->methods));
286 ASSERT_VALID_DISP(off);
290 N_RI_SET_IMM(ra + SZ_L, idx);
291 N_RX_SET_DISP(ra + SZ_L + SZ_LHI + SZ_L, off);
297 /* patcher_resolve_classref_to_flags *******************************************
299 CHECKCAST/INSTANCEOF:
301 <patched call position>
303 *******************************************************************************/
305 bool patcher_resolve_classref_to_flags(patchref_t *pr)
307 constant_classref *cr;
313 /* get stuff from the stack */
315 cr = (constant_classref *) pr->ref;
316 datap = (u1 *) pr->datap;
318 /* get the fieldinfo */
320 if (!(c = resolve_classref_eager(cr)))
323 PATCH_BACK_ORIGINAL_MCODE;
325 /* patch class flags */
327 *((s4 *) datap) = (s4) c->flags;
332 /* patcher_resolve_classref_to_classinfo ***************************************
338 *******************************************************************************/
340 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
342 constant_classref *cr;
348 /* get stuff from the stack */
350 cr = (constant_classref *) pr->ref;
351 datap = (u1 *) pr->datap;
353 /* get the classinfo */
355 if (!(c = resolve_classref_eager(cr)))
358 PATCH_BACK_ORIGINAL_MCODE;
360 /* patch the classinfo pointer */
362 *((ptrint *) datap) = (ptrint) c;
367 /* patcher_resolve_classref_to_vftbl *******************************************
372 *******************************************************************************/
374 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
376 constant_classref *cr;
382 /* get stuff from the stack */
384 cr = (constant_classref *) pr->ref;
385 datap = (u1 *) pr->datap;
387 /* get the fieldinfo */
389 if (!(c = resolve_classref_eager(cr)))
392 PATCH_BACK_ORIGINAL_MCODE;
394 /* patch super class' vftbl */
396 *((ptrint *) datap) = (ptrint) c->vftbl;
401 /* patcher_checkcast_instanceof_interface **************************************
405 *******************************************************************************/
407 bool patcher_checkcast_instanceof_interface(patchref_t *pr)
411 constant_classref *cr;
416 /* get stuff from the stack */
419 cr = (constant_classref *) pr->ref;
421 /* get the fieldinfo */
423 if (!(c = resolve_classref_eager(cr)))
426 /* patch back original code */
428 PATCH_BACK_ORIGINAL_MCODE;
430 /* If NOPs are generated, skip them */
433 ra += PATCHER_NOPS_SKIP;
435 /* patch super class index */
437 /* From here, split your editor and open codegen.c */
439 switch (N_RX_GET_REG(ra)) {
441 /* First M_ALD is into ITMP1 */
442 /* INSTANCEOF code */
444 N_RI_SET_IMM(ra + SZ_L + SZ_L, - c->index);
446 ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC,
447 (int16_t)(OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*))
452 /* First M_ALD is into ITMP2 */
455 N_RI_SET_IMM(ra + SZ_L + SZ_L, - c->index);
457 ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC + SZ_ILL,
458 (int16_t)(OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*))
472 * These are local overrides for various environment variables in Emacs.
473 * Please do not remove this and leave it at the end of the file, where
474 * Emacs will automagically detect them.
475 * ---------------------------------------------------------------------
478 * indent-tabs-mode: t
482 * vim:noexpandtab:sw=4:ts=4: