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