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