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