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