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