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