* src/native/vm/openjdk/jvm.cpp (JVM_CurrentClassLoader): Implemented.
[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    Copyright (C) 2008 Theobroma Systems Ltd.
6
7    This file is part of CACAO.
8
9    This program is free software; you can redistribute it and/or
10    modify it under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2, or (at
12    your option) any later version.
13
14    This program is distributed in the hope that it will be useful, but
15    WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22    02110-1301, USA.
23
24 */
25
26
27 #include "config.h"
28
29 #include <assert.h>
30 #include <stdint.h>
31
32 #include "vm/types.h"
33
34 #include "vm/jit/powerpc64/md.h"
35
36 #include "mm/memory.hpp"
37
38 #include "native/native.hpp"
39
40 #include "vm/jit/builtin.hpp"
41 #include "vm/class.hpp"
42 #include "vm/field.hpp"
43 #include "vm/initialize.hpp"
44 #include "vm/options.h"
45 #include "vm/references.h"
46 #include "vm/resolve.hpp"
47
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/methodheader.h"
50 #include "vm/jit/patcher-common.hpp"
51
52
53 /* patcher_patch_code **********************************************************
54
55    Just patches back the original machine code.
56
57 *******************************************************************************/
58
59 void patcher_patch_code(patchref_t *pr)
60 {
61         // Patch back original code.
62         *((uint32_t*) pr->mpc) = pr->mcode;
63
64         // Synchronize instruction cache.
65         md_icacheflush((void*) pr->mpc, 1 * 4);
66 }
67
68
69 /**
70  * Check if the trap instruction at the given PC is valid.
71  *
72  * @param pc Program counter.
73  *
74  * @return true if valid, false otherwise.
75  */
76 bool patcher_is_valid_trap_instruction_at(void* pc)
77 {
78         uint32_t mcode = *((uint32_t*) pc);
79
80         // Check for the undefined instruction we use.
81         return (mcode == 0x00000000);
82 }
83
84
85 /* patcher_get_putstatic *******************************************************
86
87    Machine code:
88
89    <patched call position>
90    816dffc8    lwz   r11,-56(r13)
91    80ab0000    lwz   r5,0(r11)
92
93 *******************************************************************************/
94
95 bool patcher_get_putstatic(patchref_t* pr)
96 {
97         unresolved_field* uf    = (unresolved_field*) pr->ref;
98         uintptr_t*        datap = (uintptr_t*)        pr->datap;
99
100         // Resolve the field.
101         fieldinfo* fi = resolve_field_eager(uf);
102
103         if (fi == NULL)
104                 return false;
105
106         // Check if the field's class is initialized.
107         if (!(fi->clazz->state & CLASS_INITIALIZED))
108                 if (!initialize_class(fi->clazz))
109                         return false;
110
111         // Patch the field value's address.
112         *datap = (uintptr_t) fi->value;
113
114         // Synchronize data cache.
115         md_dcacheflush(datap, SIZEOF_VOID_P);
116
117         // Patch back the original code.
118         patcher_patch_code(pr);
119
120         return true;
121 }
122
123
124 /* patcher_get_putfield ********************************************************
125
126    Machine code:
127
128    <patched call position>
129    811f0014    lwz   r8,20(r31)
130
131 *******************************************************************************/
132
133 bool patcher_get_putfield(patchref_t* pr)
134 {
135         unresolved_field* uf = (unresolved_field*) pr->ref;
136
137         // Resolve the field.
138         fieldinfo* fi = resolve_field_eager(uf);
139
140         if (fi == NULL)
141                 return false;
142
143         // Patch the field offset in the patcher.  We also need this to
144         // validate patchers.
145         pr->mcode |= (int16_t) (fi->offset & 0x0000ffff);
146
147         // Patch back the original code.
148         patcher_patch_code(pr);
149
150         return true;
151 }
152
153
154 /* patcher_invokestatic_special ************************************************
155
156    Machine code:
157
158    <patched call position>
159    81adffd8    lwz   r13,-40(r13)
160    7da903a6    mtctr r13
161    4e800421    bctrl
162
163 ******************************************************************************/
164
165 bool patcher_invokestatic_special(patchref_t* pr)
166 {
167         unresolved_method* um    = (unresolved_method*) pr->ref;
168         uintptr_t*         datap = (uintptr_t*)         pr->datap;
169
170         // Resolve the method.
171         methodinfo* m = resolve_method_eager(um);
172
173         if (m == NULL)
174                 return false;
175
176         // Patch stubroutine.
177         *datap = (uintptr_t) m->stubroutine;
178
179         // Synchronize data cache.
180         md_dcacheflush(datap, SIZEOF_VOID_P);
181
182         // Patch back the original code.
183         patcher_patch_code(pr);
184
185         return true;
186 }
187
188
189 /* patcher_invokevirtual *******************************************************
190
191    Machine code:
192
193    <patched call position>
194    81830000    lwz   r12,0(r3)
195    81ac0088    lwz   r13,136(r12)
196    7da903a6    mtctr r13
197    4e800421    bctrl
198
199 *******************************************************************************/
200
201 bool patcher_invokevirtual(patchref_t* pr)
202 {
203         uint32_t*          pc = (uint32_t*)          pr->mpc;
204         unresolved_method* um = (unresolved_method*) pr->ref;
205
206         // Resolve the method.
207         methodinfo* m = resolve_method_eager(um);
208
209         if (m == NULL)
210                 return false;
211
212         // Patch vftbl index.
213         int32_t disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
214
215         pc[1] |= (disp & 0x0000ffff);
216
217         // Synchronize instruction cache.
218         md_icacheflush(pc + 1, 1 * 4);
219
220         // Patch back the original code.
221         patcher_patch_code(pr);
222
223         return true;
224 }
225
226
227 /* patcher_invokeinterface *****************************************************
228
229    Machine code:
230
231    <patched call position>
232    81830000    lwz   r12,0(r3)
233    818cffd0    lwz   r12,-48(r12)
234    81ac000c    lwz   r13,12(r12)
235    7da903a6    mtctr r13
236    4e800421    bctrl
237
238 *******************************************************************************/
239
240 bool patcher_invokeinterface(patchref_t* pr)
241 {
242         uint32_t*          pc = (uint32_t*)          pr->mpc;
243         unresolved_method* um = (unresolved_method*) pr->ref;
244
245         // Resolve the method.
246         methodinfo* m = resolve_method_eager(um);
247
248         if (m == NULL)
249                 return false;
250
251         // Patch interfacetable index.
252         int32_t disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index;
253
254         // XXX TWISTI: check displacement
255         pc[1] |= (disp & 0x0000ffff);
256
257         // Patch method offset.
258         disp = sizeof(methodptr) * (m - m->clazz->methods);
259
260         // XXX TWISTI: check displacement
261         pc[2] |= (disp & 0x0000ffff);
262
263         // Synchronize instruction cache.
264         md_icacheflush(pc + 1, 2 * 4);
265
266         // Patch back the original code.
267         patcher_patch_code(pr);
268
269         return true;
270 }
271
272
273 /* patcher_checkcast_interface **************************************
274
275    Machine code:
276
277    <patched call position>
278    81870000    lwz   r12,0(r7)
279    800c0010    lwz   r0,16(r12)
280    34000000    addic.        r0,r0,0
281    408101fc    bgt-  0x3002e518         FIXME
282    83c00003    lwz   r30,3(0)           FIXME
283    800c0000    lwz   r0,0(r12)
284
285 *******************************************************************************/
286
287 bool patcher_checkcast_interface(patchref_t* pr)
288 {
289         uint32_t*          pc = (uint32_t*)          pr->mpc;
290         constant_classref* cr = (constant_classref*) pr->ref;
291
292         // Resolve the class.
293         classinfo* c = resolve_classref_eager(cr);
294
295         if (c == NULL)
296                 return false;
297
298         // Patch super class index.
299         int32_t disp = -(c->index);
300         pc[2] |= (disp & 0x0000ffff);
301
302         disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
303         pc[5] |= (disp & 0x0000ffff);
304
305         // Synchronize instruction cache.
306         md_icacheflush(pc + 2, 4 * 4);
307
308         // Patch back the original code.
309         patcher_patch_code(pr);
310
311         return true;
312 }
313
314
315 /* patcher_instanceof_interface **************************************
316
317    Machine code:
318
319    <patched call position>
320    81870000    lwz   r12,0(r7)
321    800c0010    lwz   r0,16(r12)
322    34000000    addic.        r0,r0,0
323    408101fc    ble-  0x3002e518
324    800c0000    lwz   r0,0(r12)
325
326 *******************************************************************************/
327
328 bool patcher_instanceof_interface(patchref_t* pr)
329 {
330         uint32_t*          pc = (uint32_t*)          pr->mpc;
331         constant_classref* cr = (constant_classref*) pr->ref;
332
333         // Resolve the class.
334         classinfo* c = resolve_classref_eager(cr);
335
336         if (c == NULL)
337                 return false;
338
339         // Patch super class index.
340         int32_t disp = -(c->index);
341         pc[2] |= (disp & 0x0000ffff);
342
343         disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
344         pc[4] |= (disp & 0x0000ffff);
345
346         // Synchronize instruction cache.
347         md_icacheflush(pc + 2, 3 * 4);
348
349         // Patch back the original code.
350         patcher_patch_code(pr);
351
352         return true;
353 }
354
355
356 /* patcher_resolve_classref_to_classinfo ***************************************
357
358    ACONST:
359
360    <patched call postition>
361    806dffc4    lwz   r3,-60(r13)
362    81adffc0    lwz   r13,-64(r13)
363    7da903a6    mtctr r13
364    4e800421    bctrl
365
366
367    MULTIANEWARRAY:
368
369    <patched call position>
370    808dffc0    lwz   r4,-64(r13)
371    38a10038    addi  r5,r1,56
372    81adffbc    lwz   r13,-68(r13)
373    7da903a6    mtctr r13
374    4e800421    bctrl
375
376
377    ARRAYCHECKCAST:
378
379    <patched call position>
380    808dffd8    lwz   r4,-40(r13)
381    81adffd4    lwz   r13,-44(r13)
382    7da903a6    mtctr r13
383    4e800421    bctrl
384
385 *******************************************************************************/
386
387 bool patcher_resolve_classref_to_classinfo(patchref_t* pr)
388 {
389         constant_classref* cr    = (constant_classref*) pr->ref;
390         uintptr_t*         datap = (uintptr_t*)         pr->datap;
391
392         // Resolve the class.
393         classinfo* c = resolve_classref_eager(cr);
394
395         if (c == NULL)
396                 return false;
397
398         // Patch the classinfo pointer.
399         *datap = (uintptr_t) c;
400
401         // Synchronize data cache.
402         md_dcacheflush(datap, SIZEOF_VOID_P);
403
404         // Patch back the original code.
405         patcher_patch_code(pr);
406
407         return true;
408 }
409
410
411 /* patcher_resolve_classref_to_vftbl *******************************************
412
413    CHECKCAST (class):
414
415    <patched call position>
416    81870000    lwz   r12,0(r7)
417    800c0014    lwz   r0,20(r12)
418    818dff78    lwz   r12,-136(r13)
419
420
421    INSTANCEOF (class):
422
423    <patched call position>
424    817d0000    lwz   r11,0(r29)
425    818dff8c    lwz   r12,-116(r13)
426
427 *******************************************************************************/
428
429 bool patcher_resolve_classref_to_vftbl(patchref_t* pr)
430 {
431         constant_classref* cr    = (constant_classref*) pr->ref;
432         uintptr_t*         datap = (uintptr_t*)         pr->datap;
433
434         // Resolve the class.
435         classinfo* c = resolve_classref_eager(cr);
436
437         if (c == NULL)
438                 return false;
439
440         // Patch super class' vftbl.
441         *datap = (uintptr_t) c->vftbl;
442
443         // Synchronize data cache.
444         md_dcacheflush(datap, SIZEOF_VOID_P);
445
446         // Patch back the original code.
447         patcher_patch_code(pr);
448
449         return true;
450 }
451
452 /* patcher_resolve_classref_to_flags *******************************************
453
454    CHECKCAST/INSTANCEOF:
455
456    <patched call position>
457    818dff7c    lwz   r12,-132(r13)
458
459 *******************************************************************************/
460
461 bool patcher_resolve_classref_to_flags(patchref_t* pr)
462 {
463         constant_classref* cr    = (constant_classref*) pr->ref;
464         int32_t*           datap = (int32_t*)           pr->datap;
465
466         // Resolve the class.
467         classinfo* c = resolve_classref_eager(cr);
468
469         if (c == NULL)
470                 return false;
471
472         // Patch class flags.
473         *datap = (int32_t) c->flags;
474
475         // Synchronize data cache.
476         md_dcacheflush(datap, SIZEOF_VOID_P);
477
478         // Patch back the original code.
479         patcher_patch_code(pr);
480
481         return true;
482 }
483
484
485 /*
486  * These are local overrides for various environment variables in Emacs.
487  * Please do not remove this and leave it at the end of the file, where
488  * Emacs will automagically detect them.
489  * ---------------------------------------------------------------------
490  * Local variables:
491  * mode: c
492  * indent-tabs-mode: t
493  * c-basic-offset: 4
494  * tab-width: 4
495  * End:
496  * vim:noexpandtab:sw=4:ts=4:
497  */