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