* src/vmcore/field.h (fieldinfo): Renamed class to clazz.
[cacao.git] / src / vm / jit / intrp / codegen.c
1 /* src/vm/jit/intrp/codegen.c - code generator for Interpreter
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 <stdio.h>
30
31 #if defined(WITH_FFI)
32 # include <ffi.h>
33 #elif defined(WITH_FFCALL)
34 # include <avcall.h>
35 #else
36 # error neither WITH_FFI nor WITH_FFCALL defined
37 #endif
38
39 #include "vm/types.h"
40
41 #include "arch.h"
42
43 #include "vm/jit/intrp/codegen.h"
44 #include "vm/jit/intrp/intrp.h"
45
46 #include "mm/memory.h"
47
48 #include "native/native.h"
49
50 #include "vm/builtin.h"
51 #include "vm/exceptions.h"
52 #include "vm/global.h"
53 #include "vm/stringlocal.h"
54 #include "vm/vm.h"
55
56 #include "vm/jit/asmpart.h"
57 #include "vm/jit/codegen-common.h"
58 #include "vm/jit/dseg.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/parse.h"
61 #include "vm/jit/patcher.h"
62 #include "vm/jit/stack.h"
63 #include "vm/jit/stacktrace.h"
64
65 #include "vmcore/class.h"
66 #include "vmcore/options.h"
67
68
69 #define gen_branch(_inst) { \
70   gen_##_inst(cd, 0); \
71   codegen_addreference(cd, BLOCK_OF(iptr->dst.insindex)); \
72 }
73
74 #define index2offset(_i) (-(_i) * SIZEOF_VOID_P)
75
76 /* functions used by cacao-gen.i */
77
78 void genarg_v(codegendata *cd1, Cell v)
79 {
80         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
81         *((Cell *) *mcodepp) = v;
82         (*mcodepp)++;
83 }
84
85 void genarg_i(codegendata *cd1, s4 i)
86 {
87         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
88         *((Cell *) *mcodepp) = i;
89         (*mcodepp)++;
90 }
91
92 void genarg_b(codegendata *cd1, s4 i)
93 {
94   genarg_i(cd1, i);
95 }
96
97 void genarg_f(codegendata *cd1, float f)
98 {
99         s4 fi;
100
101         vm_f2Cell(f,fi);
102         genarg_i(cd1, fi);
103 }
104
105 void genarg_l(codegendata *cd1, s8 l)
106 {
107         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
108         vm_l2twoCell(l, ((Cell *) *mcodepp)[1], ((Cell *) *mcodepp)[0]);
109         (*mcodepp) +=2;
110 }
111
112 void genarg_aRef(codegendata *cd1, java_objectheader *a)
113 {
114         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
115         *((java_objectheader **) *mcodepp) = a;
116         (*mcodepp)++;
117 }
118
119 void genarg_aArray(codegendata *cd1, java_arrayheader *a)
120 {
121         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
122         *((java_arrayheader **) *mcodepp) = a;
123         (*mcodepp)++;
124 }
125
126 void genarg_aaTarget(codegendata *cd1, Inst **a)
127 {
128         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
129         *((Inst ***) *mcodepp) = a;
130         (*mcodepp)++;
131 }
132
133 void genarg_aClass(codegendata *cd1, classinfo *a)
134 {
135         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
136         *((classinfo **) *mcodepp) = a;
137         (*mcodepp)++;
138 }
139
140 void genarg_acr(codegendata *cd1, constant_classref *a)
141 {
142         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
143         *((constant_classref **) *mcodepp) = a;
144         (*mcodepp)++;
145 }
146
147 void genarg_addr(codegendata *cd1, u1 *a)
148 {
149         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
150         *((u1 **) *mcodepp) = a;
151         (*mcodepp)++;
152 }
153
154 void genarg_af(codegendata *cd1, functionptr a)
155 {
156         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
157         *((functionptr *) *mcodepp) = a;
158         (*mcodepp)++;
159 }
160
161 void genarg_afi(codegendata *cd1, fieldinfo *a)
162 {
163         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
164         *((fieldinfo **) *mcodepp) = a;
165         (*mcodepp)++;
166 }
167
168 void genarg_am(codegendata *cd1, methodinfo *a)
169 {
170         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
171         *((methodinfo **) *mcodepp) = a;
172         (*mcodepp)++;
173 }
174
175 void genarg_acell(codegendata *cd1, Cell *a)
176 {
177         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
178         *((Cell **) *mcodepp) = a;
179         (*mcodepp)++;
180 }
181
182 void genarg_ainst(codegendata *cd1, Inst *a)
183 {
184         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
185         *((Inst **) *mcodepp) = a;
186         (*mcodepp)++;
187 }
188
189 void genarg_auf(codegendata *cd1, unresolved_field *a)
190 {
191         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
192         *((unresolved_field **) *mcodepp) = a;
193         (*mcodepp)++;
194 }
195
196 void genarg_aum(codegendata *cd1, unresolved_method *a)
197 {
198         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
199         *((unresolved_method **) *mcodepp) = a;
200         (*mcodepp)++;
201 }
202
203 void genarg_avftbl(codegendata *cd1, vftbl_t *a)
204 {
205         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
206         *((vftbl_t **) *mcodepp) = a;
207         (*mcodepp)++;
208 }
209
210
211 /* include the interpreter generation functions *******************************/
212
213 /* Do not use "java-gen.i", it does not work with builddir. */
214 #include <java-gen.i>
215
216
217 typedef void (*genfunctionptr) (codegendata *);
218
219 typedef struct builtin_gen builtin_gen;
220
221 struct builtin_gen {
222         functionptr builtin;
223         genfunctionptr gen;
224 };
225
226 struct builtin_gen builtin_gen_table[] = {
227     {BUILTIN_new,                     gen_NEW,             }, 
228     {BUILTIN_newarray,                gen_NEWARRAY,        },
229     {BUILTIN_newarray_boolean,        gen_NEWARRAY_BOOLEAN,},
230     {BUILTIN_newarray_byte,           gen_NEWARRAY_BYTE,   },
231     {BUILTIN_newarray_char,           gen_NEWARRAY_CHAR,   },
232     {BUILTIN_newarray_short,          gen_NEWARRAY_SHORT,  },    
233     {BUILTIN_newarray_int,            gen_NEWARRAY_INT,    },
234     {BUILTIN_newarray_long,           gen_NEWARRAY_LONG,   },
235     {BUILTIN_newarray_float,          gen_NEWARRAY_FLOAT,  },    
236     {BUILTIN_newarray_double,         gen_NEWARRAY_DOUBLE, },
237     {BUILTIN_arrayinstanceof,         gen_ARRAYINSTANCEOF, },
238
239 #if defined(ENABLE_THREADS)
240     {LOCK_monitor_enter,              gen_MONITORENTER,    },
241     {LOCK_monitor_exit,               gen_MONITOREXIT,     },
242 #endif
243
244 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
245     {BUILTIN_f2l,                     gen_F2L,             },
246 #endif
247
248 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
249     {BUILTIN_d2l,                                         gen_D2L,                         },
250 #endif
251
252 #if !(SUPPORT_FLOAT && SUPPORT_F2I)
253     {BUILTIN_f2i,                                         gen_F2I,                         },
254 #endif
255
256 #if !(SUPPORT_DOUBLE && SUPPORT_D2I)
257     {BUILTIN_d2i,                                         gen_D2I,                         },
258 #endif
259
260 #if !SUPPORT_DIVISION
261     {BUILTIN_idiv,                                        gen_IDIV,                        },
262     {BUILTIN_irem,                                        gen_IREM,                        },
263 #endif
264
265 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
266     {BUILTIN_ldiv,                                        gen_LDIV,                        },
267     {BUILTIN_lrem,                                        gen_LREM,                        },
268 #endif
269
270     {BUILTIN_frem,                                        gen_FREM,                        },
271     {BUILTIN_drem,                                        gen_DREM,            },
272 };
273
274
275 /* codegen *********************************************************************
276
277    Generates machine code.
278
279 *******************************************************************************/
280
281 #define I(value)   iptr[0].sx.val.i = (value); break;
282
283 bool intrp_codegen(jitdata *jd)
284 {
285         methodinfo         *m;
286         codegendata        *cd;
287         registerdata       *rd;
288         s4                  i, len, s1, s2, d;
289         basicblock         *bptr;
290         instruction        *iptr;
291         u2                  currentline;
292         methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
293         unresolved_method  *um;
294         builtintable_entry *bte;
295         methoddesc         *md;
296         fieldinfo          *fi;
297         unresolved_field   *uf;
298         s4                  fieldtype;
299
300         /* get required compiler data */
301
302         m  = jd->m;
303         cd = jd->cd;
304         rd = jd->rd;
305
306         /* prevent compiler warnings */
307
308         d = 0;
309         currentline = 0;
310         lm = NULL;
311         bte = NULL;
312
313         /* determine stackframe size (in units of ptrint slots) */
314
315         cd->stackframesize = m->maxlocals;
316
317 #if defined(ENABLE_THREADS)
318         if (checksync && code_is_synchronized(code))
319                 cd->stackframesize += 1;
320 #endif
321
322         /* create method header */
323
324         (void) dseg_add_unique_address(cd, jd->code);
325         (void) dseg_add_unique_s4(cd, cd->stackframesize * SIZEOF_VOID_P);
326
327         code->synchronizedoffset = rd->memuse * 8;
328
329         /* REMOVEME: We still need it for exception handling in assembler. */
330
331         if (code_is_leafmethod(code))
332                 (void) dseg_add_unique_s4(cd, 1);
333         else
334                 (void) dseg_add_unique_s4(cd, 0);
335
336         (void) dseg_add_unique_s4(cd, 0);
337         (void) dseg_add_unique_s4(cd, 0);
338
339         dseg_addlinenumbertablesize(cd);
340
341 #if 0   
342         /* initialize mcode variables */
343         
344         cd->mcodeptr = cd->mcodebase;
345         cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
346 #endif
347
348         gen_BBSTART;
349
350 #if defined(ENABLE_THREADS)
351         if (checksync && code_is_synchronized(code)) {
352                 if (m->flags & ACC_STATIC) {
353                         gen_ACONST(cd, (java_objectheader *) m->clazz);
354                 }
355                 else {
356                         gen_ALOAD(cd, 0);
357                         gen_DUP(cd);
358                         gen_ASTORE(cd, index2offset(m->maxlocals));
359                 }
360                 
361                 gen_MONITORENTER(cd);
362         }                       
363 #endif
364
365         if (opt_verbosecall)
366                 gen_TRACECALL(cd, m);
367
368         gen_BBEND;
369
370         /* walk through all basic blocks */
371
372         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
373
374                 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
375
376                 if (bptr->flags != BBDELETED) {
377
378                 /* walk through all instructions */
379                 
380                 len = bptr->icount;
381
382                 gen_BBSTART;
383
384                 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
385                         if (iptr->line != currentline) {
386                                 dseg_addlinenumber(cd, iptr->line);
387                                 currentline = iptr->line;
388                         }
389
390                 MCODECHECK(64);       /* an instruction usually needs < 64 words      */
391
392 switch_again:
393                 switch (iptr->opc) {
394
395                 case ICMD_INLINE_START:
396                 case ICMD_INLINE_END:
397                         break;
398
399                 case ICMD_NOP:        /* ...  ==> ...                                 */
400                         break;
401
402                 case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
403
404                         gen_CHECKNULL(cd);
405                         break;
406
407                 /* constant operations ************************************************/
408
409                 case ICMD_ICONST:     /* ...  ==> ..., constant                       */
410                                       /* op1 = 0, val.i = constant                    */
411
412                         /* optimize ICONST (2^x) .. IREM --> IREMPOW2 (const) */
413
414                         if (len >= 2 && iptr[1].opc == ICMD_IREM) {
415                                 switch (iptr[0].sx.val.i) {
416         case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
417         case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
418         case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
419         case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
420         case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
421         case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
422         case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
423         case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
424                                         iptr[0].opc = ICMD_IREMPOW2;
425                                         iptr[0].sx.val.i--;
426                                         iptr[1].opc = ICMD_NOP;
427                                         goto switch_again;
428                                 }
429                         }
430
431                         /* optimize ICONST (2^x) .. IDIV --> IDIVPOW2 (const) */
432
433                         if (len >= 2 && iptr[1].opc == ICMD_IDIV) {
434                                 switch (iptr[0].sx.val.i) {
435                                case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
436         case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
437         case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
438         case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
439         case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
440         case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
441         case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
442         case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
443         default: goto dont_opt_IDIVPOW2;
444                                 }
445                                 iptr[0].opc = ICMD_IDIVPOW2;
446                                 iptr[1].opc = ICMD_NOP;
447                                 goto switch_again;
448                         }
449 dont_opt_IDIVPOW2:
450
451                         /* optimize ICONST .. IF_ICMPxx --> IFxx (const) */
452
453                         if (len >= 2) {
454                                 switch (iptr[1].opc) {
455                                         case ICMD_IF_ICMPEQ: iptr[0].opc = ICMD_IFEQ; break;
456                                         case ICMD_IF_ICMPNE: iptr[0].opc = ICMD_IFNE; break;
457                                         case ICMD_IF_ICMPLT: iptr[0].opc = ICMD_IFLT; break;
458                                         case ICMD_IF_ICMPLE: iptr[0].opc = ICMD_IFLE; break;
459                                         case ICMD_IF_ICMPGT: iptr[0].opc = ICMD_IFGT; break;
460                                         case ICMD_IF_ICMPGE: iptr[0].opc = ICMD_IFGE; break;
461                                         default:        goto dont_opt_IFxx;
462                                 }
463                                 iptr[0].dst.insindex = iptr[1].dst.insindex;
464                                 iptr[1].opc = ICMD_NOP;
465                                 goto switch_again;
466                         }
467 dont_opt_IFxx:
468
469                         gen_ICONST(cd, iptr->sx.val.i);
470                         break;
471
472                 case ICMD_LCONST:     /* ...  ==> ..., constant                       */
473                                       /* op1 = 0, val.l = constant                    */
474
475                         /* optimize LCONST (2^x) .. LREM --> LREMPOW2 (const) */
476
477                         if (len >= 2 && iptr[1].opc == ICMD_LREM) {
478                                 switch (iptr[0].sx.val.l) {
479         case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
480         case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
481         case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
482         case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
483         case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
484         case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
485         case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
486         case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
487                                         iptr[0].opc = ICMD_LREMPOW2;
488                                         iptr[0].sx.val.l--;
489                                         iptr[1].opc = ICMD_NOP;
490                                         goto switch_again;
491                                 }
492                         }
493
494                         /* optimize LCONST (2^x) .. LDIV --> LDIVPOW2 (const) */
495
496                         if (len >= 2 && iptr[1].opc == ICMD_LDIV) {
497                                 switch (iptr[0].sx.val.l) {
498                                case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
499         case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
500         case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
501         case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
502         case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
503         case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
504         case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
505         case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
506         default: goto dont_opt_LDIVPOW2;
507                                 }
508                                 iptr[0].opc = ICMD_LDIVPOW2;
509                                 iptr[1].opc = ICMD_NOP;
510                                 goto switch_again;
511                         }
512 dont_opt_LDIVPOW2:
513
514                         /* optimize LCONST .. LCMP .. IFxx (0) --> IF_Lxx */
515
516                         if (len >= 3 && iptr[1].opc == ICMD_LCMP && iptr[2].sx.val.i == 0) {
517                                 switch (iptr[2].opc) {
518                                         case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LEQ; break;
519                                         case ICMD_IFNE: iptr[0].opc = ICMD_IF_LNE; break;
520                                         case ICMD_IFLT: iptr[0].opc = ICMD_IF_LLT; break;
521                                         case ICMD_IFLE: iptr[0].opc = ICMD_IF_LLE; break;
522                                         case ICMD_IFGT: iptr[0].opc = ICMD_IF_LGT; break;
523                                         case ICMD_IFGE: iptr[0].opc = ICMD_IF_LGE; break;
524                                         default:        goto dont_opt_IF_Lxx;
525                                 }
526                                 iptr[0].dst.insindex = iptr[2].dst.insindex;
527                                 iptr[1].opc = ICMD_NOP;
528                                 iptr[2].opc = ICMD_NOP;
529                                 goto switch_again;
530                         }
531 dont_opt_IF_Lxx:
532
533                         gen_LCONST(cd, iptr->sx.val.l);
534                         break;
535
536                 case ICMD_FCONST:     /* ...  ==> ..., constant                       */
537                                       /* op1 = 0, val.f = constant                    */
538                         {
539                                 ptrint fi;
540
541                                 vm_f2Cell(iptr->sx.val.f, fi);
542                                 gen_ICONST(cd, fi);
543                         }
544                         break;
545                         
546                 case ICMD_DCONST:     /* ...  ==> ..., constant                       */
547                                       /* op1 = 0, val.d = constant                    */
548
549                         gen_LCONST(cd, *(s8 *)&(iptr->sx.val.d));
550                         break;
551
552                 case ICMD_ACONST:     /* ...  ==> ..., constant                       */
553                                       /* op1 = 0, val.a = constant                    */
554
555                         if (INSTRUCTION_IS_UNRESOLVED(iptr))
556                                 gen_PATCHER_ACONST(cd, NULL, iptr->sx.val.c.ref);
557                         else
558                                 gen_ACONST(cd, iptr->sx.val.anyptr);
559                         break;
560
561
562                 /* load/store operations **********************************************/
563
564                 case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
565                                       /* op1 = local variable                         */
566
567                         gen_ILOAD(cd, index2offset(iptr->s1.varindex));
568                         break;
569
570                 case ICMD_LLOAD:      /* ...  ==> ..., content of local variable      */
571                                       /* op1 = local variable                         */
572
573                         gen_LLOAD(cd, index2offset(iptr->s1.varindex));
574                         break;
575
576                 case ICMD_ALOAD:      /* ...  ==> ..., content of local variable      */
577                                       /* op1 = local variable                         */
578
579                         gen_ALOAD(cd, index2offset(iptr->s1.varindex));
580                         break;
581
582                 case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
583                                       /* op1 = local variable                         */
584
585                         gen_ILOAD(cd, index2offset(iptr->s1.varindex));
586                         break;
587
588                 case ICMD_DLOAD:      /* ...  ==> ..., content of local variable      */
589                                       /* op1 = local variable                         */
590
591                         gen_LLOAD(cd, index2offset(iptr->s1.varindex));
592                         break;
593
594
595                 case ICMD_ISTORE:     /* ..., value  ==> ...                          */
596                                       /* op1 = local variable                         */
597
598                         gen_ISTORE(cd, index2offset(iptr->dst.varindex));
599                         break;
600
601                 case ICMD_LSTORE:     /* ..., value  ==> ...                          */
602                                       /* op1 = local variable                         */
603
604                         gen_LSTORE(cd, index2offset(iptr->dst.varindex));
605                         break;
606
607                 case ICMD_ASTORE:     /* ..., value  ==> ...                          */
608                                       /* op1 = local variable                         */
609
610                         gen_ASTORE(cd, index2offset(iptr->dst.varindex));
611                         break;
612
613
614                 case ICMD_FSTORE:     /* ..., value  ==> ...                          */
615                                       /* op1 = local variable                         */
616
617                         gen_ISTORE(cd, index2offset(iptr->dst.varindex));
618                         break;
619
620                 case ICMD_DSTORE:     /* ..., value  ==> ...                          */
621                                       /* op1 = local variable                         */
622
623                         gen_LSTORE(cd, index2offset(iptr->dst.varindex));
624                         break;
625
626
627                 /* pop/dup/swap operations ********************************************/
628
629                 case ICMD_POP:        /* ..., value  ==> ...                          */
630
631                         gen_POP(cd);
632                         break;
633
634                 case ICMD_POP2:       /* ..., value, value  ==> ...                   */
635
636                         gen_POP2(cd);
637                         break;
638
639                 case ICMD_DUP:        /* ..., a ==> ..., a, a                         */
640
641                         gen_DUP(cd);
642                         break;
643
644                 case ICMD_DUP_X1:     /* ..., a, b ==> ..., b, a, b                   */
645
646                         gen_DUP_X1(cd);
647                         break;
648
649                 case ICMD_DUP_X2:     /* ..., a, b, c ==> ..., c, a, b, c             */
650
651                         gen_DUP_X2(cd);
652                         break;
653
654                 case ICMD_DUP2:       /* ..., a, b ==> ..., a, b, a, b                */
655
656                         gen_DUP2(cd);
657                         break;
658
659                 case ICMD_DUP2_X1:    /* ..., a, b, c ==> ..., b, c, a, b, c          */
660
661                         gen_DUP2_X1(cd);
662                         break;
663
664                 case ICMD_DUP2_X2:    /* ..., a, b, c, d ==> ..., c, d, a, b, c, d    */
665
666                         gen_DUP2_X2(cd);
667                         break;
668
669                 case ICMD_SWAP:       /* ..., a, b ==> ..., b, a                      */
670
671                         gen_SWAP(cd);
672                         break;
673
674
675                 /* integer operations *************************************************/
676
677                 case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
678
679                         gen_INEG(cd);
680                         break;
681
682                 case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
683
684                         gen_LNEG(cd);
685                         break;
686
687                 case ICMD_I2L:        /* ..., value  ==> ..., value                   */
688
689                         gen_I2L(cd);
690                         break;
691
692                 case ICMD_L2I:        /* ..., value  ==> ..., value                   */
693
694                         gen_L2I(cd);
695                         break;
696
697                 case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
698
699                         gen_INT2BYTE(cd);
700                         break;
701
702                 case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
703
704                         gen_INT2CHAR(cd);
705                         break;
706
707                 case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
708
709                         gen_INT2SHORT(cd);
710                         break;
711
712
713                 case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
714
715                         gen_IADD(cd);
716                         break;
717
718                 case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
719
720                         gen_LADD(cd);
721                         break;
722
723                 case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
724
725                         gen_ISUB(cd);
726                         break;
727
728                 case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
729
730                         gen_LSUB(cd);
731                         break;
732
733                 case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
734
735                         gen_IMUL(cd);
736                         break;
737
738                 case ICMD_LMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
739
740                         gen_LMUL(cd);
741                         break;
742
743                 case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
744
745                         gen_IDIV(cd);
746                         break;
747
748                 case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
749
750                         gen_IREM(cd);
751                         break;
752
753                 case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
754
755                         gen_LDIV(cd);
756                         break;
757
758                 case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
759
760                         gen_LREM(cd);
761                         break;
762
763                 case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
764                                       /* val.i = constant                             */
765                                       
766                         gen_IDIVPOW2(cd, iptr->sx.val.i);
767                         break;
768
769                 case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
770                                       /* val.i = constant                             */
771
772                         gen_IREMPOW2(cd, iptr->sx.val.i);
773                         break;
774
775                 case ICMD_LDIVPOW2:   /* ..., value  ==> ..., value << constant       */
776                                       /* val.i = constant                             */
777                                       
778                         gen_LDIVPOW2(cd, iptr->sx.val.i);
779                         break;
780
781                 case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant        */
782                                       /* val.l = constant                             */
783
784                         gen_LREMPOW2(cd, iptr->sx.val.i);
785                         break;
786
787                 case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
788
789                         gen_ISHL(cd);
790                         break;
791
792                 case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
793
794                         gen_ISHR(cd);
795                         break;
796
797                 case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
798
799                         gen_IUSHR(cd);
800                         break;
801
802                 case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
803
804                         gen_LSHL(cd);
805                         break;
806
807                 case ICMD_LSHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
808
809                         gen_LSHR(cd);
810                         break;
811
812                 case ICMD_LUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
813
814                         gen_LUSHR(cd);
815                         break;
816
817                 case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
818
819                         gen_IAND(cd);
820                         break;
821
822                 case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
823
824                         gen_LAND(cd);
825                         break;
826
827                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
828
829                         gen_IOR(cd);
830                         break;
831
832                 case ICMD_LOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
833
834                         gen_LOR(cd);
835                         break;
836
837                 case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
838
839                         gen_IXOR(cd);
840                         break;
841
842                 case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
843
844                         gen_LXOR(cd);
845                         break;
846
847
848                 case ICMD_LCMP:       /* ..., val1, val2  ==> ..., val1 cmp val2      */
849
850                         /* optimize LCMP .. IFxx (0) --> IF_LCMPxx */
851
852                         if (len >= 2 && iptr[1].sx.val.i == 0) {
853                                 switch (iptr[1].opc) {
854                                         case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LCMPEQ; break;
855                                         case ICMD_IFNE: iptr[0].opc = ICMD_IF_LCMPNE; break;
856                                         case ICMD_IFLT: iptr[0].opc = ICMD_IF_LCMPLT; break;
857                                         case ICMD_IFLE: iptr[0].opc = ICMD_IF_LCMPLE; break;
858                                         case ICMD_IFGT: iptr[0].opc = ICMD_IF_LCMPGT; break;
859                                         case ICMD_IFGE: iptr[0].opc = ICMD_IF_LCMPGE; break;
860                                         default:        goto dont_opt_IF_LCMPxx;
861                                 }
862                                 iptr[0].dst.insindex = iptr[1].dst.insindex;
863                                 iptr[1].opc = ICMD_NOP;
864                                 goto switch_again;
865                         }
866 dont_opt_IF_LCMPxx:
867
868                         gen_LCMP(cd);
869                         break;
870
871
872                 case ICMD_IINC:       /* ..., value  ==> ..., value + constant        */
873                                       /* op1 = variable, val.i = constant             */
874
875                         gen_IINC(cd, index2offset(iptr->s1.varindex), iptr->sx.val.i);
876                         break;
877
878
879                 /* floating operations ************************************************/
880
881                 case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
882
883                         gen_FNEG(cd);
884                         break;
885
886                 case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
887
888                         gen_DNEG(cd);
889                         break;
890
891                 case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
892
893                         gen_FADD(cd);
894                         break;
895
896                 case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
897
898                         gen_DADD(cd);
899                         break;
900
901                 case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
902
903                         gen_FSUB(cd);
904                         break;
905
906                 case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
907
908                         gen_DSUB(cd);
909                         break;
910
911                 case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
912
913                         gen_FMUL(cd);
914                         break;
915
916                 case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 *** val2      */
917
918                         gen_DMUL(cd);
919                         break;
920
921                 case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
922
923                         gen_FDIV(cd);
924                         break;
925
926                 case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
927
928                         gen_DDIV(cd);
929                         break;
930                 
931                 case ICMD_FREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
932
933                         gen_FREM(cd);
934                         break;
935
936                 case ICMD_DREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
937
938                         gen_DREM(cd);
939                         break;
940                 
941                 case ICMD_I2F:       /* ..., value  ==> ..., (float) value            */
942
943                         gen_I2F(cd);
944                         break;
945
946                 case ICMD_L2F:       /* ..., value  ==> ..., (float) value            */
947
948                         gen_L2F(cd);
949                         break;
950
951                 case ICMD_I2D:       /* ..., value  ==> ..., (double) value           */
952
953                         gen_I2D(cd);
954                         break;
955                         
956                 case ICMD_L2D:       /* ..., value  ==> ..., (double) value           */
957
958                         gen_L2D(cd);
959                         break;
960                         
961                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
962
963                         gen_F2I(cd);
964                         break;
965                 
966                 case ICMD_D2I:       /* ..., value  ==> ..., (int) value              */
967
968                         gen_D2I(cd);
969                         break;
970                 
971                 case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */
972
973                         gen_F2L(cd);
974                         break;
975
976                 case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */
977
978                         gen_D2L(cd);
979                         break;
980
981                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
982
983                         gen_F2D(cd);
984                         break;
985                                         
986                 case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */
987
988                         gen_D2F(cd);
989                         break;
990                 
991                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
992
993                         gen_FCMPL(cd);
994                         break;
995                         
996                 case ICMD_DCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
997
998                         gen_DCMPL(cd);
999                         break;
1000                         
1001                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1002
1003                         gen_FCMPG(cd);
1004                         break;
1005
1006                 case ICMD_DCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1007
1008                         gen_DCMPG(cd);
1009                         break;
1010
1011
1012                 /* memory operations **************************************************/
1013
1014                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
1015
1016                         gen_ARRAYLENGTH(cd);
1017                         break;
1018
1019                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
1020
1021                         gen_BALOAD(cd);
1022                         break;
1023
1024                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
1025
1026                         gen_CALOAD(cd);
1027                         break;                  
1028
1029                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
1030
1031                         gen_SALOAD(cd);
1032                         break;
1033
1034                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
1035
1036                         gen_IALOAD(cd);
1037                         break;
1038
1039                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
1040
1041                         gen_FALOAD(cd);
1042                         break;
1043
1044                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
1045                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
1046
1047                         gen_LALOAD(cd);
1048                         break;
1049
1050                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
1051
1052                         gen_AALOAD(cd);
1053                         break;
1054
1055
1056                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
1057
1058                         gen_BASTORE(cd);
1059                         break;
1060
1061                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
1062                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
1063
1064                         gen_CASTORE(cd);
1065                         break;
1066
1067                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
1068
1069                         gen_IASTORE(cd);
1070                         break;
1071
1072                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
1073
1074                         gen_FASTORE(cd);
1075                         break;
1076
1077                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
1078                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
1079
1080                         gen_LASTORE(cd);
1081                         break;
1082
1083                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
1084
1085                         gen_AASTORE(cd);
1086                         break;
1087
1088
1089                 case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
1090                                       /* op1 = type, val.a = field address            */
1091
1092                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1093                                 fi        = NULL;
1094                                 uf        = iptr->sx.s23.s3.uf;
1095                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1096                         }
1097                         else {
1098                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1099                                 uf        = NULL;
1100                                 fieldtype = fi->type;
1101                         }
1102
1103                         switch (fieldtype) {
1104                         case TYPE_INT:
1105                                 if (fi == NULL)
1106                                         gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
1107                                 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1108                                         gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
1109                                 else
1110                                         gen_GETSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1111                                 break;
1112                         case TYPE_FLT:
1113                                 if (fi == NULL)
1114                                         gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
1115                                 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1116                                         gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
1117                                 else
1118                                         gen_GETSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1119                                 break;
1120                         case TYPE_LNG:
1121                         case TYPE_DBL:
1122                                 if (fi == NULL)
1123                                         gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
1124                                 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1125                                         gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
1126                                 else
1127                                         gen_GETSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1128                                 break;
1129                         case TYPE_ADR:
1130                                 if (fi == NULL)
1131                                         gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
1132                                 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1133                                         gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
1134                                 else
1135                                         gen_GETSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1136                                 break;
1137                         }
1138                         break;
1139
1140                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
1141                                       /* op1 = type, val.a = field address            */
1142
1143                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1144                                 fi        = NULL;
1145                                 uf        = iptr->sx.s23.s3.uf;
1146                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1147                         }
1148                         else {
1149                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1150                                 uf        = NULL;
1151                                 fieldtype = fi->type;
1152                         }
1153
1154                         switch (fieldtype) {
1155                         case TYPE_INT:
1156                                 if (fi == NULL)
1157                                         gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
1158                                 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1159                                         gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
1160                                 else
1161                                         gen_PUTSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1162                                 break;
1163                         case TYPE_FLT:
1164                                 if (fi == NULL)
1165                                         gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
1166                                 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1167                                         gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
1168                                 else
1169                                         gen_PUTSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1170                                 break;
1171                         case TYPE_LNG:
1172                         case TYPE_DBL:
1173                                 if (fi == NULL)
1174                                         gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
1175                                 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1176                                         gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
1177                                 else
1178                                         gen_PUTSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1179                                 break;
1180                         case TYPE_ADR:
1181                                 if (fi == NULL)
1182                                         gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
1183                                 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1184                                         gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
1185                                 else
1186                                         gen_PUTSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1187                                 break;
1188                         }
1189                         break;
1190
1191
1192                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
1193                                       /* op1 = type, val.a = field address            */
1194
1195                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1196                                 fi        = NULL;
1197                                 uf        = iptr->sx.s23.s3.uf;
1198                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1199                         }
1200                         else {
1201                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1202                                 uf        = NULL;
1203                                 fieldtype = fi->type;
1204                         }
1205
1206                         switch (fieldtype) {
1207                         case TYPE_INT:
1208                                 if (fi == NULL)
1209                                         gen_PATCHER_GETFIELD_INT(cd, 0, uf);
1210                                 else
1211                                         gen_GETFIELD_INT(cd, fi->offset, fi);
1212                                 break;
1213                         case TYPE_FLT:
1214                                 if (fi == NULL)
1215                                         gen_PATCHER_GETFIELD_FLOAT(cd, 0, uf);
1216                                 else
1217                                         gen_GETFIELD_FLOAT(cd, fi->offset, fi);
1218                                 break;
1219                         case TYPE_LNG:
1220                         case TYPE_DBL:
1221                                 if (fi == NULL)
1222                                         gen_PATCHER_GETFIELD_LONG(cd, 0, uf);
1223                                 else
1224                                         gen_GETFIELD_LONG(cd, fi->offset, fi);
1225                                 break;
1226                         case TYPE_ADR:
1227                                 if (fi == NULL)
1228                                         gen_PATCHER_GETFIELD_CELL(cd, 0, uf);
1229                                 else
1230                                         gen_GETFIELD_CELL(cd, fi->offset, fi);
1231                                 break;
1232                         }
1233                         break;
1234
1235                 case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
1236                                       /* op1 = type, val.a = field address            */
1237
1238                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1239                                 fi        = NULL;
1240                                 uf        = iptr->sx.s23.s3.uf;
1241                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1242                         }
1243                         else {
1244                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1245                                 uf        = NULL;
1246                                 fieldtype = fi->type;
1247                         }
1248
1249                         switch (fieldtype) {
1250                         case TYPE_INT:
1251                                 if (fi == NULL)
1252                                         gen_PATCHER_PUTFIELD_INT(cd, 0, uf);
1253                                 else
1254                                         gen_PUTFIELD_INT(cd, fi->offset, fi);
1255                                 break;
1256                         case TYPE_FLT:
1257                                 if (fi == NULL)
1258                                         gen_PATCHER_PUTFIELD_FLOAT(cd, 0, uf);
1259                                 else
1260                                         gen_PUTFIELD_FLOAT(cd, fi->offset, fi);
1261                                 break;
1262                         case TYPE_LNG:
1263                         case TYPE_DBL:
1264                                 if (fi == NULL)
1265                                         gen_PATCHER_PUTFIELD_LONG(cd, 0, uf);
1266                                 else
1267                                         gen_PUTFIELD_LONG(cd, fi->offset, fi);
1268                                 break;
1269                         case TYPE_ADR:
1270                                 if (fi == NULL)
1271                                         gen_PATCHER_PUTFIELD_CELL(cd, 0, uf);
1272                                 else
1273                                         gen_PUTFIELD_CELL(cd, fi->offset, fi);
1274                                 break;
1275                         }
1276                         break;
1277
1278
1279                 /* branch operations **************************************************/
1280
1281                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
1282
1283                         gen_ATHROW(cd);
1284                         break;
1285
1286                 case ICMD_GOTO:         /* ... ==> ...                                */
1287                                         /* op1 = target JavaVM pc                     */
1288                         gen_branch(GOTO);
1289                         break;
1290
1291                 case ICMD_JSR:          /* ... ==> ...                                */
1292                                         /* op1 = target JavaVM pc                     */
1293
1294                         gen_JSR(cd, NULL);
1295                         codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex));
1296                         break;
1297
1298                 case ICMD_RET:          /* ... ==> ...                                */
1299                                         /* op1 = local variable                       */
1300
1301                         gen_RET(cd, index2offset(iptr->s1.varindex));
1302                         break;
1303
1304                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
1305                                         /* op1 = target JavaVM pc                     */
1306
1307                         gen_branch(IFNULL);
1308                         break;
1309
1310                 case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
1311                                         /* op1 = target JavaVM pc                     */
1312
1313                         gen_branch(IFNONNULL);
1314                         break;
1315
1316                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
1317                                         /* op1 = target JavaVM pc, val.i = constant   */
1318
1319                         if (iptr->sx.val.i == 0) {
1320                                 gen_branch(IFEQ);
1321                         } else {
1322                                 gen_ICONST(cd, iptr->sx.val.i);
1323                                 gen_branch(IF_ICMPEQ);
1324                         }
1325                         break;
1326
1327                 case ICMD_IFLT:         /* ..., value ==> ...                         */
1328                                         /* op1 = target JavaVM pc, val.i = constant   */
1329
1330                         if (iptr->sx.val.i == 0) {
1331                                 gen_branch(IFLT);
1332                         } else {
1333                                 gen_ICONST(cd, iptr->sx.val.i);
1334                                 gen_branch(IF_ICMPLT);
1335                         }
1336                         break;
1337
1338                 case ICMD_IFLE:         /* ..., value ==> ...                         */
1339                                         /* op1 = target JavaVM pc, val.i = constant   */
1340
1341                         if (iptr->sx.val.i == 0) {
1342                                 gen_branch(IFLE);
1343                         } else {
1344                                 gen_ICONST(cd, iptr->sx.val.i);
1345                                 gen_branch(IF_ICMPLE);
1346                         }
1347                         break;
1348
1349                 case ICMD_IFNE:         /* ..., value ==> ...                         */
1350                                         /* op1 = target JavaVM pc, val.i = constant   */
1351
1352                         if (iptr->sx.val.i == 0) {
1353                                 gen_branch(IFNE);
1354                         } else {
1355                                 gen_ICONST(cd, iptr->sx.val.i);
1356                                 gen_branch(IF_ICMPNE);
1357                         }
1358                         break;
1359
1360                 case ICMD_IFGT:         /* ..., value ==> ...                         */
1361                                         /* op1 = target JavaVM pc, val.i = constant   */
1362
1363                         if (iptr->sx.val.i == 0) {
1364                                 gen_branch(IFGT);
1365                         } else {
1366                                 gen_ICONST(cd, iptr->sx.val.i);
1367                                 gen_branch(IF_ICMPGT);
1368                         }
1369                         break;
1370
1371                 case ICMD_IFGE:         /* ..., value ==> ...                         */
1372                                         /* op1 = target JavaVM pc, val.i = constant   */
1373
1374                         if (iptr->sx.val.i == 0) {
1375                                 gen_branch(IFGE);
1376                         } else {
1377                                 gen_ICONST(cd, iptr->sx.val.i);
1378                                 gen_branch(IF_ICMPGE);
1379                         }
1380                         break;
1381
1382
1383                 case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
1384                                         /* op1 = target JavaVM pc, val.l = constant   */
1385
1386                         gen_LCONST(cd, iptr->sx.val.l);
1387                         gen_branch(IF_LCMPEQ);
1388                         break;
1389
1390                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
1391                                         /* op1 = target JavaVM pc, val.l = constant   */
1392
1393                         gen_LCONST(cd, iptr->sx.val.l);
1394                         gen_branch(IF_LCMPLT);
1395                         break;
1396
1397                 case ICMD_IF_LLE:       /* ..., value ==> ...                         */
1398                                         /* op1 = target JavaVM pc, val.l = constant   */
1399
1400                         gen_LCONST(cd, iptr->sx.val.l);
1401                         gen_branch(IF_LCMPLE);
1402                         break;
1403
1404                 case ICMD_IF_LNE:       /* ..., value ==> ...                         */
1405                                         /* op1 = target JavaVM pc, val.l = constant   */
1406
1407                         gen_LCONST(cd, iptr->sx.val.l);
1408                         gen_branch(IF_LCMPNE);
1409                         break;
1410
1411                 case ICMD_IF_LGT:       /* ..., value ==> ...                         */
1412                                         /* op1 = target JavaVM pc, val.l = constant   */
1413
1414                         gen_LCONST(cd, iptr->sx.val.l);
1415                         gen_branch(IF_LCMPGT);
1416                         break;
1417
1418                 case ICMD_IF_LGE:       /* ..., value ==> ...                         */
1419                                         /* op1 = target JavaVM pc, val.l = constant   */
1420
1421                         gen_LCONST(cd, iptr->sx.val.l);
1422                         gen_branch(IF_LCMPGE);
1423                         break;
1424
1425                 case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
1426                                         /* op1 = target JavaVM pc                     */
1427
1428                         gen_branch(IF_LCMPEQ);
1429                         break;
1430
1431                 case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
1432                                         /* op1 = target JavaVM pc                     */
1433
1434                         gen_branch(IF_LCMPNE);
1435                         break;
1436
1437                 case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
1438                                         /* op1 = target JavaVM pc                     */
1439
1440                         gen_branch(IF_LCMPLT);
1441                         break;
1442
1443                 case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
1444                                         /* op1 = target JavaVM pc                     */
1445
1446                         gen_branch(IF_LCMPGT);
1447                         break;
1448
1449                 case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
1450                                         /* op1 = target JavaVM pc                     */
1451
1452                         gen_branch(IF_LCMPLE);
1453                         break;
1454
1455                 case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
1456                                         /* op1 = target JavaVM pc                     */
1457
1458                         gen_branch(IF_LCMPGE);
1459                         break;
1460
1461
1462                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
1463                                         /* op1 = target JavaVM pc                     */
1464
1465                         gen_branch(IF_ICMPEQ);
1466                         break;
1467
1468                 case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
1469                                         /* op1 = target JavaVM pc                     */
1470
1471                         gen_branch(IF_ACMPEQ);
1472                         break;
1473
1474                 case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
1475                                         /* op1 = target JavaVM pc                     */
1476
1477                         gen_branch(IF_ICMPNE);
1478                         break;
1479
1480                 case ICMD_IF_ACMPNE:    /* ..., value, value ==> ...                  */
1481                                         /* op1 = target JavaVM pc                     */
1482
1483                         gen_branch(IF_ACMPNE);
1484                         break;
1485
1486                 case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
1487                                         /* op1 = target JavaVM pc                     */
1488
1489                         gen_branch(IF_ICMPLT);
1490                         break;
1491
1492                 case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
1493                                         /* op1 = target JavaVM pc                     */
1494
1495                         gen_branch(IF_ICMPGT);
1496                         break;
1497
1498                 case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
1499                                         /* op1 = target JavaVM pc                     */
1500
1501                         gen_branch(IF_ICMPLE);
1502                         break;
1503
1504                 case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
1505                                         /* op1 = target JavaVM pc                     */
1506
1507                         gen_branch(IF_ICMPGE);
1508                         break;
1509
1510
1511                 case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
1512                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
1513                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
1514
1515 #if defined(ENABLE_THREADS)
1516                         if (checksync && code_is_synchronized(code)) {
1517                                 if (m->flags & ACC_STATIC) {
1518                                         gen_ACONST(cd, (java_objectheader *) m->clazz);
1519                                 } else {
1520                                         gen_ALOAD(cd, index2offset(m->maxlocals));
1521                                 }
1522                                 gen_MONITOREXIT(cd);
1523                         }
1524 #endif
1525                         if (opt_verbosecall)
1526                                 gen_TRACERETURN(cd, m);
1527
1528                         gen_IRETURN(cd, index2offset(cd->stackframesize));
1529                         break;
1530
1531                 case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
1532                 case ICMD_DRETURN:      /* ..., retvalue ==> ...                      */
1533
1534 #if defined(ENABLE_THREADS)
1535                         if (checksync && code_is_synchronized(code)) {
1536                                 if (m->flags & ACC_STATIC) {
1537                                         gen_ACONST(cd, (java_objectheader *) m->clazz);
1538                                 } else {
1539                                         gen_ALOAD(cd, index2offset(m->maxlocals));
1540                                 }
1541                                 gen_MONITOREXIT(cd);
1542                         }
1543 #endif
1544                         if (opt_verbosecall)
1545                                 gen_TRACELRETURN(cd, m);
1546
1547                         gen_LRETURN(cd, index2offset(cd->stackframesize));
1548                         break;
1549
1550                 case ICMD_RETURN:       /* ...  ==> ...                               */
1551
1552 #if defined(ENABLE_THREADS)
1553                         if (checksync && code_is_synchronized(code)) {
1554                                 if (m->flags & ACC_STATIC) {
1555                                         gen_ACONST(cd, (java_objectheader *) m->clazz);
1556                                 } else {
1557                                         gen_ALOAD(cd, index2offset(m->maxlocals));
1558                                 }
1559                                 gen_MONITOREXIT(cd);
1560                         }
1561 #endif
1562                         if (opt_verbosecall)
1563                                 gen_TRACERETURN(cd, m);
1564
1565                         gen_RETURN(cd, index2offset(cd->stackframesize));
1566                         break;
1567
1568
1569                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
1570                         {
1571                         s4 i, l;
1572                         branch_target_t *table;
1573
1574                         table = iptr->dst.table;
1575
1576                         l = iptr->sx.s23.s2.tablelow;
1577                         i = iptr->sx.s23.s3.tablehigh;
1578                         
1579                         i = i - l + 1;
1580
1581                         /* arguments: low, range, datasegment address, table
1582                        offset in datasegment, default target */
1583
1584                         gen_TABLESWITCH(cd, l, i, NULL, 0, NULL);
1585
1586                         /* actually -3 cells offset */
1587
1588                         cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1589                         dseg_adddata(cd);
1590                         cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1591
1592                         codegen_addreference(cd, BLOCK_OF(table[0].insindex));
1593
1594                         /* build jump table top down and use address of lowest entry */
1595
1596                         table += i;
1597
1598                         while (--i >= 0) {
1599                                 dseg_add_target(cd, BLOCK_OF(table->insindex)); 
1600                                 --table;
1601                         }
1602                         }
1603
1604                         /* length of dataseg after last dseg_add_target is used by load */
1605                         ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1606                         break;
1607
1608
1609                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
1610                         {
1611                         s4 i;
1612                         lookup_target_t *lookup;
1613
1614                         lookup = iptr->dst.lookup;
1615
1616                         i = iptr->sx.s23.s2.lookupcount;
1617                         
1618                         /* arguments: count, datasegment address, table offset in         */
1619                         /* datasegment, default target                                    */
1620                         gen_LOOKUPSWITCH(cd, i, NULL, 0, NULL);
1621
1622                         /* actually -3 cells offset */
1623
1624                         cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1625                         dseg_adddata(cd);
1626                         cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1627
1628                         /* build jump table top down and use address of lowest entry */
1629
1630                         while (--i >= 0) {
1631                                 dseg_add_target(cd, BLOCK_OF(lookup->target.insindex)); 
1632                                 dseg_add_unique_address(cd, lookup->value);
1633                                 lookup++;
1634                         }
1635
1636                         codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex));
1637                         }
1638
1639                         /* length of dataseg after last dseg_add_target is used by load */
1640                         ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1641                         break;
1642
1643
1644                 case ICMD_BUILTIN:      /* ..., arg1, arg2, arg3 ==> ...              */
1645                                         /* op1 = arg count val.a = builtintable entry */
1646                         bte = iptr->sx.s23.s3.bte;
1647
1648                         for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
1649                                 builtin_gen *bg = &builtin_gen_table[i];
1650                                 if (bg->builtin == bte->fp) {
1651                                         (bg->gen)(cd);
1652                                         goto gen_builtin_end;
1653                                 }
1654                         }
1655
1656                         vm_abort(0);
1657
1658                 gen_builtin_end:
1659                         break;
1660
1661                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
1662                                         /* op1 = arg count, val.a = method pointer    */
1663
1664                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1665                                 um = iptr->sx.s23.s3.um;
1666                                 md = um->methodref->parseddesc.md;
1667                                 gen_PATCHER_INVOKESTATIC(cd, 0, md->paramslots, um);
1668                         }
1669                         else {
1670                                 lm = iptr->sx.s23.s3.fmiref->p.method;
1671                                 md = lm->parseddesc;
1672                                 gen_INVOKESTATIC(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1673                         }
1674                         break;
1675
1676                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1677
1678                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1679                                 um = iptr->sx.s23.s3.um;
1680                                 md = um->methodref->parseddesc.md;
1681                                 gen_PATCHER_INVOKESPECIAL(cd, 0, md->paramslots, um);
1682                         }
1683                         else {
1684                                 lm = iptr->sx.s23.s3.fmiref->p.method;
1685                                 md = lm->parseddesc;
1686                                 gen_INVOKESPECIAL(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1687                         }
1688                         break;
1689
1690                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
1691
1692                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1693                                 um = iptr->sx.s23.s3.um;
1694                                 md = um->methodref->parseddesc.md;
1695                                 gen_PATCHER_INVOKEVIRTUAL(cd, 0, md->paramslots, um);
1696                         }
1697                         else {
1698                                 lm = iptr->sx.s23.s3.fmiref->p.method;
1699                                 md = lm->parseddesc;
1700
1701                                 s1 = OFFSET(vftbl_t, table[0]) +
1702                                         sizeof(methodptr) * lm->vftblindex;
1703
1704                                 gen_INVOKEVIRTUAL(cd, s1, md->paramslots, lm);
1705                         }
1706                         break;
1707
1708                 case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer  */
1709
1710                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1711                                 um = iptr->sx.s23.s3.um;
1712                                 md = um->methodref->parseddesc.md;
1713                                 gen_PATCHER_INVOKEINTERFACE(cd, 0, 0, md->paramslots, um);
1714                         }
1715                         else {
1716                                 lm = iptr->sx.s23.s3.fmiref->p.method;
1717                                 md = lm->parseddesc;
1718
1719                                 s1 = OFFSET(vftbl_t, interfacetable[0]) -
1720                                         sizeof(methodptr*) * lm->clazz->index;
1721
1722                                 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
1723
1724                                 gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
1725                         }
1726                         break;
1727
1728
1729                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
1730                                       /* op1:   0 == array, 1 == class                */
1731                                       /* val.a: (classinfo *) superclass              */
1732
1733                         if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1734                                 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1735                                         gen_PATCHER_CHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1736                                 else
1737                                         gen_CHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1738                         }
1739                         else {
1740                                 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1741                                         gen_PATCHER_ARRAYCHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1742                                 else
1743                                         gen_ARRAYCHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1744                         }
1745                         break;
1746
1747                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
1748                                       /* op1:   0 == array, 1 == class                */
1749                                       /* val.a: (classinfo *) superclass              */
1750
1751                         if (INSTRUCTION_IS_UNRESOLVED(iptr))
1752                                 gen_PATCHER_INSTANCEOF(cd, NULL, iptr->sx.s23.s3.c.ref);
1753                         else
1754                                 gen_INSTANCEOF(cd, iptr->sx.s23.s3.c.cls, iptr->sx.s23.s3.c.ref);
1755                         break;
1756
1757                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
1758                                       /* op1 = dimension, val.a = class               */
1759
1760                         if (INSTRUCTION_IS_UNRESOLVED(iptr))
1761                                 gen_PATCHER_MULTIANEWARRAY(cd, NULL, iptr->s1.argcount, iptr->sx.s23.s3.c.ref);
1762                         else
1763                                 gen_MULTIANEWARRAY(cd, iptr->sx.s23.s3.c.cls, iptr->s1.argcount, NULL);
1764                         break;
1765
1766                 default:
1767                         exceptions_throw_internalerror("Unknown ICMD %d during code generation",
1768                                                                                    iptr->opc);
1769                         return false;
1770         } /* switch */
1771                 
1772         } /* for instruction */
1773
1774         gen_BBEND;
1775
1776         } /* if (bptr->flags != BBDELETED) */
1777         } /* for basic block */
1778
1779         dseg_createlinenumbertable(cd);
1780
1781         codegen_finish(jd);
1782
1783 #ifdef VM_PROFILING
1784         vm_block_insert(jd->code->mcode + jd->code->mcodelength);
1785 #endif
1786
1787         /* branch resolving (walk through all basic blocks) */
1788
1789         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
1790                 branchref *brefs;
1791
1792                 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
1793                         gen_resolveanybranch(((u1*) jd->code->entrypoint) + brefs->branchpos,
1794                                              ((u1 *)jd->code->entrypoint) + bptr->mpc);
1795                 }
1796         }
1797
1798         /* everything's ok */
1799
1800         return true;
1801 }
1802
1803
1804 /* createcompilerstub **********************************************************
1805
1806    Creates a stub routine which calls the compiler.
1807
1808    A stub consists of:
1809
1810    +-------------+
1811    | codeinfo *  |
1812    +-------------+ <-- stub
1813    | codeptr     |
1814    +-------------+
1815    | framesize   |  (in ptrint units, does not include return address)
1816    +-------------+
1817    | TRANSLATE   |
1818    +-------------+
1819    | methodinfo  |
1820    +-------------+
1821
1822    codeptr points either to TRANSLATE or to the translated threaded code
1823
1824    all methods are called indirectly through methodptr
1825
1826 *******************************************************************************/
1827
1828 #define COMPILERSTUB_DATASIZE    2
1829 #define COMPILERSTUB_CODESIZE    4
1830
1831 #define COMPILERSTUB_SIZE        COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
1832
1833
1834 u1 *intrp_createcompilerstub(methodinfo *m)
1835 {
1836         Inst        *s;
1837         Inst        *d;
1838         codegendata *cd;
1839         s4           stackframesize;
1840         int32_t      dumpmarker;
1841
1842         s = CNEW(Inst, COMPILERSTUB_SIZE);
1843
1844         /* set data pointer and code pointer */
1845
1846         d = s;
1847         s = s + COMPILERSTUB_DATASIZE;
1848
1849         /* The codeinfo pointer is actually a pointer to the
1850            methodinfo. This fakes a codeinfo structure. */
1851
1852         d[0] = (Inst *) m;
1853         d[1] = (Inst *) &d[0];                                    /* fake code->m */
1854
1855         /* mark start of dump memory area */
1856
1857         DMARKER;
1858         
1859         cd = DNEW(codegendata);
1860     cd->mcodeptr = (u1 *) s;
1861         cd->lastinstwithoutdispatch = ~0;
1862         cd->superstarts = NULL;
1863
1864         genarg_ainst(cd, s + 2);
1865
1866         if (m->flags & ACC_NATIVE) {
1867                 stackframesize = m->parseddesc->paramslots;
1868         } 
1869         else {
1870                 stackframesize = m->maxlocals;
1871
1872 #if defined(ENABLE_THREADS)
1873                 if (checksync && code_is_synchronized(code))
1874                         stackframesize += 1;
1875 #endif
1876         }
1877
1878         genarg_i(cd, stackframesize);
1879
1880         gen_BBSTART;
1881         gen_TRANSLATE(cd, m);
1882         gen_BBEND;
1883         
1884 #ifdef VM_PROFILING
1885         vm_block_insert(cd->mcodeptr);
1886 #endif
1887
1888 #if defined(ENABLE_STATISTICS)
1889         if (opt_stat)
1890                 count_cstub_len += COMPILERSTUB_SIZE;
1891 #endif
1892
1893         /* release dump area */
1894
1895         DRELEASE;
1896         
1897         return (u1 *) s;
1898 }
1899
1900
1901 #if defined(WITH_FFI)
1902 static ffi_type *cacaotype2ffitype(s4 cacaotype)
1903 {
1904         switch (cacaotype) {
1905         case TYPE_INT:
1906 #if SIZEOF_VOID_P == 8
1907                 return &ffi_type_sint64;
1908 #else
1909                 return &ffi_type_sint32;
1910 #endif
1911         case TYPE_LNG:
1912                 return &ffi_type_sint64;
1913         case TYPE_FLT:
1914                 return &ffi_type_float;
1915         case TYPE_DBL:
1916                 return &ffi_type_double;
1917         case TYPE_ADR:
1918                 return &ffi_type_pointer;
1919         case TYPE_VOID:
1920                 return &ffi_type_void;
1921         default:
1922                 assert(false);
1923         }
1924 }
1925 #endif
1926
1927
1928 /* native stub:
1929 +---------+
1930 |NATIVECALL|
1931 +---------+
1932 |methodinf|
1933 +---------+
1934 |function |
1935 +---------+
1936 |cif      |
1937 +---------+
1938 */
1939
1940 #if defined(WITH_FFI)
1941 static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
1942 {
1943         methoddesc  *md = m->parseddesc; 
1944         ffi_cif     *pcif = NEW(ffi_cif);
1945         ffi_type   **types = MNEW(ffi_type *, nmd->paramcount);
1946         ffi_type   **ptypes = types;
1947         s4           i;
1948
1949         /* pass env pointer */
1950
1951         *ptypes++ = &ffi_type_pointer;
1952
1953         /* for static methods, pass class pointer */
1954
1955         if (m->flags & ACC_STATIC)
1956                 *ptypes++ = &ffi_type_pointer;
1957
1958         /* pass parameter to native function */
1959
1960         for (i = 0; i < md->paramcount; i++)
1961                 *ptypes++ = cacaotype2ffitype(md->paramtypes[i].type);
1962
1963         assert(ptypes - types == nmd->paramcount);
1964
1965     if (ffi_prep_cif(pcif, FFI_DEFAULT_ABI, nmd->paramcount, cacaotype2ffitype(md->returntype.type), types) != FFI_OK)
1966                 assert(0);
1967
1968         return pcif;
1969 }
1970 #endif
1971
1972
1973 u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
1974 {
1975         methodinfo   *m;
1976         codeinfo     *code;
1977         codegendata  *cd;
1978         registerdata *rd;
1979 #if defined(WITH_FFI)
1980         ffi_cif *cif;
1981 #else
1982         u1      *cif;
1983 #endif
1984         s4            stackframesize;
1985
1986         /* get required compiler data */
1987
1988         m    = jd->m;
1989         code = jd->code;
1990         cd   = jd->cd;
1991         rd   = jd->rd;
1992
1993         /* determine stackframe size (in units of ptrint) */
1994
1995         stackframesize = nmd->paramslots;
1996
1997         /* create method header */
1998
1999         (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
2000         (void) dseg_add_unique_s4(cd, stackframesize * SIZEOF_VOID_P); /*FrameSize*/
2001         (void) dseg_add_unique_s4(cd, 0);                       /* IsSync         */
2002         (void) dseg_add_unique_s4(cd, 0);                       /* IsLeaf         */
2003         (void) dseg_add_unique_s4(cd, 0);                       /* IntSave        */
2004         (void) dseg_add_unique_s4(cd, 0);                       /* FltSave        */
2005         dseg_addlinenumbertablesize(cd);
2006         (void) dseg_add_unique_s4(cd, 0);                       /* ExTableSize    */
2007
2008 #if defined(WITH_FFI)
2009         /* prepare ffi cif structure */
2010
2011         cif = createnativecif(m, nmd);
2012 #else
2013         cif = NULL;
2014 #endif
2015
2016         gen_BBSTART;
2017
2018         if (opt_verbosecall)
2019                 gen_TRACECALL(cd, m);
2020
2021         if (f == NULL) {
2022                 gen_PATCHER_NATIVECALL(cd, m, f, (u1 *)cif);
2023         } else {
2024                 if (opt_verbosecall)
2025                         gen_TRACENATIVECALL(cd, m, f, (u1 *)cif);
2026                 else
2027                         gen_NATIVECALL(cd, m, f, (u1 *)cif);
2028         }
2029
2030         gen_BBEND;
2031
2032         codegen_finish(jd);
2033
2034 #ifdef VM_PROFILING
2035         vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2036 #endif
2037
2038         return jd->code->entrypoint;
2039 }
2040
2041
2042 /* call jni function */
2043 Cell *nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
2044 {
2045 #if defined(WITH_FFCALL)
2046         av_alist alist;
2047         methoddesc *md;
2048         Cell *p;
2049         Cell *endsp;
2050         s4 i;
2051
2052         struct {
2053                 stackframeinfo sfi;
2054                 localref_table lrt;
2055         } s;
2056
2057         md = m->parseddesc;
2058
2059         switch (md->returntype.type) {
2060         case TYPE_INT:
2061                 endsp = sp - 1 + md->paramslots;
2062                 av_start_long(alist, f, endsp);
2063                 break;
2064         case TYPE_LNG:
2065                 endsp = sp - 2 + md->paramslots;
2066                 av_start_longlong(alist, f, endsp);
2067                 break;
2068         case TYPE_FLT:
2069                 endsp = sp - 1 + md->paramslots;
2070                 av_start_float(alist, f, endsp);
2071                 break;
2072         case TYPE_DBL:
2073                 endsp = sp - 2 + md->paramslots;
2074                 av_start_double(alist, f, endsp);
2075                 break;
2076         case TYPE_ADR:
2077                 endsp = sp - 1 + md->paramslots;
2078                 av_start_ptr(alist, f, void *, endsp);
2079                 break;
2080         case TYPE_VOID:
2081                 endsp = sp + md->paramslots;
2082                 av_start_void(alist, f);
2083                 break;
2084         default:
2085                 assert(false);
2086         }
2087
2088         av_ptr(alist, _Jv_JNIEnv *, _Jv_env);
2089
2090         if (m->flags & ACC_STATIC)
2091                 av_ptr(alist, classinfo *, m->clazz);
2092
2093         for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2094                 switch (md->paramtypes[i].type) {
2095                 case TYPE_INT:
2096                         p -= 1;
2097                         av_long(alist, *p);
2098                         break;
2099                 case TYPE_LNG:
2100                         p -= 2;
2101                         av_longlong(alist, *(s8 *)p);
2102                         break;
2103                 case TYPE_FLT:
2104                         p -= 1;
2105                         av_float(alist, *((float *) p));
2106                         break;
2107                 case TYPE_DBL:
2108                         p -= 2;
2109                         av_double(alist, *(double *) p);
2110                         break;
2111                 case TYPE_ADR:
2112                         p -= 1;
2113                         av_ptr(alist, void *, *(void **) p);
2114                         break;
2115                 default:
2116                         assert(false);
2117                 }
2118         }
2119
2120         global_sp = sp;
2121
2122         /* create stackframe info structure */
2123
2124         codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2125                                                           (u1 *) fp, (u1 *) ra);
2126
2127         av_call(alist);
2128
2129         *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2130
2131         CLEAR_global_sp;
2132
2133         return endsp;
2134 #elif defined(WITH_FFI)
2135         methoddesc  *md = m->parseddesc; 
2136         ffi_cif     *pcif;
2137         void        *values[md->paramcount + 2];
2138         void       **pvalues = values;
2139         Cell        *p;
2140         Cell        *endsp;
2141         s4           i;
2142         _Jv_JNIEnv  *penv;
2143
2144         struct {
2145                 stackframeinfo sfi;
2146                 localref_table lrt;
2147         } s;
2148
2149         pcif = (ffi_cif *) addrcif;
2150
2151         /* pass env pointer */
2152
2153         penv = (_Jv_JNIEnv *) _Jv_env;
2154         *pvalues++ = &penv;
2155
2156         /* for static methods, pass class pointer */
2157
2158         if (m->flags & ACC_STATIC)
2159                 *pvalues++ = &m->clazz;
2160
2161         /* pass parameter to native function */
2162
2163         for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2164                 if (IS_2_WORD_TYPE(md->paramtypes[i].type))
2165                         p -= 2;
2166                 else
2167                         p--;
2168
2169                 *pvalues++ = p;
2170         }
2171
2172         /* calculate position of return value */
2173
2174         if (md->returntype.type == TYPE_VOID)
2175                 endsp = sp + md->paramslots;
2176         else
2177                 endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;
2178
2179         global_sp = sp;
2180
2181         /* create stackframe info structure */
2182
2183         codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2184                                                           (u1 *) fp, (u1 *) ra);
2185
2186         ffi_call(pcif, FFI_FN(f), endsp, values);
2187
2188         *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2189
2190         CLEAR_global_sp;
2191
2192         return endsp;
2193 #endif
2194 }
2195
2196
2197 u1 *createcalljavafunction(methodinfo *m)
2198 {
2199         methodinfo         *tmpm;
2200         u1                 *entrypoint;
2201         jitdata            *jd;
2202         codegendata        *cd;
2203         registerdata       *rd;
2204         methoddesc         *md;
2205         int32_t             dumpmarker;
2206
2207         /* mark dump memory */
2208
2209         DMARKER;
2210
2211         /* allocate memory */
2212
2213         jd = DNEW(jitdata);
2214
2215         tmpm = DNEW(methodinfo);
2216         cd = DNEW(codegendata);
2217         rd = DNEW(registerdata);
2218
2219         jd->m = tmpm;
2220         jd->flags = 0;
2221         jd->cd = cd;
2222         jd->rd = rd;
2223
2224         /* Allocate codeinfo memory from the heap as we need to keep them. */
2225
2226         jd->code = code_codeinfo_new(tmpm); /* XXX check allocation */
2227
2228         /* setup code generation stuff */
2229
2230         MSET(tmpm, 0, u1, sizeof(methodinfo));
2231
2232         codegen_setup(jd);
2233
2234         md = m->parseddesc;
2235
2236         /* create method header */
2237
2238         (void) dseg_add_unique_address(cd, NULL);              /* CodeinfoPointer */
2239         (void) dseg_add_unique_s4(cd, md->paramslots * SIZEOF_VOID_P);/* FrameSize*/
2240         (void) dseg_add_unique_s4(cd, 0);                       /* IsSync         */
2241         (void) dseg_add_unique_s4(cd, 0);                       /* IsLeaf         */
2242         (void) dseg_add_unique_s4(cd, 0);                       /* IntSave        */
2243         (void) dseg_add_unique_s4(cd, 0);                       /* FltSave        */
2244         dseg_addlinenumbertablesize(cd);
2245         (void) dseg_add_unique_s4(cd, 0);                       /* ExTableSize    */
2246
2247
2248         /* generate code */
2249         
2250         gen_BBSTART;
2251         gen_INVOKESTATIC(cd, (Inst **)m->stubroutine, md->paramslots, 0);
2252         gen_END(cd);
2253
2254         gen_BBEND;
2255
2256         codegen_finish(jd);
2257
2258 #ifdef VM_PROFILING
2259         vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2260 #endif
2261         entrypoint = jd->code->entrypoint;
2262
2263         /* release memory */
2264
2265         DRELEASE;
2266
2267         return entrypoint;
2268 }
2269
2270
2271 /*
2272  * These are local overrides for various environment variables in Emacs.
2273  * Please do not remove this and leave it at the end of the file, where
2274  * Emacs will automagically detect them.
2275  * ---------------------------------------------------------------------
2276  * Local variables:
2277  * mode: c
2278  * indent-tabs-mode: t
2279  * c-basic-offset: 4
2280  * tab-width: 4
2281  * End:
2282  * vim:noexpandtab:sw=4:ts=4:
2283  */