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