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