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