* src/vm/jit/arm/codegen.h (M_EORLE): Added.
[cacao.git] / src / vm / jit / arm / patcher.c
1 /* src/vm/jit/arm/patcher.c - ARM 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    $Id: patcher.c 7929 2007-05-21 11:45:31Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "mm/memory.h"
37
38 #include "native/native.h"
39
40 #include "vm/builtin.h"
41 #include "vm/exceptions.h"
42 #include "vm/initialize.h"
43
44 #include "vm/jit/asmpart.h"
45 #include "vm/jit/md.h"
46 #include "vm/jit/patcher.h"
47
48 #include "vmcore/field.h"
49 #include "vmcore/options.h"
50 #include "vmcore/references.h"
51 #include "vm/resolve.h"
52
53
54 #define gen_resolveload(inst,offset) \
55         assert((offset) >= -0x0fff && (offset) <= 0x0fff); \
56         assert(!((inst) & 0x0fff)); \
57         if ((offset) <  0) { \
58                 (inst) = ((inst) & 0xff7ff000) | ((-(offset)) & 0x0fff); \
59                 /*(inst) &= ~(1 << 23);*/ \
60         } else { \
61                 (inst) = ((inst) & 0xfffff000) | ((offset) & 0x0fff); \
62                 /*(inst) |= (1 << 23);*/ \
63         }
64
65
66 /* patcher_wrapper *************************************************************
67
68    Wrapper for all patchers.  It also creates the stackframe info
69    structure.
70
71    If the return value of the patcher function is false, it gets the
72    exception object, clears the exception pointer and returns the
73    exception.
74
75 *******************************************************************************/
76
77 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
78 {
79         stackframeinfo     sfi;
80         u1                *xpc;
81         java_objectheader *o;
82         u4                 mcode;
83         functionptr        f;
84         bool               result;
85         java_objectheader *e;
86
87         /* define the patcher function */
88
89         bool (*patcher_function)(u1 *);
90
91         assert(pv != NULL);
92
93         /* get stuff from the stack */
94
95         xpc = (u1 *)                *((ptrint *) (sp + 4 * 4));
96         o   = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
97         f   = (functionptr)         *((ptrint *) (sp + 0 * 4));
98
99         /* calculate and set the new return address */
100
101         xpc = xpc - 1 * 4;
102
103         *((ptrint *) (sp + 4 * 4)) = (ptrint) xpc;
104
105         /* store PV into the patcher function position */
106
107         *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
108
109         /* cast the passed function to a patcher function */
110
111         patcher_function = (bool (*)(u1 *)) (ptrint) f;
112
113         /* enter a monitor on the patching position */
114
115         PATCHER_MONITORENTER;
116
117         /* create the stackframeinfo */
118
119         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 8 * 4, ra, xpc);
120
121         /* call the proper patcher function */
122
123         result = (patcher_function)(sp);
124
125         /* remove the stackframeinfo */
126
127         stacktrace_remove_stackframeinfo(&sfi);
128
129         /* check for an error, get the exception and return it */
130
131         if (result == false) {
132                 e = exceptions_get_and_clear_exception();
133
134                 PATCHER_MONITOREXIT;
135
136                 return e;
137         }
138
139         /* patch back original code */
140
141         mcode = *((u4 *) (sp + 2 * 4));
142
143         *((u4 *) xpc) = mcode;
144
145         /* synchronize instruction cache */
146
147         md_icacheflush(xpc, 1 * 4);
148
149         PATCHER_MARK_PATCHED_MONITOREXIT;
150
151         return NULL;
152 }
153
154
155 /* patcher_get_putstatic *******************************************************
156
157    Machine code:
158
159    <patched call position>
160    e51c103c    ldr   r1, [ip, #-60]
161
162 *******************************************************************************/
163
164 bool patcher_get_putstatic(u1 *sp)
165 {
166         s4                disp;
167         unresolved_field *uf;
168         u1               *pv;
169         fieldinfo        *fi;
170
171         /* get stuff from the stack */
172
173         disp =                      *((s4 *)     (sp + 5 * 4));
174         uf   = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
175         pv   = (u1 *)               *((ptrint *) (sp + 0 * 4));
176
177         /* get the fieldinfo */
178
179         if (!(fi = resolve_field_eager(uf)))
180                 return false;
181
182         /* check if the field's class is initialized */
183
184         if (!(fi->class->state & CLASS_INITIALIZED))
185                 if (!initialize_class(fi->class))
186                         return false;
187
188         /* patch the field value's address */
189
190         *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
191
192         return true;
193 }
194
195
196 /* patcher_get_putfield ********************************************************
197
198    Machine code:
199
200    <patched call position>
201    e58a8000    str   r8, [sl, #__]
202
203 *******************************************************************************/
204
205 bool patcher_get_putfield(u1 *sp)
206 {
207         u1                *ra;
208         u4                 mcode;
209         unresolved_field  *uf;
210         u1                *pv;
211         fieldinfo         *fi;
212
213         /* get stuff from the stack */
214         ra    = (u1*)                 *((ptrint *) (sp + 4 * 4));
215         mcode =                       *((u4 *)     (sp + 2 * 4));
216         uf    = (unresolved_field*)   *((ptrint *) (sp + 1 * 4));
217         pv    = (u1*)                 *((ptrint *) (sp + 0 * 4));
218
219         /* get the fieldinfo */
220
221         if (!(fi = resolve_field_eager(uf)))
222                 return false;
223
224         /* if we show disassembly, we have to skip the nop */
225
226         if (opt_showdisassemble) {
227                 ra = ra + 1 * 4;
228
229                 /* patch the field's offset into the instruction */
230
231                 switch(fi->type) {
232                 case TYPE_ADR:
233                 case TYPE_INT:
234 #if defined(ENABLE_SOFTFLOAT)
235                 case TYPE_FLT:
236 #endif
237                         assert(fi->offset <= 0x0fff);
238                         *((u4 *) (ra + 0 * 4)) |= (fi->offset & 0x0fff);
239                         break;
240
241                 case TYPE_LNG:
242 #if defined(ENABLE_SOFTFLOAT)
243                 case TYPE_DBL:
244 #endif
245                         assert((fi->offset + 4) <= 0x0fff);
246                         *((u4 *) (ra + 0 * 4)) |= ((fi->offset + 0) & 0x0fff);
247                         *((u4 *) (ra + 1 * 4)) |= ((fi->offset + 4) & 0x0fff);
248                         break;
249
250 #if !defined(ENABLE_SOFTFLOAT)
251                 case TYPE_FLT:
252                 case TYPE_DBL:
253                         assert(fi->offset <= 0x03ff);
254                         *((u4 *) (ra + 0 * 4)) |= ((fi->offset >> 2) & 0x00ff);
255                         break;
256 #endif
257                 }
258         }
259         else {
260                 /* patch the field's offset into the instruction stored on the
261                    stack and the next instruction in the code */
262
263                 switch(fi->type) {
264                 case TYPE_ADR:
265                 case TYPE_INT:
266 #if defined(ENABLE_SOFTFLOAT)
267                 case TYPE_FLT:
268 #endif
269                         assert(fi->offset <= 0x0fff);
270                         *((u4 *) (sp + 2 * 4)) |= (fi->offset & 0x0fff);
271                         break;
272
273                 case TYPE_LNG:
274 #if defined(ENABLE_SOFTFLOAT)
275                 case TYPE_DBL:
276 #endif
277                         assert((fi->offset + 4) <= 0x0fff);
278                         *((u4 *) (sp + 2 * 4)) |= ((fi->offset + 0) & 0x0fff);
279                         *((u4 *) (ra + 1 * 4)) |= ((fi->offset + 4) & 0x0fff);
280                         break;
281
282 #if !defined(ENABLE_SOFTFLOAT)
283                 case TYPE_FLT:
284                 case TYPE_DBL:
285                         assert(fi->offset <= 0x03ff);
286                         *((u4 *) (sp + 2 * 4)) |= ((fi->offset >> 2) & 0x00ff);
287                         break;
288 #endif
289                 }
290         }
291
292         /* synchronize instruction cache */
293
294         md_icacheflush(ra, 2 * 4);
295
296         return true;
297 }
298
299
300 /* patcher_aconst **************************************************************
301
302    Machine code:
303
304    <patched call postition>
305    e51cc030    ldr   r0, [ip, #-48]
306
307 *******************************************************************************/
308
309 bool patcher_aconst(u1 *sp)
310 {
311         s4                 disp;
312         constant_classref *cr;
313         u1                *pv;
314         classinfo         *c;
315
316         /* get stuff from the stack */
317
318         disp =                       *((s4 *)     (sp + 5 * 4));
319         cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
320         pv   = (u1 *)                *((ptrint *) (sp + 0 * 4));
321
322         /* get the classinfo */
323
324         if (!(c = resolve_classref_eager(cr)))
325                 return false;
326
327         /* patch the classinfo pointer */
328
329         *((ptrint *) (pv + disp)) = (ptrint) c;
330
331         return true;
332 }
333
334
335 /* patcher_builtin_multianewarray **********************************************
336
337    Machine code:
338
339    <patched call position>
340    e3a00002    mov   r0, #2  ; 0x2
341    e51c1064    ldr   r1, [ip, #-100]
342    e1a0200d    mov   r2, sp
343    e1a0e00f    mov   lr, pc
344    e51cf068    ldr   pc, [ip, #-104]
345
346 *******************************************************************************/
347
348 bool patcher_builtin_multianewarray(u1 *sp)
349 {
350         s4                 disp;
351         constant_classref *cr;
352         u1                *pv;
353         classinfo         *c;
354
355         /* get stuff from the stack */
356
357         disp =                       *((s4 *)     (sp + 5 * 4));
358         cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
359         pv   = (u1 *)                *((ptrint *) (sp + 0 * 4));
360
361         /* get the classinfo */
362
363         if (!(c = resolve_classref_eager(cr)))
364                 return false;
365
366         /* patch the classinfo pointer */
367
368         *((ptrint *) (pv + disp)) = (ptrint) c;
369
370         return true;
371 }
372
373
374 /* patcher_builtin_arraycheckcast **********************************************
375
376    Machine code:
377
378    <patched call position>
379    e51c1120    ldr   r1, [ip, #-288]
380    e1a0e00f    mov   lr, pc
381    e51cf124    ldr   pc, [ip, #-292]
382
383 *******************************************************************************/
384
385 bool patcher_builtin_arraycheckcast(u1 *sp)
386 {
387         s4                 disp;
388         constant_classref *cr;
389         u1                *pv;
390         classinfo         *c;
391
392         /* get stuff from the stack */
393
394         disp =                       *((s4 *)     (sp + 5 * 4));
395         cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
396         pv   = (u1 *)                *((ptrint *) (sp + 0 * 4));
397
398         /* get the classinfo */
399
400         if (!(c = resolve_classref_eager(cr)))
401                 return false;
402
403         /* patch the classinfo pointer */
404
405         *((ptrint *) (pv + disp)) = (ptrint) c;
406
407         return true;
408 }
409
410
411 /* patcher_invokestatic_special ************************************************
412
413    Machine code:
414
415    <patched call position>
416    e51cc02c    ldr   ip, [ip, #-44]
417    e1a0e00f    mov   lr, pc
418    e1a0f00c    mov   pc, ip
419
420 ******************************************************************************/
421
422 bool patcher_invokestatic_special(u1 *sp)
423 {
424         s4                 disp;
425         unresolved_method *um;
426         u1                *pv;
427         methodinfo        *m;
428
429         /* get stuff from the stack */
430
431         disp  =                       *((s4 *)     (sp + 5 * 4));
432         um    = (unresolved_method*)  *((ptrint *) (sp + 1 * 4));
433         pv    = (u1*)                 *((ptrint *) (sp + 0 * 4));
434
435         /* get the methodinfo */
436
437         if (!(m = resolve_method_eager(um)))
438                 return false;
439
440         /* patch stubroutine */
441
442         *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
443
444         return true;
445 }
446
447
448 /* patcher_invokevirtual *******************************************************
449
450    Machine code:
451
452    <patched call position>
453    e590b000    ldr   fp, [r0]
454    e59bc000    ldr   ip, [fp, #__]
455    e1a0e00f    mov   lr, pc
456    e1a0f00c    mov   pc, ip
457
458 *******************************************************************************/
459
460 bool patcher_invokevirtual(u1 *sp)
461 {
462         u1                *ra;
463         unresolved_method *um;
464         methodinfo        *m;
465
466         /* get stuff from the stack */
467
468         ra = (u1 *)                *((ptrint *) (sp + 4 * 4));
469         um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
470
471         /* get the methodinfo */
472
473         if (!(m = resolve_method_eager(um)))
474                 return false;
475
476         /* if we show disassembly, we have to skip the nop */
477
478         if (opt_showdisassemble)
479                 ra = ra + 1 * 4;
480
481         /* patch vftbl index */
482
483         gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
484
485         /* synchronize instruction cache */
486
487         md_icacheflush(ra + 1 * 4, 1 * 4);
488
489         return true;
490 }
491
492
493 /* patcher_invokeinterface *****************************************************
494
495    Machine code:
496
497    <patched call position>
498    e590b000    ldr   fp, [r0]
499    e59bb000    ldr   fp, [fp, #__]
500    e59bc000    ldr   ip, [fp, #__]
501    e1a0e00f    mov   lr, pc
502    e1a0f00c    mov   pc, ip
503
504
505 *******************************************************************************/
506
507 bool patcher_invokeinterface(u1 *sp)
508 {
509         u1                *ra;
510         unresolved_method *um;
511         methodinfo        *m;
512
513         /* get stuff from the stack */
514
515         ra = (u1 *)                *((ptrint *) (sp + 4 * 4));
516         um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
517
518         /* get the methodinfo */
519
520         if (!(m = resolve_method_eager(um)))
521                 return false;
522
523         /* if we show disassembly, we have to skip the nop */
524
525         if (opt_showdisassemble)
526                 ra = ra + 1 * 4;
527
528         /* patch interfacetable index */
529
530         gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index));
531
532         /* patch method offset */
533
534         gen_resolveload(*((s4 *) (ra + 2 * 4)), (s4) (sizeof(methodptr) * (m - m->class->methods)));
535
536         /* synchronize instruction cache */
537
538         md_icacheflush(ra + 1 * 4, 2 * 4);
539
540         return true;
541 }
542
543
544 /* patcher_checkcast_instanceof_flags ******************************************
545
546    Machine code:
547
548    <patched call position>
549
550 *******************************************************************************/
551
552 bool patcher_checkcast_instanceof_flags(u1 *sp)
553 {
554         s4                 disp;
555         constant_classref *cr;
556         u1                *pv;
557         classinfo         *c;
558
559         /* get stuff from the stack */
560
561         disp  =                       *((s4 *)     (sp + 5 * 4));
562         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
563         pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
564
565         /* get the classinfo */
566
567         if (!(c = resolve_classref_eager(cr)))
568                 return false;
569
570         /* patch class flags */
571
572         *((s4 *) (pv + disp)) = (s4) c->flags;
573
574         return true;
575 }
576
577
578 /* patcher_checkcast_instanceof_interface **************************************
579
580    Machine code:
581
582    <patched call position>
583
584 *******************************************************************************/
585
586 bool patcher_checkcast_instanceof_interface(u1 *sp)
587 {
588         s4                 disp;
589         constant_classref *cr;
590         u1                *pv;
591         classinfo         *c;
592
593         /* get stuff from the stack */
594
595         disp =                       *((s4 *)     (sp + 5 * 4));
596         cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
597         pv   = (u1 *)                *((ptrint *) (sp + 0 * 4));
598
599         /* get the classinfo */
600
601         if (!(c = resolve_classref_eager(cr)))
602                 return false;
603
604         /* patch super class index */
605
606         *((s4 *) (pv + disp)) = (s4) c->index;
607
608         return true;
609 }
610
611
612 /* patcher_checkcast_instanceof_class ******************************************
613
614    Machine code:
615
616    <patched call position>
617
618 *******************************************************************************/
619
620 bool patcher_checkcast_instanceof_class(u1 *sp)
621 {
622         s4                 disp;
623         constant_classref *cr;
624         u1                *pv;
625         classinfo         *c;
626
627         /* get stuff from the stack */
628
629         disp =                       *((s4 *)     (sp + 5 * 4));
630         cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
631         pv   = (u1 *)                *((ptrint *) (sp + 0 * 4));
632
633         /* get the classinfo */
634
635         if (!(c = resolve_classref_eager(cr)))
636                 return false;
637
638         /* patch super class' vftbl */
639
640         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
641
642         return true;
643 }
644
645
646 /* patcher_clinit **************************************************************
647
648    XXX
649
650 *******************************************************************************/
651
652 bool patcher_clinit(u1 *sp)
653 {
654         classinfo *c;
655
656         /* get stuff from the stack */
657
658         c = (classinfo *) *((ptrint *) (sp + 1 * 4));
659
660         /* check if the class is initialized */
661
662         if (!(c->state & CLASS_INITIALIZED))
663                 if (!initialize_class(c))
664                         return false;
665
666         return true;
667 }
668
669
670 /* patcher_athrow_areturn ******************************************************
671
672    Machine code:
673
674    <patched call position>
675
676 *******************************************************************************/
677
678 #ifdef ENABLE_VERIFIER
679 bool patcher_athrow_areturn(u1 *sp)
680 {
681         unresolved_class *uc;
682
683         /* get stuff from the stack */
684
685         uc = (unresolved_class *) *((ptrint *) (sp + 1 * 4));
686
687         /* resolve the class and check subtype constraints */
688
689         if (!resolve_class_eager_no_access_check(uc))
690                 return false;
691
692         return true;
693 }
694 #endif /* ENABLE_VERIFIER */
695
696
697 /* patcher_resolve_native ******************************************************
698
699    XXX
700
701 *******************************************************************************/
702
703 #if !defined(WITH_STATIC_CLASSPATH)
704 bool patcher_resolve_native(u1 *sp)
705 {
706         s4           disp;
707         methodinfo  *m;
708         u1          *pv;
709         functionptr  f;
710
711         /* get stuff from the stack */
712
713         disp =                *((s4 *)     (sp + 5 * 4));
714         m    = (methodinfo *) *((ptrint *) (sp + 1 * 4));
715         pv   = (u1 *)         *((ptrint *) (sp + 0 * 4));
716
717         /* resolve native function */
718
719         if (!(f = native_resolve_function(m)))
720                 return false;
721
722         /* patch native function pointer */
723
724         *((ptrint *) (pv + disp)) = (ptrint) f;
725
726         return true;
727 }
728 #endif /* !defined(WITH_STATIC_CLASSPATH) */
729
730
731 /*
732  * These are local overrides for various environment variables in Emacs.
733  * Please do not remove this and leave it at the end of the file, where
734  * Emacs will automagically detect them.
735  * ---------------------------------------------------------------------
736  * Local variables:
737  * mode: c
738  * indent-tabs-mode: t
739  * c-basic-offset: 4
740  * tab-width: 4
741  * End:
742  * vim:noexpandtab:sw=4:ts=4:
743  */