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