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