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