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