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