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