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