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