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