a8ec011797b3e6c95ea32700fc1fffe547f4a439
[cacao.git] / src / vm / jit / alpha / patcher.c
1 /* src/vm/jit/alpha/patcher.c - Alpha code patching functions
2
3    Copyright (C) 1996-2005, 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
32 #include "vm/types.h"
33
34 #include "mm/memory.h"
35
36 #include "native/native.h"
37
38 #include "vm/builtin.h"
39 #include "vm/exceptions.h"
40 #include "vm/initialize.h"
41
42 #include "vm/jit/asmpart.h"
43 #include "vm/jit/patcher-common.h"
44 #include "vm/jit/md.h"
45 #include "vm/jit/methodheader.h"
46 #include "vm/jit/stacktrace.h"
47
48 #include "vmcore/class.h"
49 #include "vmcore/field.h"
50 #include "vmcore/options.h"
51 #include "vmcore/references.h"
52 #include "vm/resolve.h"
53
54
55 #define PATCH_BACK_ORIGINAL_MCODE \
56         *((u4 *) pr->mpc) = (u4) pr->mcode; \
57     md_icacheflush(NULL, 0);
58
59
60 /* patcher_patch_code **********************************************************
61
62    Just patches back the original machine code.
63
64 *******************************************************************************/
65
66 void patcher_patch_code(patchref_t *pr)
67 {
68         PATCH_BACK_ORIGINAL_MCODE;
69 }
70
71
72 /* patcher_resolve_classref_to_classinfo ***************************************
73
74    ACONST:
75
76    <patched call postition>
77    a61bff80    ldq     a0,-128(pv)
78
79    MULTIANEWARRAY:
80
81    <patched call position>
82    a63bff80    ldq     a1,-128(pv)
83    47de0412    mov     sp,a2
84    a77bff78    ldq     pv,-136(pv)
85    6b5b4000    jsr     (pv)
86
87    ARRAYCHECKCAST:
88
89    <patched call position>
90    a63bfe60    ldq     a1,-416(pv)
91    a77bfe58    ldq     pv,-424(pv)
92    6b5b4000    jsr     (pv)
93
94 *******************************************************************************/
95
96 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
97 {
98         constant_classref *cr;
99         u1                *datap;
100         classinfo         *c;
101
102         /* get stuff from the stack */
103
104         cr    = (constant_classref *) pr->ref;
105         datap = (u1 *)                pr->datap;
106
107         /* get the classinfo */
108
109         if (!(c = resolve_classref_eager(cr)))
110                 return false;
111
112         PATCH_BACK_ORIGINAL_MCODE;
113
114         /* patch the classinfo pointer */
115
116         *((ptrint *) datap) = (ptrint) c;
117
118         return true;
119 }
120
121
122 /* patcher_resolve_classref_to_vftbl *******************************************
123
124    CHECKCAST (class):
125    INSTANCEOF (class):
126
127    <patched call position>
128    a7940000    ldq     at,0(a4)
129    a7bbff28    ldq     gp,-216(pv)
130
131 *******************************************************************************/
132
133 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
134 {
135         constant_classref *cr;
136         u1                *datap;
137         classinfo         *c;
138
139         /* get stuff from the stack */
140
141         cr    = (constant_classref *) pr->ref;
142         datap = (u1 *)                pr->datap;
143
144         /* get the fieldinfo */
145
146         if (!(c = resolve_classref_eager(cr)))
147                 return false;
148
149         PATCH_BACK_ORIGINAL_MCODE;
150
151         /* patch super class' vftbl */
152
153         *((ptrint *) datap) = (ptrint) c->vftbl;
154
155         return true;
156 }
157
158
159 /* patcher_resolve_classref_to_flags *******************************************
160
161    CHECKCAST/INSTANCEOF:
162
163    <patched call position>
164
165 *******************************************************************************/
166
167 bool patcher_resolve_classref_to_flags(patchref_t *pr)
168 {
169         constant_classref *cr;
170         u1                *datap;
171         classinfo         *c;
172
173         /* get stuff from the stack */
174
175         cr    = (constant_classref *) pr->ref;
176         datap = (u1 *)                pr->datap;
177
178         /* get the fieldinfo */
179
180         if (!(c = resolve_classref_eager(cr)))
181                 return false;
182
183         PATCH_BACK_ORIGINAL_MCODE;
184
185         /* patch class flags */
186
187         *((s4 *) datap) = (s4) c->flags;
188
189         return true;
190 }
191
192
193 /* patcher_get_putstatic *******************************************************
194
195    Machine code:
196
197    <patched call position>
198    a73bff98    ldq     t11,-104(pv)
199    a2590000    ldl     a2,0(t11)
200
201 *******************************************************************************/
202
203 bool patcher_get_putstatic(patchref_t *pr)
204 {
205         unresolved_field *uf;
206         u1               *datap;
207         fieldinfo        *fi;
208
209         /* get stuff from the stack */
210
211         uf    = (unresolved_field *) pr->ref;
212         datap = (u1 *)               pr->datap;
213
214         /* get the fieldinfo */
215
216         if (!(fi = resolve_field_eager(uf)))
217                 return false;
218
219         /* check if the field's class is initialized */
220
221         if (!(fi->class->state & CLASS_INITIALIZED))
222                 if (!initialize_class(fi->class))
223                         return false;
224
225         PATCH_BACK_ORIGINAL_MCODE;
226
227         /* patch the field value's address */
228
229         *((intptr_t *) datap) = (intptr_t) fi->value;
230
231         return true;
232 }
233
234
235 /* patcher_get_putfield ********************************************************
236
237    Machine code:
238
239    <patched call position>
240    a2af0020    ldl     a5,32(s6)
241
242 *******************************************************************************/
243
244 bool patcher_get_putfield(patchref_t *pr)
245 {
246         u1               *ra;
247         unresolved_field *uf;
248         fieldinfo        *fi;
249
250         ra    = (u1 *)               pr->mpc;
251         uf    = (unresolved_field *) pr->ref;
252
253         /* get the fieldinfo */
254
255         if (!(fi = resolve_field_eager(uf)))
256                 return false;
257
258         PATCH_BACK_ORIGINAL_MCODE;
259
260         /* if we show disassembly, we have to skip the nop */
261
262         if (opt_shownops)
263                 ra = ra + 4;
264
265         /* patch the field's offset into the instruction */
266
267         *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
268
269         md_icacheflush(NULL, 0);
270
271         return true;
272 }
273
274
275 /* patcher_invokestatic_special ************************************************
276
277    Machine code:
278
279    <patched call position>
280    a77bffa8    ldq     pv,-88(pv)
281    6b5b4000    jsr     (pv)
282
283 ******************************************************************************/
284
285 bool patcher_invokestatic_special(patchref_t *pr)
286 {
287         unresolved_method *um;
288         u1                *datap;
289         methodinfo        *m;
290
291         /* get stuff from the stack */
292
293         um    = (unresolved_method *) pr->ref;
294         datap = (u1 *)                pr->datap;
295
296         /* get the fieldinfo */
297
298         if (!(m = resolve_method_eager(um)))
299                 return false;
300
301         PATCH_BACK_ORIGINAL_MCODE;
302
303         /* patch stubroutine */
304
305         *((ptrint *) datap) = (ptrint) m->stubroutine;
306
307         return true;
308 }
309
310
311 /* patcher_invokevirtual *******************************************************
312
313    Machine code:
314
315    <patched call position>
316    a7900000    ldq     at,0(a0)
317    a77c0100    ldq     pv,256(at)
318    6b5b4000    jsr     (pv)
319
320 *******************************************************************************/
321
322 bool patcher_invokevirtual(patchref_t *pr)
323 {
324         u1                *ra;
325         unresolved_method *um;
326         methodinfo        *m;
327
328         /* get stuff from the stack */
329
330         ra    = (u1 *)                pr->mpc;
331         um    = (unresolved_method *) pr->ref;
332
333         /* get the fieldinfo */
334
335         if (!(m = resolve_method_eager(um)))
336                 return false;
337
338         PATCH_BACK_ORIGINAL_MCODE;
339
340         /* if we show disassembly, we have to skip the nop */
341
342         if (opt_shownops)
343                 ra = ra + 4;
344
345         /* patch vftbl index */
346
347         *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
348                                                                  sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
349
350         md_icacheflush(NULL, 0);
351
352         return true;
353 }
354
355
356 /* patcher_invokeinterface *****************************************************
357
358    Machine code:
359
360    <patched call position>
361    a7900000    ldq     at,0(a0)
362    a79cffa0    ldq     at,-96(at)
363    a77c0018    ldq     pv,24(at)
364    6b5b4000    jsr     (pv)
365
366 *******************************************************************************/
367
368 bool patcher_invokeinterface(patchref_t *pr)
369 {
370         u1                *ra;
371         unresolved_method *um;
372         methodinfo        *m;
373
374         /* get stuff from the stack */
375
376         ra    = (u1 *)                pr->mpc;
377         um    = (unresolved_method *) pr->ref;
378
379         /* get the fieldinfo */
380
381         if (!(m = resolve_method_eager(um)))
382                 return false;
383
384         PATCH_BACK_ORIGINAL_MCODE;
385
386         /* if we show disassembly, we have to skip the nop */
387
388         if (opt_shownops)
389                 ra = ra + 4;
390
391         /* patch interfacetable index */
392
393         *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
394                                                                  sizeof(methodptr*) * m->class->index) & 0x0000ffff);
395
396         /* patch method offset */
397
398         *((s4 *) (ra + 4 + 4)) |=
399                 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
400
401         md_icacheflush(NULL, 0);
402
403         return true;
404 }
405
406
407 /* patcher_checkcast_interface *************************************************
408
409    Machine code:
410
411    <patched call position>
412    a78e0000    ldq     at,0(s5)
413    a3bc001c    ldl     gp,28(at)
414    23bdfffd    lda     gp,-3(gp)
415    efa0002e    ble     gp,0x00000200002bf6b0
416    a7bcffe8    ldq     gp,-24(at)
417
418 *******************************************************************************/
419
420 bool patcher_checkcast_interface(patchref_t *pr)
421 {
422         u1                *ra;
423         constant_classref *cr;
424         classinfo         *c;
425
426         /* get stuff from the stack */
427
428         ra    = (u1 *)                pr->mpc;
429         cr    = (constant_classref *) pr->ref;
430
431         /* get the fieldinfo */
432
433         if (!(c = resolve_classref_eager(cr)))
434                 return false;
435
436         PATCH_BACK_ORIGINAL_MCODE;
437
438         /* if we show disassembly, we have to skip the nop */
439
440         if (opt_shownops)
441                 ra = ra + 4;
442
443         /* patch super class index */
444
445         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
446
447         *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
448                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
449
450         md_icacheflush(NULL, 0);
451
452         return true;
453 }
454
455
456 /* patcher_instanceof_interface ************************************************
457
458    Machine code:
459
460    <patched call position>
461    a78e0000    ldq     at,0(s5)
462    a3bc001c    ldl     gp,28(at)
463    23bdfffd    lda     gp,-3(gp)
464    efa0002e    ble     gp,0x00000200002bf6b0
465    a7bcffe8    ldq     gp,-24(at)
466
467 *******************************************************************************/
468
469 bool patcher_instanceof_interface(patchref_t *pr)
470 {
471         u1                *ra;
472         constant_classref *cr;
473         classinfo         *c;
474
475         /* get stuff from the stack */
476
477         ra    = (u1 *)                pr->mpc;
478         cr    = (constant_classref *) pr->ref;
479
480         /* get the fieldinfo */
481
482         if (!(c = resolve_classref_eager(cr)))
483                 return false;
484
485         PATCH_BACK_ORIGINAL_MCODE;
486
487         /* if we show disassembly, we have to skip the nop */
488
489         if (opt_shownops)
490                 ra = ra + 4;
491
492         /* patch super class index */
493
494         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
495
496         *((s4 *) (ra + 4 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
497                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
498
499         md_icacheflush(NULL, 0);
500
501         return true;
502 }
503
504
505 /*
506  * These are local overrides for various environment variables in Emacs.
507  * Please do not remove this and leave it at the end of the file, where
508  * Emacs will automagically detect them.
509  * ---------------------------------------------------------------------
510  * Local variables:
511  * mode: c
512  * indent-tabs-mode: t
513  * c-basic-offset: 4
514  * tab-width: 4
515  * End:
516  * vim:noexpandtab:sw=4:ts=4:
517  */