df764b6e252042c09f777539ef97f7d5c9a2f457
[cacao.git] / src / vm / jit / i386 / patcher.c
1 /* src/vm/jit/i386/patcher.c - i386 code patching functions
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Thalinger
28
29    Changes:
30
31    $Id: patcher.c 2773 2005-06-22 09:26:04Z twisti $
32
33 */
34
35
36 #include "vm/jit/i386/types.h"
37
38 #include "native/native.h"
39 #include "vm/builtin.h"
40 #include "vm/field.h"
41 #include "vm/initialize.h"
42 #include "vm/options.h"
43 #include "vm/references.h"
44 #include "vm/jit/helper.h"
45 #include "vm/jit/patcher.h"
46
47
48 /* patcher_get_putstatic *******************************************************
49
50    Machine code:
51
52    <patched call position>
53    b8 00 00 00 00             mov    $0x00000000,%eax
54
55 *******************************************************************************/
56
57 bool patcher_get_putstatic(u1 *sp)
58 {
59         u1                *ra;
60         java_objectheader *o;
61         u8                 mcode;
62         unresolved_field  *uf;
63         fieldinfo         *fi;
64
65         /* get stuff from the stack */
66
67         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
68         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
69         mcode =                       *((u8 *)     (sp + 1 * 4));
70         uf    = (unresolved_field *)  *((ptrint *) (sp + 0 * 4));
71
72         /* calculate and set the new return address */
73
74         ra = ra - 5;
75         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
76
77         PATCHER_MONITORENTER;
78
79         /* get the fieldinfo */
80
81         if (!(fi = helper_resolve_fieldinfo(uf))) {
82                 PATCHER_MONITOREXIT;
83
84                 return false;
85         }
86
87         /* check if the field's class is initialized */
88
89         if (!fi->class->initialized) {
90                 if (!initialize_class(fi->class)) {
91                         PATCHER_MONITOREXIT;
92
93                         return false;
94                 }
95         }
96
97         /* patch back original code */
98
99         *((u4 *) (ra + 0)) = (u4) mcode;
100         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
101
102         /* if we show disassembly, we have to skip the nop's */
103
104         if (showdisassemble)
105                 ra = ra + 5;
106
107         /* patch the field value's address */
108
109         *((ptrint *) (ra + 1)) = (ptrint) &(fi->value);
110
111         PATCHER_MARK_PATCHED_MONITOREXIT;
112
113         return true;
114 }
115
116
117 /* patcher_getfield ************************************************************
118
119    Machine code:
120
121    <patched call position>
122    8b 88 00 00 00 00          mov    0x00000000(%eax),%ecx
123
124 *******************************************************************************/
125
126 bool patcher_getfield(u1 *sp)
127 {
128         u1                *ra;
129         java_objectheader *o;
130         u8                 mcode;
131         unresolved_field  *uf;
132         fieldinfo         *fi;
133
134         /* get stuff from the stack */
135
136         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
137         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
138         mcode =                       *((u8 *)     (sp + 1 * 4));
139         uf    = (unresolved_field *)  *((ptrint *) (sp + 0 * 4));
140
141         /* calculate and set the new return address */
142
143         ra = ra - 5;
144         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
145
146         PATCHER_MONITORENTER;
147
148         /* get the fieldinfo */
149
150         if (!(fi = helper_resolve_fieldinfo(uf))) {
151                 PATCHER_MONITOREXIT;
152
153                 return false;
154         }
155
156         /* patch back original code */
157
158         *((u4 *) (ra + 0)) = (u4) mcode;
159         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
160
161         /* if we show disassembly, we have to skip the nop's */
162
163         if (showdisassemble)
164                 ra = ra + 5;
165
166         /* patch the field's offset */
167
168         *((u4 *) (ra + 2)) = (u4) (fi->offset);
169
170         /* if the field has type long, we need to patch the second move too */
171
172         if (fi->type == TYPE_LNG)
173                 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
174
175         PATCHER_MARK_PATCHED_MONITOREXIT;
176
177         return true;
178 }
179
180
181 /* patcher_putfield ************************************************************
182
183    Machine code:
184
185    <patched call position>
186    8b 88 00 00 00 00          mov    0x00000000(%eax),%ecx
187
188 *******************************************************************************/
189
190 bool patcher_putfield(u1 *sp)
191 {
192         u1                *ra;
193         java_objectheader *o;
194         u8                 mcode;
195         unresolved_field  *uf;
196         fieldinfo         *fi;
197
198         /* get stuff from the stack */
199
200         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
201         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
202         mcode =                       *((u8 *)     (sp + 1 * 4));
203         uf    = (unresolved_field *)  *((ptrint *) (sp + 0 * 4));
204
205         /* calculate and set the new return address */
206
207         ra = ra - 5;
208         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
209
210         PATCHER_MONITORENTER;
211
212         /* get the fieldinfo */
213
214         if (!(fi = helper_resolve_fieldinfo(uf))) {
215                 PATCHER_MONITOREXIT;
216
217                 return false;
218         }
219
220         /* patch back original code */
221
222         *((u4 *) (ra + 0)) = (u4) mcode;
223         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
224
225         /* if we show disassembly, we have to skip the nop's */
226
227         if (showdisassemble)
228                 ra = ra + 5;
229
230         /* patch the field's offset */
231
232         if (fi->type != TYPE_LNG) {
233                 *((u4 *) (ra + 2)) = (u4) (fi->offset);
234
235         } else {
236                 /* long code is very special:
237                  *
238                  * 8b 8c 24 00 00 00 00       mov    0x00000000(%esp),%ecx
239                  * 8b 94 24 00 00 00 00       mov    0x00000000(%esp),%edx
240                  * 89 8d 00 00 00 00          mov    %ecx,0x00000000(%ebp)
241                  * 89 95 00 00 00 00          mov    %edx,0x00000000(%ebp)
242                  */
243
244                 *((u4 *) (ra + 7 + 7 + 2)) = (u4) (fi->offset);
245                 *((u4 *) (ra + 7 + 7 + 6 + 2)) = (u4) (fi->offset + 4);
246         }
247
248         PATCHER_MARK_PATCHED_MONITOREXIT;
249
250         return true;
251 }
252
253
254 /* patcher_putfieldconst *******************************************************
255
256    Machine code:
257
258    <patched call position>
259    c7 85 00 00 00 00 7b 00 00 00    movl   $0x7b,0x0(%ebp)
260
261 *******************************************************************************/
262
263 bool patcher_putfieldconst(u1 *sp)
264 {
265         u1                *ra;
266         java_objectheader *o;
267         u8                 mcode;
268         unresolved_field  *uf;
269         fieldinfo         *fi;
270
271         /* get stuff from the stack */
272
273         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
274         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
275         mcode =                       *((u8 *)     (sp + 1 * 4));
276         uf    = (unresolved_field *)  *((ptrint *) (sp + 0 * 4));
277
278         /* calculate and set the new return address */
279
280         ra = ra - 5;
281         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
282
283         PATCHER_MONITORENTER;
284
285         /* get the fieldinfo */
286
287         if (!(fi = helper_resolve_fieldinfo(uf))) {
288                 PATCHER_MONITOREXIT;
289
290                 return false;
291         }
292
293         /* patch back original code */
294
295         *((u4 *) (ra + 0)) = (u4) mcode;
296         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
297
298         /* if we show disassembly, we have to skip the nop's */
299
300         if (showdisassemble)
301                 ra = ra + 5;
302
303         /* patch the field's offset */
304
305         if (!IS_2_WORD_TYPE(fi->type)) {
306                 *((u4 *) (ra + 2)) = (u4) (fi->offset);
307
308         } else {
309                 /* long/double code is different:
310                  *
311                  * c7 80 00 00 00 00 c8 01 00 00    movl   $0x1c8,0x0(%eax)
312                  * c7 80 04 00 00 00 00 00 00 00    movl   $0x0,0x4(%eax)
313                  */
314
315                 *((u4 *) (ra + 2)) = (u4) (fi->offset);
316                 *((u4 *) (ra + 10 + 2)) = (u4) (fi->offset + 4);
317         }
318
319         PATCHER_MARK_PATCHED_MONITOREXIT;
320
321         return true;
322 }
323
324
325 /* patcher_builtin_new *********************************************************
326
327    Machine code:
328
329    c7 04 24 00 00 00 00       movl   $0x0000000,(%esp)
330    <patched call postition>
331    b8 00 00 00 00             mov    $0x0000000,%eax
332    ff d0                      call   *%eax
333
334 *******************************************************************************/
335
336 bool patcher_builtin_new(u1 *sp)
337 {
338         u1                *ra;
339         java_objectheader *o;
340         u8                 mcode;
341         constant_classref *cr;
342         classinfo         *c;
343
344         /* get stuff from the stack */
345
346         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
347         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
348         mcode =                       *((u8 *)     (sp + 1 * 4));
349         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 4));
350
351         /* calculate and set the new return address */
352
353         ra = ra - (7 + 5);
354         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
355
356         PATCHER_MONITORENTER;
357
358         /* get the classinfo */
359
360         if (!(c = helper_resolve_classinfo(cr))) {
361                 PATCHER_MONITOREXIT;
362
363                 return false;
364         }
365
366         /* patch back original code */
367
368         *((u4 *) (ra + 7 + 0)) = (u4) mcode;
369         *((u1 *) (ra + 7 + 4)) = (u1) (mcode >> 32);
370
371         /* patch the classinfo pointer */
372
373         *((ptrint *) (ra + 3)) = (ptrint) c;
374
375         /* if we show disassembly, we have to skip the nop's */
376
377         if (showdisassemble)
378                 ra = ra + 5;
379
380         /* patch new function address */
381
382         *((ptrint *) (ra + 7 + 1)) = (ptrint) BUILTIN_new;
383
384         PATCHER_MARK_PATCHED_MONITOREXIT;
385
386         return true;
387 }
388
389
390 /* patcher_builtin_newarray ****************************************************
391
392    Machine code:
393
394    c7 44 24 08 00 00 00 00    movl   $0x00000000,0x8(%esp)
395    <patched call position>
396    b8 00 00 00 00             mov    $0x00000000,%eax
397    ff d0                      call   *%eax
398
399 *******************************************************************************/
400
401 bool patcher_builtin_newarray(u1 *sp)
402 {
403         u1                *ra;
404         java_objectheader *o;
405         u8                 mcode;
406         constant_classref *cr;
407         classinfo         *c;
408
409         /* get stuff from the stack */
410
411         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
412         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
413         mcode =                       *((u8 *)     (sp + 1 * 4));
414         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 4));
415
416         /* calculate and set the new return address */
417
418         ra = ra - (8 + 5);
419         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
420
421         PATCHER_MONITORENTER;
422
423         /* get the classinfo */
424
425         if (!(c = helper_resolve_classinfo(cr))) {
426                 PATCHER_MONITOREXIT;
427
428                 return false;
429         }
430
431         /* patch back original code */
432
433         *((u4 *) (ra + 8 + 0)) = (u4) mcode;
434         *((u1 *) (ra + 8 + 4)) = (u1) (mcode >> 32);
435
436         /* patch the class' vftbl pointer */
437
438         *((ptrint *) (ra + 4)) = (ptrint) c->vftbl;
439
440         /* if we show disassembly, we have to skip the nop's */
441
442         if (showdisassemble)
443                 ra = ra + 5;
444
445         /* patch new function address */
446
447         *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_newarray;
448
449         PATCHER_MARK_PATCHED_MONITOREXIT;
450
451         return true;
452 }
453
454
455 /* patcher_builtin_multianewarray **********************************************
456
457    Machine code:
458
459    <patched call position>
460    c7 04 24 02 00 00 00       movl   $0x2,(%esp)
461    c7 44 24 04 00 00 00 00    movl   $0x00000000,0x4(%esp)
462    89 e0                      mov    %esp,%eax
463    83 c0 0c                   add    $0xc,%eax
464    89 44 24 08                mov    %eax,0x8(%esp)
465    b8 00 00 00 00             mov    $0x00000000,%eax
466    ff d0                      call   *%eax
467
468 *******************************************************************************/
469
470 bool patcher_builtin_multianewarray(u1 *sp)
471 {
472         u1                *ra;
473         java_objectheader *o;
474         u8                 mcode;
475         constant_classref *cr;
476         classinfo         *c;
477
478         /* get stuff from the stack */
479
480         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
481         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
482         mcode =                       *((u8 *)     (sp + 1 * 4));
483         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 4));
484
485         /* calculate and set the new return address */
486
487         ra = ra - 5;
488         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
489
490         PATCHER_MONITORENTER;
491
492         /* get the classinfo */
493
494         if (!(c = helper_resolve_classinfo(cr))) {
495                 PATCHER_MONITOREXIT;
496
497                 return false;
498         }
499
500         /* patch back original code */
501
502         *((u4 *) (ra + 0)) = (u4) mcode;
503         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
504
505         /* if we show disassembly, we have to skip the nop's */
506
507         if (showdisassemble)
508                 ra = ra + 5;
509
510         /* patch the class' vftbl pointer */
511
512         *((ptrint *) (ra + 7 + 4)) = (ptrint) c->vftbl;
513
514         /* patch new function address */
515
516         *((ptrint *) (ra + 7 + 8 + 2 + 3 + 4 + 1)) = (ptrint) BUILTIN_multianewarray;
517
518         PATCHER_MARK_PATCHED_MONITOREXIT;
519
520         return true;
521 }
522
523
524 /* patcher_builtin_arraycheckcast **********************************************
525
526    Machine code:
527
528    c7 44 24 08 00 00 00 00    movl   $0x00000000,0x8(%esp)
529    <patched call position>
530    b8 00 00 00 00             mov    $0x00000000,%eax
531    ff d0                      call   *%eax
532
533 *******************************************************************************/
534
535 bool patcher_builtin_arraycheckcast(u1 *sp)
536 {
537         u1                *ra;
538         java_objectheader *o;
539         u8                 mcode;
540         constant_classref *cr;
541         classinfo         *c;
542
543         /* get stuff from the stack */
544
545         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
546         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
547         mcode =                       *((u8 *)     (sp + 1 * 4));
548         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 4));
549
550         /* calculate and set the new return address */
551
552         ra = ra - (8 + 5);
553         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
554
555         PATCHER_MONITORENTER;
556
557         /* get the classinfo */
558
559         if (!(c = helper_resolve_classinfo(cr))) {
560                 PATCHER_MONITOREXIT;
561
562                 return false;
563         }
564
565         /* patch back original code */
566
567         *((u4 *) (ra + 8 + 0)) = (u4) mcode;
568         *((u1 *) (ra + 8 + 4)) = (u1) (mcode >> 32);
569
570         /* patch the class' vftbl pointer */
571
572         *((ptrint *) (ra + 4)) = (ptrint) c->vftbl;
573
574         /* if we show disassembly, we have to skip the nop's */
575
576         if (showdisassemble)
577                 ra = ra + 5;
578
579         /* patch new function address */
580
581         *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_arraycheckcast;
582
583         PATCHER_MARK_PATCHED_MONITOREXIT;
584
585         return true;
586 }
587
588
589 /* patcher_builtin_arrayinstanceof *********************************************
590
591    Machine code:
592
593    c7 44 24 08 00 00 00 00    movl   $0x00000000,0x8(%esp)
594    <patched call position>
595    b8 00 00 00 00             mov    $0x00000000,%eax
596    ff d0                      call   *%eax
597
598 *******************************************************************************/
599
600 bool patcher_builtin_arrayinstanceof(u1 *sp)
601 {
602         u1                *ra;
603         java_objectheader *o;
604         u8                 mcode;
605         constant_classref *cr;
606         classinfo         *c;
607
608         /* get stuff from the stack */
609
610         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
611         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
612         mcode =                       *((u8 *)     (sp + 1 * 4));
613         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 4));
614
615         /* calculate and set the new return address */
616
617         ra = ra - (8 + 5);
618         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
619
620         PATCHER_MONITORENTER;
621
622         /* get the classinfo */
623
624         if (!(c = helper_resolve_classinfo(cr))) {
625                 PATCHER_MONITOREXIT;
626
627                 return false;
628         }
629
630         /* patch back original code */
631
632         *((u4 *) (ra + 8 + 0)) = (u4) mcode;
633         *((u1 *) (ra + 8 + 4)) = (u1) (mcode >> 32);
634
635         /* patch the class' vftbl pointer */
636
637         *((ptrint *) (ra + 4)) = (ptrint) c->vftbl;
638
639         /* if we show disassembly, we have to skip the nop's */
640
641         if (showdisassemble)
642                 ra = ra + 5;
643
644         /* patch new function address */
645
646         *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_arrayinstanceof;
647
648         PATCHER_MARK_PATCHED_MONITOREXIT;
649
650         return true;
651 }
652
653
654 /* patcher_invokestatic_special ************************************************
655
656    Machine code:
657
658    <patched call position>
659    b9 00 00 00 00             mov    $0x00000000,%ecx
660    ff d1                      call   *%ecx
661
662 *******************************************************************************/
663
664 bool patcher_invokestatic_special(u1 *sp)
665 {
666         u1                *ra;
667         java_objectheader *o;
668         u8                 mcode;
669         unresolved_method *um;
670         methodinfo        *m;
671
672         /* get stuff from the stack */
673
674         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
675         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
676         mcode =                       *((u8 *)     (sp + 1 * 4));
677         um    = (unresolved_method *) *((ptrint *) (sp + 0 * 4));
678
679         /* calculate and set the new return address */
680
681         ra = ra - 5;
682         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
683
684         PATCHER_MONITORENTER;
685
686         /* get the fieldinfo */
687
688         if (!(m = helper_resolve_methodinfo(um))) {
689                 PATCHER_MONITOREXIT;
690
691                 return false;
692         }
693
694         /* patch back original code */
695
696         *((u4 *) (ra + 0)) = (u4) mcode;
697         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
698
699         /* if we show disassembly, we have to skip the nop's */
700
701         if (showdisassemble)
702                 ra = ra + 5;
703
704         /* patch stubroutine */
705
706         *((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
707
708         PATCHER_MARK_PATCHED_MONITOREXIT;
709
710         return true;
711 }
712
713
714 /* patcher_invokevirtual *******************************************************
715
716    Machine code:
717
718    <patched call position>
719    8b 08                      mov    (%eax),%ecx
720    8b 81 00 00 00 00          mov    0x00000000(%ecx),%eax
721    ff d0                      call   *%eax
722
723 *******************************************************************************/
724
725 bool patcher_invokevirtual(u1 *sp)
726 {
727         u1                *ra;
728         java_objectheader *o;
729         u8                 mcode;
730         unresolved_method *um;
731         methodinfo        *m;
732
733         /* get stuff from the stack */
734
735         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
736         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
737         mcode =                       *((u8 *)     (sp + 1 * 4));
738         um    = (unresolved_method *) *((ptrint *) (sp + 0 * 4));
739
740         /* calculate and set the new return address */
741
742         ra = ra - 5;
743         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
744
745         PATCHER_MONITORENTER;
746
747         /* get the fieldinfo */
748
749         if (!(m = helper_resolve_methodinfo(um))) {
750                 PATCHER_MONITOREXIT;
751
752                 return false;
753         }
754
755         /* patch back original code */
756
757         *((u4 *) (ra + 0)) = (u4) mcode;
758         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
759
760         /* if we show disassembly, we have to skip the nop's */
761
762         if (showdisassemble)
763                 ra = ra + 5;
764
765         /* patch vftbl index */
766
767         *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
768                                                                    sizeof(methodptr) * m->vftblindex);
769
770         PATCHER_MARK_PATCHED_MONITOREXIT;
771
772         return true;
773 }
774
775
776 /* patcher_invokeinterface *****************************************************
777
778    Machine code:
779
780    <patched call position>
781    8b 00                      mov    (%eax),%eax
782    8b 88 00 00 00 00          mov    0x00000000(%eax),%ecx
783    8b 81 00 00 00 00          mov    0x00000000(%ecx),%eax
784    ff d0                      call   *%eax
785
786 *******************************************************************************/
787
788 bool patcher_invokeinterface(u1 *sp)
789 {
790         u1                *ra;
791         java_objectheader *o;
792         u8                 mcode;
793         unresolved_method *um;
794         methodinfo        *m;
795
796         /* get stuff from the stack */
797
798         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
799         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
800         mcode =                       *((u8 *)     (sp + 1 * 4));
801         um    = (unresolved_method *) *((ptrint *) (sp + 0 * 4));
802
803         /* calculate and set the new return address */
804
805         ra = ra - 5;
806         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
807
808         PATCHER_MONITORENTER;
809
810         /* get the fieldinfo */
811
812         if (!(m = helper_resolve_methodinfo(um))) {
813                 PATCHER_MONITOREXIT;
814
815                 return false;
816         }
817
818         /* patch back original code */
819
820         *((u4 *) (ra + 0)) = (u4) mcode;
821         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
822
823         /* if we show disassembly, we have to skip the nop's */
824
825         if (showdisassemble)
826                 ra = ra + 5;
827
828         /* patch interfacetable index */
829
830         *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
831                                                                    sizeof(methodptr) * m->class->index);
832
833         /* patch method offset */
834
835         *((s4 *) (ra + 2 + 6 + 2)) =
836                 (s4) (sizeof(methodptr) * (m - m->class->methods));
837
838         PATCHER_MARK_PATCHED_MONITOREXIT;
839
840         return true;
841 }
842
843
844 /* patcher_checkcast_instanceof_flags ******************************************
845
846    Machine code:
847
848    <patched call position>
849    b9 00 00 00 00             mov    $0x00000000,%ecx
850
851 *******************************************************************************/
852
853 bool patcher_checkcast_instanceof_flags(u1 *sp)
854 {
855         u1                *ra;
856         java_objectheader *o;
857         u8                 mcode;
858         constant_classref *cr;
859         classinfo         *c;
860
861         /* get stuff from the stack */
862
863         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
864         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
865         mcode =                       *((u8 *)     (sp + 1 * 4));
866         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 4));
867
868         /* calculate and set the new return address */
869
870         ra = ra - 5;
871         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
872
873         PATCHER_MONITORENTER;
874
875         /* get the fieldinfo */
876
877         if (!(c = helper_resolve_classinfo(cr))) {
878                 PATCHER_MONITOREXIT;
879
880                 return false;
881         }
882
883         /* patch back original code */
884
885         *((u4 *) (ra + 0)) = (u4) mcode;
886         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
887
888         /* if we show disassembly, we have to skip the nop's */
889
890         if (showdisassemble)
891                 ra = ra + 5;
892
893         /* patch class flags */
894
895         *((s4 *) (ra + 1)) = (s4) c->flags;
896
897         PATCHER_MARK_PATCHED_MONITOREXIT;
898
899         return true;
900 }
901
902
903 /* patcher_checkcast_instanceof_interface **************************************
904
905    Machine code:
906
907    <patched call position>
908    8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
909    81 ea 00 00 00 00          sub    $0x00000000,%edx
910    85 d2                      test   %edx,%edx
911    0f 8e 00 00 00 00          jle    0x00000000
912    8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
913
914 *******************************************************************************/
915
916 bool patcher_checkcast_instanceof_interface(u1 *sp)
917 {
918         u1                *ra;
919         java_objectheader *o;
920         u8                 mcode;
921         constant_classref *cr;
922         classinfo         *c;
923
924         /* get stuff from the stack */
925
926         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
927         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
928         mcode =                       *((u8 *)     (sp + 1 * 4));
929         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 4));
930
931         /* calculate and set the new return address */
932
933         ra = ra - 5;
934         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
935
936         PATCHER_MONITORENTER;
937
938         /* get the fieldinfo */
939
940         if (!(c = helper_resolve_classinfo(cr))) {
941                 PATCHER_MONITOREXIT;
942
943                 return false;
944         }
945
946         /* patch back original code */
947
948         *((u4 *) (ra + 0)) = (u4) mcode;
949         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
950
951         /* if we show disassembly, we have to skip the nop's */
952
953         if (showdisassemble)
954                 ra = ra + 5;
955
956         /* patch super class index */
957
958         *((s4 *) (ra + 6 + 2)) = (s4) c->index;
959
960         *((s4 *) (ra + 6 + 6 + 2 + 6 + 2)) =
961                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
962                           c->index * sizeof(methodptr*));
963
964         PATCHER_MARK_PATCHED_MONITOREXIT;
965
966         return true;
967 }
968
969
970 /* patcher_checkcast_class *****************************************************
971
972    Machine code:
973
974    <patched call position>
975    ba 00 00 00 00             mov    $0x00000000,%edx
976    8b 89 00 00 00 00          mov    0x00000000(%ecx),%ecx
977    8b 92 00 00 00 00          mov    0x00000000(%edx),%edx
978    29 d1                      sub    %edx,%ecx
979    ba 00 00 00 00             mov    $0x00000000,%edx
980
981 *******************************************************************************/
982
983 bool patcher_checkcast_class(u1 *sp)
984 {
985         u1                *ra;
986         java_objectheader *o;
987         u8                 mcode;
988         constant_classref *cr;
989         classinfo         *c;
990
991         /* get stuff from the stack */
992
993         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
994         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
995         mcode =                       *((u8 *)     (sp + 1 * 4));
996         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 4));
997
998         /* calculate and set the new return address */
999
1000         ra = ra - 5;
1001         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
1002
1003         PATCHER_MONITORENTER;
1004
1005         /* get the fieldinfo */
1006
1007         if (!(c = helper_resolve_classinfo(cr))) {
1008                 PATCHER_MONITOREXIT;
1009
1010                 return false;
1011         }
1012
1013         /* patch back original code */
1014
1015         *((u4 *) (ra + 0)) = (u4) mcode;
1016         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
1017
1018         /* if we show disassembly, we have to skip the nop's */
1019
1020         if (showdisassemble)
1021                 ra = ra + 5;
1022
1023         /* patch super class' vftbl */
1024
1025         *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
1026         *((ptrint *) (ra + 5 + 6 + 6 + 2 + 1)) = (ptrint) c->vftbl;
1027
1028         PATCHER_MARK_PATCHED_MONITOREXIT;
1029
1030         return true;
1031 }
1032
1033
1034 /* patcher_instanceof_class ****************************************************
1035
1036    Machine code:
1037
1038    <patched call position>
1039    b9 00 00 00 00             mov    $0x0,%ecx
1040    8b 40 14                   mov    0x14(%eax),%eax
1041    8b 51 18                   mov    0x18(%ecx),%edx
1042    8b 49 14                   mov    0x14(%ecx),%ecx
1043
1044 *******************************************************************************/
1045
1046 bool patcher_instanceof_class(u1 *sp)
1047 {
1048         u1                *ra;
1049         java_objectheader *o;
1050         u8                 mcode;
1051         constant_classref *cr;
1052         classinfo         *c;
1053
1054         /* get stuff from the stack */
1055
1056         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
1057         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
1058         mcode =                       *((u8 *)     (sp + 1 * 4));
1059         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 4));
1060
1061         /* calculate and set the new return address */
1062
1063         ra = ra - 5;
1064         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
1065
1066         PATCHER_MONITORENTER;
1067
1068         /* get the fieldinfo */
1069
1070         if (!(c = helper_resolve_classinfo(cr))) {
1071                 PATCHER_MONITOREXIT;
1072
1073                 return false;
1074         }
1075
1076         /* patch back original code */
1077
1078         *((u4 *) (ra + 0)) = (u4) mcode;
1079         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
1080
1081         /* if we show disassembly, we have to skip the nop's */
1082
1083         if (showdisassemble)
1084                 ra = ra + 5;
1085
1086         /* patch super class' vftbl */
1087
1088         *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
1089
1090         PATCHER_MARK_PATCHED_MONITOREXIT;
1091
1092         return true;
1093 }
1094
1095
1096 /* patcher_clinit **************************************************************
1097
1098    Is used int PUT/GETSTATIC and native stub.
1099
1100    Machine code:
1101
1102    <patched call position>
1103
1104 *******************************************************************************/
1105
1106 bool patcher_clinit(u1 *sp)
1107 {
1108         u1                *ra;
1109         java_objectheader *o;
1110         u8                 mcode;
1111         classinfo         *c;
1112
1113         /* get stuff from the stack */
1114
1115         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
1116         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
1117         mcode =                       *((u8 *)     (sp + 1 * 4));
1118         c     = (classinfo *)         *((ptrint *) (sp + 0 * 4));
1119
1120         /* calculate and set the new return address */
1121
1122         ra = ra - 5;
1123         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
1124
1125         PATCHER_MONITORENTER;
1126
1127         /* check if the class is initialized */
1128
1129         if (!c->initialized) {
1130                 if (!initialize_class(c)) {
1131                         PATCHER_MONITOREXIT;
1132
1133                         return false;
1134                 }
1135         }
1136
1137         /* patch back original code */
1138
1139         *((u4 *) (ra + 0)) = (u4) mcode;
1140         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
1141
1142         PATCHER_MARK_PATCHED_MONITOREXIT;
1143
1144         return true;
1145 }
1146
1147
1148 /* patcher_resolve_native ******************************************************
1149
1150    Is used in native stub.
1151
1152    Machine code:
1153
1154    <patched call position>
1155    b8 00 00 00 00             mov    $0x0,%eax
1156    ff d0                      call   *%eax
1157
1158 *******************************************************************************/
1159
1160 bool patcher_resolve_native(u1 *sp)
1161 {
1162         u1                *ra;
1163         java_objectheader *o;
1164         u8                 mcode;
1165         methodinfo        *m;
1166         functionptr        f;
1167
1168         /* get stuff from the stack */
1169
1170         ra    = (u1 *)                *((ptrint *) (sp + 4 * 4));
1171         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
1172         mcode =                       *((u8 *)     (sp + 1 * 4));
1173         m     = (methodinfo *)        *((ptrint *) (sp + 0 * 4));
1174
1175         /* calculate and set the new return address */
1176
1177         ra = ra - 5;
1178         *((ptrint *) (sp + 4 * 4)) = (ptrint) ra;
1179
1180         PATCHER_MONITORENTER;
1181
1182         /* resolve native function */
1183
1184         if (!(f = native_resolve_function(m))) {
1185                 PATCHER_MONITOREXIT;
1186
1187                 return false;
1188         }
1189
1190         /* patch back original code */
1191
1192         *((u4 *) (ra + 0)) = (u4) mcode;
1193         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
1194
1195         /* if we show disassembly, we have to skip the nop's */
1196
1197         if (showdisassemble)
1198                 ra = ra + 5;
1199
1200         /* patch native function pointer */
1201
1202         *((ptrint *) (ra + 1)) = (ptrint) f;
1203
1204         PATCHER_MARK_PATCHED_MONITOREXIT;
1205
1206         return true;
1207 }
1208
1209
1210 /*
1211  * These are local overrides for various environment variables in Emacs.
1212  * Please do not remove this and leave it at the end of the file, where
1213  * Emacs will automagically detect them.
1214  * ---------------------------------------------------------------------
1215  * Local variables:
1216  * mode: c
1217  * indent-tabs-mode: t
1218  * c-basic-offset: 4
1219  * tab-width: 4
1220  * End:
1221  * vim:noexpandtab:sw=4:ts=4:
1222  */