2 new icmds, new exception table ordering for inlining, exception handler fix for...
[cacao.git] / src / vm / jit / i386 / codegen.c
1 /* jit/i386/codegen.c - machine code generator for i386
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    Institut f. Computersprachen, TU Wien
5    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6    S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
7    J. Wenninger
8
9    This file is part of CACAO.
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2, or (at
14    your option) any later version.
15
16    This program is distributed in the hope that it will be useful, but
17    WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24    02111-1307, USA.
25
26    Contact: cacao@complang.tuwien.ac.at
27
28    Authors: Andreas Krall
29             Christian Thalinger
30
31    $Id: codegen.c 1506 2004-11-14 14:48:49Z jowenn $
32
33 */
34
35 #define _GNU_SOURCE
36
37 #include "config.h"
38 #include "global.h"
39 #include <stdio.h>
40 #include <signal.h>
41 #include <sys/ucontext.h>
42 #include "types.h"
43 #include "main.h"
44 #include "builtin.h"
45 #include "asmpart.h"
46 #include "exceptions.h"
47 #include "jni.h"
48 #include "loader.h"
49 #include "tables.h"
50 #include "native.h"
51 #include "jit/jit.h"
52 #include "jit/parse.h"
53 #include "jit/reg.h"
54 #include "jit/i386/codegen.h"
55 #include "jit/i386/emitfuncs.h"
56
57
58 /* register descripton - array ************************************************/
59
60 /* #define REG_RES   0         reserved register for OS or code generator     */
61 /* #define REG_RET   1         return value register                          */
62 /* #define REG_EXC   2         exception value register (only old jit)        */
63 /* #define REG_SAV   3         (callee) saved register                        */
64 /* #define REG_TMP   4         scratch temporary register (caller saved)      */
65 /* #define REG_ARG   5         argument register (caller saved)               */
66
67 /* #define REG_END   -1        last entry in tables */
68
69 int nregdescint[] = {
70     REG_RET, REG_RES, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV,
71     REG_END
72 };
73
74
75 int nregdescfloat[] = {
76   /* rounding problems with callee saved registers */
77 /*      REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_RES, REG_RES, */
78 /*      REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, */
79     REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
80     REG_END
81 };
82
83
84 /*******************************************************************************
85
86     include independent code generation stuff -- include after register
87     descriptions to avoid extern definitions
88
89 *******************************************************************************/
90
91 #include "jit/codegen.inc"
92 #include "jit/reg.inc"
93
94
95 void codegen_stubcalled() {
96         log_text("Stub has been called");
97 }
98
99 void codegen_general_stubcalled() {
100         log_text("general exception stub  has been called");
101 }
102
103
104 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
105 void thread_restartcriticalsection(ucontext_t *uc)
106 {
107         void *critical;
108         if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL)
109                 uc->uc_mcontext.gregs[REG_EIP] = (u4) critical;
110 }
111 #endif
112
113
114 #define PREPARE_NATIVE_STACKINFO \
115     i386_push_reg(cd, REG_ITMP1);       /*save itmp1, needed by some stubs */ \
116     i386_alu_imm_reg(cd, I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \
117     i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1); \
118     i386_call_reg(cd, REG_ITMP1);                /*call    codegen_stubcalled*/ \
119     i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \
120     i386_call_reg(cd, REG_ITMP1);                /*call    builtin_asm_get_stackframeinfo*/ \
121     i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer  to native call stack*/ \
122     i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \
123     i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4);     /* store value on stack */ \
124     i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \
125     i386_mov_membase_reg(cd, REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \
126     i386_mov_imm_membase(cd, 0,REG_SP, 2*4);    /* builtin */ 
127
128
129 #define REMOVE_NATIVE_STACKINFO \
130     i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2); \
131     i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3); \
132     i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0); \
133     i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
134
135
136 /* NullPointerException signal handler for hardware null pointer check */
137
138 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
139 {
140         sigset_t nsig;
141 /*      long     faultaddr; */
142
143     struct ucontext *_uc = (struct ucontext *) _p;
144     struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
145         struct sigaction act;
146
147         /* Reset signal handler - necessary for SysV, does no harm for BSD */
148
149 /*      instr = *((int*)(sigctx->eip)); */
150 /*      faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f]; */
151
152 /*      fprintf(stderr, "null=%d %p addr=%p\n", sig, sigctx, sigctx->eip);*/
153
154 /*      if (faultaddr == 0) { */
155 /*              signal(sig, (void *) catch_NullPointerException); */
156         act.sa_sigaction = (void *) catch_NullPointerException;
157         act.sa_flags = SA_SIGINFO;
158         sigaction(sig, &act, NULL);                          /* reinstall handler */
159
160                 sigemptyset(&nsig);
161                 sigaddset(&nsig, sig);
162                 sigprocmask(SIG_UNBLOCK, &nsig, NULL);           /* unblock signal    */
163
164                 sigctx->ecx = sigctx->eip;                       /* REG_ITMP2_XPC     */
165                 sigctx->eax = (u4) string_java_lang_NullPointerException;
166                 sigctx->eip = (u4) asm_throw_and_handle_exception;
167                 
168                 return;
169
170 /*      } else { */
171 /*              faultaddr += (long) ((instr << 16) >> 16); */
172 /*              fprintf(stderr, "faulting address: 0x%08x\n", faultaddr); */
173 /*              panic("Stack overflow"); */
174 /*      } */
175 }
176
177
178 /* ArithmeticException signal handler for hardware divide by zero check       */
179
180 void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p)
181 {
182         sigset_t nsig;
183
184 /*      void **_p = (void **) &sig; */
185 /*      struct sigcontext *sigctx = (struct sigcontext *) ++_p; */
186     struct ucontext *_uc = (struct ucontext *) _p;
187     struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
188         struct sigaction act;
189
190         /* Reset signal handler - necessary for SysV, does no harm for BSD        */
191
192 /*      signal(sig, (void *) catch_ArithmeticException); */
193         act.sa_sigaction = (void *) catch_ArithmeticException;
194         act.sa_flags = SA_SIGINFO;
195         sigaction(sig, &act, NULL);                          /* reinstall handler */
196
197         sigemptyset(&nsig);
198         sigaddset(&nsig, sig);
199         sigprocmask(SIG_UNBLOCK, &nsig, NULL);               /* unblock signal    */
200
201         sigctx->ecx = sigctx->eip;                           /* REG_ITMP2_XPC     */
202         sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
203
204         return;
205 }
206
207
208 void init_exceptions(void)
209 {
210         struct sigaction act;
211
212         /* install signal handlers we need to convert to exceptions */
213         sigemptyset(&act.sa_mask);
214
215         if (!checknull) {
216 #if defined(SIGSEGV)
217 /*              signal(SIGSEGV, (void *) catch_NullPointerException); */
218                 act.sa_sigaction = (void *) catch_NullPointerException;
219                 act.sa_flags = SA_SIGINFO;
220                 sigaction(SIGSEGV, &act, NULL);
221 #endif
222
223 #if defined(SIGBUS)
224 /*              signal(SIGBUS, (void *) catch_NullPointerException); */
225                 act.sa_sigaction = (void *) catch_NullPointerException;
226                 act.sa_flags = SA_SIGINFO;
227                 sigaction(SIGBUS, &act, NULL);
228 #endif
229         }
230
231 /*      signal(SIGFPE, (void *) catch_ArithmeticException); */
232         act.sa_sigaction = (void *) catch_ArithmeticException;
233         act.sa_flags = SA_SIGINFO;
234         sigaction(SIGFPE, &act, NULL);
235 }
236
237
238 /* function codegen ************************************************************
239
240         generates machine code
241
242 *******************************************************************************/
243
244 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
245 {
246         s4 len, s1, s2, s3, d;
247         s4 a;
248         stackptr      src;
249         varinfo      *var;
250         basicblock   *bptr;
251         instruction  *iptr;
252         s4 parentargs_base;
253         u2 currentline;
254         s4 fpu_st_offset = 0;
255
256         exceptiontable *ex;
257
258         {
259         s4 i, p, pa, t, l;
260         s4 savedregs_num = 0;
261
262         /* space to save used callee saved registers */
263
264         savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
265         savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
266
267         parentargs_base = rd->maxmemuse + savedregs_num;
268
269 #if defined(USE_THREADS)           /* space to save argument of monitor_enter */
270
271         if (checksync && (m->flags & ACC_SYNCHRONIZED))
272                 parentargs_base++;
273
274 #endif
275
276         /* create method header */
277
278         (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
279         (void) dseg_adds4(cd, parentargs_base * 8);             /* FrameSize      */
280
281 #if defined(USE_THREADS)
282
283         /* IsSync contains the offset relative to the stack pointer for the
284            argument of monitor_exit used in the exception handler. Since the
285            offset could be zero and give a wrong meaning of the flag it is
286            offset by one.
287         */
288
289         if (checksync && (m->flags & ACC_SYNCHRONIZED))
290                 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8);         /* IsSync     */
291         else
292
293 #endif
294
295         (void) dseg_adds4(cd, 0);                                   /* IsSync     */
296                                                
297         (void) dseg_adds4(cd, m->isleafmethod);                     /* IsLeaf     */
298         (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
299         (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
300
301         /* adds a reference for the length of the line number counter. We don't
302            know the size yet, since we evaluate the information during code
303            generation, to save one additional iteration over the whole
304            instructions. During code optimization the position could have changed
305            to the information gotten from the class file */
306         (void) dseg_addlinenumbertablesize(cd);
307
308         (void) dseg_adds4(cd, cd->exceptiontablelength);        /* ExTableSize    */
309         
310         /* create exception table */
311
312         for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
313                 dseg_addtarget(cd, ex->start);
314                 dseg_addtarget(cd, ex->end);
315                 dseg_addtarget(cd, ex->handler);
316                 (void) dseg_addaddress(cd, ex->catchtype);
317         }
318
319         
320         /* initialize mcode variables */
321         
322         cd->mcodeptr = cd->mcodebase;
323         cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
324         MCODECHECK(128 + m->paramcount);
325
326         /* create stack frame (if necessary) */
327
328         if (parentargs_base) {
329                 i386_alu_imm_reg(cd, I386_SUB, parentargs_base * 8, REG_SP);
330         }
331
332         /* save return address and used callee saved registers */
333
334         p = parentargs_base;
335         for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
336                 p--; i386_mov_reg_membase(cd, rd->savintregs[i], REG_SP, p * 8);
337         }
338         for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
339                 p--; i386_fld_reg(cd, rd->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 8);
340         }
341
342         /* save monitorenter argument */
343
344 #if defined(USE_THREADS)
345         s4 func_enter = (m->flags & ACC_STATIC) ?
346                 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
347
348         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
349                 if (m->flags & ACC_STATIC) {
350                         i386_mov_imm_reg(cd, (s4) m->class, REG_ITMP1);
351                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
352
353                 } else {
354                         i386_mov_membase_reg(cd, REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
355                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
356                 }
357
358                 /* call monitorenter function */
359
360                 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
361                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
362                 i386_mov_imm_reg(cd, func_enter, REG_ITMP1);
363                 i386_call_reg(cd, REG_ITMP1);
364                 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
365         }                       
366 #endif
367
368         /* copy argument registers to stack and call trace function with pointer
369            to arguments on stack.
370         */
371
372         if (runverbose) {
373                 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
374
375                 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
376                         t = m->paramtypes[p];
377
378                         if (IS_INT_LNG_TYPE(t)) {
379                                 if (IS_2_WORD_TYPE(t)) {
380                                         i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
381                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
382                                         i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
383                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
384
385 /*                              } else if (t == TYPE_ADR) { */
386                                 } else {
387                                         i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
388                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
389                                         i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
390                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
391
392 /*                              } else { */
393 /*                                      i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
394 /*                                      i386_cltd(cd); */
395 /*                                      i386_mov_reg_membase(cd, EAX, REG_SP, p * 8); */
396 /*                                      i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4); */
397                                 }
398
399                         } else {
400                                 if (!IS_2_WORD_TYPE(t)) {
401                                         i386_flds_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
402                                         i386_fstps_membase(cd, REG_SP, p * 8);
403                                         i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
404                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
405
406                                 } else {
407                                         i386_fldl_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
408                                         i386_fstpl_membase(cd, REG_SP, p * 8);
409                                 }
410                         }
411                 }
412
413                 /* fill up the remaining arguments */
414                 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
415                 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
416                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
417                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
418                 }
419
420                 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
421                 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
422                 i386_call_reg(cd, REG_ITMP1);
423
424                 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
425         }
426
427         /* take arguments out of register or stack frame */
428
429         for (p = 0, l = 0; p < m->paramcount; p++) {
430                 t = m->paramtypes[p];
431                 var = &(rd->locals[l][t]);
432                 l++;
433                 if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
434                         l++;
435                 if (var->type < 0)
436                         continue;
437                 if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */
438                         if (p < rd->intreg_argnum) {              /* register arguments    */
439                                 panic("integer register argument");
440                                 if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
441 /*                                      M_INTMOVE (argintregs[p], r); */
442
443                                 } else {                             /* reg arg -> spilled    */
444 /*                                      M_LST (argintregs[p], REG_SP, 8 * r); */
445                                 }
446                         } else {                                 /* stack arguments       */
447                                 pa = p - rd->intreg_argnum;
448                                 if (!(var->flags & INMEMORY)) {      /* stack arg -> register */ 
449                                         i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, var->regoff);            /* + 4 for return address */
450                                 } else {                             /* stack arg -> spilled  */
451                                         if (!IS_2_WORD_TYPE(t)) {
452                                                 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1);    /* + 4 for return address */
453                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
454
455                                         } else {
456                                                 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1);    /* + 4 for return address */
457                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
458                                                 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1);    /* + 4 for return address */
459                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8 + 4);
460                                         }
461                                 }
462                         }
463                 
464                 } else {                                     /* floating args         */   
465                         if (p < rd->fltreg_argnum) {              /* register arguments    */
466                                 if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
467                                         panic("There are no float argument registers!");
468
469                                 } else {                                         /* reg arg -> spilled    */
470                                         panic("There are no float argument registers!");
471                                 }
472
473                         } else {                                 /* stack arguments       */
474                                 pa = p - rd->fltreg_argnum;
475                                 if (!(var->flags & INMEMORY)) {      /* stack-arg -> register */
476                                         if (t == TYPE_FLT) {
477                                                 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
478                                                 fpu_st_offset++;
479                                                 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
480                                                 fpu_st_offset--;
481
482                                         } else {
483                                                 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
484                                                 fpu_st_offset++;
485                                                 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
486                                                 fpu_st_offset--;
487                                         }
488
489                                 } else {                              /* stack-arg -> spilled  */
490 /*                                      i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
491 /*                                      i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r * 8); */
492                                         if (t == TYPE_FLT) {
493                                                 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
494                                                 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
495
496                                         } else {
497                                                 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
498                                                 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
499                                         }
500                                 }
501                         }
502                 }
503         }  /* end for */
504
505         }
506
507         /* end of header generation */
508
509         /* walk through all basic blocks */
510         for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
511
512                 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
513
514                 if (bptr->flags >= BBREACHED) {
515
516                 /* branch resolving */
517
518                 branchref *brefs;
519                 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
520                         gen_resolvebranch(cd->mcodebase + brefs->branchpos, 
521                                           brefs->branchpos,
522                                                           bptr->mpc);
523                 }
524
525                 /* copy interface registers to their destination */
526
527                 src = bptr->instack;
528                 len = bptr->indepth;
529                 MCODECHECK(64+len);
530                 while (src != NULL) {
531                         len--;
532                         if ((len == 0) && (bptr->type != BBTYPE_STD)) {
533                                 if (!IS_2_WORD_TYPE(src->type)) {
534                                         if (bptr->type == BBTYPE_SBR) {
535                                                 d = reg_of_var(rd, src, REG_ITMP1);
536                                                 i386_pop_reg(cd, d);
537                                                 store_reg_to_var_int(src, d);
538
539                                         } else if (bptr->type == BBTYPE_EXH) {
540                                                 d = reg_of_var(rd, src, REG_ITMP1);
541                                                 M_INTMOVE(REG_ITMP1, d);
542                                                 store_reg_to_var_int(src, d);
543                                         }
544
545                                 } else {
546                                         panic("copy interface registers: longs have to me in memory (begin 1)");
547                                 }
548
549                         } else {
550                                 d = reg_of_var(rd, src, REG_ITMP1);
551                                 if ((src->varkind != STACKVAR)) {
552                                         s2 = src->type;
553                                         if (IS_FLT_DBL_TYPE(s2)) {
554                                                 s1 = rd->interfaces[len][s2].regoff;
555                                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
556                                                         M_FLTMOVE(s1, d);
557
558                                                 } else {
559                                                         if (s2 == TYPE_FLT) {
560                                                                 i386_flds_membase(cd, REG_SP, s1 * 8);
561
562                                                         } else {
563                                                                 i386_fldl_membase(cd, REG_SP, s1 * 8);
564                                                         }
565                                                 }
566                                                 store_reg_to_var_flt(src, d);
567
568                                         } else {
569                                                 s1 = rd->interfaces[len][s2].regoff;
570                                                 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
571                                                         if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
572                                                                 M_INTMOVE(s1, d);
573
574                                                         } else {
575                                                                 i386_mov_membase_reg(cd, REG_SP, s1 * 8, d);
576                                                         }
577                                                         store_reg_to_var_int(src, d);
578
579                                                 } else {
580                                                         if (rd->interfaces[len][s2].flags & INMEMORY) {
581                                                                 M_LNGMEMMOVE(s1, src->regoff);
582
583                                                         } else {
584                                                                 panic("copy interface registers: longs have to be in memory (begin 2)");
585                                                         }
586                                                 }
587                                         }
588                                 }
589                         }
590                         src = src->prev;
591                 }
592
593                 /* walk through all instructions */
594                 
595                 src = bptr->instack;
596                 len = bptr->icount;
597                 currentline = 0;
598                 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
599                         if (iptr->line != currentline) {
600                                 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
601                                 currentline = iptr->line;
602                         }
603
604                         MCODECHECK(64);   /* an instruction usually needs < 64 words      */
605
606                 switch (iptr->opc) {
607                 case ICMD_NOP:        /* ...  ==> ...                                 */
608                         break;
609
610                 case ICMD_NULLCHECKPOP: /* ..., objectref  ==> ...                    */
611                         if (src->flags & INMEMORY) {
612                                 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
613
614                         } else {
615                                 i386_test_reg_reg(cd, src->regoff, src->regoff);
616                         }
617                         i386_jcc(cd, I386_CC_E, 0);
618                         codegen_addxnullrefs(cd, cd->mcodeptr);
619                         break;
620
621                 /* constant operations ************************************************/
622
623                 case ICMD_ICONST:     /* ...  ==> ..., constant                       */
624                                       /* op1 = 0, val.i = constant                    */
625
626                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
627                         if (iptr->dst->flags & INMEMORY) {
628                                 i386_mov_imm_membase(cd, iptr->val.i, REG_SP, iptr->dst->regoff * 8);
629
630                         } else {
631                                 if (iptr->val.i == 0) {
632                                         i386_alu_reg_reg(cd, I386_XOR, d, d);
633
634                                 } else {
635                                         i386_mov_imm_reg(cd, iptr->val.i, d);
636                                 }
637                         }
638                         break;
639
640                 case ICMD_LCONST:     /* ...  ==> ..., constant                       */
641                                       /* op1 = 0, val.l = constant                    */
642
643                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
644                         if (iptr->dst->flags & INMEMORY) {
645                                 i386_mov_imm_membase(cd, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
646                                 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
647                                 
648                         } else {
649                                 panic("LCONST: longs have to be in memory");
650                         }
651                         break;
652
653                 case ICMD_FCONST:     /* ...  ==> ..., constant                       */
654                                       /* op1 = 0, val.f = constant                    */
655
656                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
657                         if (iptr->val.f == 0.0) {
658                                 i386_fldz(cd);
659                                 fpu_st_offset++;
660
661                                 /* -0.0 */
662                                 if (iptr->val.i == 0x80000000) {
663                                         i386_fchs(cd);
664                                 }
665
666                         } else if (iptr->val.f == 1.0) {
667                                 i386_fld1(cd);
668                                 fpu_st_offset++;
669
670                         } else if (iptr->val.f == 2.0) {
671                                 i386_fld1(cd);
672                                 i386_fld1(cd);
673                                 i386_faddp(cd);
674                                 fpu_st_offset++;
675
676                         } else {
677                                 a = dseg_addfloat(cd, iptr->val.f);
678                                 i386_mov_imm_reg(cd, 0, REG_ITMP1);
679                                 dseg_adddata(cd, cd->mcodeptr);
680                                 i386_flds_membase(cd, REG_ITMP1, a);
681                                 fpu_st_offset++;
682                         }
683                         store_reg_to_var_flt(iptr->dst, d);
684                         break;
685                 
686                 case ICMD_DCONST:     /* ...  ==> ..., constant                       */
687                                       /* op1 = 0, val.d = constant                    */
688
689                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
690                         if (iptr->val.d == 0.0) {
691                                 i386_fldz(cd);
692                                 fpu_st_offset++;
693
694                                 /* -0.0 */
695                                 if (iptr->val.l == 0x8000000000000000LL) {
696                                         i386_fchs(cd);
697                                 }
698
699                         } else if (iptr->val.d == 1.0) {
700                                 i386_fld1(cd);
701                                 fpu_st_offset++;
702
703                         } else if (iptr->val.d == 2.0) {
704                                 i386_fld1(cd);
705                                 i386_fld1(cd);
706                                 i386_faddp(cd);
707                                 fpu_st_offset++;
708
709                         } else {
710                                 a = dseg_adddouble(cd, iptr->val.d);
711                                 i386_mov_imm_reg(cd, 0, REG_ITMP1);
712                                 dseg_adddata(cd, cd->mcodeptr);
713                                 i386_fldl_membase(cd, REG_ITMP1, a);
714                                 fpu_st_offset++;
715                         }
716                         store_reg_to_var_flt(iptr->dst, d);
717                         break;
718
719                 case ICMD_ACONST:     /* ...  ==> ..., constant                       */
720                                       /* op1 = 0, val.a = constant                    */
721
722                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
723                         if (iptr->dst->flags & INMEMORY) {
724                                 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
725
726                         } else {
727                                 if ((s4) iptr->val.a == 0) {
728                                         i386_alu_reg_reg(cd, I386_XOR, d, d);
729
730                                 } else {
731                                         i386_mov_imm_reg(cd, (s4) iptr->val.a, d);
732                                 }
733                         }
734                         break;
735
736
737                 /* load/store operations **********************************************/
738
739                 case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
740                 case ICMD_ALOAD:      /* op1 = local variable                         */
741
742                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
743                         if ((iptr->dst->varkind == LOCALVAR) &&
744                             (iptr->dst->varnum == iptr->op1)) {
745                                 break;
746                         }
747                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
748                         if (iptr->dst->flags & INMEMORY) {
749                                 if (var->flags & INMEMORY) {
750                                         i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, REG_ITMP1);
751                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
752
753                                 } else {
754                                         i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
755                                 }
756
757                         } else {
758                                 if (var->flags & INMEMORY) {
759                                         i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, iptr->dst->regoff);
760
761                                 } else {
762                                         M_INTMOVE(var->regoff, iptr->dst->regoff);
763                                 }
764                         }
765                         break;
766
767                 case ICMD_LLOAD:      /* ...  ==> ..., content of local variable      */
768                                       /* op1 = local variable                         */
769
770                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
771                         if ((iptr->dst->varkind == LOCALVAR) &&
772                             (iptr->dst->varnum == iptr->op1)) {
773                                 break;
774                         }
775                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
776                         if (iptr->dst->flags & INMEMORY) {
777                                 if (var->flags & INMEMORY) {
778                                         M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
779
780                                 } else {
781                                         panic("LLOAD: longs have to be in memory");
782                                 }
783
784                         } else {
785                                 panic("LLOAD: longs have to be in memory");
786                         }
787                         break;
788
789                 case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
790                                       /* op1 = local variable                         */
791
792                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
793                         if ((iptr->dst->varkind == LOCALVAR) &&
794                             (iptr->dst->varnum == iptr->op1)) {
795                                 break;
796                         }
797                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
798                         if (var->flags & INMEMORY) {
799                                 i386_flds_membase(cd, REG_SP, var->regoff * 8);
800                                 fpu_st_offset++;
801                         } else {
802                                 i386_fld_reg(cd, var->regoff + fpu_st_offset);
803                                 fpu_st_offset++;
804                         }
805                         store_reg_to_var_flt(iptr->dst, d);
806                         break;
807
808                 case ICMD_DLOAD:      /* ...  ==> ..., content of local variable      */
809                                       /* op1 = local variable                         */
810
811                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
812                         if ((iptr->dst->varkind == LOCALVAR) &&
813                             (iptr->dst->varnum == iptr->op1)) {
814                                 break;
815                         }
816                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
817                         if (var->flags & INMEMORY) {
818                                 i386_fldl_membase(cd, REG_SP, var->regoff * 8);
819                                 fpu_st_offset++;
820                         } else {
821                                 i386_fld_reg(cd, var->regoff + fpu_st_offset);
822                                 fpu_st_offset++;
823                         }
824                         store_reg_to_var_flt(iptr->dst, d);
825                         break;
826
827                 case ICMD_ISTORE:     /* ..., value  ==> ...                          */
828                 case ICMD_ASTORE:     /* op1 = local variable                         */
829
830                         if ((src->varkind == LOCALVAR) &&
831                             (src->varnum == iptr->op1)) {
832                                 break;
833                         }
834                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
835                         if (var->flags & INMEMORY) {
836                                 if (src->flags & INMEMORY) {
837                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
838                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
839                                         
840                                 } else {
841                                         i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 8);
842                                 }
843
844                         } else {
845                                 var_to_reg_int(s1, src, var->regoff);
846                                 M_INTMOVE(s1, var->regoff);
847                         }
848                         break;
849
850                 case ICMD_LSTORE:     /* ..., value  ==> ...                          */
851                                       /* op1 = local variable                         */
852
853                         if ((src->varkind == LOCALVAR) &&
854                             (src->varnum == iptr->op1)) {
855                                 break;
856                         }
857                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
858                         if (var->flags & INMEMORY) {
859                                 if (src->flags & INMEMORY) {
860                                         M_LNGMEMMOVE(src->regoff, var->regoff);
861
862                                 } else {
863                                         panic("LSTORE: longs have to be in memory");
864                                 }
865
866                         } else {
867                                 panic("LSTORE: longs have to be in memory");
868                         }
869                         break;
870
871                 case ICMD_FSTORE:     /* ..., value  ==> ...                          */
872                                       /* op1 = local variable                         */
873
874                         if ((src->varkind == LOCALVAR) &&
875                             (src->varnum == iptr->op1)) {
876                                 break;
877                         }
878                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
879                         if (var->flags & INMEMORY) {
880                                 var_to_reg_flt(s1, src, REG_FTMP1);
881                                 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
882                                 fpu_st_offset--;
883                         } else {
884                                 var_to_reg_flt(s1, src, var->regoff);
885 /*                              M_FLTMOVE(s1, var->regoff); */
886                                 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
887                                 fpu_st_offset--;
888                         }
889                         break;
890
891                 case ICMD_DSTORE:     /* ..., value  ==> ...                          */
892                                       /* op1 = local variable                         */
893
894                         if ((src->varkind == LOCALVAR) &&
895                             (src->varnum == iptr->op1)) {
896                                 break;
897                         }
898                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
899                         if (var->flags & INMEMORY) {
900                                 var_to_reg_flt(s1, src, REG_FTMP1);
901                                 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
902                                 fpu_st_offset--;
903                         } else {
904                                 var_to_reg_flt(s1, src, var->regoff);
905 /*                              M_FLTMOVE(s1, var->regoff); */
906                                 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
907                                 fpu_st_offset--;
908                         }
909                         break;
910
911
912                 /* pop/dup/swap operations ********************************************/
913
914                 /* attention: double and longs are only one entry in CACAO ICMDs      */
915
916                 case ICMD_POP:        /* ..., value  ==> ...                          */
917                 case ICMD_POP2:       /* ..., value, value  ==> ...                   */
918                         break;
919
920                 case ICMD_DUP:        /* ..., a ==> ..., a, a                         */
921                         M_COPY(src, iptr->dst);
922                         break;
923
924                 case ICMD_DUP2:       /* ..., a, b ==> ..., a, b, a, b                */
925
926                         M_COPY(src,       iptr->dst);
927                         M_COPY(src->prev, iptr->dst->prev);
928                         break;
929
930                 case ICMD_DUP_X1:     /* ..., a, b ==> ..., b, a, b                   */
931
932                         M_COPY(src,       iptr->dst);
933                         M_COPY(src->prev, iptr->dst->prev);
934                         M_COPY(iptr->dst, iptr->dst->prev->prev);
935                         break;
936
937                 case ICMD_DUP_X2:     /* ..., a, b, c ==> ..., c, a, b, c             */
938
939                         M_COPY(src,             iptr->dst);
940                         M_COPY(src->prev,       iptr->dst->prev);
941                         M_COPY(src->prev->prev, iptr->dst->prev->prev);
942                         M_COPY(iptr->dst,       iptr->dst->prev->prev->prev);
943                         break;
944
945                 case ICMD_DUP2_X1:    /* ..., a, b, c ==> ..., b, c, a, b, c          */
946
947                         M_COPY(src,             iptr->dst);
948                         M_COPY(src->prev,       iptr->dst->prev);
949                         M_COPY(src->prev->prev, iptr->dst->prev->prev);
950                         M_COPY(iptr->dst,       iptr->dst->prev->prev->prev);
951                         M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev);
952                         break;
953
954                 case ICMD_DUP2_X2:    /* ..., a, b, c, d ==> ..., c, d, a, b, c, d    */
955
956                         M_COPY(src,                   iptr->dst);
957                         M_COPY(src->prev,             iptr->dst->prev);
958                         M_COPY(src->prev->prev,       iptr->dst->prev->prev);
959                         M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
960                         M_COPY(iptr->dst,             iptr->dst->prev->prev->prev->prev);
961                         M_COPY(iptr->dst->prev,       iptr->dst->prev->prev->prev->prev->prev);
962                         break;
963
964                 case ICMD_SWAP:       /* ..., a, b ==> ..., b, a                      */
965
966                         M_COPY(src,       iptr->dst->prev);
967                         M_COPY(src->prev, iptr->dst);
968                         break;
969
970
971                 /* integer operations *************************************************/
972
973                 case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
974
975                         d = reg_of_var(rd, iptr->dst, REG_NULL);
976                         if (iptr->dst->flags & INMEMORY) {
977                                 if (src->flags & INMEMORY) {
978                                         if (src->regoff == iptr->dst->regoff) {
979                                                 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
980
981                                         } else {
982                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
983                                                 i386_neg_reg(cd, REG_ITMP1);
984                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
985                                         }
986
987                                 } else {
988                                         i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
989                                         i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
990                                 }
991
992                         } else {
993                                 if (src->flags & INMEMORY) {
994                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
995                                         i386_neg_reg(cd, iptr->dst->regoff);
996
997                                 } else {
998                                         M_INTMOVE(src->regoff, iptr->dst->regoff);
999                                         i386_neg_reg(cd, iptr->dst->regoff);
1000                                 }
1001                         }
1002                         break;
1003
1004                 case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
1005
1006                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1007                         if (iptr->dst->flags & INMEMORY) {
1008                                 if (src->flags & INMEMORY) {
1009                                         if (src->regoff == iptr->dst->regoff) {
1010                                                 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1011                                                 i386_alu_imm_membase(cd, I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1012                                                 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8 + 4);
1013
1014                                         } else {
1015                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1016                                                 i386_neg_reg(cd, REG_ITMP1);
1017                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1018                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1019                                                 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP1);
1020                                                 i386_neg_reg(cd, REG_ITMP1);
1021                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1022                                         }
1023                                 }
1024                         }
1025                         break;
1026
1027                 case ICMD_I2L:        /* ..., value  ==> ..., value                   */
1028
1029                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1030                         if (iptr->dst->flags & INMEMORY) {
1031                                 if (src->flags & INMEMORY) {
1032                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, EAX);
1033                                         i386_cltd(cd);
1034                                         i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1035                                         i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1036
1037                                 } else {
1038                                         M_INTMOVE(src->regoff, EAX);
1039                                         i386_cltd(cd);
1040                                         i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1041                                         i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1042                                 }
1043                         }
1044                         break;
1045
1046                 case ICMD_L2I:        /* ..., value  ==> ..., value                   */
1047
1048                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1049                         if (iptr->dst->flags & INMEMORY) {
1050                                 if (src->flags & INMEMORY) {
1051                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1052                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1053                                 }
1054
1055                         } else {
1056                                 if (src->flags & INMEMORY) {
1057                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1058                                 }
1059                         }
1060                         break;
1061
1062                 case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
1063
1064                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1065                         if (iptr->dst->flags & INMEMORY) {
1066                                 if (src->flags & INMEMORY) {
1067                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1068                                         i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1069                                         i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1070                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1071
1072                                 } else {
1073                                         i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1074                                         i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1075                                         i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1076                                 }
1077
1078                         } else {
1079                                 if (src->flags & INMEMORY) {
1080                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1081                                         i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1082                                         i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1083
1084                                 } else {
1085                                         M_INTMOVE(src->regoff, iptr->dst->regoff);
1086                                         i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1087                                         i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1088                                 }
1089                         }
1090                         break;
1091
1092                 case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
1093
1094                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1095                         if (iptr->dst->flags & INMEMORY) {
1096                                 if (src->flags & INMEMORY) {
1097                                         if (src->regoff == iptr->dst->regoff) {
1098                                                 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1099
1100                                         } else {
1101                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1102                                                 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, REG_ITMP1);
1103                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1104                                         }
1105
1106                                 } else {
1107                                         i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1108                                         i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1109                                 }
1110
1111                         } else {
1112                                 if (src->flags & INMEMORY) {
1113                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1114                                         i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1115
1116                                 } else {
1117                                         M_INTMOVE(src->regoff, iptr->dst->regoff);
1118                                         i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1119                                 }
1120                         }
1121                         break;
1122
1123                 case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
1124
1125                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1126                         if (iptr->dst->flags & INMEMORY) {
1127                                 if (src->flags & INMEMORY) {
1128                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1129                                         i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1130                                         i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1131                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1132
1133                                 } else {
1134                                         i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1135                                         i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1136                                         i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1137                                 }
1138
1139                         } else {
1140                                 if (src->flags & INMEMORY) {
1141                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1142                                         i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1143                                         i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1144
1145                                 } else {
1146                                         M_INTMOVE(src->regoff, iptr->dst->regoff);
1147                                         i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1148                                         i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1149                                 }
1150                         }
1151                         break;
1152
1153
1154                 case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1155
1156                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1157                         i386_emit_ialu(cd, I386_ADD, src, iptr);
1158                         break;
1159
1160                 case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
1161                                       /* val.i = constant                             */
1162
1163                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1164                         /* should we use a inc optimization for smaller code size? */
1165                         i386_emit_ialuconst(cd, I386_ADD, src, iptr);
1166                         break;
1167
1168                 case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1169
1170                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1171                         if (iptr->dst->flags & INMEMORY) {
1172                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1173                                         if (src->regoff == iptr->dst->regoff) {
1174                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1175                                                 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1176                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1177                                                 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1178
1179                                         } else if (src->prev->regoff == iptr->dst->regoff) {
1180                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1181                                                 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1182                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1183                                                 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1184
1185                                         } else {
1186                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1187                                                 i386_alu_membase_reg(cd, I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1188                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1189                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1190                                                 i386_alu_membase_reg(cd, I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1191                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1192                                         }
1193
1194                                 }
1195                         }
1196                         break;
1197
1198                 case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
1199                                       /* val.l = constant                             */
1200
1201                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1202                         if (iptr->dst->flags & INMEMORY) {
1203                                 if (src->flags & INMEMORY) {
1204                                         if (src->regoff == iptr->dst->regoff) {
1205                                                 i386_alu_imm_membase(cd, I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1206                                                 i386_alu_imm_membase(cd, I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1207
1208                                         } else {
1209                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1210                                                 i386_alu_imm_reg(cd, I386_ADD, iptr->val.l, REG_ITMP1);
1211                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1212                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1213                                                 i386_alu_imm_reg(cd, I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1214                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1215                                         }
1216                                 }
1217                         }
1218                         break;
1219
1220                 case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1221
1222                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1223                         if (iptr->dst->flags & INMEMORY) {
1224                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1225                                         if (src->prev->regoff == iptr->dst->regoff) {
1226                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1227                                                 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1228
1229                                         } else {
1230                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1231                                                 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1232                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1233                                         }
1234
1235                                 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1236                                         M_INTMOVE(src->prev->regoff, REG_ITMP1);
1237                                         i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1238                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1239
1240                                 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1241                                         if (src->prev->regoff == iptr->dst->regoff) {
1242                                                 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1243
1244                                         } else {
1245                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1246                                                 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1247                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1248                                         }
1249
1250                                 } else {
1251                                         i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1252                                         i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1253                                 }
1254
1255                         } else {
1256                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1257                                         i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1258                                         i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1259
1260                                 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1261                                         M_INTMOVE(src->prev->regoff, d);
1262                                         i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1263
1264                                 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1265                                         /* workaround for reg alloc */
1266                                         if (src->regoff == iptr->dst->regoff) {
1267                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1268                                                 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1269                                                 M_INTMOVE(REG_ITMP1, d);
1270
1271                                         } else {
1272                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1273                                                 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1274                                         }
1275
1276                                 } else {
1277                                         /* workaround for reg alloc */
1278                                         if (src->regoff == iptr->dst->regoff) {
1279                                                 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1280                                                 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1281                                                 M_INTMOVE(REG_ITMP1, d);
1282
1283                                         } else {
1284                                                 M_INTMOVE(src->prev->regoff, d);
1285                                                 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1286                                         }
1287                                 }
1288                         }
1289                         break;
1290
1291                 case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
1292                                       /* val.i = constant                             */
1293
1294                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1295                         i386_emit_ialuconst(cd, I386_SUB, src, iptr);
1296                         break;
1297
1298                 case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1299
1300                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1301                         if (iptr->dst->flags & INMEMORY) {
1302                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1303                                         if (src->prev->regoff == iptr->dst->regoff) {
1304                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1305                                                 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1306                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1307                                                 i386_alu_reg_membase(cd, I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1308
1309                                         } else {
1310                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1311                                                 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1312                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1313                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1314                                                 i386_alu_membase_reg(cd, I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1315                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1316                                         }
1317                                 }
1318                         }
1319                         break;
1320
1321                 case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
1322                                       /* val.l = constant                             */
1323
1324                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1325                         if (iptr->dst->flags & INMEMORY) {
1326                                 if (src->flags & INMEMORY) {
1327                                         if (src->regoff == iptr->dst->regoff) {
1328                                                 i386_alu_imm_membase(cd, I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1329                                                 i386_alu_imm_membase(cd, I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1330
1331                                         } else {
1332                                                 /* TODO: could be size optimized with lea -- see gcc output */
1333                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1334                                                 i386_alu_imm_reg(cd, I386_SUB, iptr->val.l, REG_ITMP1);
1335                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1336                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1337                                                 i386_alu_imm_reg(cd, I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1338                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1339                                         }
1340                                 }
1341                         }
1342                         break;
1343
1344                 case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1345
1346                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1347                         if (iptr->dst->flags & INMEMORY) {
1348                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1349                                         i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1350                                         i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1351                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1352
1353                                 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1354                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1355                                         i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1356                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1357
1358                                 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1359                                         i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1360                                         i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1361                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1362
1363                                 } else {
1364                                         i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1365                                         i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1366                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1367                                 }
1368
1369                         } else {
1370                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1371                                         i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1372                                         i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1373
1374                                 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1375                                         M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1376                                         i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1377
1378                                 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1379                                         M_INTMOVE(src->regoff, iptr->dst->regoff);
1380                                         i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1381
1382                                 } else {
1383                                         if (src->regoff == iptr->dst->regoff) {
1384                                                 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1385
1386                                         } else {
1387                                                 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1388                                                 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1389                                         }
1390                                 }
1391                         }
1392                         break;
1393
1394                 case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
1395                                       /* val.i = constant                             */
1396
1397                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1398                         if (iptr->dst->flags & INMEMORY) {
1399                                 if (src->flags & INMEMORY) {
1400                                         i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1401                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1402
1403                                 } else {
1404                                         i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1405                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1406                                 }
1407
1408                         } else {
1409                                 if (src->flags & INMEMORY) {
1410                                         i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1411
1412                                 } else {
1413                                         i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1414                                 }
1415                         }
1416                         break;
1417
1418                 case ICMD_LMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1419
1420                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1421                         if (iptr->dst->flags & INMEMORY) {
1422                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1423                                         i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);             /* mem -> EAX             */
1424                                         /* optimize move EAX -> REG_ITMP3 is slower??? */
1425 /*                                      i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1426                                         i386_mul_membase(cd, REG_SP, src->regoff * 8);                            /* mem * EAX -> EDX:EAX   */
1427
1428                                         /* TODO: optimize move EAX -> REG_ITMP3 */
1429                                         i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);   /* mem -> ITMP3           */
1430                                         i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);            /* mem * ITMP3 -> ITMP3   */
1431                                         i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX);                      /* ITMP3 + EDX -> EDX     */
1432
1433                                         i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP2);       /* mem -> ITMP3           */
1434                                         i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);        /* mem * ITMP3 -> ITMP3   */
1435
1436                                         i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX);                      /* ITMP3 + EDX -> EDX     */
1437                                         i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1438                                         i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1439                                 }
1440                         }
1441                         break;
1442
1443                 case ICMD_LMULCONST:  /* ..., value  ==> ..., value * constant        */
1444                                       /* val.l = constant                             */
1445
1446                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1447                         if (iptr->dst->flags & INMEMORY) {
1448                                 if (src->flags & INMEMORY) {
1449                                         i386_mov_imm_reg(cd, iptr->val.l, EAX);                                   /* imm -> EAX             */
1450                                         i386_mul_membase(cd, REG_SP, src->regoff * 8);                            /* mem * EAX -> EDX:EAX   */
1451                                         /* TODO: optimize move EAX -> REG_ITMP3 */
1452                                         i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);                       /* imm -> ITMP3           */
1453                                         i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);            /* mem * ITMP3 -> ITMP3   */
1454
1455                                         i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX);                      /* ITMP3 + EDX -> EDX     */
1456                                         i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2);                             /* imm -> ITMP3           */
1457                                         i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);        /* mem * ITMP3 -> ITMP3   */
1458
1459                                         i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX);                      /* ITMP3 + EDX -> EDX     */
1460                                         i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1461                                         i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1462                                 }
1463                         }
1464                         break;
1465
1466                 case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1467
1468                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1469                         var_to_reg_int(s1, src, REG_ITMP2);
1470                         gen_div_check(src);
1471                 if (src->prev->flags & INMEMORY) {
1472                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1473
1474                         } else {
1475                                 M_INTMOVE(src->prev->regoff, EAX);
1476                         }
1477                         
1478                         i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX);    /* check as described in jvm spec */
1479                         i386_jcc(cd, I386_CC_NE, 3 + 6);
1480                         i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1481                         i386_jcc(cd, I386_CC_E, 1 + 2);
1482
1483                         i386_cltd(cd);
1484                         i386_idiv_reg(cd, s1);
1485
1486                         if (iptr->dst->flags & INMEMORY) {
1487                                 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1488
1489                         } else {
1490                                 M_INTMOVE(EAX, iptr->dst->regoff);
1491                         }
1492                         break;
1493
1494                 case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
1495
1496                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1497                         var_to_reg_int(s1, src, REG_ITMP2);
1498                         gen_div_check(src);
1499                         if (src->prev->flags & INMEMORY) {
1500                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1501
1502                         } else {
1503                                 M_INTMOVE(src->prev->regoff, EAX);
1504                         }
1505                         
1506                         i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX);    /* check as described in jvm spec */
1507                         i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1508                         i386_alu_reg_reg(cd, I386_XOR, EDX, EDX);
1509                         i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1510                         i386_jcc(cd, I386_CC_E, 1 + 2);
1511
1512                         i386_cltd(cd);
1513                         i386_idiv_reg(cd, s1);
1514
1515                         if (iptr->dst->flags & INMEMORY) {
1516                                 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8);
1517
1518                         } else {
1519                                 M_INTMOVE(EDX, iptr->dst->regoff);
1520                         }
1521                         break;
1522
1523                 case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value >> constant       */
1524                                       /* val.i = constant                             */
1525
1526                         /* TODO: optimize for `/ 2' */
1527                         var_to_reg_int(s1, src, REG_ITMP1);
1528                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1529
1530                         M_INTMOVE(s1, d);
1531                         i386_test_reg_reg(cd, d, d);
1532                         a = 2;
1533                         CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1534                         i386_jcc(cd, I386_CC_NS, a);
1535                         i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, d);
1536                                 
1537                         i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1538                         store_reg_to_var_int(iptr->dst, d);
1539                         break;
1540
1541                 case ICMD_LDIVPOW2:   /* ..., value  ==> ..., value >> constant       */
1542                                       /* val.i = constant                             */
1543
1544                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1545                         if (iptr->dst->flags & INMEMORY) {
1546                                 if (src->flags & INMEMORY) {
1547                                         a = 2;
1548                                         CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1549                                         a += 3;
1550                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1551                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1552
1553                                         i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1554                                         i386_jcc(cd, I386_CC_NS, a);
1555                                         i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1556                                         i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1557                                         i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1558                                         i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1559
1560                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1561                                         i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1562                                 }
1563                         }
1564                         break;
1565
1566                 case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
1567                                       /* val.i = constant                             */
1568
1569                         var_to_reg_int(s1, src, REG_ITMP1);
1570                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1571                         if (s1 == d) {
1572                                 M_INTMOVE(s1, REG_ITMP1);
1573                                 s1 = REG_ITMP1;
1574                         } 
1575
1576                         a = 2;
1577                         a += 2;
1578                         a += 2;
1579                         CALCIMMEDIATEBYTES(a, iptr->val.i);
1580                         a += 2;
1581
1582                         /* TODO: optimize */
1583                         M_INTMOVE(s1, d);
1584                         i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1585                         i386_test_reg_reg(cd, s1, s1);
1586                         i386_jcc(cd, I386_CC_GE, a);
1587                         i386_mov_reg_reg(cd, s1, d);
1588                         i386_neg_reg(cd, d);
1589                         i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1590                         i386_neg_reg(cd, d);
1591
1592 /*                      M_INTMOVE(s1, EAX); */
1593 /*                      i386_cltd(cd); */
1594 /*                      i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1595 /*                      i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1596 /*                      i386_alu_reg_reg(cd, I386_AND, iptr->val.i, EAX); */
1597 /*                      i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1598 /*                      i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1599 /*                      M_INTMOVE(EAX, d); */
1600
1601 /*                      i386_alu_reg_reg(cd, I386_XOR, d, d); */
1602 /*                      i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1603 /*                      i386_shrd_reg_reg(cd, s1, d); */
1604 /*                      i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1605
1606                         store_reg_to_var_int(iptr->dst, d);
1607                         break;
1608
1609                 case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant        */
1610                                       /* val.l = constant                             */
1611
1612                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1613                         if (iptr->dst->flags & INMEMORY) {
1614                                 if (src->flags & INMEMORY) {
1615                                         /* Intel algorithm -- does not work, because constant is wrong */
1616 /*                                      i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1); */
1617 /*                                      i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1618
1619 /*                                      M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1620 /*                                      i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1621 /*                                      i386_jcc(cd, I386_CC_NS, offset); */
1622 /*                                      i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1623 /*                                      i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP3); */
1624                                         
1625 /*                                      i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1626 /*                                      i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1627 /*                                      i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1628
1629 /*                                      i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1630
1631 /*                                      i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1); */
1632 /*                                      i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1633 /*                                      i386_alu_reg_reg(cd, I386_SBB, REG_ITMP3, REG_ITMP2); */
1634
1635 /*                                      i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1636 /*                                      i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1637
1638                                         /* Alpha algorithm */
1639                                         a = 3;
1640                                         CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1641                                         a += 3;
1642                                         CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1643
1644                                         a += 2;
1645                                         a += 3;
1646                                         a += 2;
1647
1648                                         /* TODO: hmm, don't know if this is always correct */
1649                                         a += 2;
1650                                         CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1651                                         a += 2;
1652                                         CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1653
1654                                         a += 2;
1655                                         a += 3;
1656                                         a += 2;
1657
1658                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1659                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1660                                         
1661                                         i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1662                                         i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1663                                         i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1664                                         i386_jcc(cd, I386_CC_GE, a);
1665
1666                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1667                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1668                                         
1669                                         i386_neg_reg(cd, REG_ITMP1);
1670                                         i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1671                                         i386_neg_reg(cd, REG_ITMP2);
1672                                         
1673                                         i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1674                                         i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1675                                         
1676                                         i386_neg_reg(cd, REG_ITMP1);
1677                                         i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1678                                         i386_neg_reg(cd, REG_ITMP2);
1679
1680                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1681                                         i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1682                                 }
1683                         }
1684                         break;
1685
1686                 case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
1687
1688                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1689                         i386_emit_ishift(cd, I386_SHL, src, iptr);
1690                         break;
1691
1692                 case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
1693                                       /* val.i = constant                             */
1694
1695                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1696                         i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1697                         break;
1698
1699                 case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
1700
1701                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1702                         i386_emit_ishift(cd, I386_SAR, src, iptr);
1703                         break;
1704
1705                 case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
1706                                       /* val.i = constant                             */
1707
1708                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1709                         i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1710                         break;
1711
1712                 case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
1713
1714                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1715                         i386_emit_ishift(cd, I386_SHR, src, iptr);
1716                         break;
1717
1718                 case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
1719                                       /* val.i = constant                             */
1720
1721                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1722                         i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1723                         break;
1724
1725                 case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
1726
1727                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1728                         if (iptr->dst->flags & INMEMORY ){
1729                                 if (src->prev->flags & INMEMORY) {
1730 /*                                      if (src->prev->regoff == iptr->dst->regoff) { */
1731 /*                                              i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1732
1733 /*                                              if (src->flags & INMEMORY) { */
1734 /*                                                      i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1735 /*                                              } else { */
1736 /*                                                      M_INTMOVE(src->regoff, ECX); */
1737 /*                                              } */
1738
1739 /*                                              i386_test_imm_reg(cd, 32, ECX); */
1740 /*                                              i386_jcc(cd, I386_CC_E, 2 + 2); */
1741 /*                                              i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1742 /*                                              i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1); */
1743                                                 
1744 /*                                              i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1745 /*                                              i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1746
1747 /*                                      } else { */
1748                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1749                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1750                                                 
1751                                                 if (src->flags & INMEMORY) {
1752                                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1753                                                 } else {
1754                                                         M_INTMOVE(src->regoff, ECX);
1755                                                 }
1756                                                 
1757                                                 i386_test_imm_reg(cd, 32, ECX);
1758                                                 i386_jcc(cd, I386_CC_E, 2 + 2);
1759                                                 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1760                                                 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1761                                                 
1762                                                 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1763                                                 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1764                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1765                                                 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1766 /*                                      } */
1767                                 }
1768                         }
1769                         break;
1770
1771         case ICMD_LSHLCONST:  /* ..., value  ==> ..., value << constant       */
1772                                           /* val.i = constant                             */
1773
1774                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1775                         if (iptr->dst->flags & INMEMORY ) {
1776                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1777                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1778
1779                                 if (iptr->val.i & 0x20) {
1780                                         i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1781                                         i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1782                                         i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1783
1784                                 } else {
1785                                         i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1786                                         i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1787                                 }
1788
1789                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1790                                 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1791                         }
1792                         break;
1793
1794                 case ICMD_LSHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
1795
1796                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1797                         if (iptr->dst->flags & INMEMORY ){
1798                                 if (src->prev->flags & INMEMORY) {
1799 /*                                      if (src->prev->regoff == iptr->dst->regoff) { */
1800                                                 /* TODO: optimize */
1801 /*                                              i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1802 /*                                              i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1803
1804 /*                                              if (src->flags & INMEMORY) { */
1805 /*                                                      i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1806 /*                                              } else { */
1807 /*                                                      M_INTMOVE(src->regoff, ECX); */
1808 /*                                              } */
1809
1810 /*                                              i386_test_imm_reg(cd, 32, ECX); */
1811 /*                                              i386_jcc(cd, I386_CC_E, 2 + 3); */
1812 /*                                              i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1813 /*                                              i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1814                                                 
1815 /*                                              i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1816 /*                                              i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1817 /*                                              i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1818 /*                                              i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1819
1820 /*                                      } else { */
1821                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1822                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1823
1824                                                 if (src->flags & INMEMORY) {
1825                                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1826                                                 } else {
1827                                                         M_INTMOVE(src->regoff, ECX);
1828                                                 }
1829
1830                                                 i386_test_imm_reg(cd, 32, ECX);
1831                                                 i386_jcc(cd, I386_CC_E, 2 + 3);
1832                                                 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1833                                                 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1834                                                 
1835                                                 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1836                                                 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1837                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1838                                                 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1839 /*                                      } */
1840                                 }
1841                         }
1842                         break;
1843
1844                 case ICMD_LSHRCONST:  /* ..., value  ==> ..., value >> constant       */
1845                                       /* val.i = constant                             */
1846
1847                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1848                         if (iptr->dst->flags & INMEMORY ) {
1849                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1850                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1851
1852                                 if (iptr->val.i & 0x20) {
1853                                         i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1854                                         i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
1855                                         i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1856
1857                                 } else {
1858                                         i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1859                                         i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1860                                 }
1861
1862                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1863                                 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1864                         }
1865                         break;
1866
1867                 case ICMD_LUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
1868
1869                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1870                         if (iptr->dst->flags & INMEMORY ){
1871                                 if (src->prev->flags & INMEMORY) {
1872 /*                                      if (src->prev->regoff == iptr->dst->regoff) { */
1873                                                 /* TODO: optimize */
1874 /*                                              i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1875 /*                                              i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1876
1877 /*                                              if (src->flags & INMEMORY) { */
1878 /*                                                      i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1879 /*                                              } else { */
1880 /*                                                      M_INTMOVE(src->regoff, ECX); */
1881 /*                                              } */
1882
1883 /*                                              i386_test_imm_reg(cd, 32, ECX); */
1884 /*                                              i386_jcc(cd, I386_CC_E, 2 + 2); */
1885 /*                                              i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1886 /*                                              i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2); */
1887                                                 
1888 /*                                              i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1889 /*                                              i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
1890 /*                                              i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1891 /*                                              i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1892
1893 /*                                      } else { */
1894                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1895                                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1896
1897                                                 if (src->flags & INMEMORY) {
1898                                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1899                                                 } else {
1900                                                         M_INTMOVE(src->regoff, ECX);
1901                                                 }
1902
1903                                                 i386_test_imm_reg(cd, 32, ECX);
1904                                                 i386_jcc(cd, I386_CC_E, 2 + 2);
1905                                                 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1906                                                 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP3, REG_ITMP3);
1907                                                 
1908                                                 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1909                                                 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
1910                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1911                                                 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1912 /*                                      } */
1913                                 }
1914                         }
1915                         break;
1916
1917                 case ICMD_LUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
1918                                       /* val.l = constant                             */
1919
1920                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1921                         if (iptr->dst->flags & INMEMORY ) {
1922                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1923                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1924
1925                                 if (iptr->val.i & 0x20) {
1926                                         i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1927                                         i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
1928                                         i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1929
1930                                 } else {
1931                                         i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1932                                         i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
1933                                 }
1934
1935                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1936                                 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1937                         }
1938                         break;
1939
1940                 case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1941
1942                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1943                         i386_emit_ialu(cd, I386_AND, src, iptr);
1944                         break;
1945
1946                 case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
1947                                       /* val.i = constant                             */
1948
1949                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1950                         i386_emit_ialuconst(cd, I386_AND, src, iptr);
1951                         break;
1952
1953                 case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1954
1955                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1956                         i386_emit_lalu(cd, I386_AND, src, iptr);
1957                         break;
1958
1959                 case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
1960                                       /* val.l = constant                             */
1961
1962                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1963                         i386_emit_laluconst(cd, I386_AND, src, iptr);
1964                         break;
1965
1966                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
1967
1968                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1969                         i386_emit_ialu(cd, I386_OR, src, iptr);
1970                         break;
1971
1972                 case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
1973                                       /* val.i = constant                             */
1974
1975                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1976                         i386_emit_ialuconst(cd, I386_OR, src, iptr);
1977                         break;
1978
1979                 case ICMD_LOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
1980
1981                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1982                         i386_emit_lalu(cd, I386_OR, src, iptr);
1983                         break;
1984
1985                 case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
1986                                       /* val.l = constant                             */
1987
1988                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1989                         i386_emit_laluconst(cd, I386_OR, src, iptr);
1990                         break;
1991
1992                 case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1993
1994                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1995                         i386_emit_ialu(cd, I386_XOR, src, iptr);
1996                         break;
1997
1998                 case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1999                                       /* val.i = constant                             */
2000
2001                         d = reg_of_var(rd, iptr->dst, REG_NULL);
2002                         i386_emit_ialuconst(cd, I386_XOR, src, iptr);
2003                         break;
2004
2005                 case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
2006
2007                         d = reg_of_var(rd, iptr->dst, REG_NULL);
2008                         i386_emit_lalu(cd, I386_XOR, src, iptr);
2009                         break;
2010
2011                 case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
2012                                       /* val.l = constant                             */
2013
2014                         d = reg_of_var(rd, iptr->dst, REG_NULL);
2015                         i386_emit_laluconst(cd, I386_XOR, src, iptr);
2016                         break;
2017
2018                 case ICMD_IINC:       /* ..., value  ==> ..., value + constant        */
2019                                       /* op1 = variable, val.i = constant             */
2020
2021                         var = &(rd->locals[iptr->op1][TYPE_INT]);
2022                         if (var->flags & INMEMORY) {
2023                                 i386_alu_imm_membase(cd, I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2024
2025                         } else {
2026                                 i386_alu_imm_reg(cd, I386_ADD, iptr->val.i, var->regoff);
2027                         }
2028                         break;
2029
2030
2031                 /* floating operations ************************************************/
2032 #if 0
2033 #define ROUND_TO_SINGLE \
2034                         i386_fstps_membase(cd, REG_SP, -8); \
2035                         i386_flds_membase(cd, REG_SP, -8);
2036
2037 #define ROUND_TO_DOUBLE \
2038                         i386_fstpl_membase(cd, REG_SP, -8); \
2039                         i386_fldl_membase(cd, REG_SP, -8);
2040
2041 #define FPU_SET_24BIT_MODE \
2042                         if (!fpu_in_24bit_mode) { \
2043                                 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2044                                 fpu_in_24bit_mode = 1; \
2045                         }
2046
2047 #define FPU_SET_53BIT_MODE \
2048                         if (fpu_in_24bit_mode) { \
2049                                 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2050                                 fpu_in_24bit_mode = 0; \
2051                         }
2052 #else
2053 #define ROUND_TO_SINGLE
2054 #define ROUND_TO_DOUBLE
2055 #define FPU_SET_24BIT_MODE
2056 #define FPU_SET_53BIT_MODE
2057 #endif
2058                 case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
2059
2060                         FPU_SET_24BIT_MODE;
2061                         var_to_reg_flt(s1, src, REG_FTMP1);
2062                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2063                         i386_fchs(cd);
2064                         store_reg_to_var_flt(iptr->dst, d);
2065                         break;
2066
2067                 case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
2068
2069                         FPU_SET_53BIT_MODE;
2070                         var_to_reg_flt(s1, src, REG_FTMP1);
2071                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2072                         i386_fchs(cd);
2073                         store_reg_to_var_flt(iptr->dst, d);
2074                         break;
2075
2076                 case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
2077
2078                         FPU_SET_24BIT_MODE;
2079                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2080                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
2081                         var_to_reg_flt(s2, src, REG_FTMP2);
2082                         i386_faddp(cd);
2083                         fpu_st_offset--;
2084                         store_reg_to_var_flt(iptr->dst, d);
2085                         break;
2086
2087                 case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
2088
2089                         FPU_SET_53BIT_MODE;
2090                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2091                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
2092                         var_to_reg_flt(s2, src, REG_FTMP2);
2093                         i386_faddp(cd);
2094                         fpu_st_offset--;
2095                         store_reg_to_var_flt(iptr->dst, d);
2096                         break;
2097
2098                 case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
2099
2100                         FPU_SET_24BIT_MODE;
2101                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2102                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
2103                         var_to_reg_flt(s2, src, REG_FTMP2);
2104                         i386_fsubp(cd);
2105                         fpu_st_offset--;
2106                         store_reg_to_var_flt(iptr->dst, d);
2107                         break;
2108
2109                 case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
2110
2111                         FPU_SET_53BIT_MODE;
2112                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2113                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
2114                         var_to_reg_flt(s2, src, REG_FTMP2);
2115                         i386_fsubp(cd);
2116                         fpu_st_offset--;
2117                         store_reg_to_var_flt(iptr->dst, d);
2118                         break;
2119
2120                 case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
2121
2122                         FPU_SET_24BIT_MODE;
2123                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2124                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
2125                         var_to_reg_flt(s2, src, REG_FTMP2);
2126                         i386_fmulp(cd);
2127                         fpu_st_offset--;
2128                         ROUND_TO_SINGLE;
2129                         store_reg_to_var_flt(iptr->dst, d);
2130                         break;
2131
2132                 case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
2133
2134                         FPU_SET_53BIT_MODE;
2135                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2136                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
2137
2138 /*                      i386_fldt_mem(cd, subnormal_bias1); */
2139 /*                      i386_fmulp(cd); */
2140
2141                         var_to_reg_flt(s2, src, REG_FTMP2);
2142
2143                         i386_fmulp(cd);
2144                         fpu_st_offset--;
2145
2146 /*                      i386_fldt_mem(cd, subnormal_bias2); */
2147 /*                      i386_fmulp(cd); */
2148
2149                         store_reg_to_var_flt(iptr->dst, d);
2150                         break;
2151
2152                 case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
2153
2154                         FPU_SET_24BIT_MODE;
2155                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2156                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
2157                         var_to_reg_flt(s2, src, REG_FTMP2);
2158                         i386_fdivp(cd);
2159                         fpu_st_offset--;
2160                         ROUND_TO_SINGLE;
2161                         store_reg_to_var_flt(iptr->dst, d);
2162                         break;
2163
2164                 case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
2165
2166                         FPU_SET_53BIT_MODE;
2167                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2168                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
2169
2170 /*                      i386_fldt_mem(cd, subnormal_bias1); */
2171 /*                      i386_fmulp(cd); */
2172
2173                         var_to_reg_flt(s2, src, REG_FTMP2);
2174
2175                         i386_fdivp(cd);
2176                         fpu_st_offset--;
2177
2178 /*                      i386_fldt_mem(cd, subnormal_bias2); */
2179 /*                      i386_fmulp(cd); */
2180
2181                         store_reg_to_var_flt(iptr->dst, d);
2182                         break;
2183
2184                 case ICMD_FREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
2185
2186                         FPU_SET_24BIT_MODE;
2187                         /* exchanged to skip fxch */
2188                         var_to_reg_flt(s2, src, REG_FTMP2);
2189                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
2190                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2191 /*                      i386_fxch(cd); */
2192                         i386_fprem(cd);
2193                         i386_wait(cd);
2194                         i386_fnstsw(cd);
2195                         i386_sahf(cd);
2196                         i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2197                         store_reg_to_var_flt(iptr->dst, d);
2198                         i386_ffree_reg(cd, 0);
2199                         i386_fincstp(cd);
2200                         fpu_st_offset--;
2201                         break;
2202
2203                 case ICMD_DREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
2204
2205                         FPU_SET_53BIT_MODE;
2206                         /* exchanged to skip fxch */
2207                         var_to_reg_flt(s2, src, REG_FTMP2);
2208                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
2209                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2210 /*                      i386_fxch(cd); */
2211                         i386_fprem(cd);
2212                         i386_wait(cd);
2213                         i386_fnstsw(cd);
2214                         i386_sahf(cd);
2215                         i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2216                         store_reg_to_var_flt(iptr->dst, d);
2217                         i386_ffree_reg(cd, 0);
2218                         i386_fincstp(cd);
2219                         fpu_st_offset--;
2220                         break;
2221
2222                 case ICMD_I2F:       /* ..., value  ==> ..., (float) value            */
2223                 case ICMD_I2D:       /* ..., value  ==> ..., (double) value           */
2224
2225                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2226                         if (src->flags & INMEMORY) {
2227                                 i386_fildl_membase(cd, REG_SP, src->regoff * 8);
2228                                 fpu_st_offset++;
2229
2230                         } else {
2231                                 a = dseg_adds4(cd, 0);
2232                                 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2233                                 dseg_adddata(cd, cd->mcodeptr);
2234                                 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, a);
2235                                 i386_fildl_membase(cd, REG_ITMP1, a);
2236                                 fpu_st_offset++;
2237                         }
2238                         store_reg_to_var_flt(iptr->dst, d);
2239                         break;
2240
2241                 case ICMD_L2F:       /* ..., value  ==> ..., (float) value            */
2242                 case ICMD_L2D:       /* ..., value  ==> ..., (double) value           */
2243
2244                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2245                         if (src->flags & INMEMORY) {
2246                                 i386_fildll_membase(cd, REG_SP, src->regoff * 8);
2247                                 fpu_st_offset++;
2248
2249                         } else {
2250                                 panic("L2F: longs have to be in memory");
2251                         }
2252                         store_reg_to_var_flt(iptr->dst, d);
2253                         break;
2254                         
2255                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
2256
2257                         var_to_reg_flt(s1, src, REG_FTMP1);
2258                         d = reg_of_var(rd, iptr->dst, REG_NULL);
2259
2260                         a = dseg_adds4(cd, 0x0e7f);    /* Round to zero, 53-bit mode, exception masked */
2261                         i386_mov_imm_reg(cd, 0, REG_ITMP1);
2262                         dseg_adddata(cd, cd->mcodeptr);
2263                         i386_fldcw_membase(cd, REG_ITMP1, a);
2264
2265                         if (iptr->dst->flags & INMEMORY) {
2266                                 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2267                                 fpu_st_offset--;
2268
2269                                 a = dseg_adds4(cd, 0x027f);    /* Round to nearest, 53-bit mode, exceptions masked */
2270                                 i386_fldcw_membase(cd, REG_ITMP1, a);
2271
2272                                 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2273
2274                                 a = 3;
2275                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2276                                 a += 5 + 2 + 3;
2277                                 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2278
2279                         } else {
2280                                 a = dseg_adds4(cd, 0);
2281                                 i386_fistpl_membase(cd, REG_ITMP1, a);
2282                                 fpu_st_offset--;
2283                                 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2284
2285                                 a = dseg_adds4(cd, 0x027f);    /* Round to nearest, 53-bit mode, exceptions masked */
2286                                 i386_fldcw_membase(cd, REG_ITMP1, a);
2287
2288                                 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2289
2290                                 a = 3;
2291                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2292                                 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2293                         }
2294
2295                         i386_jcc(cd, I386_CC_NE, a);
2296
2297                         /* XXX: change this when we use registers */
2298                         i386_flds_membase(cd, REG_SP, src->regoff * 8);
2299                         i386_mov_imm_reg(cd, (s4) asm_builtin_f2i, REG_ITMP1);
2300                         i386_call_reg(cd, REG_ITMP1);
2301
2302                         if (iptr->dst->flags & INMEMORY) {
2303                                 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2304
2305                         } else {
2306                                 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2307                         }
2308                         break;
2309
2310                 case ICMD_D2I:       /* ..., value  ==> ..., (int) value              */
2311
2312                         var_to_reg_flt(s1, src, REG_FTMP1);
2313                         d = reg_of_var(rd, iptr->dst, REG_NULL);
2314
2315                         a = dseg_adds4(cd, 0x0e7f);    /* Round to zero, 53-bit mode, exception masked */
2316                         i386_mov_imm_reg(cd, 0, REG_ITMP1);
2317                         dseg_adddata(cd, cd->mcodeptr);
2318                         i386_fldcw_membase(cd, REG_ITMP1, a);
2319
2320                         if (iptr->dst->flags & INMEMORY) {
2321                                 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2322                                 fpu_st_offset--;
2323
2324                                 a = dseg_adds4(cd, 0x027f);    /* Round to nearest, 53-bit mode, exceptions masked */
2325                                 i386_fldcw_membase(cd, REG_ITMP1, a);
2326
2327                                 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2328
2329                                 a = 3;
2330                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2331                                 a += 5 + 2 + 3;
2332                                 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2333
2334                         } else {
2335                                 a = dseg_adds4(cd, 0);
2336                                 i386_fistpl_membase(cd, REG_ITMP1, a);
2337                                 fpu_st_offset--;
2338                                 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2339
2340                                 a = dseg_adds4(cd, 0x027f);    /* Round to nearest, 53-bit mode, exceptions masked */
2341                                 i386_fldcw_membase(cd, REG_ITMP1, a);
2342
2343                                 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2344
2345                                 a = 3;
2346                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2347                                 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2348                         }
2349
2350                         i386_jcc(cd, I386_CC_NE, a);
2351
2352                         /* XXX: change this when we use registers */
2353                         i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2354                         i386_mov_imm_reg(cd, (s4) asm_builtin_d2i, REG_ITMP1);
2355                         i386_call_reg(cd, REG_ITMP1);
2356
2357                         if (iptr->dst->flags & INMEMORY) {
2358                                 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2359                         } else {
2360                                 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2361                         }
2362                         break;
2363
2364                 case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */
2365
2366                         var_to_reg_flt(s1, src, REG_FTMP1);
2367                         d = reg_of_var(rd, iptr->dst, REG_NULL);
2368
2369                         a = dseg_adds4(cd, 0x0e7f);    /* Round to zero, 53-bit mode, exception masked */
2370                         i386_mov_imm_reg(cd, 0, REG_ITMP1);
2371                         dseg_adddata(cd, cd->mcodeptr);
2372                         i386_fldcw_membase(cd, REG_ITMP1, a);
2373
2374                         if (iptr->dst->flags & INMEMORY) {
2375                                 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2376                                 fpu_st_offset--;
2377
2378                                 a = dseg_adds4(cd, 0x027f);    /* Round to nearest, 53-bit mode, exceptions masked */
2379                                 i386_fldcw_membase(cd, REG_ITMP1, a);
2380
2381                                 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2382
2383                                 a = 6 + 4;
2384                                 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2385                                 a += 3;
2386                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2387                                 a += 5 + 2;
2388                                 a += 3;
2389                                 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2390                                 a += 3;
2391                                 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2392
2393                                 i386_jcc(cd, I386_CC_NE, a);
2394
2395                                 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2396
2397                                 a = 3;
2398                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2399                                 a += 5 + 2 + 3;
2400                                 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2401
2402                                 i386_jcc(cd, I386_CC_NE, a);
2403
2404                                 /* XXX: change this when we use registers */
2405                                 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2406                                 i386_mov_imm_reg(cd, (s4) asm_builtin_f2l, REG_ITMP1);
2407                                 i386_call_reg(cd, REG_ITMP1);
2408                                 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2409                                 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2410
2411                         } else {
2412                                 panic("F2L: longs have to be in memory");
2413                         }
2414                         break;
2415
2416                 case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */
2417
2418                         var_to_reg_flt(s1, src, REG_FTMP1);
2419                         d = reg_of_var(rd, iptr->dst, REG_NULL);
2420
2421                         a = dseg_adds4(cd, 0x0e7f);    /* Round to zero, 53-bit mode, exception masked */
2422                         i386_mov_imm_reg(cd, 0, REG_ITMP1);
2423                         dseg_adddata(cd, cd->mcodeptr);
2424                         i386_fldcw_membase(cd, REG_ITMP1, a);
2425
2426                         if (iptr->dst->flags & INMEMORY) {
2427                                 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2428                                 fpu_st_offset--;
2429
2430                                 a = dseg_adds4(cd, 0x027f);    /* Round to nearest, 53-bit mode, exceptions masked */
2431                                 i386_fldcw_membase(cd, REG_ITMP1, a);
2432
2433                                 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2434
2435                                 a = 6 + 4;
2436                                 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2437                                 a += 3;
2438                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2439                                 a += 5 + 2;
2440                                 a += 3;
2441                                 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2442                                 a += 3;
2443                                 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2444
2445                                 i386_jcc(cd, I386_CC_NE, a);
2446
2447                                 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2448
2449                                 a = 3;
2450                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2451                                 a += 5 + 2 + 3;
2452                                 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2453
2454                                 i386_jcc(cd, I386_CC_NE, a);
2455
2456                                 /* XXX: change this when we use registers */
2457                                 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2458                                 i386_mov_imm_reg(cd, (s4) asm_builtin_d2l, REG_ITMP1);
2459                                 i386_call_reg(cd, REG_ITMP1);
2460                                 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2461                                 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2462
2463                         } else {
2464                                 panic("D2L: longs have to be in memory");
2465                         }
2466                         break;
2467
2468                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
2469
2470                         var_to_reg_flt(s1, src, REG_FTMP1);
2471                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2472                         /* nothing to do */
2473                         store_reg_to_var_flt(iptr->dst, d);
2474                         break;
2475
2476                 case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */
2477
2478                         var_to_reg_flt(s1, src, REG_FTMP1);
2479                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2480                         /* nothing to do */
2481                         store_reg_to_var_flt(iptr->dst, d);
2482                         break;
2483
2484                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
2485                 case ICMD_DCMPL:
2486
2487                         /* exchanged to skip fxch */
2488                         var_to_reg_flt(s2, src->prev, REG_FTMP1);
2489                         var_to_reg_flt(s1, src, REG_FTMP2);
2490                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2491 /*                      i386_fxch(cd); */
2492                         i386_fucompp(cd);
2493                         fpu_st_offset -= 2;
2494                         i386_fnstsw(cd);
2495                         i386_test_imm_reg(cd, 0x400, EAX);    /* unordered treat as GT */
2496                         i386_jcc(cd, I386_CC_E, 6);
2497                         i386_alu_imm_reg(cd, I386_AND, 0x000000ff, EAX);
2498                         i386_sahf(cd);
2499                         i386_mov_imm_reg(cd, 0, d);    /* does not affect flags */
2500                         i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2501                         i386_jcc(cd, I386_CC_B, 3 + 5);
2502                         i386_alu_imm_reg(cd, I386_SUB, 1, d);
2503                         i386_jmp_imm(cd, 3);
2504                         i386_alu_imm_reg(cd, I386_ADD, 1, d);
2505                         store_reg_to_var_int(iptr->dst, d);
2506                         break;
2507
2508                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
2509                 case ICMD_DCMPG:
2510
2511                         /* exchanged to skip fxch */
2512                         var_to_reg_flt(s2, src->prev, REG_FTMP1);
2513                         var_to_reg_flt(s1, src, REG_FTMP2);
2514                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2515 /*                      i386_fxch(cd); */
2516                         i386_fucompp(cd);
2517                         fpu_st_offset -= 2;
2518                         i386_fnstsw(cd);
2519                         i386_test_imm_reg(cd, 0x400, EAX);    /* unordered treat as LT */
2520                         i386_jcc(cd, I386_CC_E, 3);
2521                         i386_movb_imm_reg(cd, 1, I386_AH);
2522                         i386_sahf(cd);
2523                         i386_mov_imm_reg(cd, 0, d);    /* does not affect flags */
2524                         i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2525                         i386_jcc(cd, I386_CC_B, 3 + 5);
2526                         i386_alu_imm_reg(cd, I386_SUB, 1, d);
2527                         i386_jmp_imm(cd, 3);
2528                         i386_alu_imm_reg(cd, I386_ADD, 1, d);
2529                         store_reg_to_var_int(iptr->dst, d);
2530                         break;
2531
2532
2533                 /* memory operations **************************************************/
2534
2535                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
2536
2537                         var_to_reg_int(s1, src, REG_ITMP1);
2538                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2539                         gen_nullptr_check(s1);
2540                         i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2541                         store_reg_to_var_int(iptr->dst, d);
2542                         break;
2543
2544                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
2545
2546                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2547                         var_to_reg_int(s2, src, REG_ITMP2);
2548                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2549                         if (iptr->op1 == 0) {
2550                                 gen_nullptr_check(s1);
2551                                 gen_bound_check;
2552                         }
2553                         i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2554                         store_reg_to_var_int(iptr->dst, d);
2555                         break;
2556
2557                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
2558
2559                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2560                         var_to_reg_int(s2, src, REG_ITMP2);
2561                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2562                         if (iptr->op1 == 0) {
2563                                 gen_nullptr_check(s1);
2564                                 gen_bound_check;
2565                         }
2566                         
2567                         if (iptr->dst->flags & INMEMORY) {
2568                                 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2569                                 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2570                                 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2571                                 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2572                         }
2573                         break;
2574
2575                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
2576
2577                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2578                         var_to_reg_int(s2, src, REG_ITMP2);
2579                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2580                         if (iptr->op1 == 0) {
2581                                 gen_nullptr_check(s1);
2582                                 gen_bound_check;
2583                         }
2584                         i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2585                         store_reg_to_var_int(iptr->dst, d);
2586                         break;
2587
2588                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
2589
2590                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2591                         var_to_reg_int(s2, src, REG_ITMP2);
2592                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2593                         if (iptr->op1 == 0) {
2594                                 gen_nullptr_check(s1);
2595                                 gen_bound_check;
2596                         }
2597                         i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2598                         fpu_st_offset++;
2599                         store_reg_to_var_flt(iptr->dst, d);
2600                         break;
2601
2602                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
2603
2604                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2605                         var_to_reg_int(s2, src, REG_ITMP2);
2606                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2607                         if (iptr->op1 == 0) {
2608                                 gen_nullptr_check(s1);
2609                                 gen_bound_check;
2610                         }
2611                         i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2612                         fpu_st_offset++;
2613                         store_reg_to_var_flt(iptr->dst, d);
2614                         break;
2615
2616                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
2617
2618                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2619                         var_to_reg_int(s2, src, REG_ITMP2);
2620                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2621                         if (iptr->op1 == 0) {
2622                                 gen_nullptr_check(s1);
2623                                 gen_bound_check;
2624                         }
2625                         i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2626                         store_reg_to_var_int(iptr->dst, d);
2627                         break;                  
2628
2629                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
2630
2631                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2632                         var_to_reg_int(s2, src, REG_ITMP2);
2633                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2634                         if (iptr->op1 == 0) {
2635                                 gen_nullptr_check(s1);
2636                                 gen_bound_check;
2637                         }
2638                         i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2639                         store_reg_to_var_int(iptr->dst, d);
2640                         break;
2641
2642                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
2643
2644                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2645                         var_to_reg_int(s2, src, REG_ITMP2);
2646                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2647                         if (iptr->op1 == 0) {
2648                                 gen_nullptr_check(s1);
2649                                 gen_bound_check;
2650                         }
2651                         i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2652                         store_reg_to_var_int(iptr->dst, d);
2653                         break;
2654
2655
2656                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
2657
2658                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2659                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2660                         if (iptr->op1 == 0) {
2661                                 gen_nullptr_check(s1);
2662                                 gen_bound_check;
2663                         }
2664                         var_to_reg_int(s3, src, REG_ITMP3);
2665                         i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2666                         break;
2667
2668                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
2669
2670                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2671                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2672                         if (iptr->op1 == 0) {
2673                                 gen_nullptr_check(s1);
2674                                 gen_bound_check;
2675                         }
2676
2677                         if (src->flags & INMEMORY) {
2678                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
2679                                 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2680                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2681                                 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2682                         }
2683                         break;
2684
2685                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
2686
2687                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2688                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2689                         if (iptr->op1 == 0) {
2690                                 gen_nullptr_check(s1);
2691                                 gen_bound_check;
2692                         }
2693                         var_to_reg_int(s3, src, REG_ITMP3);
2694                         i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2695                         break;
2696
2697                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
2698
2699                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2700                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2701                         if (iptr->op1 == 0) {
2702                                 gen_nullptr_check(s1);
2703                                 gen_bound_check;
2704                         }
2705                         var_to_reg_flt(s3, src, REG_FTMP1);
2706                         i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2707                         fpu_st_offset--;
2708                         break;
2709
2710                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
2711
2712                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2713                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2714                         if (iptr->op1 == 0) {
2715                                 gen_nullptr_check(s1);
2716                                 gen_bound_check;
2717                         }
2718                         var_to_reg_flt(s3, src, REG_FTMP1);
2719                         i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2720                         fpu_st_offset--;
2721                         break;
2722
2723                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
2724
2725                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2726                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2727                         if (iptr->op1 == 0) {
2728                                 gen_nullptr_check(s1);
2729                                 gen_bound_check;
2730                         }
2731                         var_to_reg_int(s3, src, REG_ITMP3);
2732                         i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2733                         break;
2734
2735                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
2736
2737                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2738                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2739                         if (iptr->op1 == 0) {
2740                                 gen_nullptr_check(s1);
2741                                 gen_bound_check;
2742                         }
2743                         var_to_reg_int(s3, src, REG_ITMP3);
2744                         i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2745                         break;
2746
2747                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
2748
2749                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2750                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2751                         if (iptr->op1 == 0) {
2752                                 gen_nullptr_check(s1);
2753                                 gen_bound_check;
2754                         }
2755                         var_to_reg_int(s3, src, REG_ITMP3);
2756                         if (s3 >= EBP) {    /* because EBP, ESI, EDI have no xH and xL nibbles */
2757                                 M_INTMOVE(s3, REG_ITMP3);
2758                                 s3 = REG_ITMP3;
2759                         }
2760                         i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2761                         break;
2762
2763                 case ICMD_IASTORECONST: /* ..., arrayref, index  ==> ...              */
2764
2765                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2766                         var_to_reg_int(s2, src, REG_ITMP2);
2767                         if (iptr->op1 == 0) {
2768                                 gen_nullptr_check(s1);
2769                                 gen_bound_check;
2770                         }
2771                         i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2772                         break;
2773
2774                 case ICMD_LASTORECONST: /* ..., arrayref, index  ==> ...              */
2775
2776                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2777                         var_to_reg_int(s2, src, REG_ITMP2);
2778                         if (iptr->op1 == 0) {
2779                                 gen_nullptr_check(s1);
2780                                 gen_bound_check;
2781                         }
2782
2783                         i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2784                         i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2785                         break;
2786
2787                 case ICMD_AASTORECONST: /* ..., arrayref, index  ==> ...              */
2788
2789                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2790                         var_to_reg_int(s2, src, REG_ITMP2);
2791                         if (iptr->op1 == 0) {
2792                                 gen_nullptr_check(s1);
2793                                 gen_bound_check;
2794                         }
2795                         i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2796                         break;
2797
2798                 case ICMD_BASTORECONST: /* ..., arrayref, index  ==> ...              */
2799
2800                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2801                         var_to_reg_int(s2, src, REG_ITMP2);
2802                         if (iptr->op1 == 0) {
2803                                 gen_nullptr_check(s1);
2804                                 gen_bound_check;
2805                         }
2806                         i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2807                         break;
2808
2809                 case ICMD_CASTORECONST:   /* ..., arrayref, index  ==> ...            */
2810
2811                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2812                         var_to_reg_int(s2, src, REG_ITMP2);
2813                         if (iptr->op1 == 0) {
2814                                 gen_nullptr_check(s1);
2815                                 gen_bound_check;
2816                         }
2817                         i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2818                         break;
2819
2820                 case ICMD_SASTORECONST:   /* ..., arrayref, index  ==> ...            */
2821
2822                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2823                         var_to_reg_int(s2, src, REG_ITMP2);
2824                         if (iptr->op1 == 0) {
2825                                 gen_nullptr_check(s1);
2826                                 gen_bound_check;
2827                         }
2828                         i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2829                         break;
2830
2831
2832                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
2833                                       /* op1 = type, val.a = field address            */
2834
2835                         /* if class isn't yet initialized, do it */
2836                         if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2837                                 /* call helper function which patches this code */
2838                                 i386_mov_imm_reg(cd, (s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2839                                 i386_mov_imm_reg(cd, (s4) asm_check_clinit, REG_ITMP2);
2840                                 i386_call_reg(cd, REG_ITMP2);
2841                         }
2842
2843                         a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
2844                         /* here it's slightly slower */
2845                         i386_mov_imm_reg(cd, 0, REG_ITMP2);
2846                         dseg_adddata(cd, cd->mcodeptr);
2847                         i386_mov_membase_reg(cd, REG_ITMP2, a, REG_ITMP2);
2848                         switch (iptr->op1) {
2849                         case TYPE_INT:
2850                         case TYPE_ADR:
2851                                 var_to_reg_int(s2, src, REG_ITMP1);
2852                                 i386_mov_reg_membase(cd, s2, REG_ITMP2, 0);
2853                                 break;
2854                         case TYPE_LNG:
2855                                 if (src->flags & INMEMORY) {
2856                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
2857                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_ITMP2, 0);
2858                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
2859                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_ITMP2, 0 + 4);
2860                                 } else {
2861                                         panic("PUTSTATIC: longs have to be in memory");
2862                                 }
2863                                 break;
2864                         case TYPE_FLT:
2865                                 var_to_reg_flt(s2, src, REG_FTMP1);
2866                                 i386_fstps_membase(cd, REG_ITMP2, 0);
2867                                 fpu_st_offset--;
2868                                 break;
2869                         case TYPE_DBL:
2870                                 var_to_reg_flt(s2, src, REG_FTMP1);
2871                                 i386_fstpl_membase(cd, REG_ITMP2, 0);
2872                                 fpu_st_offset--;
2873                                 break;
2874                         default: panic ("internal error");
2875                         }
2876                         break;
2877
2878                 case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
2879                                       /* op1 = type, val.a = field address            */
2880
2881                         /* if class isn't yet initialized, do it */
2882                         if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2883                                 /* call helper function which patches this code */
2884                                 i386_mov_imm_reg(cd, (s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2885                                 i386_mov_imm_reg(cd, (s4) asm_check_clinit, REG_ITMP2);
2886                                 i386_call_reg(cd, REG_ITMP2);
2887                         }
2888
2889                         a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
2890                         i386_mov_imm_reg(cd, 0, REG_ITMP2);
2891                         dseg_adddata(cd, cd->mcodeptr);
2892                         i386_mov_membase_reg(cd, REG_ITMP2, a, REG_ITMP2);
2893                         switch (iptr->op1) {
2894                         case TYPE_INT:
2895                         case TYPE_ADR:
2896                                 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2897                                 i386_mov_membase_reg(cd, REG_ITMP2, 0, d);
2898                                 store_reg_to_var_int(iptr->dst, d);
2899                                 break;
2900                         case TYPE_LNG:
2901                                 d = reg_of_var(rd, iptr->dst, REG_NULL);
2902                                 if (iptr->dst->flags & INMEMORY) {
2903                                         i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP1);
2904                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2905                                         i386_mov_membase_reg(cd, REG_ITMP2, 0 + 4, REG_ITMP1);
2906                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
2907                                 } else {
2908                                         panic("GETSTATIC: longs have to be in memory");
2909                                 }
2910                                 break;
2911                         case TYPE_FLT:
2912                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2913                                 i386_flds_membase(cd, REG_ITMP2, 0);
2914                                 fpu_st_offset++;
2915                                 store_reg_to_var_flt(iptr->dst, d);
2916                                 break;
2917                         case TYPE_DBL:                          
2918                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2919                                 i386_fldl_membase(cd, REG_ITMP2, 0);
2920                                 fpu_st_offset++;
2921                                 store_reg_to_var_flt(iptr->dst, d);
2922                                 break;
2923                         default: panic ("internal error");
2924                         }
2925                         break;
2926
2927                 case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
2928                                       /* op1 = type, val.i = field offset             */
2929
2930                         a = ((fieldinfo *)(iptr->val.a))->offset;
2931                         switch (iptr->op1) {
2932                                 case TYPE_INT:
2933                                 case TYPE_ADR:
2934                                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2935                                         var_to_reg_int(s2, src, REG_ITMP2);
2936                                         gen_nullptr_check(s1);
2937                                         i386_mov_reg_membase(cd, s2, s1, a);
2938                                         break;
2939                                 case TYPE_LNG:
2940                                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2941                                         gen_nullptr_check(s1);
2942                                         if (src->flags & INMEMORY) {
2943                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);
2944                                                 i386_mov_reg_membase(cd, REG_ITMP2, s1, a);
2945                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2946                                                 i386_mov_reg_membase(cd, REG_ITMP2, s1, a + 4);
2947                                         } else {
2948                                                 panic("PUTFIELD: longs have to be in memory");
2949                                         }
2950                                         break;
2951                                 case TYPE_FLT:
2952                                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2953                                         var_to_reg_flt(s2, src, REG_FTMP1);
2954                                         gen_nullptr_check(s1);
2955                                         i386_fstps_membase(cd, s1, a);
2956                                         fpu_st_offset--;
2957                                         break;
2958                                 case TYPE_DBL:
2959                                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2960                                         var_to_reg_flt(s2, src, REG_FTMP1);
2961                                         gen_nullptr_check(s1);
2962                                         i386_fstpl_membase(cd, s1, a);
2963                                         fpu_st_offset--;
2964                                         break;
2965                                 default: panic ("internal error");
2966                                 }
2967                         break;
2968
2969                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
2970                                       /* op1 = type, val.i = field offset             */
2971
2972                         a = ((fieldinfo *)(iptr->val.a))->offset;
2973                         switch (iptr->op1) {
2974                                 case TYPE_INT:
2975                                 case TYPE_ADR:
2976                                         var_to_reg_int(s1, src, REG_ITMP1);
2977                                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2978                                         gen_nullptr_check(s1);
2979                                         i386_mov_membase_reg(cd, s1, a, d);
2980                                         store_reg_to_var_int(iptr->dst, d);
2981                                         break;
2982                                 case TYPE_LNG:
2983                                         var_to_reg_int(s1, src, REG_ITMP1);
2984                                         d = reg_of_var(rd, iptr->dst, REG_NULL);
2985                                         gen_nullptr_check(s1);
2986                                         i386_mov_membase_reg(cd, s1, a, REG_ITMP2);
2987                                         i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
2988                                         i386_mov_membase_reg(cd, s1, a + 4, REG_ITMP2);
2989                                         i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2990                                         break;
2991                                 case TYPE_FLT:
2992                                         var_to_reg_int(s1, src, REG_ITMP1);
2993                                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2994                                         gen_nullptr_check(s1);
2995                                         i386_flds_membase(cd, s1, a);
2996                                         fpu_st_offset++;
2997                                         store_reg_to_var_flt(iptr->dst, d);
2998                                         break;
2999                                 case TYPE_DBL:                          
3000                                         var_to_reg_int(s1, src, REG_ITMP1);
3001                                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3002                                         gen_nullptr_check(s1);
3003                                         i386_fldl_membase(cd, s1, a);
3004                                         fpu_st_offset++;
3005                                         store_reg_to_var_flt(iptr->dst, d);
3006                                         break;
3007                                 default: panic ("internal error");
3008                                 }
3009                         break;
3010
3011
3012                 /* branch operations **************************************************/
3013
3014                         /* TWISTI */
3015 /*  #define ALIGNCODENOP {if((int)((long)cd->mcodeptr&7)){M_NOP;}} */
3016 #define ALIGNCODENOP do {} while (0)
3017
3018                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
3019
3020                         var_to_reg_int(s1, src, REG_ITMP1);
3021                         M_INTMOVE(s1, REG_ITMP1_XPTR);
3022
3023                         i386_call_imm(cd, 0);                    /* passing exception pointer */
3024                         i386_pop_reg(cd, REG_ITMP2_XPC);
3025
3026                         i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
3027                         i386_jmp_reg(cd, REG_ITMP3);
3028                         ALIGNCODENOP;
3029                         break;
3030
3031                 case ICMD_GOTO:         /* ... ==> ...                                */
3032                                         /* op1 = target JavaVM pc                     */
3033
3034                         i386_jmp_imm(cd, 0);
3035                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3036                         ALIGNCODENOP;
3037                         break;
3038
3039                 case ICMD_JSR:          /* ... ==> ...                                */
3040                                         /* op1 = target JavaVM pc                     */
3041
3042                         i386_call_imm(cd, 0);
3043                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3044                         break;
3045                         
3046                 case ICMD_RET:          /* ... ==> ...                                */
3047                                         /* op1 = local variable                       */
3048
3049                         var = &(rd->locals[iptr->op1][TYPE_ADR]);
3050                         var_to_reg_int(s1, var, REG_ITMP1);
3051                         i386_jmp_reg(cd, s1);
3052                         break;
3053
3054                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
3055                                         /* op1 = target JavaVM pc                     */
3056
3057                         if (src->flags & INMEMORY) {
3058                                 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3059
3060                         } else {
3061                                 i386_test_reg_reg(cd, src->regoff, src->regoff);
3062                         }
3063                         i386_jcc(cd, I386_CC_E, 0);
3064                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3065                         break;
3066
3067                 case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
3068                                         /* op1 = target JavaVM pc                     */
3069
3070                         if (src->flags & INMEMORY) {
3071                                 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3072
3073                         } else {
3074                                 i386_test_reg_reg(cd, src->regoff, src->regoff);
3075                         }
3076                         i386_jcc(cd, I386_CC_NE, 0);
3077                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3078                         break;
3079
3080                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
3081                                         /* op1 = target JavaVM pc, val.i = constant   */
3082
3083                         if (src->flags & INMEMORY) {
3084                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3085
3086                         } else {
3087                                 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3088                         }
3089                         i386_jcc(cd, I386_CC_E, 0);
3090                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3091                         break;
3092
3093                 case ICMD_IFLT:         /* ..., value ==> ...                         */
3094                                         /* op1 = target JavaVM pc, val.i = constant   */
3095
3096                         if (src->flags & INMEMORY) {
3097                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3098
3099                         } else {
3100                                 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3101                         }
3102                         i386_jcc(cd, I386_CC_L, 0);
3103                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3104                         break;
3105
3106                 case ICMD_IFLE:         /* ..., value ==> ...                         */
3107                                         /* op1 = target JavaVM pc, val.i = constant   */
3108
3109                         if (src->flags & INMEMORY) {
3110                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3111
3112                         } else {
3113                                 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3114                         }
3115                         i386_jcc(cd, I386_CC_LE, 0);
3116                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3117                         break;
3118
3119                 case ICMD_IFNE:         /* ..., value ==> ...                         */
3120                                         /* op1 = target JavaVM pc, val.i = constant   */
3121
3122                         if (src->flags & INMEMORY) {
3123                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3124
3125                         } else {
3126                                 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3127                         }
3128                         i386_jcc(cd, I386_CC_NE, 0);
3129                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3130                         break;
3131
3132                 case ICMD_IFGT:         /* ..., value ==> ...                         */
3133                                         /* op1 = target JavaVM pc, val.i = constant   */
3134
3135                         if (src->flags & INMEMORY) {
3136                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3137
3138                         } else {
3139                                 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3140                         }
3141                         i386_jcc(cd, I386_CC_G, 0);
3142                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3143                         break;
3144
3145                 case ICMD_IFGE:         /* ..., value ==> ...                         */
3146                                         /* op1 = target JavaVM pc, val.i = constant   */
3147
3148                         if (src->flags & INMEMORY) {
3149                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3150
3151                         } else {
3152                                 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3153                         }
3154                         i386_jcc(cd, I386_CC_GE, 0);
3155                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3156                         break;
3157
3158                 case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
3159                                         /* op1 = target JavaVM pc, val.l = constant   */
3160
3161                         if (src->flags & INMEMORY) {
3162                                 if (iptr->val.l == 0) {
3163                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3164                                         i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3165
3166                                 } else {
3167                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3168                                         i386_alu_imm_reg(cd, I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3169                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3170                                         i386_alu_imm_reg(cd, I386_XOR, iptr->val.l, REG_ITMP1);
3171                                         i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3172                                 }
3173                         }
3174                         i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3175                         i386_jcc(cd, I386_CC_E, 0);
3176                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3177                         break;
3178
3179                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
3180                                         /* op1 = target JavaVM pc, val.l = constant   */
3181
3182                         if (src->flags & INMEMORY) {
3183                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3184                                 i386_jcc(cd, I386_CC_L, 0);
3185                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3186
3187                                 a = 3 + 6;
3188                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3189                                 CALCIMMEDIATEBYTES(a, iptr->val.l);
3190
3191                                 i386_jcc(cd, I386_CC_G, a);
3192
3193                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3194                                 i386_jcc(cd, I386_CC_B, 0);
3195                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3196                         }                       
3197                         break;
3198
3199                 case ICMD_IF_LLE:       /* ..., value ==> ...                         */
3200                                         /* op1 = target JavaVM pc, val.l = constant   */
3201
3202                         if (src->flags & INMEMORY) {
3203                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3204                                 i386_jcc(cd, I386_CC_L, 0);
3205                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3206
3207                                 a = 3 + 6;
3208                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3209                                 CALCIMMEDIATEBYTES(a, iptr->val.l);
3210                                 
3211                                 i386_jcc(cd, I386_CC_G, a);
3212
3213                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3214                                 i386_jcc(cd, I386_CC_BE, 0);
3215                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3216                         }                       
3217                         break;
3218
3219                 case ICMD_IF_LNE:       /* ..., value ==> ...                         */
3220                                         /* op1 = target JavaVM pc, val.l = constant   */
3221
3222                         if (src->flags & INMEMORY) {
3223                                 if (iptr->val.l == 0) {
3224                                         i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3225                                         i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3226
3227                                 } else {
3228                                         i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3229                                         i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3230                                         i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3231                                         i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3232                                         i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3233                                 }
3234                         }
3235                         i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3236                         i386_jcc(cd, I386_CC_NE, 0);
3237                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3238                         break;
3239
3240                 case ICMD_IF_LGT:       /* ..., value ==> ...                         */
3241                                         /* op1 = target JavaVM pc, val.l = constant   */
3242
3243                         if (src->flags & INMEMORY) {
3244                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3245                                 i386_jcc(cd, I386_CC_G, 0);
3246                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3247
3248                                 a = 3 + 6;
3249                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3250                                 CALCIMMEDIATEBYTES(a, iptr->val.l);
3251
3252                                 i386_jcc(cd, I386_CC_L, a);
3253
3254                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3255                                 i386_jcc(cd, I386_CC_A, 0);
3256                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3257                         }                       
3258                         break;
3259
3260                 case ICMD_IF_LGE:       /* ..., value ==> ...                         */
3261                                         /* op1 = target JavaVM pc, val.l = constant   */
3262
3263                         if (src->flags & INMEMORY) {
3264                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3265                                 i386_jcc(cd, I386_CC_G, 0);
3266                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3267
3268                                 a = 3 + 6;
3269                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3270                                 CALCIMMEDIATEBYTES(a, iptr->val.l);
3271
3272                                 i386_jcc(cd, I386_CC_L, a);
3273
3274                                 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3275                                 i386_jcc(cd, I386_CC_AE, 0);
3276                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3277                         }                       
3278                         break;
3279
3280                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
3281                 case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
3282
3283                         if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3284                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3285                                 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3286
3287                         } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3288                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3289
3290                         } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3291                                 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3292
3293                         } else {
3294                                 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3295                         }
3296                         i386_jcc(cd, I386_CC_E, 0);
3297                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3298                         break;
3299
3300                 case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
3301                                         /* op1 = target JavaVM pc                     */
3302
3303                         if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3304                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3305                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3306                                 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3307                                 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3308                                 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3309                                 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3310                         }                       
3311                         i386_jcc(cd, I386_CC_E, 0);
3312                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3313                         break;
3314
3315                 case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
3316                 case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
3317
3318                         if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3319                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3320                                 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3321
3322                         } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3323                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3324
3325                         } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3326                                 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3327
3328                         } else {
3329                                 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3330                         }
3331                         i386_jcc(cd, I386_CC_NE, 0);
3332                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3333                         break;
3334
3335                 case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
3336                                         /* op1 = target JavaVM pc                     */
3337
3338                         if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3339                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3340                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3341                                 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3342                                 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3343                                 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3344                                 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3345                         }                       
3346                         i386_jcc(cd, I386_CC_NE, 0);
3347                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3348                         break;
3349
3350                 case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
3351                                         /* op1 = target JavaVM pc                     */
3352
3353                         if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3354                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3355                                 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3356
3357                         } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3358                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3359
3360                         } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3361                                 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3362
3363                         } else {
3364                                 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3365                         }
3366                         i386_jcc(cd, I386_CC_L, 0);
3367                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3368                         break;
3369
3370                 case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
3371                                     /* op1 = target JavaVM pc                     */
3372
3373                         if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3374                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3375                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3376                                 i386_jcc(cd, I386_CC_L, 0);
3377                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3378
3379                                 a = 3 + 3 + 6;
3380                                 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3381                                 CALCOFFSETBYTES(a, REG_SP, src->regoff);
3382
3383                                 i386_jcc(cd, I386_CC_G, a);
3384
3385                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3386                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3387                                 i386_jcc(cd, I386_CC_B, 0);
3388                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3389                         }                       
3390                         break;
3391
3392                 case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
3393                                         /* op1 = target JavaVM pc                     */
3394
3395                         if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3396                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3397                                 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3398
3399                         } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3400                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3401
3402                         } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3403                                 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3404
3405                         } else {
3406                                 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3407                         }
3408                         i386_jcc(cd, I386_CC_G, 0);
3409                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3410                         break;
3411
3412                 case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
3413                                 /* op1 = target JavaVM pc                     */
3414
3415                         if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3416                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3417                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3418                                 i386_jcc(cd, I386_CC_G, 0);
3419                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3420
3421                                 a = 3 + 3 + 6;
3422                                 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3423                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3424
3425                                 i386_jcc(cd, I386_CC_L, a);
3426
3427                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3428                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3429                                 i386_jcc(cd, I386_CC_A, 0);
3430                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3431                         }                       
3432                         break;
3433
3434                 case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
3435                                         /* op1 = target JavaVM pc                     */
3436
3437                         if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3438                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3439                                 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3440
3441                         } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3442                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3443
3444                         } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3445                                 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3446
3447                         } else {
3448                                 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3449                         }
3450                         i386_jcc(cd, I386_CC_LE, 0);
3451                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3452                         break;
3453
3454                 case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
3455                                         /* op1 = target JavaVM pc                     */
3456
3457                         if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3458                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3459                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3460                                 i386_jcc(cd, I386_CC_L, 0);
3461                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3462
3463                                 a = 3 + 3 + 6;
3464                                 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3465                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3466
3467                                 i386_jcc(cd, I386_CC_G, a);
3468
3469                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3470                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3471                                 i386_jcc(cd, I386_CC_BE, 0);
3472                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3473                         }                       
3474                         break;
3475
3476                 case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
3477                                         /* op1 = target JavaVM pc                     */
3478
3479                         if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3480                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3481                                 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3482
3483                         } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3484                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3485
3486                         } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3487                                 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3488
3489                         } else {
3490                                 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3491                         }
3492                         i386_jcc(cd, I386_CC_GE, 0);
3493                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3494                         break;
3495
3496                 case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
3497                                     /* op1 = target JavaVM pc                     */
3498
3499                         if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3500                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3501                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3502                                 i386_jcc(cd, I386_CC_G, 0);
3503                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3504
3505                                 a = 3 + 3 + 6;
3506                                 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3507                                 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3508
3509                                 i386_jcc(cd, I386_CC_L, a);
3510
3511                                 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3512                                 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3513                                 i386_jcc(cd, I386_CC_AE, 0);
3514                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3515                         }                       
3516                         break;
3517
3518                 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST                           */
3519
3520                 case ICMD_ELSE_ICONST:  /* handled by IFxx_ICONST                     */
3521                         break;
3522
3523                 case ICMD_IFEQ_ICONST:  /* ..., value ==> ..., constant               */
3524                                         /* val.i = constant                           */
3525
3526                         d = reg_of_var(rd, iptr->dst, REG_NULL);
3527                         i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
3528                         break;
3529
3530                 case ICMD_IFNE_ICONST:  /* ..., value ==> ..., constant               */
3531                                         /* val.i = constant                           */
3532
3533                         d = reg_of_var(rd, iptr->dst, REG_NULL);
3534                         i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
3535                         break;
3536
3537                 case ICMD_IFLT_ICONST:  /* ..., value ==> ..., constant               */
3538                                         /* val.i = constant                           */
3539
3540                         d = reg_of_var(rd, iptr->dst, REG_NULL);
3541                         i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
3542                         break;
3543
3544                 case ICMD_IFGE_ICONST:  /* ..., value ==> ..., constant               */
3545                                         /* val.i = constant                           */
3546
3547                         d = reg_of_var(rd, iptr->dst, REG_NULL);
3548                         i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
3549                         break;
3550
3551                 case ICMD_IFGT_ICONST:  /* ..., value ==> ..., constant               */
3552                                         /* val.i = constant                           */
3553
3554                         d = reg_of_var(rd, iptr->dst, REG_NULL);
3555                         i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
3556                         break;
3557
3558                 case ICMD_IFLE_ICONST:  /* ..., value ==> ..., constant               */
3559                                         /* val.i = constant                           */
3560
3561                         d = reg_of_var(rd, iptr->dst, REG_NULL);
3562                         i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
3563                         break;
3564
3565
3566                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
3567                 case ICMD_ARETURN:
3568
3569                         var_to_reg_int(s1, src, REG_RESULT);
3570                         M_INTMOVE(s1, REG_RESULT);
3571
3572                         goto nowperformreturn;
3573
3574                 case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
3575
3576                         if (src->flags & INMEMORY) {
3577                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_RESULT);
3578                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3579
3580                         } else {
3581                                 panic("LRETURN: longs have to be in memory");
3582                         }
3583
3584                         goto nowperformreturn;
3585
3586                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
3587                 case ICMD_DRETURN:      /* ..., retvalue ==> ...                      */
3588
3589                         var_to_reg_flt(s1, src, REG_FRESULT);
3590                         /* this may be an early return -- keep the offset correct for the
3591                            remaining code */
3592                         fpu_st_offset--;
3593
3594                         goto nowperformreturn;
3595
3596                 case ICMD_RETURN:      /* ...  ==> ...                                */
3597
3598 nowperformreturn:
3599                         {
3600                         s4 i, p;
3601                         
3602                         p = parentargs_base;
3603                         
3604                         /* call trace function */
3605                         if (runverbose) {
3606                                 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3607
3608                                 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3609
3610                                 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3611                                 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3612                                 
3613                                 i386_fstl_membase(cd, REG_SP, 4 + 8);
3614                                 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3615
3616                                 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3617                                 i386_call_reg(cd, REG_ITMP1);
3618
3619                                 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3620                                 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3621
3622                                 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3623                         }
3624
3625 #if defined(USE_THREADS)
3626                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3627                                 i386_mov_membase_reg(cd, REG_SP, 8 * rd->maxmemuse, REG_ITMP2);
3628
3629                                 /* we need to save the proper return value */
3630                                 switch (iptr->opc) {
3631                                 case ICMD_IRETURN:
3632                                 case ICMD_ARETURN:
3633                                         i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
3634                                         break;
3635
3636                                 case ICMD_LRETURN:
3637                                         i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
3638                                         i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, rd->maxmemuse * 8 + 4);
3639                                         break;
3640
3641                                 case ICMD_FRETURN:
3642                                         i386_fsts_membase(cd, REG_SP, rd->maxmemuse * 8);
3643                                         break;
3644
3645                                 case ICMD_DRETURN:
3646                                         i386_fstl_membase(cd, REG_SP, rd->maxmemuse * 8);
3647                                         break;
3648                                 }
3649
3650                                 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
3651                                 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, 0);
3652                                 i386_mov_imm_reg(cd, (s4) builtin_monitorexit, REG_ITMP1);
3653                                 i386_call_reg(cd, REG_ITMP1);
3654                                 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
3655
3656                                 /* and now restore the proper return value */
3657                                 switch (iptr->opc) {
3658                                 case ICMD_IRETURN:
3659                                 case ICMD_ARETURN:
3660                                         i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
3661                                         break;
3662
3663                                 case ICMD_LRETURN:
3664                                         i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
3665                                         i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8 + 4, REG_RESULT2);
3666                                         break;
3667
3668                                 case ICMD_FRETURN:
3669                                         i386_flds_membase(cd, REG_SP, rd->maxmemuse * 8);
3670                                         break;
3671
3672                                 case ICMD_DRETURN:
3673                                         i386_fldl_membase(cd, REG_SP, rd->maxmemuse * 8);
3674                                         break;
3675                                 }
3676                         }
3677 #endif
3678
3679                         /* restore saved registers */
3680                         for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
3681                                 p--;
3682                                 i386_mov_membase_reg(cd, REG_SP, p * 8, rd->savintregs[i]);
3683                         }
3684                         for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
3685                                 p--;
3686                                 i386_fldl_membase(cd, REG_SP, p * 8);
3687                                 fpu_st_offset++;
3688                                 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3689                                         i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
3690                                 } else {
3691                                         i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
3692                                 }
3693                                 fpu_st_offset--;
3694                         }
3695
3696                         /* deallocate stack                                               */
3697                         if (parentargs_base) {
3698                                 i386_alu_imm_reg(cd, I386_ADD, parentargs_base * 8, REG_SP);
3699                         }
3700
3701                         i386_ret(cd);
3702                         ALIGNCODENOP;
3703                         }
3704                         break;
3705
3706
3707                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
3708                         {
3709                                 s4 i, l, *s4ptr;
3710                                 void **tptr;
3711
3712                                 tptr = (void **) iptr->target;
3713
3714                                 s4ptr = iptr->val.a;
3715                                 l = s4ptr[1];                          /* low     */
3716                                 i = s4ptr[2];                          /* high    */
3717
3718                                 var_to_reg_int(s1, src, REG_ITMP1);
3719                                 M_INTMOVE(s1, REG_ITMP1);
3720                                 if (l != 0) {
3721                                         i386_alu_imm_reg(cd, I386_SUB, l, REG_ITMP1);
3722                                 }
3723                                 i = i - l + 1;
3724
3725                 /* range check */
3726
3727                                 i386_alu_imm_reg(cd, I386_CMP, i - 1, REG_ITMP1);
3728                                 i386_jcc(cd, I386_CC_A, 0);
3729
3730                 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
3731                                 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3732
3733                                 /* build jump table top down and use address of lowest entry */
3734
3735                 /* s4ptr += 3 + i; */
3736                                 tptr += i;
3737
3738                                 while (--i >= 0) {
3739                                         /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
3740                                         dseg_addtarget(cd, (basicblock *) tptr[0]); 
3741                                         --tptr;
3742                                 }
3743
3744                                 /* length of dataseg after last dseg_addtarget is used by load */
3745
3746                                 i386_mov_imm_reg(cd, 0, REG_ITMP2);
3747                                 dseg_adddata(cd, cd->mcodeptr);
3748                                 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3749                                 i386_jmp_reg(cd, REG_ITMP1);
3750                                 ALIGNCODENOP;
3751                         }
3752                         break;
3753
3754
3755                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
3756                         {
3757                                 s4 i, l, val, *s4ptr;
3758                                 void **tptr;
3759
3760                                 tptr = (void **) iptr->target;
3761
3762                                 s4ptr = iptr->val.a;
3763                                 l = s4ptr[0];                          /* default  */
3764                                 i = s4ptr[1];                          /* count    */
3765                         
3766                                 MCODECHECK((i<<2)+8);
3767                                 var_to_reg_int(s1, src, REG_ITMP1);    /* reg compare should always be faster */
3768                                 while (--i >= 0) {
3769                                         s4ptr += 2;
3770                                         ++tptr;
3771
3772                                         val = s4ptr[0];
3773                                         i386_alu_imm_reg(cd, I386_CMP, val, s1);
3774                                         i386_jcc(cd, I386_CC_E, 0);
3775                                         /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), cd->mcodeptr); */
3776                                         codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr); 
3777                                 }
3778
3779                                 i386_jmp_imm(cd, 0);
3780                                 /* codegen_addreference(cd, BlockPtrOfPC(l), cd->mcodeptr); */
3781                         
3782                                 tptr = (void **) iptr->target;
3783                                 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3784
3785                                 ALIGNCODENOP;
3786                         }
3787                         break;
3788
3789
3790                 case ICMD_BUILTIN3:     /* ..., arg1, arg2, arg3 ==> ...              */
3791                                         /* op1 = return type, val.a = function pointer*/
3792                         s3 = 3;
3793                         goto gen_method;
3794
3795                 case ICMD_BUILTIN2:     /* ..., arg1, arg2 ==> ...                    */
3796                                         /* op1 = return type, val.a = function pointer*/
3797                         s3 = 2;
3798                         goto gen_method;
3799
3800                 case ICMD_BUILTIN1:     /* ..., arg1 ==> ...                          */
3801                                         /* op1 = return type, val.a = function pointer*/
3802                         s3 = 1;
3803                         goto gen_method;
3804
3805                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
3806                                         /* op1 = arg count, val.a = method pointer    */
3807
3808                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3809                                         /* op1 = arg count, val.a = method pointer    */
3810
3811                 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3812                                         /* op1 = arg count, val.a = method pointer    */
3813
3814                 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3815                                         /* op1 = arg count, val.a = method pointer    */
3816
3817                         s3 = iptr->op1;
3818
3819 gen_method: {
3820                         methodinfo *lm;
3821
3822                         MCODECHECK((s3 << 1) + 64);
3823
3824                         /* copy arguments to registers or stack location                  */
3825
3826                         for (; --s3 >= 0; src = src->prev) {
3827                                 if (src->varkind == ARGVAR) {
3828                                         continue;
3829                                 }
3830
3831                                 if (IS_INT_LNG_TYPE(src->type)) {
3832                                         if (s3 < rd->intreg_argnum) {
3833                                                 panic("No integer argument registers available!");
3834
3835                                         } else {
3836                                                 if (!IS_2_WORD_TYPE(src->type)) {
3837                                                         if (src->flags & INMEMORY) {
3838                                                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3839                                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s3 * 8);
3840
3841                                                         } else {
3842                                                                 i386_mov_reg_membase(cd, src->regoff, REG_SP, s3 * 8);
3843                                                         }
3844
3845                                                 } else {
3846                                                         if (src->flags & INMEMORY) {
3847                                                                 M_LNGMEMMOVE(src->regoff, s3);
3848
3849                                                         } else {
3850                                                                 panic("copy arguments: longs have to be in memory");
3851                                                         }
3852                                                 }
3853                                         }
3854
3855                                 } else {
3856                                         if (s3 < rd->fltreg_argnum) {
3857                                                 panic("No float argument registers available!");
3858
3859                                         } else {
3860                                                 var_to_reg_flt(d, src, REG_FTMP1);
3861                                                 if (src->type == TYPE_FLT) {
3862                                                         i386_fstps_membase(cd, REG_SP, s3 * 8);
3863
3864                                                 } else {
3865                                                         i386_fstpl_membase(cd, REG_SP, s3 * 8);
3866                                                 }
3867                                         }
3868                                 }
3869                         } /* end of for */
3870
3871                         lm = iptr->val.a;
3872                         switch (iptr->opc) {
3873                         case ICMD_BUILTIN3:
3874                         case ICMD_BUILTIN2:
3875                         case ICMD_BUILTIN1:
3876                                 a = (u4) lm;
3877                                 d = iptr->op1;
3878
3879                                 i386_mov_imm_reg(cd, a, REG_ITMP1);
3880                                 i386_call_reg(cd, REG_ITMP1);
3881                                 break;
3882
3883                         case ICMD_INVOKESTATIC:
3884                                 a = (u4) lm->stubroutine;
3885                                 d = lm->returntype;
3886
3887                                 i386_mov_imm_reg(cd, a, REG_ITMP2);
3888                                 i386_call_reg(cd, REG_ITMP2);
3889                                 break;
3890
3891                         case ICMD_INVOKESPECIAL:
3892                                 a = (u4) lm->stubroutine;
3893                                 d = lm->returntype;
3894
3895                                 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3896                                 gen_nullptr_check(REG_ITMP1);
3897                                 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1);    /* access memory for hardware nullptr */
3898
3899                                 i386_mov_imm_reg(cd, a, REG_ITMP2);
3900                                 i386_call_reg(cd, REG_ITMP2);
3901                                 break;
3902
3903                         case ICMD_INVOKEVIRTUAL:
3904                                 d = lm->returntype;
3905
3906                                 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3907                                 gen_nullptr_check(REG_ITMP1);
3908                                 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
3909                                 i386_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
3910
3911                                 i386_call_reg(cd, REG_ITMP1);
3912                                 break;
3913
3914                         case ICMD_INVOKEINTERFACE:
3915                                 d = lm->returntype;
3916
3917                                 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3918                                 gen_nullptr_check(REG_ITMP1);
3919                                 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3920                                 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * lm->class->index, REG_ITMP2);
3921                                 i386_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - lm->class->methods), REG_ITMP1);
3922
3923                                 i386_call_reg(cd, REG_ITMP1);
3924                                 break;
3925                         }
3926
3927                         /* d contains return type */
3928
3929                         if (d != TYPE_VOID) {
3930                                 d = reg_of_var(rd, iptr->dst, REG_NULL);
3931
3932                                 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3933                                         if (IS_2_WORD_TYPE(iptr->dst->type)) {
3934                                                 if (iptr->dst->flags & INMEMORY) {
3935                                                         i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3936                                                         i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
3937
3938                                                 } else {
3939                                                         panic("RETURN: longs have to be in memory");
3940                                                 }
3941
3942                                         } else {
3943                                                 if (iptr->dst->flags & INMEMORY) {
3944                                                         i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3945
3946                                                 } else {
3947                                                         M_INTMOVE(REG_RESULT, iptr->dst->regoff);
3948                                                 }
3949                                         }
3950
3951                                 } else {
3952                                         /* fld from called function -- has other fpu_st_offset counter */
3953                                         fpu_st_offset++;
3954                                         store_reg_to_var_flt(iptr->dst, d);
3955                                 }
3956                         }
3957                         }
3958                         break;
3959
3960
3961                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
3962
3963                                       /* op1:   0 == array, 1 == class                */
3964                                       /* val.a: (classinfo*) superclass               */
3965
3966 /*          superclass is an interface:
3967  *
3968  *          return (sub != NULL) &&
3969  *                 (sub->vftbl->interfacetablelength > super->index) &&
3970  *                 (sub->vftbl->interfacetable[-super->index] != NULL);
3971  *
3972  *          superclass is a class:
3973  *
3974  *          return ((sub != NULL) && (0
3975  *                  <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3976  *                  super->vftbl->diffvall));
3977  */
3978
3979                         {
3980                         classinfo *super = (classinfo*) iptr->val.a;
3981                         
3982 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3983                         codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3984 #endif
3985                         var_to_reg_int(s1, src, REG_ITMP1);
3986                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3987                         if (s1 == d) {
3988                                 M_INTMOVE(s1, REG_ITMP1);
3989                                 s1 = REG_ITMP1;
3990                         }
3991                         i386_alu_reg_reg(cd, I386_XOR, d, d);
3992                         if (iptr->op1) {                               /* class/interface */
3993                                 if (super->flags & ACC_INTERFACE) {        /* interface       */
3994                                         i386_test_reg_reg(cd, s1, s1);
3995
3996                                         /* TODO: clean up this calculation */
3997                                         a = 2;
3998                                         CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
3999
4000                                         a += 2;
4001                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4002                                         
4003                                         a += 2;
4004 /*                                      CALCOFFSETBYTES(a, super->index); */
4005                                         CALCIMMEDIATEBYTES(a, super->index);
4006                                         
4007                                         a += 3;
4008                                         a += 6;
4009
4010                                         a += 2;
4011                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4012
4013                                         a += 3;
4014
4015                                         a += 6;    /* jcc */
4016                                         a += 5;
4017
4018                                         i386_jcc(cd, I386_CC_E, a);
4019
4020                                         i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4021                                         i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4022                                         i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4023                                         /* TODO: test */
4024                                         i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4025
4026                                         /* TODO: clean up this calculation */
4027                                         a = 0;
4028                                         a += 2;
4029                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4030
4031                                         a += 3;
4032
4033                                         a += 6;    /* jcc */
4034                                         a += 5;
4035
4036                                         i386_jcc(cd, I386_CC_LE, a);
4037                                         i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4038                                         /* TODO: test */
4039                                         i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP1);
4040 /*                                      i386_setcc_reg(cd, I386_CC_A, d); */
4041 /*                                      i386_jcc(cd, I386_CC_BE, 5); */
4042                                         i386_jcc(cd, I386_CC_E, 5);
4043                                         i386_mov_imm_reg(cd, 1, d);
4044                                         
4045
4046                                 } else {                                   /* class           */
4047                                         i386_test_reg_reg(cd, s1, s1);
4048
4049                                         /* TODO: clean up this calculation */
4050                                         a = 2;
4051                                         CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4052                                         a += 5;
4053                                         a += 2;
4054                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4055                                         a += 2;
4056                                         CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4057                                         
4058                                         a += 2;
4059                                         CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4060                                         
4061                                         a += 2;
4062                                         a += 2;    /* xor */
4063
4064                                         a += 2;
4065
4066                                         a += 6;    /* jcc */
4067                                         a += 5;
4068
4069                                         i386_jcc(cd, I386_CC_E, a);
4070
4071                                         i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4072                                         i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4073 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4074                                         codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4075 #endif
4076                                         i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4077                                         i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4078                                         i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4079 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4080                                         codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4081 #endif
4082                                         i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4083                                         i386_alu_reg_reg(cd, I386_XOR, d, d);
4084
4085                                         i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4086                                         i386_jcc(cd, I386_CC_A, 5);
4087                                         i386_mov_imm_reg(cd, 1, d);
4088                                 }
4089                         }
4090                         else
4091                                 panic ("internal error: no inlined array instanceof");
4092                         }
4093                         store_reg_to_var_int(iptr->dst, d);
4094                         break;
4095
4096                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
4097
4098                                       /* op1:   0 == array, 1 == class                */
4099                                       /* val.a: (classinfo*) superclass               */
4100
4101 /*          superclass is an interface:
4102  *
4103  *          OK if ((sub == NULL) ||
4104  *                 (sub->vftbl->interfacetablelength > super->index) &&
4105  *                 (sub->vftbl->interfacetable[-super->index] != NULL));
4106  *
4107  *          superclass is a class:
4108  *
4109  *          OK if ((sub == NULL) || (0
4110  *                 <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4111  *                 super->vftbl->diffvall));
4112  */
4113
4114                         {
4115                         classinfo *super = (classinfo*) iptr->val.a;
4116                         
4117 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4118                         codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4119 #endif
4120                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4121                         var_to_reg_int(s1, src, d);
4122                         if (iptr->op1) {                               /* class/interface */
4123                                 if (super->flags & ACC_INTERFACE) {        /* interface       */
4124                                         i386_test_reg_reg(cd, s1, s1);
4125
4126                                         /* TODO: clean up this calculation */
4127                                         a = 2;
4128                                         CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4129
4130                                         a += 2;
4131                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4132
4133                                         a += 2;
4134 /*                                      CALCOFFSETBYTES(a, super->index); */
4135                                         CALCIMMEDIATEBYTES(a, super->index);
4136
4137                                         a += 3;
4138                                         a += 6;
4139
4140                                         a += 2;
4141                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4142
4143                                         a += 3;
4144                                         a += 6;
4145
4146                                         i386_jcc(cd, I386_CC_E, a);
4147
4148                                         i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4149                                         i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4150                                         i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4151                                         /* TODO: test */
4152                                         i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4153                                         i386_jcc(cd, I386_CC_LE, 0);
4154                                         codegen_addxcastrefs(cd, cd->mcodeptr);
4155                                         i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
4156                                         /* TODO: test */
4157                                         i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4158                                         i386_jcc(cd, I386_CC_E, 0);
4159                                         codegen_addxcastrefs(cd, cd->mcodeptr);
4160
4161                                 } else {                                     /* class           */
4162                                         i386_test_reg_reg(cd, s1, s1);
4163
4164                                         /* TODO: clean up this calculation */
4165                                         a = 2;
4166                                         CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4167
4168                                         a += 5;
4169
4170                                         a += 2;
4171                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4172
4173                                         if (d != REG_ITMP3) {
4174                                                 a += 2;
4175                                                 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4176                                                 
4177                                                 a += 2;
4178                                                 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4179
4180                                                 a += 2;
4181                                                 
4182                                         } else {
4183                                                 a += 2;
4184                                                 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4185
4186                                                 a += 2;
4187
4188                                                 a += 5;
4189
4190                                                 a += 2;
4191                                                 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4192                                         }
4193
4194                                         a += 2;
4195
4196                                         a += 6;
4197
4198                                         i386_jcc(cd, I386_CC_E, a);
4199
4200                                         i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4201                                         i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4202 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4203                                         codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4204 #endif
4205                                         i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4206                                         if (d != REG_ITMP3) {
4207                                                 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4208                                                 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4209 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4210                                                 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4211 #endif
4212                                                 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4213
4214                                         } else {
4215                                                 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
4216                                                 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1);
4217                                                 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4218                                                 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4219 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4220                                                 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4221 #endif
4222                                         }
4223
4224                                         i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4225                                         i386_jcc(cd, I386_CC_A, 0);    /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
4226                                         codegen_addxcastrefs(cd, cd->mcodeptr);
4227                                 }
4228
4229                         } else
4230                                 panic ("internal error: no inlined array checkcast");
4231                         }
4232                         M_INTMOVE(s1, d);
4233                         store_reg_to_var_int(iptr->dst, d);
4234                         break;
4235
4236                 case ICMD_CHECKASIZE:  /* ..., size ==> ..., size                     */
4237
4238                         if (src->flags & INMEMORY) {
4239                                 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4240                                 
4241                         } else {
4242                                 i386_test_reg_reg(cd, src->regoff, src->regoff);
4243                         }
4244                         i386_jcc(cd, I386_CC_L, 0);
4245                         codegen_addxcheckarefs(cd, cd->mcodeptr);
4246                         break;
4247
4248                 case ICMD_CHECKEXCEPTION:  /* ... ==> ...                             */
4249
4250                         i386_test_reg_reg(cd, REG_RESULT, REG_RESULT);
4251                         i386_jcc(cd, I386_CC_E, 0);
4252                         codegen_addxexceptionrefs(cd, cd->mcodeptr);
4253                         break;
4254
4255                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
4256                                       /* op1 = dimension, val.a = array descriptor    */
4257
4258                         /* check for negative sizes and copy sizes to stack if necessary  */
4259
4260                         MCODECHECK((iptr->op1 << 1) + 64);
4261
4262                         for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4263                                 if (src->flags & INMEMORY) {
4264                                         i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4265
4266                                 } else {
4267                                         i386_test_reg_reg(cd, src->regoff, src->regoff);
4268                                 }
4269                                 i386_jcc(cd, I386_CC_L, 0);
4270                                 codegen_addxcheckarefs(cd, cd->mcodeptr);
4271
4272                                 /* 
4273                                  * copy sizes to new stack location, be cause native function
4274                                  * builtin_nmultianewarray access them as (int *)
4275                                  */
4276                                 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
4277                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);
4278
4279                                 /* copy sizes to stack (argument numbers >= INT_ARG_CNT)      */
4280
4281                                 if (src->varkind != ARGVAR) {
4282                                         if (src->flags & INMEMORY) {
4283                                                 i386_mov_membase_reg(cd, REG_SP, (src->regoff + INT_ARG_CNT) * 8, REG_ITMP1);
4284                                                 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, (s1 + INT_ARG_CNT) * 8);
4285
4286                                         } else {
4287                                                 i386_mov_reg_membase(cd, src->regoff, REG_SP, (s1 + INT_ARG_CNT) * 8);
4288                                         }
4289                                 }
4290                         }
4291                         i386_alu_imm_reg(cd, I386_SUB, iptr->op1 * 4, REG_SP);
4292
4293                         /* a0 = dimension count */
4294
4295                         /* save stack pointer */
4296                         M_INTMOVE(REG_SP, REG_ITMP1);
4297
4298                         i386_alu_imm_reg(cd, I386_SUB, 12, REG_SP);
4299                         i386_mov_imm_membase(cd, iptr->op1, REG_SP, 0);
4300
4301                         /* a1 = arraydescriptor */
4302
4303                         i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, 4);
4304
4305                         /* a2 = pointer to dimensions = stack pointer */
4306
4307                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 8);
4308
4309                         i386_mov_imm_reg(cd, (s4) (builtin_nmultianewarray), REG_ITMP1);
4310                         i386_call_reg(cd, REG_ITMP1);
4311                         i386_alu_imm_reg(cd, I386_ADD, 12 + iptr->op1 * 4, REG_SP);
4312
4313                         s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
4314                         M_INTMOVE(REG_RESULT, s1);
4315                         store_reg_to_var_int(iptr->dst, s1);
4316                         break;
4317
4318                 case ICMD_INLINE_START:
4319                 case ICMD_INLINE_END:
4320                         break;
4321                 default:
4322                         error ("Unknown pseudo command: %d", iptr->opc);
4323         } /* switch */
4324                 
4325         } /* for instruction */
4326                 
4327         /* copy values to interface registers */
4328
4329         src = bptr->outstack;
4330         len = bptr->outdepth;
4331         MCODECHECK(64+len);
4332         while (src) {
4333                 len--;
4334                 if ((src->varkind != STACKVAR)) {
4335                         s2 = src->type;
4336                         if (IS_FLT_DBL_TYPE(s2)) {
4337                                 var_to_reg_flt(s1, src, REG_FTMP1);
4338                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4339                                         M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
4340
4341                                 } else {
4342                                         panic("double store");
4343 /*                                      M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4344                                 }
4345
4346                         } else {
4347                                 var_to_reg_int(s1, src, REG_ITMP1);
4348                                 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
4349                                         if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4350                                                 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
4351
4352                                         } else {
4353                                                 i386_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
4354                                         }
4355
4356                                 } else {
4357                                         if (rd->interfaces[len][s2].flags & INMEMORY) {
4358                                                 M_LNGMEMMOVE(s1, rd->interfaces[len][s2].regoff);
4359
4360                                         } else {
4361                                                 panic("copy interface registers: longs have to be in memory (end)");
4362                                         }
4363                                 }
4364                         }
4365                 }
4366                 src = src->prev;
4367         }
4368         } /* if (bptr -> flags >= BBREACHED) */
4369         } /* for basic block */
4370
4371         codegen_createlinenumbertable(cd);
4372
4373         {
4374
4375         /* generate bound check stubs */
4376
4377         u1 *xcodeptr = NULL;
4378         branchref *bref;
4379
4380         for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
4381                 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4382                                   bref->branchpos,
4383                                                   cd->mcodeptr - cd->mcodebase);
4384
4385                 MCODECHECK(100);
4386
4387                 /* move index register into REG_ITMP1 */
4388                 i386_mov_reg_reg(cd, bref->reg, REG_ITMP1);                /* 2 bytes */
4389
4390                 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC);                    /* 5 bytes */
4391                 dseg_adddata(cd, cd->mcodeptr);
4392                 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3);      /* 5 bytes */
4393                 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP3, REG_ITMP2_XPC);  /* 2 bytes */
4394
4395                 if (xcodeptr != NULL) {
4396                         i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4397
4398                 } else {
4399                         xcodeptr = cd->mcodeptr;
4400
4401                         i386_push_reg(cd, REG_ITMP2_XPC);
4402
4403                         PREPARE_NATIVE_STACKINFO;
4404
4405                         i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4406                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 4);
4407                         i386_mov_imm_reg(cd, (u4) new_arrayindexoutofboundsexception, REG_ITMP1);
4408                         i386_call_reg(cd, REG_ITMP1);   /* return value is REG_ITMP1_XPTR */
4409                         i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4410
4411                         REMOVE_NATIVE_STACKINFO;
4412
4413                         i386_pop_reg(cd, REG_ITMP2_XPC);
4414
4415                         i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4416                         i386_jmp_reg(cd, REG_ITMP3);
4417                 }
4418         }
4419
4420         /* generate negative array size check stubs */
4421
4422         xcodeptr = NULL;
4423         
4424         for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
4425                 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4426                         gen_resolvebranch(cd->mcodebase + bref->branchpos, 
4427                                                           bref->branchpos,
4428                                                           xcodeptr - cd->mcodebase - (5 + 5 + 2));
4429                         continue;
4430                 }
4431
4432                 gen_resolvebranch(cd->mcodebase + bref->branchpos, 
4433                                   bref->branchpos,
4434                                                   cd->mcodeptr - cd->mcodebase);
4435
4436                 MCODECHECK(100);
4437
4438                 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC);                    /* 5 bytes */
4439                 dseg_adddata(cd, cd->mcodeptr);
4440                 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1);      /* 5 bytes */
4441                 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC);  /* 2 bytes */
4442
4443                 if (xcodeptr != NULL) {
4444                         i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4445
4446                 } else {
4447                         xcodeptr = cd->mcodeptr;
4448
4449                         i386_push_reg(cd, REG_ITMP2_XPC);
4450
4451                         PREPARE_NATIVE_STACKINFO;
4452
4453                         i386_mov_imm_reg(cd, (u4) new_negativearraysizeexception, REG_ITMP1);
4454                         i386_call_reg(cd, REG_ITMP1);   /* return value is REG_ITMP1_XPTR */
4455                         /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4456
4457
4458                         REMOVE_NATIVE_STACKINFO;
4459
4460                         i386_pop_reg(cd, REG_ITMP2_XPC);
4461
4462                         i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4463                         i386_jmp_reg(cd, REG_ITMP3);
4464                 }
4465         }
4466
4467         /* generate cast check stubs */
4468
4469         xcodeptr = NULL;
4470         
4471         for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
4472                 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4473                         gen_resolvebranch(cd->mcodebase + bref->branchpos, 
4474                                                           bref->branchpos,
4475                                                           xcodeptr - cd->mcodebase - (5 + 5 + 2));
4476                         continue;
4477                 }
4478
4479                 gen_resolvebranch(cd->mcodebase + bref->branchpos, 
4480                                   bref->branchpos,
4481                                                   cd->mcodeptr - cd->mcodebase);
4482
4483                 MCODECHECK(100);
4484
4485                 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC);                    /* 5 bytes */
4486                 dseg_adddata(cd, cd->mcodeptr);
4487                 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1);      /* 5 bytes */
4488                 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC);  /* 2 bytes */
4489
4490                 if (xcodeptr != NULL) {
4491                         i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4492                 
4493                 } else {
4494                         xcodeptr = cd->mcodeptr;
4495
4496                         i386_push_reg(cd, REG_ITMP2_XPC);
4497
4498                         PREPARE_NATIVE_STACKINFO;
4499
4500                         i386_mov_imm_reg(cd, (u4) new_classcastexception, REG_ITMP1);
4501                         i386_call_reg(cd, REG_ITMP1);   /* return value is REG_ITMP1_XPTR */
4502                         /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4503
4504
4505                         REMOVE_NATIVE_STACKINFO;
4506
4507                         i386_pop_reg(cd, REG_ITMP2_XPC);
4508
4509                         i386_mov_imm_reg(cd, (u4) asm_handle_exception, REG_ITMP3);
4510                         i386_jmp_reg(cd, REG_ITMP3);
4511                 }
4512         }
4513
4514         /* generate divide by zero check stubs */
4515
4516         xcodeptr = NULL;
4517         
4518         for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
4519                 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4520                         gen_resolvebranch(cd->mcodebase + bref->branchpos, 
4521                                                           bref->branchpos,
4522                                                           xcodeptr - cd->mcodebase - (5 + 5 + 2));
4523                         continue;
4524                 }
4525
4526                 gen_resolvebranch(cd->mcodebase + bref->branchpos, 
4527                                   bref->branchpos,
4528                                                   cd->mcodeptr - cd->mcodebase);
4529
4530                 MCODECHECK(100);
4531
4532                 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC);                    /* 5 bytes */
4533                 dseg_adddata(cd, cd->mcodeptr);
4534                 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1);      /* 5 bytes */
4535                 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC);  /* 2 bytes */
4536
4537                 if (xcodeptr != NULL) {
4538                         i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4539                 
4540                 } else {
4541                         xcodeptr = cd->mcodeptr;
4542
4543                         i386_push_reg(cd, REG_ITMP2_XPC);
4544
4545                         PREPARE_NATIVE_STACKINFO;
4546
4547                         i386_mov_imm_reg(cd, (u4) new_arithmeticexception, REG_ITMP1);
4548                         i386_call_reg(cd, REG_ITMP1);   /* return value is REG_ITMP1_XPTR */
4549
4550                         REMOVE_NATIVE_STACKINFO;
4551
4552                         i386_pop_reg(cd, REG_ITMP2_XPC);
4553
4554                         i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4555                         i386_jmp_reg(cd, REG_ITMP3);
4556                 }
4557         }
4558
4559         /* generate exception check stubs */
4560
4561         xcodeptr = NULL;
4562         
4563         for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
4564                 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4565                         gen_resolvebranch(cd->mcodebase + bref->branchpos,
4566                                                           bref->branchpos,
4567                                                           xcodeptr - cd->mcodebase - (5 + 5 + 2));
4568                         continue;
4569                 }
4570
4571                 gen_resolvebranch(cd->mcodebase + bref->branchpos, 
4572                                   bref->branchpos,
4573                                                   cd->mcodeptr - cd->mcodebase);
4574
4575                 MCODECHECK(200);
4576
4577                 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC);                    /* 5 bytes */
4578                 dseg_adddata(cd, cd->mcodeptr);
4579                 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1);      /* 5 bytes */
4580                 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC);  /* 2 bytes */
4581
4582                 if (xcodeptr != NULL) {
4583                         i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4584                 
4585                 } else {
4586                         xcodeptr = cd->mcodeptr;
4587
4588                         i386_push_reg(cd, REG_ITMP2_XPC);
4589
4590                         PREPARE_NATIVE_STACKINFO;
4591
4592                         i386_mov_imm_reg(cd, (s4) codegen_general_stubcalled, REG_ITMP1);
4593                         i386_call_reg(cd, REG_ITMP1);                
4594
4595 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4596                         i386_mov_imm_reg(cd, (s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4597                         i386_call_reg(cd, REG_ITMP1);
4598                         i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP3);
4599                         i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
4600                         i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1_XPTR);
4601 #else
4602                         i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP3);
4603                         i386_mov_membase_reg(cd, REG_ITMP3, 0, REG_ITMP1_XPTR);
4604                         i386_mov_imm_membase(cd, 0, REG_ITMP3, 0);
4605 #endif
4606                         i386_push_imm(cd, 0);
4607                         i386_push_reg(cd, REG_ITMP1_XPTR);
4608
4609 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4610 java stack at this point*/
4611                         i386_mov_membase_reg(cd, REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4612                         i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, class), REG_ITMP1);
4613                         i386_push_imm(cd, (u4) utf_fillInStackTrace_desc);
4614                         i386_push_imm(cd, (u4) utf_fillInStackTrace_name);
4615                         i386_push_reg(cd, REG_ITMP1);
4616                         i386_mov_imm_reg(cd, (s4) class_resolvemethod, REG_ITMP3);
4617                         i386_call_reg(cd, REG_ITMP3);
4618 /*cleanup parameters of class_resolvemethod*/
4619                         i386_alu_imm_reg(cd, I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4620 /*prepare call to asm_calljavafunction2 */                      
4621                         i386_push_imm(cd, 0);
4622                         i386_push_imm(cd, TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte  (make this dynamic) (JOWENN)*/
4623                         i386_push_reg(cd, REG_SP);
4624                         i386_push_imm(cd, sizeof(jni_callblock));
4625                         i386_push_imm(cd, 1);
4626                         i386_push_reg(cd, REG_RESULT);
4627                         
4628                         i386_mov_imm_reg(cd, (s4) asm_calljavafunction2, REG_ITMP3);
4629                         i386_call_reg(cd, REG_ITMP3);
4630
4631                         /* check exceptionptr + fail (JOWENN)*/                 
4632
4633                         i386_alu_imm_reg(cd, I386_ADD,6*4,REG_SP);
4634
4635                         i386_pop_reg(cd, REG_ITMP1_XPTR);
4636                         i386_pop_reg(cd, REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4637
4638                         REMOVE_NATIVE_STACKINFO;
4639
4640                         i386_pop_reg(cd, REG_ITMP2_XPC);
4641
4642                         i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4643                         i386_jmp_reg(cd, REG_ITMP3);
4644                 }
4645         }
4646
4647         /* generate null pointer check stubs */
4648
4649         xcodeptr = NULL;
4650         
4651         for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
4652                 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4653                         gen_resolvebranch(cd->mcodebase + bref->branchpos, 
4654                                                           bref->branchpos,
4655                                                           xcodeptr - cd->mcodebase - (5 + 5 + 2));
4656                         continue;
4657                 }
4658
4659                 gen_resolvebranch(cd->mcodebase + bref->branchpos, 
4660                                                   bref->branchpos,
4661                                                   cd->mcodeptr - cd->mcodebase);
4662                 
4663                 MCODECHECK(100);
4664
4665                 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC);                    /* 5 bytes */
4666                 dseg_adddata(cd, cd->mcodeptr);
4667                 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1);      /* 5 bytes */
4668                 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC);  /* 2 bytes */
4669                 
4670                 if (xcodeptr != NULL) {
4671                         i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4672                         
4673                 } else {
4674                         xcodeptr = cd->mcodeptr;
4675                         
4676                         i386_push_reg(cd, REG_ITMP2_XPC);
4677
4678                         PREPARE_NATIVE_STACKINFO;
4679
4680 #if 0
4681                         /* create native call block*/
4682                         i386_alu_imm_reg(cd, I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4683
4684
4685                         i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1);
4686                         i386_call_reg(cd, REG_ITMP1);                /*call    codegen_stubcalled*/
4687
4688                         i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4689                         i386_call_reg(cd, REG_ITMP1);                /*call    builtin_asm_get_stackframeinfo*/
4690                         i386_mov_imm_membase(cd, 0,REG_SP, 2*4);        /* builtin */
4691                         i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer  to native call stack*/
4692                         i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4693                         i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */
4694                         i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4695 #endif                          
4696
4697                         i386_mov_imm_reg(cd, (u4) new_nullpointerexception, REG_ITMP1);
4698                         i386_call_reg(cd, REG_ITMP1);   /* return value is REG_ITMP1_XPTR */
4699
4700                         REMOVE_NATIVE_STACKINFO;
4701
4702 #if 0
4703                         /* restore native call stack */
4704                         i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2);
4705                         i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3);
4706                         i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0);
4707                         i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
4708 #endif
4709
4710                         i386_pop_reg(cd, REG_ITMP2_XPC);
4711
4712                         i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4713                         i386_jmp_reg(cd, REG_ITMP3);
4714                 }
4715         }
4716         }
4717         
4718         codegen_finish(m, cd, (u4) (cd->mcodeptr - cd->mcodebase));
4719 }
4720
4721
4722 /* function createcompilerstub *************************************************
4723
4724    creates a stub routine which calls the compiler
4725         
4726 *******************************************************************************/
4727
4728 #define COMPSTUBSIZE 12
4729
4730 u1 *createcompilerstub(methodinfo *m)
4731 {
4732     u1 *s = CNEW(u1, COMPSTUBSIZE);     /* memory to hold the stub            */
4733         codegendata *cd = NEW(codegendata);
4734
4735     cd->mcodeptr = s;
4736
4737     /* code for the stub */
4738     i386_mov_imm_reg(cd, (u4) m, REG_ITMP1);/* pass method pointer to compiler*/
4739
4740         /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching  */
4741     i386_mov_imm_reg(cd, (u4) asm_call_jit_compiler, REG_ITMP3);
4742     i386_jmp_reg(cd, REG_ITMP3);        /* jump to compiler                   */
4743
4744         /* free codegendata memory */
4745         codegen_close(m);
4746
4747 #if defined(STATISTICS)
4748         if (opt_stat)
4749                 count_cstub_len += COMPSTUBSIZE;
4750 #endif
4751
4752         FREE(cd, codegendata);
4753
4754     return s;
4755 }
4756
4757
4758 /* function removecompilerstub *************************************************
4759
4760      deletes a compilerstub from memory  (simply by freeing it)
4761
4762 *******************************************************************************/
4763
4764 void removecompilerstub(u1 *stub) 
4765 {
4766     CFREE(stub, COMPSTUBSIZE);
4767 }
4768
4769
4770 /* function: createnativestub **************************************************
4771
4772         creates a stub routine which calls a native method
4773
4774 *******************************************************************************/
4775
4776 #define NATIVESTUBSIZE 350
4777
4778 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4779 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4780 #endif
4781
4782 void i386_native_stub_debug(void **p) {
4783         printf("Pos on stack: %p\n",p);
4784         printf("Return adress should be: %p\n",*p);
4785 }
4786
4787 void i386_native_stub_debug2(void **p) {
4788         printf("Pos on stack: %p\n",p);
4789         printf("Return for lookup is: %p\n",*p);
4790 }
4791
4792 void traverseStackInfo() {
4793         void **p=builtin_asm_get_stackframeinfo();
4794         
4795         while ((*p)!=0) {
4796                 methodinfo *m;
4797                 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4798                 m=*((methodinfo**)((*p)+8));
4799                 utf_display(m->name);
4800                 printf("\n");
4801                 p=*p;
4802         }
4803         
4804
4805 }
4806
4807 u1 *createnativestub(functionptr f, methodinfo *m)
4808 {
4809     u1 *s = CNEW(u1, NATIVESTUBSIZE);   /* memory to hold the stub            */
4810     int addmethod=0;
4811     u1 *tptr;
4812     int i;
4813     int stackframesize = 4+12;           /* initial 4 bytes is space for jni env,
4814                                                 + 4 byte thread pointer + 4 byte previous pointer + method info*/
4815     int stackframeoffset = 4;
4816
4817     int p, t;
4818
4819     void**  callAddrPatchPos=0;
4820     u1* jmpInstrPos=0;
4821     void** jmpInstrPatchPos=0;
4822
4823         codegendata *cd = NEW(codegendata);
4824         registerdata *rd = NEW(registerdata);
4825         t_inlining_globals *id = NEW(t_inlining_globals);
4826
4827         /* setup registers before using it */
4828         inlining_setup(m, id);
4829         reg_setup(m, rd, id);
4830
4831         cd->mcodeptr = s;
4832
4833         if (m->flags & ACC_STATIC) {
4834                 stackframesize += 4;
4835                 stackframeoffset += 4;
4836         }
4837
4838     reg_init(m);
4839     descriptor2types(m);                     /* set paramcount and paramtypes */
4840   
4841 /*DEBUG*/
4842 /*      i386_push_reg(cd, REG_SP);
4843         i386_mov_imm_reg(cd, (s4) i386_native_stub_debug, REG_ITMP1);
4844         i386_call_reg(cd, REG_ITMP1);
4845         i386_pop_reg(cd, REG_ITMP1);*/
4846
4847
4848         /* if function is static, check for initialized */
4849
4850         if (m->flags & ACC_STATIC) {
4851         /* if class isn't yet initialized, do it */
4852                 if (!m->class->initialized) {
4853                         s4 *header = (s4 *) s;
4854                         *header = 0;/*extablesize*/
4855                         header;
4856                         *header = 0;/*line number table start*/
4857                         header++;
4858                         *header = 0;/*line number table size*/
4859                         header++;
4860                         *header = 0;/*fltsave*/
4861                         header++;
4862                         *header = 0;/*intsave*/
4863                         header++;
4864                         *header = 0;/*isleaf*/
4865                         header++;
4866                         *header = 0;/*issync*/
4867                         header++;
4868                         *header = 0;/*framesize*/
4869                         header++;
4870                         *header = (u4) m;/*methodpointer*/
4871                         *header++;
4872                         cd->mcodeptr = s = (u1 *) header;
4873                         addmethod = 1;
4874
4875                         /* call helper function which patches this code */
4876                         i386_mov_imm_reg(cd, (u4) m->class, REG_ITMP1);
4877                         i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP2);
4878                         i386_call_reg(cd, REG_ITMP2);
4879                 }
4880         }
4881
4882     if (runverbose) {
4883         i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4884         
4885         for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
4886             t = m->paramtypes[p];
4887             if (IS_INT_LNG_TYPE(t)) {
4888                 if (IS_2_WORD_TYPE(t)) {
4889                     i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4890                     i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
4891                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4892                                         i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4893
4894                 } else if (t == TYPE_ADR) {
4895                     i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4896                     i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
4897                                         i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4898                                         i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4899
4900                 } else {
4901                     i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
4902                     i386_cltd(cd);
4903                                         i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
4904                                         i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
4905                 }
4906
4907             } else {
4908                 if (!IS_2_WORD_TYPE(t)) {
4909                     i386_flds_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4910                     i386_fstps_membase(cd, REG_SP, p * 8);
4911                     i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
4912                     i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4913
4914                 } else {
4915                     i386_fldl_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4916                     i386_fstpl_membase(cd, REG_SP, p * 8);
4917                 }
4918             }
4919         }
4920                 
4921         i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
4922         for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
4923             i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4924             i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
4925         }
4926
4927         i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
4928
4929         i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
4930         i386_call_reg(cd, REG_ITMP1);
4931
4932         i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4933     }
4934
4935     /*
4936          * mark the whole fpu stack as free for native functions
4937          * (only for saved register count == 0)
4938          */
4939     i386_ffree_reg(cd, 0);
4940     i386_ffree_reg(cd, 1);
4941     i386_ffree_reg(cd, 2);
4942     i386_ffree_reg(cd, 3);
4943     i386_ffree_reg(cd, 4);
4944     i386_ffree_reg(cd, 5);
4945     i386_ffree_reg(cd, 6);
4946     i386_ffree_reg(cd, 7);
4947
4948         /* calculate stackframe size for native function */
4949     tptr = m->paramtypes;
4950     for (i = 0; i < m->paramcount; i++) {
4951         switch (*tptr++) {
4952         case TYPE_INT:
4953         case TYPE_FLT:
4954         case TYPE_ADR:
4955             stackframesize += 4;
4956             break;
4957
4958         case TYPE_LNG:
4959         case TYPE_DBL:
4960             stackframesize += 8;
4961             break;
4962
4963         default:
4964             panic("unknown parameter type in native function");
4965         }
4966     }
4967
4968         i386_alu_imm_reg(cd, I386_SUB, stackframesize, REG_SP);
4969
4970 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
4971    i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
4972    i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
4973    i386_call_reg(cd, REG_ITMP1);
4974    i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
4975    i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); 
4976    i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
4977    i386_mov_reg_reg(cd, REG_SP,REG_ITMP2);
4978    i386_alu_imm_reg(cd, I386_ADD,stackframesize-12,REG_ITMP2);
4979    i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0);
4980
4981 /*TESTING ONLY */
4982 /*   i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
4983    i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
4984    i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-12);*/
4985
4986 /* CREATE DYNAMIC STACK INFO -- END*/
4987
4988 /* RESOLVE NATIVE METHOD -- BEGIN*/
4989 #ifndef STATIC_CLASSPATH
4990    if (f==0) {
4991      log_text("Dynamic classpath: preparing for delayed native function resolving");
4992      i386_jmp_imm(cd,0);
4993      jmpInstrPos=cd->mcodeptr-4;
4994      /*patchposition*/
4995      i386_mov_imm_reg(cd,jmpInstrPos,REG_ITMP1);
4996      i386_push_reg(cd,REG_ITMP1);
4997      /*jmp offset*/
4998      i386_mov_imm_reg(cd,0,REG_ITMP1);
4999      jmpInstrPatchPos=cd->mcodeptr-4;
5000      i386_push_reg(cd,REG_ITMP1);
5001      /*position of call address to patch*/
5002      i386_mov_imm_reg(cd,0,REG_ITMP1);
5003      callAddrPatchPos=(cd->mcodeptr-4);
5004      i386_push_reg(cd,REG_ITMP1);
5005      /*method info structure*/
5006      i386_mov_imm_reg(cd,(s4) m, REG_ITMP1);
5007      i386_push_reg(cd,REG_ITMP1);
5008      /*call resolve functions*/
5009      i386_mov_imm_reg(cd, (s4)codegen_resolve_native,REG_ITMP1);
5010      i386_call_reg(cd,REG_ITMP1);
5011      /*cleanup*/
5012      i386_pop_reg(cd,REG_ITMP1);
5013      i386_pop_reg(cd,REG_ITMP1);
5014      i386_pop_reg(cd,REG_ITMP1);
5015      i386_pop_reg(cd,REG_ITMP1);
5016      /*fix jmp offset replacement*/
5017      (*jmpInstrPatchPos)=cd->mcodeptr-jmpInstrPos-4;
5018    } else log_text("Dynamic classpath: immediate native function resolution possible");
5019 #endif
5020 /* RESOLVE NATIVE METHOD -- END*/
5021
5022
5023
5024     tptr = m->paramtypes;
5025     for (i = 0; i < m->paramcount; i++) {
5026         switch (*tptr++) {
5027         case TYPE_INT:
5028         case TYPE_FLT:
5029         case TYPE_ADR:
5030             i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5031             i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5032             stackframeoffset += 4;
5033             break;
5034
5035         case TYPE_LNG:
5036         case TYPE_DBL:
5037             i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5038             i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5039             i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5040             i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, stackframeoffset + 4);
5041             stackframeoffset += 8;
5042             break;
5043
5044         default:
5045             panic("unknown parameter type in native function");
5046         }
5047     }
5048
5049         if (m->flags & ACC_STATIC) {
5050                 /* put class into second argument */
5051                 i386_mov_imm_membase(cd, (s4) m->class, REG_SP, 4);
5052         }
5053
5054         /* put env into first argument */
5055         i386_mov_imm_membase(cd, (s4) &env, REG_SP, 0);
5056
5057     i386_mov_imm_reg(cd, (s4) f, REG_ITMP1);
5058 #ifndef STATIC_CLASSPATH
5059     if (f==0)
5060       (*callAddrPatchPos)=(cd->mcodeptr-4);
5061 #endif
5062     i386_call_reg(cd, REG_ITMP1);
5063
5064 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5065     i386_push_reg(cd, REG_RESULT2);
5066     i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
5067     i386_mov_membase_reg(cd, REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
5068     i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT2,0);
5069     i386_pop_reg(cd, REG_RESULT2);
5070 /*REMOVE DYNAMIC STACK INFO -END */
5071
5072     i386_alu_imm_reg(cd, I386_ADD, stackframesize, REG_SP);
5073
5074
5075     if (runverbose) {
5076         i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5077                 
5078         i386_mov_imm_membase(cd, (u4) m, REG_SP, 0);
5079                 
5080         i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
5081         i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
5082                 
5083         i386_fstl_membase(cd, REG_SP, 4 + 8);
5084         i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5085
5086         i386_mov_imm_reg(cd, (u4) builtin_displaymethodstop, REG_ITMP1);
5087         i386_call_reg(cd, REG_ITMP1);
5088                 
5089         i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
5090         i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
5091                 
5092         i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5093     }
5094
5095
5096         /* we can't use REG_ITMP3 == REG_RESULT2 */
5097 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5098         i386_push_reg(cd, REG_RESULT);
5099         i386_push_reg(cd, REG_RESULT2);
5100         i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5101         i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP2);
5102         i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5103         i386_pop_reg(cd, REG_RESULT2);
5104         i386_pop_reg(cd, REG_RESULT);
5105 #else
5106         i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5107         i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP2);
5108         i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5109 #endif
5110         i386_jcc(cd, I386_CC_NE, 1);
5111
5112         i386_ret(cd);
5113
5114 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5115         i386_push_reg(cd, REG_ITMP2);
5116         i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5117         i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5118         i386_pop_reg(cd, REG_ITMP1_XPTR);
5119 #else
5120         i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1_XPTR);
5121         i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5122         i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5123 #endif
5124         i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP2_XPC);
5125         i386_alu_imm_reg(cd, I386_SUB, 2, REG_ITMP2_XPC);
5126
5127         i386_mov_imm_reg(cd, (s4) asm_handle_nat_exception, REG_ITMP3);
5128         i386_jmp_reg(cd, REG_ITMP3);
5129
5130         if (addmethod) {
5131                 codegen_insertmethod(s, cd->mcodeptr);
5132         }
5133
5134 #if 0
5135         dolog_plain("native stubentry: %p, stubsize: %x (for %d params) --", (s4)s,(s4) (cd->mcodeptr - s), m->paramcount);
5136         utf_display(m->name);
5137         dolog_plain("\n");
5138 #endif
5139
5140         /* free codegendata memory */
5141         codegen_close(m);
5142
5143 #if defined(STATISTICS)
5144         if (opt_stat)
5145                 count_nstub_len += NATIVESTUBSIZE;
5146 #endif
5147
5148         FREE(cd, codegendata);
5149         FREE(rd, registerdata);
5150         FREE(id, t_inlining_globals);
5151
5152         return s;
5153 }
5154
5155
5156 /* function: removenativestub **************************************************
5157
5158     removes a previously created native-stub from memory
5159     
5160 *******************************************************************************/
5161
5162 void removenativestub(u1 *stub)
5163 {
5164     CFREE(stub, NATIVESTUBSIZE);
5165 }
5166
5167
5168 /*
5169  * These are local overrides for various environment variables in Emacs.
5170  * Please do not remove this and leave it at the end of the file, where
5171  * Emacs will automagically detect them.
5172  * ---------------------------------------------------------------------
5173  * Local variables:
5174  * mode: c
5175  * indent-tabs-mode: t
5176  * c-basic-offset: 4
5177  * tab-width: 4
5178  * End:
5179  */