* src/vm/jit/i386/codegen.c (codegen): Pass register number to
[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 5089 2006-07-08 20:32:30Z 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 == NULL)
4632                                         s3 += (opt_showdisassemble ? 5 : 0);
4633
4634                                 /* if class is not resolved, check which code to call */
4635
4636                                 if (super == NULL) {
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 == NULL) || (super->flags & ACC_INTERFACE)) {
4655                                         if (super != NULL) {
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 == NULL) {
4665                                                 codegen_addpatchref(cd,
4666                                                                                         PATCHER_checkcast_instanceof_interface,
4667                                                                                         (constant_classref *) iptr->target,
4668                                                                                         0);
4669
4670                                                 if (opt_showdisassemble) {
4671                                                         M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4672                                                 }
4673                                         }
4674
4675                                         i386_mov_membase32_reg(cd, REG_ITMP2,
4676                                                                                    OFFSET(vftbl_t, interfacetablelength),
4677                                                                                    REG_ITMP3);
4678                                         i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4679                                         i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4680                                         i386_jcc(cd, I386_CC_LE, 0);
4681                                         codegen_add_classcastexception_ref(cd, s1);
4682                                         i386_mov_membase32_reg(cd, REG_ITMP2,
4683                                                                                    OFFSET(vftbl_t, interfacetable[0]) -
4684                                                                                    superindex * sizeof(methodptr*),
4685                                                                                    REG_ITMP3);
4686                                         M_TEST(REG_ITMP3);
4687                                         M_BEQ(0);
4688                                         codegen_add_classcastexception_ref(cd, s1);
4689
4690                                         if (super == NULL)
4691                                                 M_JMP_IMM(s3);
4692                                 }
4693
4694                                 /* class checkcast code */
4695
4696                                 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
4697                                         if (super != NULL) {
4698                                                 M_TEST(s1);
4699                                                 M_BEQ(s3);
4700                                         }
4701
4702                                         i386_mov_membase_reg(cd, s1,
4703                                                                                  OFFSET(java_objectheader, vftbl),
4704                                                                                  REG_ITMP2);
4705
4706                                         if (super == NULL) {
4707                                                 codegen_addpatchref(cd, PATCHER_checkcast_class,
4708                                                                                         (constant_classref *) iptr->target,
4709                                                                                         0);
4710
4711                                                 if (opt_showdisassemble) {
4712                                                         M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4713                                                 }
4714                                         }
4715
4716                                         i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4717 #if defined(ENABLE_THREADS)
4718                                         codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4719 #endif
4720                                         i386_mov_membase32_reg(cd, REG_ITMP2,
4721                                                                                    OFFSET(vftbl_t, baseval),
4722                                                                                    REG_ITMP2);
4723
4724                                         /*                              if (s1 != REG_ITMP1) { */
4725                                         /*                                      i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
4726                                         /*                                      i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
4727                                         /* #if defined(ENABLE_THREADS) */
4728                                         /*                                      codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
4729                                         /* #endif */
4730                                         /*                                      i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
4731
4732                                         /*                              } else { */
4733                                         i386_mov_membase32_reg(cd, REG_ITMP3,
4734                                                                                    OFFSET(vftbl_t, baseval),
4735                                                                                    REG_ITMP3);
4736                                         i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP3, REG_ITMP2);
4737                                         i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4738                                         i386_mov_membase_reg(cd, REG_ITMP3,
4739                                                                                  OFFSET(vftbl_t, diffval),
4740                                                                                  REG_ITMP3);
4741 #if defined(ENABLE_THREADS)
4742                                         codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4743 #endif
4744                                         /*                              } */
4745
4746                                         i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP2);
4747                                         i386_jcc(cd, I386_CC_A, 0);    /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
4748                                         codegen_add_classcastexception_ref(cd, s1);
4749                                 }
4750
4751                                 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
4752                         }
4753                         else {
4754                                 /* array type cast-check */
4755
4756                                 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4757                                 M_AST(s1, REG_SP, 0 * 4);
4758
4759                                 if (iptr->val.a == NULL) {
4760                                         codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
4761                                                                                 iptr->target, 0);
4762
4763                                         if (opt_showdisassemble) {
4764                                                 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4765                                         }
4766                                 }
4767
4768                                 M_AST_IMM(iptr->val.a, REG_SP, 1 * 4);
4769                                 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP3);
4770                                 M_CALL(REG_ITMP3);
4771                                 M_TEST(REG_RESULT);
4772                                 M_BEQ(0);
4773                                 codegen_add_classcastexception_ref(cd, s1);
4774
4775                                 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4776                                 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
4777                         }
4778
4779                         M_INTMOVE(s1, d);
4780                         emit_store(jd, iptr, iptr->dst, d);
4781                         break;
4782
4783                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
4784
4785                                       /* op1:   0 == array, 1 == class                */
4786                                       /* val.a: (classinfo*) superclass               */
4787                         /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4788                         /* EAX: S|D|YES ECX: YES S|D|EDX: S|D|YES OUTPUT: REG_NULL*/
4789                         /* ????? Really necessary to block all ?????              */
4790
4791                         /*  superclass is an interface:
4792                          *
4793                          *  return (sub != NULL) &&
4794                          *         (sub->vftbl->interfacetablelength > super->index) &&
4795                          *         (sub->vftbl->interfacetable[-super->index] != NULL);
4796                          *
4797                          *  superclass is a class:
4798                          *
4799                          *  return ((sub != NULL) && (0
4800                          *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4801                          *          super->vftbl->diffvall));
4802                          */
4803
4804                         {
4805                         classinfo *super;
4806                         vftbl_t   *supervftbl;
4807                         s4         superindex;
4808
4809                         super = (classinfo *) iptr->val.a;
4810
4811                         if (!super) {
4812                                 superindex = 0;
4813                                 supervftbl = NULL;
4814
4815                         } else {
4816                                 superindex = super->index;
4817                                 supervftbl = super->vftbl;
4818                         }
4819                         
4820 #if defined(ENABLE_THREADS)
4821                         codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4822 #endif
4823
4824                         s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4825                         d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
4826                         if (s1 == d) {
4827                                 M_INTMOVE(s1, REG_ITMP1);
4828                                 s1 = REG_ITMP1;
4829                         }
4830
4831                         /* calculate interface instanceof code size */
4832
4833                         s2 = 2; /* mov_membase_reg */
4834                         CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4835
4836                         s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
4837                                    2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4838                                    2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4839
4840                         if (!super)
4841                                 s2 += (opt_showdisassemble ? 5 : 0);
4842
4843                         /* calculate class instanceof code size */
4844
4845                         s3 = 2; /* mov_membase_reg */
4846                         CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4847                         s3 += 5; /* mov_imm_reg */
4848                         s3 += 2;
4849                         CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
4850                         s3 += 2;
4851                         CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
4852                         s3 += 2;
4853                         CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
4854
4855                         s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
4856                                    2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4857
4858                         if (!super)
4859                                 s3 += (opt_showdisassemble ? 5 : 0);
4860
4861                         i386_alu_reg_reg(cd, ALU_XOR, d, d);
4862
4863                         /* if class is not resolved, check which code to call */
4864
4865                         if (!super) {
4866                                 i386_test_reg_reg(cd, s1, s1);
4867                                 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4868
4869                                 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
4870                                                                         (constant_classref *) iptr->target, 0);
4871
4872                                 if (opt_showdisassemble) {
4873                                         M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4874                                 }
4875
4876                                 i386_mov_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
4877                                 i386_alu_imm32_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
4878                                 i386_jcc(cd, I386_CC_Z, s2 + 5);
4879                         }
4880
4881                         /* interface instanceof code */
4882
4883                         if (!super || (super->flags & ACC_INTERFACE)) {
4884                                 if (super) {
4885                                         M_TEST(s1);
4886                                         M_BEQ(s2);
4887                                 }
4888
4889                                 i386_mov_membase_reg(cd, s1,
4890                                                                          OFFSET(java_objectheader, vftbl),
4891                                                                          REG_ITMP1);
4892
4893                                 if (!super) {
4894                                         codegen_addpatchref(cd,
4895                                                                                 PATCHER_checkcast_instanceof_interface,
4896                                                                                 (constant_classref *) iptr->target, 0);
4897
4898                                         if (opt_showdisassemble) {
4899                                                 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4900                                         }
4901                                 }
4902
4903                                 i386_mov_membase32_reg(cd, REG_ITMP1,
4904                                                                            OFFSET(vftbl_t, interfacetablelength),
4905                                                                            REG_ITMP3);
4906                                 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4907                                 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4908
4909                                 disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
4910                                                 6 /* jcc */ + 5 /* mov_imm_reg */);
4911
4912                                 M_BLE(disp);
4913                                 i386_mov_membase32_reg(cd, REG_ITMP1,
4914                                                                            OFFSET(vftbl_t, interfacetable[0]) -
4915                                                                            superindex * sizeof(methodptr*),
4916                                                                            REG_ITMP1);
4917                                 M_TEST(REG_ITMP1);
4918 /*                                      i386_setcc_reg(cd, I386_CC_A, d); */
4919 /*                                      i386_jcc(cd, I386_CC_BE, 5); */
4920                                 M_BEQ(5);
4921                                 M_MOV_IMM(1, d);
4922
4923                                 if (!super)
4924                                         M_JMP_IMM(s3);
4925                         }
4926
4927                         /* class instanceof code */
4928
4929                         if (!super || !(super->flags & ACC_INTERFACE)) {
4930                                 if (super) {
4931                                         M_TEST(s1);
4932                                         M_BEQ(s3);
4933                                 }
4934
4935                                 i386_mov_membase_reg(cd, s1,
4936                                                                          OFFSET(java_objectheader, vftbl),
4937                                                                          REG_ITMP1);
4938
4939                                 if (!super) {
4940                                         codegen_addpatchref(cd, PATCHER_instanceof_class,
4941                                                                                 (constant_classref *) iptr->target, 0);
4942
4943                                         if (opt_showdisassemble) {
4944                                                 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4945                                         }
4946                                 }
4947
4948                                 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
4949 #if defined(ENABLE_THREADS)
4950                                 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4951 #endif
4952                                 i386_mov_membase_reg(cd, REG_ITMP1,
4953                                                                          OFFSET(vftbl_t, baseval),
4954                                                                          REG_ITMP1);
4955                                 i386_mov_membase_reg(cd, REG_ITMP2,
4956                                                                          OFFSET(vftbl_t, diffval),
4957                                                                          REG_ITMP3);
4958                                 i386_mov_membase_reg(cd, REG_ITMP2,
4959                                                                          OFFSET(vftbl_t, baseval),
4960                                                                          REG_ITMP2);
4961 #if defined(ENABLE_THREADS)
4962                                 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4963 #endif
4964                                 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
4965                                 i386_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
4966                                 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
4967                                 i386_jcc(cd, I386_CC_A, 5);
4968                                 i386_mov_imm_reg(cd, 1, d);
4969                         }
4970                         emit_store(jd, iptr, iptr->dst, d);
4971                         }
4972                         break;
4973
4974                         break;
4975
4976                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
4977                                       /* op1 = dimension, val.a = class               */
4978                         /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4979                         /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
4980
4981                         /* check for negative sizes and copy sizes to stack if necessary  */
4982
4983                         MCODECHECK((iptr->op1 << 1) + 64);
4984
4985                         for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4986                                 /* copy SAVEDVAR sizes to stack */
4987
4988                                 if (src->varkind != ARGVAR) {
4989                                         if (src->flags & INMEMORY) {
4990                                                 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
4991                                                 M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4);
4992
4993                                         } else {
4994                                                 M_IST(src->regoff, REG_SP, (s1 + 3) * 4);
4995                                         }
4996                                 }
4997                         }
4998
4999                         /* is a patcher function set? */
5000
5001                         if (iptr->val.a == NULL) {
5002                                 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
5003                                                                         (constant_classref *) iptr->target, 0);
5004
5005                                 if (opt_showdisassemble) {
5006                                         M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5007                                 }
5008
5009                                 disp = 0;
5010
5011                         } else {
5012                                 disp = (ptrint) iptr->val.a;
5013                         }
5014
5015                         /* a0 = dimension count */
5016
5017                         M_IST_IMM(iptr->op1, REG_SP, 0 * 4);
5018
5019                         /* a1 = arraydescriptor */
5020
5021                         M_IST_IMM(disp, REG_SP, 1 * 4);
5022
5023                         /* a2 = pointer to dimensions = stack pointer */
5024
5025                         M_MOV(REG_SP, REG_ITMP1);
5026                         M_AADD_IMM(3 * 4, REG_ITMP1);
5027                         M_AST(REG_ITMP1, REG_SP, 2 * 4);
5028
5029                         M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
5030                         M_CALL(REG_ITMP1);
5031
5032                         /* check for exception before result assignment */
5033
5034                         M_TEST(REG_RESULT);
5035                         M_BEQ(0);
5036                         codegen_add_fillinstacktrace_ref(cd);
5037
5038                         s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
5039                         M_INTMOVE(REG_RESULT, s1);
5040                         emit_store(jd, iptr, iptr->dst, s1);
5041                         break;
5042
5043                 default:
5044                         *exceptionptr =
5045                                 new_internalerror("Unknown ICMD %d", iptr->opc);
5046                         return false;
5047         } /* switch */
5048                 
5049         } /* for instruction */
5050                 
5051         /* copy values to interface registers */
5052
5053         src = bptr->outstack;
5054         len = bptr->outdepth;
5055         MCODECHECK(64+len);
5056 #if defined(ENABLE_LSRA)
5057         if (!opt_lsra)
5058 #endif
5059         while (src) {
5060                 len--;
5061                 if ((src->varkind != STACKVAR)) {
5062                         s2 = src->type;
5063                         if (IS_FLT_DBL_TYPE(s2)) {
5064                                 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
5065                                 if (!(rd->interfaces[len][s2].flags & INMEMORY))
5066                                         M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
5067                                 else
5068                                         M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5069
5070                         } else {
5071                                 if (IS_2_WORD_TYPE(s2))
5072                                         assert(0);
5073 /*                                      s1 = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP1, REG_ITMP2)); */
5074                                 else
5075                                         s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
5076
5077                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5078                                         if (IS_2_WORD_TYPE(s2))
5079                                                 M_LNGMOVE(s1, rd->interfaces[len][s2].regoff);
5080                                         else
5081                                                 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
5082
5083                                 } else {
5084                                         if (IS_2_WORD_TYPE(s2))
5085                                                 M_LST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5086                                         else
5087                                                 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5088                                 }
5089                         }
5090                 }
5091                 src = src->prev;
5092         }
5093
5094         /* At the end of a basic block we may have to append some nops,
5095            because the patcher stub calling code might be longer than the
5096            actual instruction. So codepatching does not change the
5097            following block unintentionally. */
5098
5099         if (cd->mcodeptr < cd->lastmcodeptr) {
5100                 while (cd->mcodeptr < cd->lastmcodeptr) {
5101                         M_NOP;
5102                 }
5103         }
5104
5105         } /* if (bptr -> flags >= BBREACHED) */
5106         } /* for basic block */
5107
5108         dseg_createlinenumbertable(cd);
5109
5110
5111         /* generate exception and patcher stubs */
5112
5113         {
5114                 exceptionref *eref;
5115                 patchref     *pref;
5116                 u8            mcode;
5117                 u1           *savedmcodeptr;
5118                 u1           *tmpmcodeptr;
5119
5120                 savedmcodeptr = NULL;
5121
5122                 /* generate exception stubs */
5123
5124                 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
5125                         gen_resolvebranch(cd->mcodebase + eref->branchpos,
5126                                                           eref->branchpos,
5127                                                           cd->mcodeptr - cd->mcodebase);
5128
5129                         MCODECHECK(512);
5130
5131                         /* Check if the exception is an
5132                            ArrayIndexOutOfBoundsException.  If so, move index register
5133                            into REG_ITMP1. */
5134
5135                         if (eref->reg != -1)
5136                                 M_INTMOVE(eref->reg, REG_ITMP1);
5137
5138                         /* calcuate exception address */
5139
5140                         M_MOV_IMM(0, REG_ITMP2_XPC);
5141                         dseg_adddata(cd);
5142                         M_AADD_IMM32(eref->branchpos - 6, REG_ITMP2_XPC);
5143
5144                         /* move function to call into REG_ITMP3 */
5145
5146                         M_MOV_IMM(eref->function, REG_ITMP3);
5147
5148                         if (savedmcodeptr != NULL) {
5149                                 M_JMP_IMM((savedmcodeptr - cd->mcodeptr) - 5);
5150
5151                         } else {
5152                                 savedmcodeptr = cd->mcodeptr;
5153
5154                                 M_ASUB_IMM(5 * 4, REG_SP);
5155
5156                                 /* first save REG_ITMP1 so we can use it */
5157
5158                                 M_AST(REG_ITMP1, REG_SP, 4 * 4);                /* for AIOOBE */
5159
5160                                 M_AST_IMM(0, REG_SP, 0 * 4);
5161                                 dseg_adddata(cd);
5162                                 M_MOV(REG_SP, REG_ITMP1);
5163                                 M_AADD_IMM(5 * 4, REG_ITMP1);
5164                                 M_AST(REG_ITMP1, REG_SP, 1 * 4);
5165                                 M_ALD(REG_ITMP1, REG_SP, (5 + stackframesize) * 4);
5166                                 M_AST(REG_ITMP1, REG_SP, 2 * 4);
5167                                 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5168
5169                                 M_CALL(REG_ITMP3);
5170
5171                                 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5172                                 M_AADD_IMM(5 * 4, REG_SP);
5173
5174                                 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
5175                                 M_JMP(REG_ITMP3);
5176                         }
5177                 }
5178
5179
5180                 /* generate code patching stub call code */
5181
5182                 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5183                         /* check code segment size */
5184
5185                         MCODECHECK(512);
5186
5187                         /* Get machine code which is patched back in later. A
5188                            `call rel32' is 5 bytes long. */
5189
5190                         savedmcodeptr = cd->mcodebase + pref->branchpos;
5191                         mcode = *((u8 *) savedmcodeptr);
5192
5193                         /* patch in `call rel32' to call the following code */
5194
5195                         tmpmcodeptr  = cd->mcodeptr;    /* save current mcodeptr          */
5196                         cd->mcodeptr = savedmcodeptr;   /* set mcodeptr to patch position */
5197
5198                         M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
5199
5200                         cd->mcodeptr = tmpmcodeptr;     /* restore the current mcodeptr   */
5201
5202                         /* save REG_ITMP3 */
5203
5204                         M_PUSH(REG_ITMP3);
5205
5206                         /* move pointer to java_objectheader onto stack */
5207
5208 #if defined(ENABLE_THREADS)
5209                         (void) dseg_addaddress(cd, NULL);                         /* flcword    */
5210                         (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
5211                         off = dseg_addaddress(cd, NULL);                          /* vftbl      */
5212
5213                         M_MOV_IMM(0, REG_ITMP3);
5214                         dseg_adddata(cd);
5215                         M_AADD_IMM(off, REG_ITMP3);
5216                         M_PUSH(REG_ITMP3);
5217 #else
5218                         M_PUSH_IMM(0);
5219 #endif
5220
5221                         /* move machine code bytes and classinfo pointer into registers */
5222
5223                         M_PUSH_IMM(mcode >> 32);
5224                         M_PUSH_IMM(mcode);
5225                         M_PUSH_IMM(pref->ref);
5226                         M_PUSH_IMM(pref->patcher);
5227
5228                         M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
5229                         M_JMP(REG_ITMP3);
5230                 }
5231         }
5232
5233         /* generate replacement-out stubs */
5234
5235         {
5236                 int i;
5237
5238                 replacementpoint = jd->code->rplpoints;
5239
5240                 for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
5241                         /* check code segment size */
5242
5243                         MCODECHECK(512);
5244
5245                         /* note start of stub code */
5246
5247                         replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
5248
5249                         /* make machine code for patching */
5250
5251                         disp = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
5252                         replacementpoint->mcode = 0xe9 | ((u8)disp << 8);
5253
5254                         /* push address of `rplpoint` struct */
5255                         
5256                         M_PUSH_IMM(replacementpoint);
5257
5258                         /* jump to replacement function */
5259
5260                         M_PUSH_IMM(asm_replacement_out);
5261                         M_RET;
5262                 }
5263         }
5264         
5265         codegen_finish(jd);
5266
5267         /* everything's ok */
5268
5269         return true;
5270 }
5271
5272
5273 /* createcompilerstub **********************************************************
5274
5275    Creates a stub routine which calls the compiler.
5276         
5277 *******************************************************************************/
5278
5279 #define COMPILERSTUB_DATASIZE    3 * SIZEOF_VOID_P
5280 #define COMPILERSTUB_CODESIZE    12
5281
5282 #define COMPILERSTUB_SIZE        COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
5283
5284
5285 u1 *createcompilerstub(methodinfo *m)
5286 {
5287         u1          *s;                     /* memory to hold the stub            */
5288         ptrint      *d;
5289         codeinfo    *code;
5290         codegendata *cd;
5291         s4           dumpsize;
5292
5293         s = CNEW(u1, COMPILERSTUB_SIZE);
5294
5295         /* set data pointer and code pointer */
5296
5297         d = (ptrint *) s;
5298         s = s + COMPILERSTUB_DATASIZE;
5299
5300         /* mark start of dump memory area */
5301
5302         dumpsize = dump_size();
5303
5304         cd = DNEW(codegendata);
5305         cd->mcodeptr = s;
5306
5307         /* Store the codeinfo pointer in the same place as in the
5308            methodheader for compiled methods. */
5309
5310         code = code_codeinfo_new(m);
5311
5312         d[0] = (ptrint) asm_call_jit_compiler;
5313         d[1] = (ptrint) m;
5314         d[2] = (ptrint) code;
5315
5316         M_MOV_IMM(m, REG_ITMP1);
5317
5318         /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching  */
5319         M_MOV_IMM(asm_call_jit_compiler, REG_ITMP3);
5320         M_JMP(REG_ITMP3);
5321
5322 #if defined(ENABLE_STATISTICS)
5323         if (opt_stat)
5324                 count_cstub_len += COMPILERSTUB_SIZE;
5325 #endif
5326
5327         /* release dump area */
5328
5329         dump_release(dumpsize);
5330         
5331         return s;
5332 }
5333
5334
5335 /* createnativestub ************************************************************
5336
5337    Creates a stub routine which calls a native method.
5338
5339 *******************************************************************************/
5340
5341 #if defined(ENABLE_THREADS)
5342 /* this way we can call the function directly with a memory call */
5343
5344 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
5345 #endif
5346
5347 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
5348 {
5349         methodinfo   *m;
5350         codeinfo     *code;
5351         codegendata  *cd;
5352         registerdata *rd;
5353         methoddesc   *md;
5354         s4            stackframesize;
5355         s4            nativeparams;
5356         s4            i, j;                 /* count variables                    */
5357         s4            t;
5358         s4            s1, s2, disp;
5359
5360         /* get required compiler data */
5361
5362         m    = jd->m;
5363         code = jd->code;
5364         cd   = jd->cd;
5365         rd   = jd->rd;
5366
5367         /* set some variables */
5368
5369         md = m->parseddesc;
5370         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
5371
5372         /* calculate stackframe size */
5373
5374         stackframesize =
5375                 sizeof(stackframeinfo) / SIZEOF_VOID_P +
5376                 sizeof(localref_table) / SIZEOF_VOID_P +
5377                 1 +                             /* function pointer                   */
5378                 4 * 4 +                         /* 4 arguments (start_native_call)    */
5379                 nmd->memuse;
5380
5381         /* create method header */
5382
5383         (void) dseg_addaddress(cd, code);                      /* CodeinfoPointer */
5384         (void) dseg_adds4(cd, stackframesize * 4);             /* FrameSize       */
5385         (void) dseg_adds4(cd, 0);                              /* IsSync          */
5386         (void) dseg_adds4(cd, 0);                              /* IsLeaf          */
5387         (void) dseg_adds4(cd, 0);                              /* IntSave         */
5388         (void) dseg_adds4(cd, 0);                              /* FltSave         */
5389         (void) dseg_addlinenumbertablesize(cd);
5390         (void) dseg_adds4(cd, 0);                              /* ExTableSize     */
5391
5392         /* generate native method profiling code */
5393
5394         if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
5395                 /* count frequency */
5396
5397                 M_MOV_IMM(code, REG_ITMP1);
5398                 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(codeinfo, frequency));
5399         }
5400
5401         /* calculate stackframe size for native function */
5402
5403         M_ASUB_IMM(stackframesize * 4, REG_SP);
5404
5405 #if !defined(NDEBUG)
5406         if (opt_verbosecall) {
5407                 s4 p, t;
5408
5409                 disp = stackframesize * 4;
5410
5411                 M_ASUB_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5412     
5413                 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
5414                         t = md->paramtypes[p].type;
5415                         if (IS_INT_LNG_TYPE(t)) {
5416                                 if (IS_2_WORD_TYPE(t)) {
5417                                         M_ILD(REG_ITMP1, REG_SP,
5418                                                   4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5419                                         M_ILD(REG_ITMP2, REG_SP,
5420                                                   4 + TRACE_ARGS_NUM * 8 + 4 + disp + 4);
5421                                         M_IST(REG_ITMP1, REG_SP, p * 8);
5422                                         M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5423
5424                                 } else if (t == TYPE_ADR) {
5425                                         M_ALD(REG_ITMP1, REG_SP,
5426                                                   4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5427                                         M_CLR(REG_ITMP2);
5428                                         M_AST(REG_ITMP1, REG_SP, p * 8);
5429                                         M_AST(REG_ITMP2, REG_SP, p * 8 + 4);
5430
5431                                 } else {
5432                                         M_ILD(EAX, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5433                                         i386_cltd(cd);
5434                                         M_IST(EAX, REG_SP, p * 8);
5435                                         M_IST(EDX, REG_SP, p * 8 + 4);
5436                                 }
5437
5438                         } else {
5439                                 if (!IS_2_WORD_TYPE(t)) {
5440                                         i386_flds_membase(cd, REG_SP,
5441                                                                           4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5442                                         i386_fstps_membase(cd, REG_SP, p * 8);
5443                                         i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
5444                                         M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5445
5446                                 } else {
5447                                         i386_fldl_membase(cd, REG_SP,
5448                                             4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5449                                         i386_fstpl_membase(cd, REG_SP, p * 8);
5450                                 }
5451                         }
5452                         disp += (IS_2_WORD_TYPE(t)) ? 8 : 4;
5453                 }
5454         
5455                 M_CLR(REG_ITMP1);
5456                 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
5457                         M_IST(REG_ITMP1, REG_SP, p * 8);
5458                         M_IST(REG_ITMP1, REG_SP, p * 8 + 4);
5459                 }
5460
5461                 M_AST_IMM(m, REG_SP, TRACE_ARGS_NUM * 8);
5462
5463                 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
5464                 M_CALL(REG_ITMP1);
5465
5466                 M_AADD_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5467         }
5468 #endif /* !defined(NDEBUG) */
5469
5470         /* get function address (this must happen before the stackframeinfo) */
5471
5472 #if !defined(WITH_STATIC_CLASSPATH)
5473         if (f == NULL) {
5474                 codegen_addpatchref(cd, PATCHER_resolve_native, m, 0);
5475
5476                 if (opt_showdisassemble) {
5477                         M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5478                 }
5479         }
5480 #endif
5481
5482         M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
5483
5484         /* Mark the whole fpu stack as free for native functions (only for saved  */
5485         /* register count == 0).                                                  */
5486
5487         i386_ffree_reg(cd, 0);
5488         i386_ffree_reg(cd, 1);
5489         i386_ffree_reg(cd, 2);
5490         i386_ffree_reg(cd, 3);
5491         i386_ffree_reg(cd, 4);
5492         i386_ffree_reg(cd, 5);
5493         i386_ffree_reg(cd, 6);
5494         i386_ffree_reg(cd, 7);
5495
5496         /* prepare data structures for native function call */
5497
5498         M_MOV(REG_SP, REG_ITMP1);
5499         M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5500
5501         M_AST(REG_ITMP1, REG_SP, 0 * 4);
5502         M_IST_IMM(0, REG_SP, 1 * 4);
5503         dseg_adddata(cd);
5504
5505         M_MOV(REG_SP, REG_ITMP2);
5506         M_AADD_IMM(stackframesize * 4 + SIZEOF_VOID_P, REG_ITMP2);
5507
5508         M_AST(REG_ITMP2, REG_SP, 2 * 4);
5509         M_ALD(REG_ITMP3, REG_SP, stackframesize * 4);
5510         M_AST(REG_ITMP3, REG_SP, 3 * 4);
5511         M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
5512         M_CALL(REG_ITMP1);
5513
5514         M_ALD(REG_ITMP3, REG_SP, 4 * 4);
5515
5516         /* copy arguments into new stackframe */
5517
5518         for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
5519                 t = md->paramtypes[i].type;
5520
5521                 if (!md->params[i].inmemory) {
5522                         /* no integer argument registers */
5523                 } else {       /* float/double in memory can be copied like int/longs */
5524                         s1 = (md->params[i].regoff + stackframesize + 1) * 4;
5525                         s2 = nmd->params[j].regoff * 4;
5526
5527                         M_ILD(REG_ITMP1, REG_SP, s1);
5528                         M_IST(REG_ITMP1, REG_SP, s2);
5529                         if (IS_2_WORD_TYPE(t)) {
5530                                 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
5531                                 M_IST(REG_ITMP1, REG_SP, s2 + 4);
5532                         }
5533                 }
5534         }
5535
5536         /* if function is static, put class into second argument */
5537
5538         if (m->flags & ACC_STATIC)
5539                 M_AST_IMM((ptrint) m->class, REG_SP, 1 * 4);
5540
5541         /* put env into first argument */
5542
5543         M_AST_IMM((ptrint) _Jv_env, REG_SP, 0 * 4);
5544
5545         /* call the native function */
5546
5547         M_CALL(REG_ITMP3);
5548
5549         /* save return value */
5550
5551         if (md->returntype.type != TYPE_VOID) {
5552                 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5553                         if (IS_2_WORD_TYPE(md->returntype.type))
5554                                 M_IST(REG_RESULT2, REG_SP, 2 * 4);
5555                         M_IST(REG_RESULT, REG_SP, 1 * 4);
5556                 }
5557                 else {
5558                         if (IS_2_WORD_TYPE(md->returntype.type))
5559                                 i386_fstl_membase(cd, REG_SP, 1 * 4);
5560                         else
5561                                 i386_fsts_membase(cd, REG_SP, 1 * 4);
5562                 }
5563         }
5564
5565 #if !defined(NDEBUG)
5566     if (opt_verbosecall) {
5567                 /* restore return value */
5568
5569                 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5570                         if (IS_2_WORD_TYPE(md->returntype.type))
5571                                 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5572                         M_ILD(REG_RESULT, REG_SP, 1 * 4);
5573         
5574                 } else {
5575                         if (IS_2_WORD_TYPE(md->returntype.type))
5576                                 i386_fldl_membase(cd, REG_SP, 1 * 4);
5577                         else
5578                                 i386_flds_membase(cd, REG_SP, 1 * 4);
5579                 }
5580
5581                 M_ASUB_IMM(4 + 8 + 8 + 4, REG_SP);
5582
5583                 M_AST_IMM((ptrint) m, REG_SP, 0);
5584
5585                 M_IST(REG_RESULT, REG_SP, 4);
5586                 M_IST(REG_RESULT2, REG_SP, 4 + 4);
5587
5588                 i386_fstl_membase(cd, REG_SP, 4 + 8);
5589                 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5590
5591                 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
5592                 M_CALL(REG_ITMP1);
5593
5594                 M_AADD_IMM(4 + 8 + 8 + 4, REG_SP);
5595     }
5596 #endif /* !defined(NDEBUG) */
5597
5598         /* remove native stackframe info */
5599
5600         M_MOV(REG_SP, REG_ITMP1);
5601         M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5602
5603         M_AST(REG_ITMP1, REG_SP, 0 * 4);
5604         M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
5605         M_CALL(REG_ITMP1);
5606         M_MOV(REG_RESULT, REG_ITMP2);                 /* REG_ITMP3 == REG_RESULT2 */
5607
5608         /* restore return value */
5609
5610         if (md->returntype.type != TYPE_VOID) {
5611                 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5612                         if (IS_2_WORD_TYPE(md->returntype.type))
5613                                 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5614                         M_ILD(REG_RESULT, REG_SP, 1 * 4);
5615                 }
5616                 else {
5617                         if (IS_2_WORD_TYPE(md->returntype.type))
5618                                 i386_fldl_membase(cd, REG_SP, 1 * 4);
5619                         else
5620                                 i386_flds_membase(cd, REG_SP, 1 * 4);
5621                 }
5622         }
5623
5624         M_AADD_IMM(stackframesize * 4, REG_SP);
5625
5626         /* check for exception */
5627
5628         M_TEST(REG_ITMP2);
5629         M_BNE(1);
5630
5631         M_RET;
5632
5633         /* handle exception */
5634
5635         M_MOV(REG_ITMP2, REG_ITMP1_XPTR);
5636         M_ALD(REG_ITMP2_XPC, REG_SP, 0);
5637         M_ASUB_IMM(2, REG_ITMP2_XPC);
5638
5639         M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
5640         M_JMP(REG_ITMP3);
5641
5642
5643         /* process patcher calls **************************************************/
5644
5645         {
5646                 u1       *xcodeptr;
5647                 patchref *pref;
5648                 u8        mcode;
5649                 u1       *tmpmcodeptr;
5650
5651                 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5652                         /* Get machine code which is patched back in later. A
5653                            `call rel32' is 5 bytes long. */
5654
5655                         xcodeptr = cd->mcodebase + pref->branchpos;
5656                         mcode =  *((u8 *) xcodeptr);
5657
5658                         /* patch in `call rel32' to call the following code */
5659
5660                         tmpmcodeptr  = cd->mcodeptr;    /* save current mcodeptr          */
5661                         cd->mcodeptr = xcodeptr;        /* set mcodeptr to patch position */
5662
5663                         M_CALL_IMM(tmpmcodeptr - (xcodeptr + PATCHER_CALL_SIZE));
5664
5665                         cd->mcodeptr = tmpmcodeptr;     /* restore the current mcodeptr   */
5666
5667                         /* save REG_ITMP3 */
5668
5669                         M_PUSH(REG_ITMP3);
5670
5671                         /* move pointer to java_objectheader onto stack */
5672
5673 #if defined(ENABLE_THREADS)
5674                         /* create a virtual java_objectheader */
5675
5676                         (void) dseg_addaddress(cd, NULL);                         /* flcword    */
5677                         (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
5678                         disp = dseg_addaddress(cd, NULL);                         /* vftbl      */
5679
5680                         M_MOV_IMM(0, REG_ITMP3);
5681                         dseg_adddata(cd);
5682                         M_AADD_IMM(disp, REG_ITMP3);
5683                         M_PUSH(REG_ITMP3);
5684 #else
5685                         M_PUSH_IMM(0);
5686 #endif
5687
5688                         /* move machine code bytes and classinfo pointer onto stack */
5689
5690                         M_PUSH_IMM((mcode >> 32));
5691                         M_PUSH_IMM(mcode);
5692                         M_PUSH_IMM(pref->ref);
5693                         M_PUSH_IMM(pref->patcher);
5694
5695                         M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
5696                         M_JMP(REG_ITMP3);
5697                 }
5698         }
5699
5700         codegen_finish(jd);
5701
5702         return jd->code->entrypoint;
5703 }
5704
5705
5706 /*
5707  * These are local overrides for various environment variables in Emacs.
5708  * Please do not remove this and leave it at the end of the file, where
5709  * Emacs will automagically detect them.
5710  * ---------------------------------------------------------------------
5711  * Local variables:
5712  * mode: c
5713  * indent-tabs-mode: t
5714  * c-basic-offset: 4
5715  * tab-width: 4
5716  * End:
5717  * vim:noexpandtab:sw=4:ts=4:
5718  */