660adfd959cd23dc0835ea23d6a136db1bdf8190
[cacao.git] / src / vm / jit / powerpc64 / patcher.c
1 /* src/vm/jit/powerpc64/patcher.c - PowerPC64 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 #include <stdint.h>
30
31 #include "vm/types.h"
32
33 #include "vm/jit/powerpc64/md.h"
34
35 #include "mm/memory.h"
36
37 #include "native/native.h"
38
39 #include "vm/builtin.h"
40 #include "vm/class.h"
41 #include "vm/field.h"
42 #include "vm/initialize.h"
43 #include "vm/options.h"
44 #include "vm/references.h"
45 #include "vm/resolve.h"
46
47 #include "vm/jit/asmpart.h"
48 #include "vm/jit/methodheader.h"
49 #include "vm/jit/patcher-common.h"
50
51
52 /* patcher_patch_code **********************************************************
53
54    Just patches back the original machine code.
55
56 *******************************************************************************/
57
58 void patcher_patch_code(patchref_t *pr)
59 {
60         // Patch back original code.
61         *((uint32_t*) pr->mpc) = pr->mcode;
62
63         // Synchronize instruction cache.
64         md_icacheflush((void*) pr->mpc, 1 * 4);
65 }
66
67
68 /* patcher_get_putstatic *******************************************************
69
70    Machine code:
71
72    <patched call position>
73    816dffc8    lwz   r11,-56(r13)
74    80ab0000    lwz   r5,0(r11)
75
76 *******************************************************************************/
77
78 bool patcher_get_putstatic(patchref_t *pr)
79 {
80         u1               *ra;
81         u4                mcode;
82         unresolved_field *uf;
83         u1               *datap;
84         fieldinfo        *fi;
85
86         /* get stuff from the stack */
87
88         ra    = (u1 *)                pr->mpc;
89         mcode =                       pr->mcode;
90         uf    = (unresolved_field *)  pr->ref;
91         datap = (u1 *)                pr->datap;
92
93         /* get the fieldinfo */
94
95         if (!(fi = resolve_field_eager(uf)))
96                 return false;
97
98         /* check if the field's class is initialized */
99
100         if (!(fi->clazz->state & CLASS_INITIALIZED))
101                 if (!initialize_class(fi->clazz))
102                         return false;
103
104         /* patch the field value's address */
105
106         *((intptr_t *) datap) = (intptr_t) fi->value;
107
108         /* synchronize data cache */
109
110         md_dcacheflush(datap, SIZEOF_VOID_P);
111
112         // Patch back the original code.
113         patcher_patch_code(pr);
114
115         return true;
116 }
117
118
119 /* patcher_get_putfield ********************************************************
120
121    Machine code:
122
123    <patched call position>
124    811f0014    lwz   r8,20(r31)
125
126 *******************************************************************************/
127
128 bool patcher_get_putfield(patchref_t *pr)
129 {
130         u1               *ra;
131         u4                mcode;
132         unresolved_field *uf;
133         fieldinfo        *fi;
134
135         ra    = (u1 *)                pr->mpc;
136         mcode =                       pr->mcode;
137         uf    = (unresolved_field *)  pr->ref;
138
139         /* get the fieldinfo */
140
141         if (!(fi = resolve_field_eager(uf)))
142                 return false;
143
144         // Patch the field offset in the patcher.  We also need this to
145         // validate patchers.
146         pr->mcode |= (int16_t) (fi->offset & 0x0000ffff);
147
148         // Patch back the original code.
149         patcher_patch_code(pr);
150
151         return true;
152 }
153
154
155 /* patcher_invokestatic_special ************************************************
156
157    Machine code:
158
159    <patched call position>
160    81adffd8    lwz   r13,-40(r13)
161    7da903a6    mtctr r13
162    4e800421    bctrl
163
164 ******************************************************************************/
165
166 bool patcher_invokestatic_special(patchref_t *pr)
167 {
168         u1                *ra;
169         u4                 mcode;
170         unresolved_method *um;
171         u1                *datap;
172         methodinfo        *m;
173
174         /* get stuff from the stack */
175
176         ra    = (u1 *)                pr->mpc;
177         mcode =                       pr->mcode;
178         um    = (unresolved_method *) pr->ref;
179         datap = (u1 *)                pr->datap;
180
181         /* get the fieldinfo */
182
183         if (!(m = resolve_method_eager(um)))
184                 return false;
185
186         // Patch stubroutine.
187         *((ptrint *) datap) = (ptrint) m->stubroutine;
188
189         // Synchronize data cache.
190         md_dcacheflush(datap, SIZEOF_VOID_P);
191
192         // Patch back the original code.
193         patcher_patch_code(pr);
194
195         return true;
196 }
197
198
199 /* patcher_invokevirtual *******************************************************
200
201    Machine code:
202
203    <patched call position>
204    81830000    lwz   r12,0(r3)
205    81ac0088    lwz   r13,136(r12)
206    7da903a6    mtctr r13
207    4e800421    bctrl
208
209 *******************************************************************************/
210
211 bool patcher_invokevirtual(patchref_t *pr)
212 {
213         u1                *ra;
214         u4                 mcode;
215         unresolved_method *um;
216         methodinfo        *m;
217         s4                 disp;
218
219         /* get stuff from the stack */
220
221         ra    = (u1 *)                pr->mpc;
222         mcode =                       pr->mcode;
223         um    = (unresolved_method *) pr->ref;
224
225         /* get the fieldinfo */
226
227         if (!(m = resolve_method_eager(um)))
228                 return false;
229
230         // Patch vftbl index.
231         disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
232
233         *((uint32_t*) (ra + 1 * 4)) |= (disp & 0x0000ffff);
234
235         // Synchronize instruction cache.
236         md_icacheflush(ra, 2 * 4);
237
238         // Patch back the original code.
239         patcher_patch_code(pr);
240
241         return true;
242 }
243
244
245 /* patcher_invokeinterface *****************************************************
246
247    Machine code:
248
249    <patched call position>
250    81830000    lwz   r12,0(r3)
251    818cffd0    lwz   r12,-48(r12)
252    81ac000c    lwz   r13,12(r12)
253    7da903a6    mtctr r13
254    4e800421    bctrl
255
256 *******************************************************************************/
257
258 bool patcher_invokeinterface(patchref_t *pr)
259 {
260         u1                *ra;
261         u4                 mcode;
262         unresolved_method *um;
263         methodinfo        *m;
264         s4                 disp;
265
266         /* get stuff from the stack */
267
268         ra    = (u1 *)                pr->mpc;
269         mcode =                       pr->mcode;
270         um    = (unresolved_method *) pr->ref;
271
272         /* get the fieldinfo */
273
274         if (!(m = resolve_method_eager(um)))
275                 return false;
276
277         // Patch interfacetable index.
278         disp = OFFSET(vftbl_t, interfacetable[0]) -
279                 sizeof(methodptr*) * m->clazz->index;
280
281         // XXX TWISTI: check displacement
282         *((uint32_t*) (ra + 1 * 4)) |= (disp & 0x0000ffff);
283
284         // Patch method offset.
285         disp = sizeof(methodptr) * (m - m->clazz->methods);
286
287         // XXX TWISTI: check displacement
288         *((uint32_t*) (ra + 2 * 4)) |= (disp & 0x0000ffff);
289
290         // Synchronize instruction cache.
291         md_icacheflush(ra, 3 * 4);
292
293         // Patch back the original code.
294         patcher_patch_code(pr);
295
296         return true;
297 }
298
299
300 /* patcher_checkcast_interface **************************************
301
302    Machine code:
303
304    <patched call position>
305    81870000    lwz   r12,0(r7)
306    800c0010    lwz   r0,16(r12)
307    34000000    addic.        r0,r0,0
308    408101fc    bgt-  0x3002e518         FIXME
309    83c00003    lwz   r30,3(0)           FIXME
310    800c0000    lwz   r0,0(r12)
311
312 *******************************************************************************/
313
314 bool patcher_checkcast_interface(patchref_t *pr)
315 {
316         u1                *ra;
317         constant_classref *cr;
318         classinfo         *c;
319         s4                 disp;
320         u4                 mcode;
321
322         /* get stuff from stack */
323         ra    = (u1 *)                pr->mpc;
324         mcode =                       pr->mcode;
325         cr    = (constant_classref *) pr->ref;
326
327         /* get the fieldinfo */
328         if (!(c = resolve_classref_eager(cr)))  {
329                 return false;
330         }
331
332         // Patch super class index.
333         disp = -(c->index);
334         *((uint32_t*) (ra + 2 * 4)) |= (disp & 0x0000ffff);
335
336         disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
337         *((uint32_t*) (ra + 5 * 4)) |= (disp & 0x0000ffff);
338
339         // Synchronize instruction cache.
340         md_icacheflush(ra, 6 * 4);
341
342         // Patch back the original code.
343         patcher_patch_code(pr);
344
345         return true;
346 }
347
348
349 /* patcher_instanceof_interface **************************************
350
351    Machine code:
352
353    <patched call position>
354    81870000    lwz   r12,0(r7)
355    800c0010    lwz   r0,16(r12)
356    34000000    addic.        r0,r0,0
357    408101fc    ble-  0x3002e518
358    800c0000    lwz   r0,0(r12)
359
360 *******************************************************************************/
361
362 bool patcher_instanceof_interface(patchref_t *pr)
363 {
364         u1                *ra;
365         u4                 mcode;
366         constant_classref *cr;
367         classinfo         *c;
368         s4                 disp;
369
370         /* get stuff from the stack */
371
372         ra    = (u1 *)                pr->mpc;
373         mcode =                       pr->mcode;
374         cr    = (constant_classref *) pr->ref;
375
376         /* get the fieldinfo */
377
378         if (!(c = resolve_classref_eager(cr)))
379                 return false;
380
381         // Patch super class index.
382         disp = -(c->index);
383         *((uint32_t*) (ra + 2 * 4)) |= (disp & 0x0000ffff);
384
385         disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
386         *((uint32_t*) (ra + 4 * 4)) |= (disp & 0x0000ffff);
387
388         // Synchronize instruction cache.
389         md_icacheflush(ra, 5 * 4);
390
391         // Patch back the original code.
392         patcher_patch_code(pr);
393
394         return true;
395 }
396
397
398 /* patcher_resolve_classref_to_classinfo ***************************************
399
400    ACONST:
401
402    <patched call postition>
403    806dffc4    lwz   r3,-60(r13)
404    81adffc0    lwz   r13,-64(r13)
405    7da903a6    mtctr r13
406    4e800421    bctrl
407
408
409    MULTIANEWARRAY:
410
411    <patched call position>
412    808dffc0    lwz   r4,-64(r13)
413    38a10038    addi  r5,r1,56
414    81adffbc    lwz   r13,-68(r13)
415    7da903a6    mtctr r13
416    4e800421    bctrl
417
418
419    ARRAYCHECKCAST:
420
421    <patched call position>
422    808dffd8    lwz   r4,-40(r13)
423    81adffd4    lwz   r13,-44(r13)
424    7da903a6    mtctr r13
425    4e800421    bctrl
426
427 *******************************************************************************/
428
429 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
430 {
431         constant_classref *cr;
432         u1                *datap, *ra;
433         u4                 mcode;
434         classinfo         *c;
435
436         /* get stuff from the stack */
437
438         ra    = (u1 *)                pr->mpc;
439         mcode =                       pr->mcode;
440         cr    = (constant_classref *) pr->ref;
441         datap = (u1 *)                pr->datap;
442
443         /* get the classinfo */
444
445         if (!(c = resolve_classref_eager(cr)))
446                 return false;
447
448         // Patch the classinfo pointer.
449         *((uintptr_t*) datap) = (uintptr_t) c;
450
451         // Synchronize data cache.
452         md_dcacheflush(datap, SIZEOF_VOID_P);
453
454         // Patch back the original code.
455         patcher_patch_code(pr);
456
457         return true;
458 }
459
460
461 /* patcher_resolve_classref_to_vftbl *******************************************
462
463    CHECKCAST (class):
464
465    <patched call position>
466    81870000    lwz   r12,0(r7)
467    800c0014    lwz   r0,20(r12)
468    818dff78    lwz   r12,-136(r13)
469
470
471    INSTANCEOF (class):
472
473    <patched call position>
474    817d0000    lwz   r11,0(r29)
475    818dff8c    lwz   r12,-116(r13)
476
477 *******************************************************************************/
478
479 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
480 {
481         constant_classref *cr;
482         u1                *datap, *ra;
483         u4                 mcode;
484         classinfo         *c;
485
486         /* get stuff from the stack */
487
488         ra    = (u1 *)                pr->mpc;
489         mcode =                       pr->mcode;
490         cr    = (constant_classref *) pr->ref;
491         datap = (u1 *)                pr->datap;
492
493         /* get the fieldinfo */
494
495         if (!(c = resolve_classref_eager(cr)))
496                 return false;
497
498         // Patch super class' vftbl.
499         *((uintptr_t*) datap) = (uintptr_t) c->vftbl;
500
501         // Synchronize data cache.
502         md_dcacheflush(datap, SIZEOF_VOID_P);
503
504         // Patch back the original code.
505         patcher_patch_code(pr);
506
507         return true;
508 }
509
510 /* patcher_resolve_classref_to_flags *******************************************
511
512    CHECKCAST/INSTANCEOF:
513
514    <patched call position>
515    818dff7c    lwz   r12,-132(r13)
516
517 *******************************************************************************/
518
519 bool patcher_resolve_classref_to_flags(patchref_t *pr)
520 {
521         constant_classref *cr;
522         u1                *datap, *ra;
523         u4                 mcode;
524         classinfo         *c;
525
526         /* get stuff from the stack */
527
528         ra    = (u1 *)                pr->mpc;
529         mcode =                       pr->mcode;
530         cr    = (constant_classref *) pr->ref;
531         datap = (u1 *)                pr->datap;
532
533         /* get the fieldinfo */
534
535         if (!(c = resolve_classref_eager(cr)))
536                 return false;
537
538         // Patch class flags.
539         *((int32_t*) datap) = (int32_t) c->flags;
540
541         // Synchronize data cache.
542         md_dcacheflush(datap, SIZEOF_VOID_P);
543
544         // Patch back the original code.
545         patcher_patch_code(pr);
546
547         return true;
548 }
549
550
551 /*
552  * These are local overrides for various environment variables in Emacs.
553  * Please do not remove this and leave it at the end of the file, where
554  * Emacs will automagically detect them.
555  * ---------------------------------------------------------------------
556  * Local variables:
557  * mode: c
558  * indent-tabs-mode: t
559  * c-basic-offset: 4
560  * tab-width: 4
561  * End:
562  * vim:noexpandtab:sw=4:ts=4:
563  */