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