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