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