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