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