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