* src/vm/jit/patcher-common.c: Moved to .cpp.
[cacao.git] / src / vm / jit / s390 / patcher.c
1 /* src/vm/jit/s390/patcher.c - s390 code patching functions
2
3    Copyright (C) 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
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.
12
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.
17
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
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30
31 #include "mm/memory.h"
32 #include "native/native.h"
33
34 #include "vm/jit/builtin.hpp"
35 #include "vm/class.h"
36 #include "vm/field.hpp"
37 #include "vm/initialize.h"
38 #include "vm/options.h"
39 #include "vm/references.h"
40 #include "vm/resolve.h"
41 #include "vm/types.h"
42
43 #include "vm/jit/patcher-common.hpp"
44 #include "vm/jit/s390/codegen.h"
45 #include "vm/jit/s390/md-abi.h"
46
47
48 #define PATCH_BACK_ORIGINAL_MCODE \
49         *((u2 *) pr->mpc) = (u2) pr->mcode;
50
51 #define PATCHER_TRACE 
52
53
54 /* patcher_patch_code **********************************************************
55
56    Just patches back the original machine code.
57
58 *******************************************************************************/
59
60 void patcher_patch_code(patchref_t *pr)
61 {
62         PATCH_BACK_ORIGINAL_MCODE;
63 }
64
65
66 /* patcher_get_putstatic *******************************************************
67
68    Machine code:
69
70 *******************************************************************************/
71
72 bool patcher_get_putstatic(patchref_t *pr)
73 {
74         unresolved_field *uf;
75         u1               *datap;
76         fieldinfo        *fi;
77
78         PATCHER_TRACE;
79
80         /* get stuff from the stack */
81
82         uf    = (unresolved_field *) pr->ref;
83         datap = (u1 *)               pr->datap;
84
85         /* get the fieldinfo */
86
87         if (!(fi = resolve_field_eager(uf)))
88                 return false;
89
90         /* check if the field's class is initialized */
91
92         if (!(fi->clazz->state & CLASS_INITIALIZED))
93                 if (!initialize_class(fi->clazz))
94                         return false;
95
96         PATCH_BACK_ORIGINAL_MCODE;
97
98         /* patch the field value's address */
99
100         *((intptr_t *) datap) = (intptr_t) fi->value;
101
102         return true;
103 }
104
105
106 /* patcher_get_putfield ********************************************************
107
108    Machine code:
109
110 *******************************************************************************/
111
112 bool patcher_get_putfield(patchref_t *pr)
113 {
114         u1               *ra;
115         unresolved_field *uf;
116         fieldinfo        *fi;
117         s4                disp;
118
119         PATCHER_TRACE;
120
121         /* get stuff from the stack */
122
123         ra    = (u1 *)               pr->mpc;
124         uf    = (unresolved_field *) pr->ref;
125         disp  =                      pr->disp;
126
127         /* get the fieldinfo */
128
129         if (!(fi = resolve_field_eager(uf)))
130                 return false;
131
132         PATCH_BACK_ORIGINAL_MCODE;
133
134         /* If there is an operand load before, skip the load size passed in disp (see ICMD_PUTFIELD) */
135
136         ra += disp;
137
138         /* patch correct offset */
139
140         if (fi->type == TYPE_LNG) {
141                 ASSERT_VALID_DISP(fi->offset + 4);
142                 /* 2 RX operations, for 2 words; each already contains a 0 or 4 offset. */
143                 N_RX_SET_DISP(ra, fi->offset + N_RX_GET_DISP(ra));
144                 ra += SZ_RX;
145                 N_RX_SET_DISP(ra, fi->offset + N_RX_GET_DISP(ra));
146         } else {
147                 ASSERT_VALID_DISP(fi->offset);
148                 /* 1 RX operation */
149                 N_RX_SET_DISP(ra, fi->offset);
150         }
151
152         return true;
153 }
154
155 /* patcher_invokestatic_special ************************************************
156
157    Machine code:
158
159 *******************************************************************************/
160
161 bool patcher_invokestatic_special(patchref_t *pr)
162 {
163         unresolved_method *um;
164         u1                *datap;
165         methodinfo        *m;
166
167         PATCHER_TRACE;
168
169         /* get stuff from the stack */
170
171         um    = (unresolved_method *) pr->ref;
172         datap = (u1 *)                pr->datap;
173
174         /* get the fieldinfo */
175
176         if (!(m = resolve_method_eager(um)))
177                 return false;
178
179         PATCH_BACK_ORIGINAL_MCODE;
180
181         /* patch stubroutine */
182
183         *((ptrint *) datap) = (ptrint) m->stubroutine;
184
185         return true;
186 }
187
188 /* patcher_invokevirtual *******************************************************
189
190    Machine code:
191
192 *******************************************************************************/
193
194 bool patcher_invokevirtual(patchref_t *pr)
195 {
196         u1                *ra;
197         unresolved_method *um;
198         methodinfo        *m;
199         s4                 off;
200
201         PATCHER_TRACE;
202
203         /* get stuff from the stack */
204
205         ra    = (u1 *)                pr->mpc;
206         um    = (unresolved_method *) pr->ref;
207
208         /* get the fieldinfo */
209
210         if (!(m = resolve_method_eager(um)))
211                 return false;
212
213         /* patch back original code */
214
215         PATCH_BACK_ORIGINAL_MCODE;
216
217         /* patch vftbl index */
218
219
220         off = (s4) (OFFSET(vftbl_t, table[0]) +
221                                                                    sizeof(methodptr) * m->vftblindex);
222
223         ASSERT_VALID_DISP(off);
224
225         N_RX_SET_DISP(ra + SZ_RX, off);
226
227         return true;
228 }
229
230
231 /* patcher_invokeinterface *****************************************************
232
233    Machine code:
234
235 *******************************************************************************/
236
237 bool patcher_invokeinterface(patchref_t *pr)
238 {
239         u1                *ra;
240         unresolved_method *um;
241         methodinfo        *m;
242         s4                 idx, off;
243
244         PATCHER_TRACE;
245
246         /* get stuff from the stack */
247
248         ra    = (u1 *)                pr->mpc;
249         um    = (unresolved_method *) pr->ref;
250
251         /* get the fieldinfo */
252
253         if (!(m = resolve_method_eager(um)))
254                 return false;
255
256         /* patch back original code */
257
258         PATCH_BACK_ORIGINAL_MCODE;
259
260         /* get interfacetable index */
261
262         idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
263                 sizeof(methodptr) * m->clazz->index);
264
265         ASSERT_VALID_IMM(idx);
266
267         /* get method offset */
268
269         off =
270                 (s4) (sizeof(methodptr) * (m - m->clazz->methods));
271
272         ASSERT_VALID_DISP(off);
273
274         /* patch them */
275
276         N_RI_SET_IMM(ra + SZ_L, idx);
277         N_RX_SET_DISP(ra + SZ_L + SZ_LHI + SZ_L, off);
278
279         return true;
280 }
281
282
283 /* patcher_resolve_classref_to_flags *******************************************
284
285    CHECKCAST/INSTANCEOF:
286
287    <patched call position>
288
289 *******************************************************************************/
290
291 bool patcher_resolve_classref_to_flags(patchref_t *pr)
292 {
293         constant_classref *cr;
294         u1                *datap;
295         classinfo         *c;
296
297         PATCHER_TRACE;
298
299         /* get stuff from the stack */
300
301         cr    = (constant_classref *) pr->ref;
302         datap = (u1 *)                pr->datap;
303
304         /* get the fieldinfo */
305
306         if (!(c = resolve_classref_eager(cr)))
307                 return false;
308
309         PATCH_BACK_ORIGINAL_MCODE;
310
311         /* patch class flags */
312
313         *((s4 *) datap) = (s4) c->flags;
314
315         return true;
316 }
317
318 /* patcher_resolve_classref_to_classinfo ***************************************
319
320    ACONST:
321    MULTIANEWARRAY:
322    ARRAYCHECKCAST:
323
324 *******************************************************************************/
325
326 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
327 {
328         constant_classref *cr;
329         u1                *datap;
330         classinfo         *c;
331
332         PATCHER_TRACE;
333
334         /* get stuff from the stack */
335
336         cr    = (constant_classref *) pr->ref;
337         datap = (u1 *)                pr->datap;
338
339         /* get the classinfo */
340
341         if (!(c = resolve_classref_eager(cr)))
342                 return false;
343
344         PATCH_BACK_ORIGINAL_MCODE;
345
346         /* patch the classinfo pointer */
347
348         *((ptrint *) datap) = (ptrint) c;
349
350         return true;
351 }
352
353 /* patcher_resolve_classref_to_vftbl *******************************************
354
355    CHECKCAST (class):
356    INSTANCEOF (class):
357
358 *******************************************************************************/
359
360 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
361 {
362         constant_classref *cr;
363         u1                *datap;
364         classinfo         *c;
365
366         PATCHER_TRACE;
367
368         /* get stuff from the stack */
369
370         cr    = (constant_classref *) pr->ref;
371         datap = (u1 *)                pr->datap;
372
373         /* get the fieldinfo */
374
375         if (!(c = resolve_classref_eager(cr)))
376                 return false;
377
378         PATCH_BACK_ORIGINAL_MCODE;
379
380         /* patch super class' vftbl */
381
382         *((ptrint *) datap) = (ptrint) c->vftbl;
383
384         return true;
385 }
386
387 /* patcher_checkcast_instanceof_interface **************************************
388
389    Machine code:
390
391 *******************************************************************************/
392
393 bool patcher_checkcast_instanceof_interface(patchref_t *pr)
394 {
395
396         u1                *ra;
397         constant_classref *cr;
398         classinfo         *c;
399
400         PATCHER_TRACE;
401
402         /* get stuff from the stack */
403
404         ra    = (u1 *)                pr->mpc;
405         cr    = (constant_classref *) pr->ref;
406
407         /* get the fieldinfo */
408
409         if (!(c = resolve_classref_eager(cr)))
410                 return false;
411
412         /* patch back original code */
413
414         PATCH_BACK_ORIGINAL_MCODE;
415
416         /* patch super class index */
417
418         /* From here, split your editor and open codegen.c */
419
420         switch (N_RX_GET_REG(ra)) {
421                 case REG_ITMP1: 
422                         /* First M_ALD is into ITMP1 */
423                         /* INSTANCEOF code */
424
425                         N_RI_SET_IMM(ra + SZ_L + SZ_L, - c->index);
426                         N_RI_SET_IMM(
427                                 ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC,
428                                 (int16_t)(OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*))
429                         );
430                         break;
431
432                 case REG_ITMP2:
433                         /* First M_ALD is into ITMP2 */
434                         /* CHECKCAST code */
435
436                         N_RI_SET_IMM(ra + SZ_L + SZ_L, - c->index);
437                         N_RI_SET_IMM(
438                                 ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC + SZ_ILL,
439                                 (int16_t)(OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*))
440                         );
441                         break;
442
443                 default:
444                         assert(0);
445                         break;
446         }
447
448         return true;
449 }
450
451
452 /*
453  * These are local overrides for various environment variables in Emacs.
454  * Please do not remove this and leave it at the end of the file, where
455  * Emacs will automagically detect them.
456  * ---------------------------------------------------------------------
457  * Local variables:
458  * mode: c
459  * indent-tabs-mode: t
460  * c-basic-offset: 4
461  * tab-width: 4
462  * End:
463  * vim:noexpandtab:sw=4:ts=4:
464  */