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