1 /* jit/i386/codegen.c - machine code generator for i386
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,
9 This file is part of CACAO.
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.
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.
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
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Andreas Krall
31 $Id: codegen.c 1296 2004-07-10 17:02:15Z stefan $
40 #include <sys/ucontext.h>
50 #include "jit/parse.h"
52 #include "jit/i386/codegen.h"
53 #include "jit/i386/emitfuncs.h"
55 /* include independent code generation stuff */
56 #include "jit/codegen.inc"
57 #include "jit/reg.inc"
60 /* register descripton - array ************************************************/
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) */
69 /* #define REG_END -1 last entry in tables */
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
78 REG_RET, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV,
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,
92 void codegen_stubcalled() {
93 log_text("Stub has been called");
96 void codegen_general_stubcalled() {
97 log_text("general exception stub has been called");
101 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
102 void thread_restartcriticalsection(ucontext_t *uc)
105 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL)
106 uc->uc_mcontext.gregs[REG_EIP] = (u4) critical;
111 #define PREPARE_NATIVE_STACKINFO \
112 i386_push_reg(REG_ITMP1); /*save itmp1, needed by some stubs */ \
113 i386_alu_imm_reg(I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \
114 i386_mov_imm_reg((s4) codegen_stubcalled,REG_ITMP1); \
115 i386_call_reg(REG_ITMP1); /*call codegen_stubcalled*/ \
116 i386_mov_imm_reg((s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \
117 i386_call_reg(REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/ \
118 i386_mov_reg_membase(REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/ \
119 i386_mov_membase_reg(REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \
120 i386_mov_reg_membase(REG_ITMP2,REG_SP,0*4); /* store value on stack */ \
121 i386_mov_reg_membase(REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \
122 i386_mov_membase_reg(REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \
123 i386_mov_imm_membase(0,REG_SP, 2*4); /* builtin */
126 #define REMOVE_NATIVE_STACKINFO \
127 i386_mov_membase_reg(REG_SP,0,REG_ITMP2); \
128 i386_mov_membase_reg(REG_SP,4,REG_ITMP3); \
129 i386_mov_reg_membase(REG_ITMP2,REG_ITMP3,0); \
130 i386_alu_imm_reg(I386_ADD,3*4,REG_SP);
134 /* NullPointerException signal handler for hardware null pointer check */
136 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
139 /* long faultaddr; */
141 struct ucontext *_uc = (struct ucontext *) _p;
142 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
143 struct sigaction act;
145 /* Reset signal handler - necessary for SysV, does no harm for BSD */
147 /* instr = *((int*)(sigctx->eip)); */
148 /* faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f]; */
150 /* fprintf(stderr, "null=%d %p addr=%p\n", sig, sigctx, sigctx->eip);*/
152 /* if (faultaddr == 0) { */
153 /* signal(sig, (void *) catch_NullPointerException); */
154 act.sa_sigaction = (void *) catch_NullPointerException;
155 act.sa_flags = SA_SIGINFO;
156 sigaction(sig, &act, NULL); /* reinstall handler */
159 sigaddset(&nsig, sig);
160 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
162 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
163 sigctx->eax = (u4) string_java_lang_NullPointerException;
164 sigctx->eip = (u4) asm_throw_and_handle_exception;
169 /* faultaddr += (long) ((instr << 16) >> 16); */
170 /* fprintf(stderr, "faulting address: 0x%08x\n", faultaddr); */
171 /* panic("Stack overflow"); */
176 /* ArithmeticException signal handler for hardware divide by zero check */
178 void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p)
182 /* void **_p = (void **) &sig; */
183 /* struct sigcontext *sigctx = (struct sigcontext *) ++_p; */
184 struct ucontext *_uc = (struct ucontext *) _p;
185 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
186 struct sigaction act;
188 /* Reset signal handler - necessary for SysV, does no harm for BSD */
190 /* signal(sig, (void *) catch_ArithmeticException); */
191 act.sa_sigaction = (void *) catch_ArithmeticException;
192 act.sa_flags = SA_SIGINFO;
193 sigaction(sig, &act, NULL); /* reinstall handler */
196 sigaddset(&nsig, sig);
197 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
199 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
200 sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
206 void init_exceptions(void)
208 struct sigaction act;
210 /* install signal handlers we need to convert to exceptions */
214 /* signal(SIGSEGV, (void *) catch_NullPointerException); */
215 act.sa_sigaction = (void *) catch_NullPointerException;
216 act.sa_flags = SA_SIGINFO;
217 sigaction(SIGSEGV, &act, NULL);
221 /* signal(SIGBUS, (void *) catch_NullPointerException); */
222 act.sa_sigaction = (void *) catch_NullPointerException;
223 act.sa_flags = SA_SIGINFO;
224 sigaction(SIGBUS, &act, NULL);
228 /* signal(SIGFPE, (void *) catch_ArithmeticException); */
229 act.sa_sigaction = (void *) catch_ArithmeticException;
230 act.sa_flags = SA_SIGINFO;
231 sigaction(SIGFPE, &act, NULL);
235 /* function codegen ************************************************************
237 generates machine code
239 *******************************************************************************/
241 /* global code generation pointer */
244 void codegen(methodinfo *m)
246 int len, s1, s2, s3, d;
254 s4 fpu_st_offset = 0;
260 s4 savedregs_num = 0;
262 /* keep code size smaller */
265 /* space to save used callee saved registers */
267 savedregs_num += (r->savintregcnt - r->maxsavintreguse);
268 savedregs_num += (r->savfltregcnt - r->maxsavfltreguse);
270 parentargs_base = r->maxmemuse + savedregs_num;
272 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
274 if (checksync && (m->flags & ACC_SYNCHRONIZED))
279 /* create method header */
281 (void) dseg_addaddress(m); /* MethodPointer */
282 (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
284 #if defined(USE_THREADS)
286 /* IsSync contains the offset relative to the stack pointer for the
287 argument of monitor_exit used in the exception handler. Since the
288 offset could be zero and give a wrong meaning of the flag it is
292 if (checksync && (m->flags & ACC_SYNCHRONIZED))
293 (void) dseg_adds4((r->maxmemuse + 1) * 8); /* IsSync */
298 (void) dseg_adds4(0); /* IsSync */
300 (void) dseg_adds4(m->isleafmethod); /* IsLeaf */
301 (void) dseg_adds4(r->savintregcnt - r->maxsavintreguse);/* IntSave */
302 (void) dseg_adds4(r->savfltregcnt - r->maxsavfltreguse);/* FltSave */
304 /* adds a reference for the length of the line number counter. We don't
305 know the size yet, since we evaluate the information during code
306 generation, to save one additional iteration over the whole
307 instructions. During code optimization the position could have changed
308 to the information gotten from the class file */
309 (void) dseg_addlinenumbertablesize();
311 (void) dseg_adds4(m->exceptiontablelength); /* ExTableSize */
313 /* create exception table */
315 for (ex = m->exceptiontable; ex != NULL; ex = ex->down) {
316 dseg_addtarget(ex->start);
317 dseg_addtarget(ex->end);
318 dseg_addtarget(ex->handler);
319 (void) dseg_addaddress(ex->catchtype);
323 /* initialize mcode variables */
325 mcodeptr = (u1*) mcodebase;
326 mcodeend = (s4*) (mcodebase + mcodesize);
327 MCODECHECK(128 + m->paramcount);
329 /* create stack frame (if necessary) */
331 if (parentargs_base) {
332 i386_alu_imm_reg(I386_SUB, parentargs_base * 8, REG_SP);
335 /* save return address and used callee saved registers */
338 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
339 p--; i386_mov_reg_membase(r->savintregs[i], REG_SP, p * 8);
341 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
342 p--; i386_fld_reg(r->savfltregs[i]); i386_fstpl_membase(REG_SP, p * 8);
345 /* save monitorenter argument */
347 #if defined(USE_THREADS)
348 s4 func_enter = (m->flags & ACC_STATIC) ?
349 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
351 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
352 if (m->flags & ACC_STATIC) {
353 i386_mov_imm_reg((s4) m->class, REG_ITMP1);
354 i386_mov_reg_membase(REG_ITMP1, REG_SP, r->maxmemuse * 8);
357 i386_mov_membase_reg(REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
358 i386_mov_reg_membase(REG_ITMP1, REG_SP, r->maxmemuse * 8);
361 /* call monitorenter function */
363 i386_alu_imm_reg(I386_SUB, 4, REG_SP);
364 i386_mov_reg_membase(REG_ITMP1, REG_SP, 0);
365 i386_mov_imm_reg(func_enter, REG_ITMP1);
366 i386_call_reg(REG_ITMP1);
367 i386_alu_imm_reg(I386_ADD, 4, REG_SP);
371 /* copy argument registers to stack and call trace function with pointer
372 to arguments on stack.
376 i386_alu_imm_reg(I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
378 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
379 t = m->paramtypes[p];
381 if (IS_INT_LNG_TYPE(t)) {
382 if (IS_2_WORD_TYPE(t)) {
383 i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
384 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
385 i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
386 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
388 /* } else if (t == TYPE_ADR) { */
390 i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
391 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
392 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
393 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
396 /* i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
398 /* i386_mov_reg_membase(EAX, REG_SP, p * 8); */
399 /* i386_mov_reg_membase(EDX, REG_SP, p * 8 + 4); */
403 if (!IS_2_WORD_TYPE(t)) {
404 i386_flds_membase(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
405 i386_fstps_membase(REG_SP, p * 8);
406 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
407 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
410 i386_fldl_membase(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
411 i386_fstpl_membase(REG_SP, p * 8);
416 /* fill up the remaining arguments */
417 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
418 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
419 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
420 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
423 i386_mov_imm_membase((s4) m, REG_SP, TRACE_ARGS_NUM * 8);
424 i386_mov_imm_reg((s4) builtin_trace_args, REG_ITMP1);
425 i386_call_reg(REG_ITMP1);
427 i386_alu_imm_reg(I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
430 /* take arguments out of register or stack frame */
432 for (p = 0, l = 0; p < m->paramcount; p++) {
433 t = m->paramtypes[p];
434 var = &(r->locals[l][t]);
436 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
440 if (IS_INT_LNG_TYPE(t)) { /* integer args */
441 if (p < r->intreg_argnum) { /* register arguments */
442 panic("integer register argument");
443 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
444 /* M_INTMOVE (argintregs[p], r); */
446 } else { /* reg arg -> spilled */
447 /* M_LST (argintregs[p], REG_SP, 8 * r); */
449 } else { /* stack arguments */
450 pa = p - r->intreg_argnum;
451 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
452 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, var->regoff); /* + 4 for return address */
453 } else { /* stack arg -> spilled */
454 if (!IS_2_WORD_TYPE(t)) {
455 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
456 i386_mov_reg_membase(REG_ITMP1, REG_SP, var->regoff * 8);
459 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
460 i386_mov_reg_membase(REG_ITMP1, REG_SP, var->regoff * 8);
461 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1); /* + 4 for return address */
462 i386_mov_reg_membase(REG_ITMP1, REG_SP, var->regoff * 8 + 4);
467 } else { /* floating args */
468 if (p < r->fltreg_argnum) { /* register arguments */
469 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
470 panic("There are no float argument registers!");
472 } else { /* reg arg -> spilled */
473 panic("There are no float argument registers!");
476 } else { /* stack arguments */
477 pa = p - r->fltreg_argnum;
478 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
480 i386_flds_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
482 i386_fstp_reg(var->regoff + fpu_st_offset);
486 i386_fldl_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
488 i386_fstp_reg(var->regoff + fpu_st_offset);
492 } else { /* stack-arg -> spilled */
493 /* i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
494 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, r * 8); */
496 i386_flds_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
497 i386_fstps_membase(REG_SP, var->regoff * 8);
500 i386_fldl_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
501 i386_fstpl_membase(REG_SP, var->regoff * 8);
510 /* end of header generation */
512 /* walk through all basic blocks */
513 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
515 bptr->mpc = (s4) ((u1 *) mcodeptr - mcodebase);
517 if (bptr->flags >= BBREACHED) {
519 /* branch resolving */
522 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
523 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
524 brefs->branchpos, bptr->mpc);
527 /* copy interface registers to their destination */
532 while (src != NULL) {
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);
539 store_reg_to_var_int(src, d);
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);
548 panic("copy interface registers: longs have to me in memory (begin 1)");
552 d = reg_of_var(m, src, REG_ITMP1);
553 if ((src->varkind != STACKVAR)) {
555 if (IS_FLT_DBL_TYPE(s2)) {
556 s1 = r->interfaces[len][s2].regoff;
557 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
561 if (s2 == TYPE_FLT) {
562 i386_flds_membase(REG_SP, s1 * 8);
565 i386_fldl_membase(REG_SP, s1 * 8);
568 store_reg_to_var_flt(src, d);
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)) {
577 i386_mov_membase_reg(REG_SP, s1 * 8, d);
579 store_reg_to_var_int(src, d);
582 if (r->interfaces[len][s2].flags & INMEMORY) {
583 M_LNGMEMMOVE(s1, src->regoff);
586 panic("copy interface registers: longs have to be in memory (begin 2)");
595 /* walk through all instructions */
599 for (iptr = bptr->iinstr;
601 src = iptr->dst, len--, iptr++) {
603 if (iptr->line!=currentline) {
604 dseg_addlinenumber(iptr->line,mcodeptr);
605 currentline=iptr->line;
607 MCODECHECK(64); /* an instruction usually needs < 64 words */
610 case ICMD_NOP: /* ... ==> ... */
613 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
614 if (src->flags & INMEMORY) {
615 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
618 i386_test_reg_reg(src->regoff, src->regoff);
620 i386_jcc(I386_CC_E, 0);
621 codegen_addxnullrefs(mcodeptr);
624 /* constant operations ************************************************/
626 case ICMD_ICONST: /* ... ==> ..., constant */
627 /* op1 = 0, val.i = constant */
629 d = reg_of_var(m, iptr->dst, REG_ITMP1);
630 if (iptr->dst->flags & INMEMORY) {
631 i386_mov_imm_membase(iptr->val.i, REG_SP, iptr->dst->regoff * 8);
634 if (iptr->val.i == 0) {
635 i386_alu_reg_reg(I386_XOR, d, d);
638 i386_mov_imm_reg(iptr->val.i, d);
643 case ICMD_LCONST: /* ... ==> ..., constant */
644 /* op1 = 0, val.l = constant */
646 d = reg_of_var(m, iptr->dst, REG_ITMP1);
647 if (iptr->dst->flags & INMEMORY) {
648 i386_mov_imm_membase(iptr->val.l, REG_SP, iptr->dst->regoff * 8);
649 i386_mov_imm_membase(iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
652 panic("LCONST: longs have to be in memory");
656 case ICMD_FCONST: /* ... ==> ..., constant */
657 /* op1 = 0, val.f = constant */
659 d = reg_of_var(m, iptr->dst, REG_FTMP1);
660 if (iptr->val.f == 0.0) {
665 if (iptr->val.i == 0x80000000) {
669 } else if (iptr->val.f == 1.0) {
673 } else if (iptr->val.f == 2.0) {
680 a = dseg_addfloat(iptr->val.f);
681 i386_mov_imm_reg(0, REG_ITMP1);
682 dseg_adddata(mcodeptr);
683 i386_flds_membase(REG_ITMP1, a);
686 store_reg_to_var_flt(iptr->dst, d);
689 case ICMD_DCONST: /* ... ==> ..., constant */
690 /* op1 = 0, val.d = constant */
692 d = reg_of_var(m, iptr->dst, REG_FTMP1);
693 if (iptr->val.d == 0.0) {
698 if (iptr->val.l == 0x8000000000000000LL) {
702 } else if (iptr->val.d == 1.0) {
706 } else if (iptr->val.d == 2.0) {
713 a = dseg_adddouble(iptr->val.d);
714 i386_mov_imm_reg(0, REG_ITMP1);
715 dseg_adddata(mcodeptr);
716 i386_fldl_membase(REG_ITMP1, a);
719 store_reg_to_var_flt(iptr->dst, d);
722 case ICMD_ACONST: /* ... ==> ..., constant */
723 /* op1 = 0, val.a = constant */
725 d = reg_of_var(m, iptr->dst, REG_ITMP1);
726 if (iptr->dst->flags & INMEMORY) {
727 i386_mov_imm_membase((s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
730 if ((s4) iptr->val.a == 0) {
731 i386_alu_reg_reg(I386_XOR, d, d);
734 i386_mov_imm_reg((s4) iptr->val.a, d);
740 /* load/store operations **********************************************/
742 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
743 case ICMD_ALOAD: /* op1 = local variable */
745 d = reg_of_var(m, iptr->dst, REG_ITMP1);
746 if ((iptr->dst->varkind == LOCALVAR) &&
747 (iptr->dst->varnum == iptr->op1)) {
750 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
751 if (iptr->dst->flags & INMEMORY) {
752 if (var->flags & INMEMORY) {
753 i386_mov_membase_reg(REG_SP, var->regoff * 8, REG_ITMP1);
754 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
757 i386_mov_reg_membase(var->regoff, REG_SP, iptr->dst->regoff * 8);
761 if (var->flags & INMEMORY) {
762 i386_mov_membase_reg(REG_SP, var->regoff * 8, iptr->dst->regoff);
765 M_INTMOVE(var->regoff, iptr->dst->regoff);
770 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
771 /* op1 = local variable */
773 d = reg_of_var(m, iptr->dst, REG_ITMP1);
774 if ((iptr->dst->varkind == LOCALVAR) &&
775 (iptr->dst->varnum == iptr->op1)) {
778 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
779 if (iptr->dst->flags & INMEMORY) {
780 if (var->flags & INMEMORY) {
781 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
784 panic("LLOAD: longs have to be in memory");
788 panic("LLOAD: longs have to be in memory");
792 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
793 /* op1 = local variable */
795 d = reg_of_var(m, iptr->dst, REG_FTMP1);
796 if ((iptr->dst->varkind == LOCALVAR) &&
797 (iptr->dst->varnum == iptr->op1)) {
800 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
801 if (var->flags & INMEMORY) {
802 i386_flds_membase(REG_SP, var->regoff * 8);
805 i386_fld_reg(var->regoff + fpu_st_offset);
808 store_reg_to_var_flt(iptr->dst, d);
811 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
812 /* op1 = local variable */
814 d = reg_of_var(m, iptr->dst, REG_FTMP1);
815 if ((iptr->dst->varkind == LOCALVAR) &&
816 (iptr->dst->varnum == iptr->op1)) {
819 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
820 if (var->flags & INMEMORY) {
821 i386_fldl_membase(REG_SP, var->regoff * 8);
824 i386_fld_reg(var->regoff + fpu_st_offset);
827 store_reg_to_var_flt(iptr->dst, d);
830 case ICMD_ISTORE: /* ..., value ==> ... */
831 case ICMD_ASTORE: /* op1 = local variable */
833 if ((src->varkind == LOCALVAR) &&
834 (src->varnum == iptr->op1)) {
837 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
838 if (var->flags & INMEMORY) {
839 if (src->flags & INMEMORY) {
840 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
841 i386_mov_reg_membase(REG_ITMP1, REG_SP, var->regoff * 8);
844 i386_mov_reg_membase(src->regoff, REG_SP, var->regoff * 8);
848 var_to_reg_int(s1, src, var->regoff);
849 M_INTMOVE(s1, var->regoff);
853 case ICMD_LSTORE: /* ..., value ==> ... */
854 /* op1 = local variable */
856 if ((src->varkind == LOCALVAR) &&
857 (src->varnum == iptr->op1)) {
860 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
861 if (var->flags & INMEMORY) {
862 if (src->flags & INMEMORY) {
863 M_LNGMEMMOVE(src->regoff, var->regoff);
866 panic("LSTORE: longs have to be in memory");
870 panic("LSTORE: longs have to be in memory");
874 case ICMD_FSTORE: /* ..., value ==> ... */
875 /* op1 = local variable */
877 if ((src->varkind == LOCALVAR) &&
878 (src->varnum == iptr->op1)) {
881 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
882 if (var->flags & INMEMORY) {
883 var_to_reg_flt(s1, src, REG_FTMP1);
884 i386_fstps_membase(REG_SP, var->regoff * 8);
887 var_to_reg_flt(s1, src, var->regoff);
888 /* M_FLTMOVE(s1, var->regoff); */
889 i386_fstp_reg(var->regoff + fpu_st_offset);
894 case ICMD_DSTORE: /* ..., value ==> ... */
895 /* op1 = local variable */
897 if ((src->varkind == LOCALVAR) &&
898 (src->varnum == iptr->op1)) {
901 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
902 if (var->flags & INMEMORY) {
903 var_to_reg_flt(s1, src, REG_FTMP1);
904 i386_fstpl_membase(REG_SP, var->regoff * 8);
907 var_to_reg_flt(s1, src, var->regoff);
908 /* M_FLTMOVE(s1, var->regoff); */
909 i386_fstp_reg(var->regoff + fpu_st_offset);
915 /* pop/dup/swap operations ********************************************/
917 /* attention: double and longs are only one entry in CACAO ICMDs */
919 case ICMD_POP: /* ..., value ==> ... */
920 case ICMD_POP2: /* ..., value, value ==> ... */
923 #define M_COPY(from,to) \
924 d = reg_of_var(m, to, REG_ITMP1); \
925 if ((from->regoff != to->regoff) || \
926 ((from->flags ^ to->flags) & INMEMORY)) { \
927 if (IS_FLT_DBL_TYPE(from->type)) { \
928 var_to_reg_flt(s1, from, d); \
929 /* M_FLTMOVE(s1, d);*/ \
930 store_reg_to_var_flt(to, d); \
932 if (!IS_2_WORD_TYPE(from->type)) { \
933 if (to->flags & INMEMORY) { \
934 if (from->flags & INMEMORY) { \
935 i386_mov_membase_reg(REG_SP, from->regoff * 8, REG_ITMP1); \
936 i386_mov_reg_membase(REG_ITMP1, REG_SP, to->regoff * 8); \
938 i386_mov_reg_membase(from->regoff, REG_SP, to->regoff * 8); \
941 if (from->flags & INMEMORY) { \
942 i386_mov_membase_reg(REG_SP, from->regoff * 8, to->regoff); \
944 i386_mov_reg_reg(from->regoff, to->regoff); \
948 M_LNGMEMMOVE(from->regoff, to->regoff); \
953 case ICMD_DUP: /* ..., a ==> ..., a, a */
954 M_COPY(src, iptr->dst);
957 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
959 M_COPY(src, iptr->dst->prev->prev);
961 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
963 M_COPY(src, iptr->dst);
964 M_COPY(src->prev, iptr->dst->prev);
967 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
969 M_COPY(src->prev, iptr->dst->prev->prev->prev);
971 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
973 M_COPY(src, iptr->dst);
974 M_COPY(src->prev, iptr->dst->prev);
975 M_COPY(src->prev->prev, iptr->dst->prev->prev);
976 M_COPY(src, iptr->dst->prev->prev->prev);
979 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
981 M_COPY(src, iptr->dst);
982 M_COPY(src->prev, iptr->dst->prev);
983 M_COPY(src->prev->prev, iptr->dst->prev->prev);
984 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
985 M_COPY(src, iptr->dst->prev->prev->prev->prev);
986 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
989 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
991 M_COPY(src, iptr->dst->prev);
992 M_COPY(src->prev, iptr->dst);
996 /* integer operations *************************************************/
998 case ICMD_INEG: /* ..., value ==> ..., - value */
1000 d = reg_of_var(m, iptr->dst, REG_NULL);
1001 if (iptr->dst->flags & INMEMORY) {
1002 if (src->flags & INMEMORY) {
1003 if (src->regoff == iptr->dst->regoff) {
1004 i386_neg_membase(REG_SP, iptr->dst->regoff * 8);
1007 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1008 i386_neg_reg(REG_ITMP1);
1009 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1013 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1014 i386_neg_membase(REG_SP, iptr->dst->regoff * 8);
1018 if (src->flags & INMEMORY) {
1019 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1020 i386_neg_reg(iptr->dst->regoff);
1023 M_INTMOVE(src->regoff, iptr->dst->regoff);
1024 i386_neg_reg(iptr->dst->regoff);
1029 case ICMD_LNEG: /* ..., value ==> ..., - value */
1031 d = reg_of_var(m, iptr->dst, REG_NULL);
1032 if (iptr->dst->flags & INMEMORY) {
1033 if (src->flags & INMEMORY) {
1034 if (src->regoff == iptr->dst->regoff) {
1035 i386_neg_membase(REG_SP, iptr->dst->regoff * 8);
1036 i386_alu_imm_membase(I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1037 i386_neg_membase(REG_SP, iptr->dst->regoff * 8 + 4);
1040 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1041 i386_neg_reg(REG_ITMP1);
1042 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1043 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1044 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP1);
1045 i386_neg_reg(REG_ITMP1);
1046 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1052 case ICMD_I2L: /* ..., value ==> ..., value */
1054 d = reg_of_var(m, iptr->dst, REG_NULL);
1055 if (iptr->dst->flags & INMEMORY) {
1056 if (src->flags & INMEMORY) {
1057 i386_mov_membase_reg(REG_SP, src->regoff * 8, EAX);
1059 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1060 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1063 M_INTMOVE(src->regoff, EAX);
1065 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1066 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1071 case ICMD_L2I: /* ..., value ==> ..., value */
1073 d = reg_of_var(m, iptr->dst, REG_NULL);
1074 if (iptr->dst->flags & INMEMORY) {
1075 if (src->flags & INMEMORY) {
1076 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1077 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1081 if (src->flags & INMEMORY) {
1082 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1087 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1089 d = reg_of_var(m, iptr->dst, REG_NULL);
1090 if (iptr->dst->flags & INMEMORY) {
1091 if (src->flags & INMEMORY) {
1092 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1093 i386_shift_imm_reg(I386_SHL, 24, REG_ITMP1);
1094 i386_shift_imm_reg(I386_SAR, 24, REG_ITMP1);
1095 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1098 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1099 i386_shift_imm_membase(I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1100 i386_shift_imm_membase(I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1104 if (src->flags & INMEMORY) {
1105 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1106 i386_shift_imm_reg(I386_SHL, 24, iptr->dst->regoff);
1107 i386_shift_imm_reg(I386_SAR, 24, iptr->dst->regoff);
1110 M_INTMOVE(src->regoff, iptr->dst->regoff);
1111 i386_shift_imm_reg(I386_SHL, 24, iptr->dst->regoff);
1112 i386_shift_imm_reg(I386_SAR, 24, iptr->dst->regoff);
1117 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1119 d = reg_of_var(m, iptr->dst, REG_NULL);
1120 if (iptr->dst->flags & INMEMORY) {
1121 if (src->flags & INMEMORY) {
1122 if (src->regoff == iptr->dst->regoff) {
1123 i386_alu_imm_membase(I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1126 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1127 i386_alu_imm_reg(I386_AND, 0x0000ffff, REG_ITMP1);
1128 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1132 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1133 i386_alu_imm_membase(I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1137 if (src->flags & INMEMORY) {
1138 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1139 i386_alu_imm_reg(I386_AND, 0x0000ffff, iptr->dst->regoff);
1142 M_INTMOVE(src->regoff, iptr->dst->regoff);
1143 i386_alu_imm_reg(I386_AND, 0x0000ffff, iptr->dst->regoff);
1148 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1150 d = reg_of_var(m, iptr->dst, REG_NULL);
1151 if (iptr->dst->flags & INMEMORY) {
1152 if (src->flags & INMEMORY) {
1153 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1154 i386_shift_imm_reg(I386_SHL, 16, REG_ITMP1);
1155 i386_shift_imm_reg(I386_SAR, 16, REG_ITMP1);
1156 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1159 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1160 i386_shift_imm_membase(I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1161 i386_shift_imm_membase(I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1165 if (src->flags & INMEMORY) {
1166 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1167 i386_shift_imm_reg(I386_SHL, 16, iptr->dst->regoff);
1168 i386_shift_imm_reg(I386_SAR, 16, iptr->dst->regoff);
1171 M_INTMOVE(src->regoff, iptr->dst->regoff);
1172 i386_shift_imm_reg(I386_SHL, 16, iptr->dst->regoff);
1173 i386_shift_imm_reg(I386_SAR, 16, iptr->dst->regoff);
1179 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1181 d = reg_of_var(m, iptr->dst, REG_NULL);
1182 i386_emit_ialu(I386_ADD, src, iptr);
1185 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1186 /* val.i = constant */
1188 d = reg_of_var(m, iptr->dst, REG_NULL);
1189 /* should we use a inc optimization for smaller code size? */
1190 i386_emit_ialuconst(I386_ADD, src, iptr);
1193 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1195 d = reg_of_var(m, iptr->dst, REG_NULL);
1196 if (iptr->dst->flags & INMEMORY) {
1197 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1198 if (src->regoff == iptr->dst->regoff) {
1199 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1200 i386_alu_reg_membase(I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1201 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1202 i386_alu_reg_membase(I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1204 } else if (src->prev->regoff == iptr->dst->regoff) {
1205 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1206 i386_alu_reg_membase(I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1207 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1208 i386_alu_reg_membase(I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1211 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1212 i386_alu_membase_reg(I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1213 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1214 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1215 i386_alu_membase_reg(I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1216 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1223 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1224 /* val.l = constant */
1226 d = reg_of_var(m, iptr->dst, REG_NULL);
1227 if (iptr->dst->flags & INMEMORY) {
1228 if (src->flags & INMEMORY) {
1229 if (src->regoff == iptr->dst->regoff) {
1230 i386_alu_imm_membase(I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1231 i386_alu_imm_membase(I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1234 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1235 i386_alu_imm_reg(I386_ADD, iptr->val.l, REG_ITMP1);
1236 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1237 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1238 i386_alu_imm_reg(I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1239 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1245 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1247 d = reg_of_var(m, iptr->dst, REG_NULL);
1248 if (iptr->dst->flags & INMEMORY) {
1249 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1250 if (src->prev->regoff == iptr->dst->regoff) {
1251 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1252 i386_alu_reg_membase(I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1255 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1256 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1257 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1260 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1261 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1262 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1263 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1265 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1266 if (src->prev->regoff == iptr->dst->regoff) {
1267 i386_alu_reg_membase(I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1270 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1271 i386_alu_reg_reg(I386_SUB, src->regoff, REG_ITMP1);
1272 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1276 i386_mov_reg_membase(src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1277 i386_alu_reg_membase(I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1281 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1282 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, d);
1283 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, d);
1285 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1286 M_INTMOVE(src->prev->regoff, d);
1287 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, d);
1289 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1290 /* workaround for reg alloc */
1291 if (src->regoff == iptr->dst->regoff) {
1292 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1293 i386_alu_reg_reg(I386_SUB, src->regoff, REG_ITMP1);
1294 M_INTMOVE(REG_ITMP1, d);
1297 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, d);
1298 i386_alu_reg_reg(I386_SUB, src->regoff, d);
1302 /* workaround for reg alloc */
1303 if (src->regoff == iptr->dst->regoff) {
1304 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1305 i386_alu_reg_reg(I386_SUB, src->regoff, REG_ITMP1);
1306 M_INTMOVE(REG_ITMP1, d);
1309 M_INTMOVE(src->prev->regoff, d);
1310 i386_alu_reg_reg(I386_SUB, src->regoff, d);
1316 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1317 /* val.i = constant */
1319 d = reg_of_var(m, iptr->dst, REG_NULL);
1320 i386_emit_ialuconst(I386_SUB, src, iptr);
1323 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1325 d = reg_of_var(m, iptr->dst, REG_NULL);
1326 if (iptr->dst->flags & INMEMORY) {
1327 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1328 if (src->prev->regoff == iptr->dst->regoff) {
1329 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1330 i386_alu_reg_membase(I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1331 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1332 i386_alu_reg_membase(I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1335 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1336 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1337 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1338 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1339 i386_alu_membase_reg(I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1340 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1346 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1347 /* val.l = constant */
1349 d = reg_of_var(m, iptr->dst, REG_NULL);
1350 if (iptr->dst->flags & INMEMORY) {
1351 if (src->flags & INMEMORY) {
1352 if (src->regoff == iptr->dst->regoff) {
1353 i386_alu_imm_membase(I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1354 i386_alu_imm_membase(I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1357 /* TODO: could be size optimized with lea -- see gcc output */
1358 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1359 i386_alu_imm_reg(I386_SUB, iptr->val.l, REG_ITMP1);
1360 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1361 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1362 i386_alu_imm_reg(I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1363 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1369 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1371 d = reg_of_var(m, iptr->dst, REG_NULL);
1372 if (iptr->dst->flags & INMEMORY) {
1373 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1374 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1375 i386_imul_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1376 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1378 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1379 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1380 i386_imul_reg_reg(src->prev->regoff, REG_ITMP1);
1381 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1383 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1384 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1385 i386_imul_reg_reg(src->regoff, REG_ITMP1);
1386 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1389 i386_mov_reg_reg(src->prev->regoff, REG_ITMP1);
1390 i386_imul_reg_reg(src->regoff, REG_ITMP1);
1391 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1395 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1396 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1397 i386_imul_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1399 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1400 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1401 i386_imul_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1403 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1404 M_INTMOVE(src->regoff, iptr->dst->regoff);
1405 i386_imul_membase_reg(REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1408 if (src->regoff == iptr->dst->regoff) {
1409 i386_imul_reg_reg(src->prev->regoff, iptr->dst->regoff);
1412 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1413 i386_imul_reg_reg(src->regoff, iptr->dst->regoff);
1419 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1420 /* val.i = constant */
1422 d = reg_of_var(m, iptr->dst, REG_NULL);
1423 if (iptr->dst->flags & INMEMORY) {
1424 if (src->flags & INMEMORY) {
1425 i386_imul_imm_membase_reg(iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1426 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1429 i386_imul_imm_reg_reg(iptr->val.i, src->regoff, REG_ITMP1);
1430 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1434 if (src->flags & INMEMORY) {
1435 i386_imul_imm_membase_reg(iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1438 i386_imul_imm_reg_reg(iptr->val.i, src->regoff, iptr->dst->regoff);
1443 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1445 d = reg_of_var(m, iptr->dst, REG_NULL);
1446 if (iptr->dst->flags & INMEMORY) {
1447 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1448 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, EAX); /* mem -> EAX */
1449 /* optimize move EAX -> REG_ITMP3 is slower??? */
1450 /* i386_mov_reg_reg(EAX, REG_ITMP3); */
1451 i386_mul_membase(REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1453 /* TODO: optimize move EAX -> REG_ITMP3 */
1454 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); /* mem -> ITMP3 */
1455 i386_imul_membase_reg(REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1456 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1458 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP2); /* mem -> ITMP3 */
1459 i386_imul_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1461 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1462 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1463 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1468 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1469 /* val.l = constant */
1471 d = reg_of_var(m, iptr->dst, REG_NULL);
1472 if (iptr->dst->flags & INMEMORY) {
1473 if (src->flags & INMEMORY) {
1474 i386_mov_imm_reg(iptr->val.l, EAX); /* imm -> EAX */
1475 i386_mul_membase(REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1476 /* TODO: optimize move EAX -> REG_ITMP3 */
1477 i386_mov_imm_reg(iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1478 i386_imul_membase_reg(REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1480 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1481 i386_mov_imm_reg(iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1482 i386_imul_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1484 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1485 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1486 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1491 #define gen_div_check(v) \
1493 if ((v)->flags & INMEMORY) { \
1494 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8); \
1496 i386_test_reg_reg(src->regoff, src->regoff); \
1498 i386_jcc(I386_CC_E, 0); \
1499 codegen_addxdivrefs(mcodeptr); \
1502 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1504 d = reg_of_var(m, iptr->dst, REG_NULL);
1505 var_to_reg_int(s1, src, REG_ITMP2);
1507 if (src->prev->flags & INMEMORY) {
1508 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, EAX);
1511 M_INTMOVE(src->prev->regoff, EAX);
1514 i386_alu_imm_reg(I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1515 i386_jcc(I386_CC_NE, 3 + 6);
1516 i386_alu_imm_reg(I386_CMP, -1, s1);
1517 i386_jcc(I386_CC_E, 1 + 2);
1522 if (iptr->dst->flags & INMEMORY) {
1523 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1526 M_INTMOVE(EAX, iptr->dst->regoff);
1530 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1532 d = reg_of_var(m, iptr->dst, REG_NULL);
1533 var_to_reg_int(s1, src, REG_ITMP2);
1535 if (src->prev->flags & INMEMORY) {
1536 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, EAX);
1539 M_INTMOVE(src->prev->regoff, EAX);
1542 i386_alu_imm_reg(I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1543 i386_jcc(I386_CC_NE, 2 + 3 + 6);
1544 i386_alu_reg_reg(I386_XOR, EDX, EDX);
1545 i386_alu_imm_reg(I386_CMP, -1, s1);
1546 i386_jcc(I386_CC_E, 1 + 2);
1551 if (iptr->dst->flags & INMEMORY) {
1552 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8);
1555 M_INTMOVE(EDX, iptr->dst->regoff);
1559 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1560 /* val.i = constant */
1562 /* TODO: optimize for `/ 2' */
1563 var_to_reg_int(s1, src, REG_ITMP1);
1564 d = reg_of_var(m, iptr->dst, REG_ITMP1);
1567 i386_test_reg_reg(d, d);
1569 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1570 i386_jcc(I386_CC_NS, a);
1571 i386_alu_imm_reg(I386_ADD, (1 << iptr->val.i) - 1, d);
1573 i386_shift_imm_reg(I386_SAR, iptr->val.i, d);
1574 store_reg_to_var_int(iptr->dst, d);
1577 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1578 /* val.i = constant */
1580 d = reg_of_var(m, iptr->dst, REG_NULL);
1581 if (iptr->dst->flags & INMEMORY) {
1582 if (src->flags & INMEMORY) {
1584 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1586 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1587 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1589 i386_test_reg_reg(REG_ITMP2, REG_ITMP2);
1590 i386_jcc(I386_CC_NS, a);
1591 i386_alu_imm_reg(I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1592 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP2);
1593 i386_shrd_imm_reg_reg(iptr->val.i, REG_ITMP2, REG_ITMP1);
1594 i386_shift_imm_reg(I386_SAR, iptr->val.i, REG_ITMP2);
1596 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1597 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1602 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1603 /* val.i = constant */
1605 var_to_reg_int(s1, src, REG_ITMP1);
1606 d = reg_of_var(m, iptr->dst, REG_ITMP2);
1608 M_INTMOVE(s1, REG_ITMP1);
1615 CALCIMMEDIATEBYTES(a, iptr->val.i);
1618 /* TODO: optimize */
1620 i386_alu_imm_reg(I386_AND, iptr->val.i, d);
1621 i386_test_reg_reg(s1, s1);
1622 i386_jcc(I386_CC_GE, a);
1623 i386_mov_reg_reg(s1, d);
1625 i386_alu_imm_reg(I386_AND, iptr->val.i, d);
1628 /* M_INTMOVE(s1, EAX); */
1630 /* i386_alu_reg_reg(I386_XOR, EDX, EAX); */
1631 /* i386_alu_reg_reg(I386_SUB, EDX, EAX); */
1632 /* i386_alu_reg_reg(I386_AND, iptr->val.i, EAX); */
1633 /* i386_alu_reg_reg(I386_XOR, EDX, EAX); */
1634 /* i386_alu_reg_reg(I386_SUB, EDX, EAX); */
1635 /* M_INTMOVE(EAX, d); */
1637 /* i386_alu_reg_reg(I386_XOR, d, d); */
1638 /* i386_mov_imm_reg(iptr->val.i, ECX); */
1639 /* i386_shrd_reg_reg(s1, d); */
1640 /* i386_shift_imm_reg(I386_SHR, 32 - iptr->val.i, d); */
1642 store_reg_to_var_int(iptr->dst, d);
1645 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1646 /* val.l = constant */
1648 d = reg_of_var(m, iptr->dst, REG_NULL);
1649 if (iptr->dst->flags & INMEMORY) {
1650 if (src->flags & INMEMORY) {
1651 /* Intel algorithm -- does not work, because constant is wrong */
1652 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1); */
1653 /* i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1655 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1656 /* i386_test_reg_reg(REG_ITMP3, REG_ITMP3); */
1657 /* i386_jcc(I386_CC_NS, offset); */
1658 /* i386_alu_imm_reg(I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1659 /* i386_alu_imm_reg(I386_ADC, 0, REG_ITMP3); */
1661 /* i386_shrd_imm_reg_reg(iptr->val.l, REG_ITMP3, REG_ITMP2); */
1662 /* i386_shift_imm_reg(I386_SAR, iptr->val.l, REG_ITMP3); */
1663 /* i386_shld_imm_reg_reg(iptr->val.l, REG_ITMP2, REG_ITMP3); */
1665 /* i386_shift_imm_reg(I386_SHL, iptr->val.l, REG_ITMP2); */
1667 /* i386_alu_reg_reg(I386_SUB, REG_ITMP2, REG_ITMP1); */
1668 /* i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1669 /* i386_alu_reg_reg(I386_SBB, REG_ITMP3, REG_ITMP2); */
1671 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1672 /* i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1674 /* Alpha algorithm */
1676 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1678 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1684 /* TODO: hmm, don't know if this is always correct */
1686 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1688 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1694 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1695 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1697 i386_alu_imm_reg(I386_AND, iptr->val.l, REG_ITMP1);
1698 i386_alu_imm_reg(I386_AND, iptr->val.l >> 32, REG_ITMP2);
1699 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1700 i386_jcc(I386_CC_GE, a);
1702 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1703 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1705 i386_neg_reg(REG_ITMP1);
1706 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP2);
1707 i386_neg_reg(REG_ITMP2);
1709 i386_alu_imm_reg(I386_AND, iptr->val.l, REG_ITMP1);
1710 i386_alu_imm_reg(I386_AND, iptr->val.l >> 32, REG_ITMP2);
1712 i386_neg_reg(REG_ITMP1);
1713 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP2);
1714 i386_neg_reg(REG_ITMP2);
1716 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1717 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1722 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1724 d = reg_of_var(m, iptr->dst, REG_NULL);
1725 i386_emit_ishift(I386_SHL, src, iptr);
1728 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1729 /* val.i = constant */
1731 d = reg_of_var(m, iptr->dst, REG_NULL);
1732 i386_emit_ishiftconst(I386_SHL, src, iptr);
1735 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1737 d = reg_of_var(m, iptr->dst, REG_NULL);
1738 i386_emit_ishift(I386_SAR, src, iptr);
1741 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1742 /* val.i = constant */
1744 d = reg_of_var(m, iptr->dst, REG_NULL);
1745 i386_emit_ishiftconst(I386_SAR, src, iptr);
1748 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1750 d = reg_of_var(m, iptr->dst, REG_NULL);
1751 i386_emit_ishift(I386_SHR, src, iptr);
1754 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1755 /* val.i = constant */
1757 d = reg_of_var(m, iptr->dst, REG_NULL);
1758 i386_emit_ishiftconst(I386_SHR, src, iptr);
1761 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1763 d = reg_of_var(m, iptr->dst, REG_NULL);
1764 if (iptr->dst->flags & INMEMORY ){
1765 if (src->prev->flags & INMEMORY) {
1766 /* if (src->prev->regoff == iptr->dst->regoff) { */
1767 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1769 /* if (src->flags & INMEMORY) { */
1770 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX); */
1772 /* M_INTMOVE(src->regoff, ECX); */
1775 /* i386_test_imm_reg(32, ECX); */
1776 /* i386_jcc(I386_CC_E, 2 + 2); */
1777 /* i386_mov_reg_reg(REG_ITMP1, REG_ITMP2); */
1778 /* i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1); */
1780 /* i386_shld_reg_membase(REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1781 /* i386_shift_membase(I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1784 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1785 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1787 if (src->flags & INMEMORY) {
1788 i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX);
1790 M_INTMOVE(src->regoff, ECX);
1793 i386_test_imm_reg(32, ECX);
1794 i386_jcc(I386_CC_E, 2 + 2);
1795 i386_mov_reg_reg(REG_ITMP1, REG_ITMP3);
1796 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
1798 i386_shld_reg_reg(REG_ITMP1, REG_ITMP3);
1799 i386_shift_reg(I386_SHL, REG_ITMP1);
1800 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1801 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1807 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1808 /* val.i = constant */
1810 d = reg_of_var(m, iptr->dst, REG_NULL);
1811 if (iptr->dst->flags & INMEMORY ) {
1812 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1813 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1815 if (iptr->val.i & 0x20) {
1816 i386_mov_reg_reg(REG_ITMP1, REG_ITMP2);
1817 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
1818 i386_shld_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1821 i386_shld_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1822 i386_shift_imm_reg(I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1825 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1826 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1830 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1832 d = reg_of_var(m, iptr->dst, REG_NULL);
1833 if (iptr->dst->flags & INMEMORY ){
1834 if (src->prev->flags & INMEMORY) {
1835 /* if (src->prev->regoff == iptr->dst->regoff) { */
1836 /* TODO: optimize */
1837 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1838 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1840 /* if (src->flags & INMEMORY) { */
1841 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX); */
1843 /* M_INTMOVE(src->regoff, ECX); */
1846 /* i386_test_imm_reg(32, ECX); */
1847 /* i386_jcc(I386_CC_E, 2 + 3); */
1848 /* i386_mov_reg_reg(REG_ITMP2, REG_ITMP1); */
1849 /* i386_shift_imm_reg(I386_SAR, 31, REG_ITMP2); */
1851 /* i386_shrd_reg_reg(REG_ITMP2, REG_ITMP1); */
1852 /* i386_shift_reg(I386_SAR, REG_ITMP2); */
1853 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1854 /* i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1857 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1858 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1860 if (src->flags & INMEMORY) {
1861 i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX);
1863 M_INTMOVE(src->regoff, ECX);
1866 i386_test_imm_reg(32, ECX);
1867 i386_jcc(I386_CC_E, 2 + 3);
1868 i386_mov_reg_reg(REG_ITMP3, REG_ITMP1);
1869 i386_shift_imm_reg(I386_SAR, 31, REG_ITMP3);
1871 i386_shrd_reg_reg(REG_ITMP3, REG_ITMP1);
1872 i386_shift_reg(I386_SAR, REG_ITMP3);
1873 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1874 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1880 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1881 /* val.i = constant */
1883 d = reg_of_var(m, iptr->dst, REG_NULL);
1884 if (iptr->dst->flags & INMEMORY ) {
1885 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1886 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1888 if (iptr->val.i & 0x20) {
1889 i386_mov_reg_reg(REG_ITMP2, REG_ITMP1);
1890 i386_shift_imm_reg(I386_SAR, 31, REG_ITMP2);
1891 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1894 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1895 i386_shift_imm_reg(I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1898 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1899 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1903 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1905 d = reg_of_var(m, iptr->dst, REG_NULL);
1906 if (iptr->dst->flags & INMEMORY ){
1907 if (src->prev->flags & INMEMORY) {
1908 /* if (src->prev->regoff == iptr->dst->regoff) { */
1909 /* TODO: optimize */
1910 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1911 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1913 /* if (src->flags & INMEMORY) { */
1914 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX); */
1916 /* M_INTMOVE(src->regoff, ECX); */
1919 /* i386_test_imm_reg(32, ECX); */
1920 /* i386_jcc(I386_CC_E, 2 + 2); */
1921 /* i386_mov_reg_reg(REG_ITMP2, REG_ITMP1); */
1922 /* i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2); */
1924 /* i386_shrd_reg_reg(REG_ITMP2, REG_ITMP1); */
1925 /* i386_shift_reg(I386_SHR, REG_ITMP2); */
1926 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1927 /* i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1930 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1931 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1933 if (src->flags & INMEMORY) {
1934 i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX);
1936 M_INTMOVE(src->regoff, ECX);
1939 i386_test_imm_reg(32, ECX);
1940 i386_jcc(I386_CC_E, 2 + 2);
1941 i386_mov_reg_reg(REG_ITMP3, REG_ITMP1);
1942 i386_alu_reg_reg(I386_XOR, REG_ITMP3, REG_ITMP3);
1944 i386_shrd_reg_reg(REG_ITMP3, REG_ITMP1);
1945 i386_shift_reg(I386_SHR, REG_ITMP3);
1946 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1947 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1953 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1954 /* val.l = constant */
1956 d = reg_of_var(m, iptr->dst, REG_NULL);
1957 if (iptr->dst->flags & INMEMORY ) {
1958 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1959 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1961 if (iptr->val.i & 0x20) {
1962 i386_mov_reg_reg(REG_ITMP2, REG_ITMP1);
1963 i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2);
1964 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1967 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1968 i386_shift_imm_reg(I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
1971 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1972 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1976 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1978 d = reg_of_var(m, iptr->dst, REG_NULL);
1979 i386_emit_ialu(I386_AND, src, iptr);
1982 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1983 /* val.i = constant */
1985 d = reg_of_var(m, iptr->dst, REG_NULL);
1986 i386_emit_ialuconst(I386_AND, src, iptr);
1989 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1991 d = reg_of_var(m, iptr->dst, REG_NULL);
1992 i386_emit_lalu(I386_AND, src, iptr);
1995 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1996 /* val.l = constant */
1998 d = reg_of_var(m, iptr->dst, REG_NULL);
1999 i386_emit_laluconst(I386_AND, src, iptr);
2002 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2004 d = reg_of_var(m, iptr->dst, REG_NULL);
2005 i386_emit_ialu(I386_OR, src, iptr);
2008 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2009 /* val.i = constant */
2011 d = reg_of_var(m, iptr->dst, REG_NULL);
2012 i386_emit_ialuconst(I386_OR, src, iptr);
2015 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2017 d = reg_of_var(m, iptr->dst, REG_NULL);
2018 i386_emit_lalu(I386_OR, src, iptr);
2021 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2022 /* val.l = constant */
2024 d = reg_of_var(m, iptr->dst, REG_NULL);
2025 i386_emit_laluconst(I386_OR, src, iptr);
2028 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2030 d = reg_of_var(m, iptr->dst, REG_NULL);
2031 i386_emit_ialu(I386_XOR, src, iptr);
2034 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2035 /* val.i = constant */
2037 d = reg_of_var(m, iptr->dst, REG_NULL);
2038 i386_emit_ialuconst(I386_XOR, src, iptr);
2041 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2043 d = reg_of_var(m, iptr->dst, REG_NULL);
2044 i386_emit_lalu(I386_XOR, src, iptr);
2047 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2048 /* val.l = constant */
2050 d = reg_of_var(m, iptr->dst, REG_NULL);
2051 i386_emit_laluconst(I386_XOR, src, iptr);
2054 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2055 /* op1 = variable, val.i = constant */
2057 var = &(r->locals[iptr->op1][TYPE_INT]);
2058 if (var->flags & INMEMORY) {
2059 i386_alu_imm_membase(I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2062 i386_alu_imm_reg(I386_ADD, iptr->val.i, var->regoff);
2067 /* floating operations ************************************************/
2069 #define ROUND_TO_SINGLE \
2070 i386_fstps_membase(REG_SP, -8); \
2071 i386_flds_membase(REG_SP, -8);
2073 #define ROUND_TO_DOUBLE \
2074 i386_fstpl_membase(REG_SP, -8); \
2075 i386_fldl_membase(REG_SP, -8);
2077 #define FPU_SET_24BIT_MODE \
2078 if (!fpu_in_24bit_mode) { \
2079 i386_fldcw_mem(&fpu_ctrlwrd_24bit); \
2080 fpu_in_24bit_mode = 1; \
2083 #define FPU_SET_53BIT_MODE \
2084 if (fpu_in_24bit_mode) { \
2085 i386_fldcw_mem(&fpu_ctrlwrd_53bit); \
2086 fpu_in_24bit_mode = 0; \
2089 #define ROUND_TO_SINGLE
2090 #define ROUND_TO_DOUBLE
2091 #define FPU_SET_24BIT_MODE
2092 #define FPU_SET_53BIT_MODE
2094 case ICMD_FNEG: /* ..., value ==> ..., - value */
2097 var_to_reg_flt(s1, src, REG_FTMP1);
2098 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2100 store_reg_to_var_flt(iptr->dst, d);
2103 case ICMD_DNEG: /* ..., value ==> ..., - value */
2106 var_to_reg_flt(s1, src, REG_FTMP1);
2107 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2109 store_reg_to_var_flt(iptr->dst, d);
2112 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2115 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2116 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2117 var_to_reg_flt(s2, src, REG_FTMP2);
2120 store_reg_to_var_flt(iptr->dst, d);
2123 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2126 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2127 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2128 var_to_reg_flt(s2, src, REG_FTMP2);
2131 store_reg_to_var_flt(iptr->dst, d);
2134 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2137 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2138 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2139 var_to_reg_flt(s2, src, REG_FTMP2);
2142 store_reg_to_var_flt(iptr->dst, d);
2145 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2148 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2149 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2150 var_to_reg_flt(s2, src, REG_FTMP2);
2153 store_reg_to_var_flt(iptr->dst, d);
2156 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2159 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2160 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2161 var_to_reg_flt(s2, src, REG_FTMP2);
2165 store_reg_to_var_flt(iptr->dst, d);
2168 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2171 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2172 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2174 /* i386_fldt_mem(subnormal_bias1); */
2177 var_to_reg_flt(s2, src, REG_FTMP2);
2182 /* i386_fldt_mem(subnormal_bias2); */
2185 store_reg_to_var_flt(iptr->dst, d);
2188 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2191 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2192 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2193 var_to_reg_flt(s2, src, REG_FTMP2);
2197 store_reg_to_var_flt(iptr->dst, d);
2200 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2203 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2204 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2206 /* i386_fldt_mem(subnormal_bias1); */
2209 var_to_reg_flt(s2, src, REG_FTMP2);
2214 /* i386_fldt_mem(subnormal_bias2); */
2217 store_reg_to_var_flt(iptr->dst, d);
2220 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2223 /* exchanged to skip fxch */
2224 var_to_reg_flt(s2, src, REG_FTMP2);
2225 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2226 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2232 i386_jcc(I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2233 store_reg_to_var_flt(iptr->dst, d);
2239 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2242 /* exchanged to skip fxch */
2243 var_to_reg_flt(s2, src, REG_FTMP2);
2244 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2245 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2251 i386_jcc(I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2252 store_reg_to_var_flt(iptr->dst, d);
2258 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2259 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2261 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2262 if (src->flags & INMEMORY) {
2263 i386_fildl_membase(REG_SP, src->regoff * 8);
2268 i386_mov_imm_reg(0, REG_ITMP1);
2269 dseg_adddata(mcodeptr);
2270 i386_mov_reg_membase(src->regoff, REG_ITMP1, a);
2271 i386_fildl_membase(REG_ITMP1, a);
2274 store_reg_to_var_flt(iptr->dst, d);
2277 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2278 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2280 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2281 if (src->flags & INMEMORY) {
2282 i386_fildll_membase(REG_SP, src->regoff * 8);
2286 panic("L2F: longs have to be in memory");
2288 store_reg_to_var_flt(iptr->dst, d);
2291 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2293 var_to_reg_flt(s1, src, REG_FTMP1);
2294 d = reg_of_var(m, iptr->dst, REG_NULL);
2296 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2297 i386_mov_imm_reg(0, REG_ITMP1);
2298 dseg_adddata(mcodeptr);
2299 i386_fldcw_membase(REG_ITMP1, a);
2301 if (iptr->dst->flags & INMEMORY) {
2302 i386_fistpl_membase(REG_SP, iptr->dst->regoff * 8);
2305 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2306 i386_fldcw_membase(REG_ITMP1, a);
2308 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2311 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2313 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2317 i386_fistpl_membase(REG_ITMP1, a);
2319 i386_mov_membase_reg(REG_ITMP1, a, iptr->dst->regoff);
2321 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2322 i386_fldcw_membase(REG_ITMP1, a);
2324 i386_alu_imm_reg(I386_CMP, 0x80000000, iptr->dst->regoff);
2327 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2328 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2331 i386_jcc(I386_CC_NE, a);
2333 /* XXX: change this when we use registers */
2334 i386_flds_membase(REG_SP, src->regoff * 8);
2335 i386_mov_imm_reg((s4) asm_builtin_f2i, REG_ITMP1);
2336 i386_call_reg(REG_ITMP1);
2338 if (iptr->dst->flags & INMEMORY) {
2339 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2342 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2346 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2348 var_to_reg_flt(s1, src, REG_FTMP1);
2349 d = reg_of_var(m, iptr->dst, REG_NULL);
2351 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2352 i386_mov_imm_reg(0, REG_ITMP1);
2353 dseg_adddata(mcodeptr);
2354 i386_fldcw_membase(REG_ITMP1, a);
2356 if (iptr->dst->flags & INMEMORY) {
2357 i386_fistpl_membase(REG_SP, iptr->dst->regoff * 8);
2360 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2361 i386_fldcw_membase(REG_ITMP1, a);
2363 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2366 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2368 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2372 i386_fistpl_membase(REG_ITMP1, a);
2374 i386_mov_membase_reg(REG_ITMP1, a, iptr->dst->regoff);
2376 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2377 i386_fldcw_membase(REG_ITMP1, a);
2379 i386_alu_imm_reg(I386_CMP, 0x80000000, iptr->dst->regoff);
2382 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2383 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2386 i386_jcc(I386_CC_NE, a);
2388 /* XXX: change this when we use registers */
2389 i386_fldl_membase(REG_SP, src->regoff * 8);
2390 i386_mov_imm_reg((s4) asm_builtin_d2i, REG_ITMP1);
2391 i386_call_reg(REG_ITMP1);
2393 if (iptr->dst->flags & INMEMORY) {
2394 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2396 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2400 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2402 var_to_reg_flt(s1, src, REG_FTMP1);
2403 d = reg_of_var(m, iptr->dst, REG_NULL);
2405 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2406 i386_mov_imm_reg(0, REG_ITMP1);
2407 dseg_adddata(mcodeptr);
2408 i386_fldcw_membase(REG_ITMP1, a);
2410 if (iptr->dst->flags & INMEMORY) {
2411 i386_fistpll_membase(REG_SP, iptr->dst->regoff * 8);
2414 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2415 i386_fldcw_membase(REG_ITMP1, a);
2417 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2420 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2422 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2425 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2427 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2429 i386_jcc(I386_CC_NE, a);
2431 i386_alu_imm_membase(I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2434 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2436 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2438 i386_jcc(I386_CC_NE, a);
2440 /* XXX: change this when we use registers */
2441 i386_flds_membase(REG_SP, src->regoff * 8);
2442 i386_mov_imm_reg((s4) asm_builtin_f2l, REG_ITMP1);
2443 i386_call_reg(REG_ITMP1);
2444 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2445 i386_mov_reg_membase(REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2448 panic("F2L: longs have to be in memory");
2452 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2454 var_to_reg_flt(s1, src, REG_FTMP1);
2455 d = reg_of_var(m, iptr->dst, REG_NULL);
2457 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2458 i386_mov_imm_reg(0, REG_ITMP1);
2459 dseg_adddata(mcodeptr);
2460 i386_fldcw_membase(REG_ITMP1, a);
2462 if (iptr->dst->flags & INMEMORY) {
2463 i386_fistpll_membase(REG_SP, iptr->dst->regoff * 8);
2466 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2467 i386_fldcw_membase(REG_ITMP1, a);
2469 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2472 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2474 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2477 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2479 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2481 i386_jcc(I386_CC_NE, a);
2483 i386_alu_imm_membase(I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2486 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2488 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2490 i386_jcc(I386_CC_NE, a);
2492 /* XXX: change this when we use registers */
2493 i386_fldl_membase(REG_SP, src->regoff * 8);
2494 i386_mov_imm_reg((s4) asm_builtin_d2l, REG_ITMP1);
2495 i386_call_reg(REG_ITMP1);
2496 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2497 i386_mov_reg_membase(REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2500 panic("D2L: longs have to be in memory");
2504 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2506 var_to_reg_flt(s1, src, REG_FTMP1);
2507 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2509 store_reg_to_var_flt(iptr->dst, d);
2512 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2514 var_to_reg_flt(s1, src, REG_FTMP1);
2515 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2517 store_reg_to_var_flt(iptr->dst, d);
2520 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2523 /* exchanged to skip fxch */
2524 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2525 var_to_reg_flt(s1, src, REG_FTMP2);
2526 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2531 i386_test_imm_reg(0x400, EAX); /* unordered treat as GT */
2532 i386_jcc(I386_CC_E, 6);
2533 i386_alu_imm_reg(I386_AND, 0x000000ff, EAX);
2535 i386_mov_imm_reg(0, d); /* does not affect flags */
2536 i386_jcc(I386_CC_E, 6 + 3 + 5 + 3);
2537 i386_jcc(I386_CC_B, 3 + 5);
2538 i386_alu_imm_reg(I386_SUB, 1, d);
2540 i386_alu_imm_reg(I386_ADD, 1, d);
2541 store_reg_to_var_int(iptr->dst, d);
2544 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2547 /* exchanged to skip fxch */
2548 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2549 var_to_reg_flt(s1, src, REG_FTMP2);
2550 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2555 i386_test_imm_reg(0x400, EAX); /* unordered treat as LT */
2556 i386_jcc(I386_CC_E, 3);
2557 i386_movb_imm_reg(1, I386_AH);
2559 i386_mov_imm_reg(0, d); /* does not affect flags */
2560 i386_jcc(I386_CC_E, 6 + 3 + 5 + 3);
2561 i386_jcc(I386_CC_B, 3 + 5);
2562 i386_alu_imm_reg(I386_SUB, 1, d);
2564 i386_alu_imm_reg(I386_ADD, 1, d);
2565 store_reg_to_var_int(iptr->dst, d);
2569 /* memory operations **************************************************/
2571 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2573 var_to_reg_int(s1, src, REG_ITMP1);
2574 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2575 gen_nullptr_check(s1);
2576 i386_mov_membase_reg(s1, OFFSET(java_arrayheader, size), d);
2577 store_reg_to_var_int(iptr->dst, d);
2580 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2582 var_to_reg_int(s1, src->prev, REG_ITMP1);
2583 var_to_reg_int(s2, src, REG_ITMP2);
2584 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2585 if (iptr->op1 == 0) {
2586 gen_nullptr_check(s1);
2589 i386_mov_memindex_reg(OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2590 store_reg_to_var_int(iptr->dst, d);
2593 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2595 var_to_reg_int(s1, src->prev, REG_ITMP1);
2596 var_to_reg_int(s2, src, REG_ITMP2);
2597 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2598 if (iptr->op1 == 0) {
2599 gen_nullptr_check(s1);
2603 if (iptr->dst->flags & INMEMORY) {
2604 i386_mov_memindex_reg(OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2605 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2606 i386_mov_memindex_reg(OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2607 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2611 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2613 var_to_reg_int(s1, src->prev, REG_ITMP1);
2614 var_to_reg_int(s2, src, REG_ITMP2);
2615 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2616 if (iptr->op1 == 0) {
2617 gen_nullptr_check(s1);
2620 i386_mov_memindex_reg(OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2621 store_reg_to_var_int(iptr->dst, d);
2624 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2626 var_to_reg_int(s1, src->prev, REG_ITMP1);
2627 var_to_reg_int(s2, src, REG_ITMP2);
2628 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2629 if (iptr->op1 == 0) {
2630 gen_nullptr_check(s1);
2633 i386_flds_memindex(OFFSET(java_floatarray, data[0]), s1, s2, 2);
2635 store_reg_to_var_flt(iptr->dst, d);
2638 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2640 var_to_reg_int(s1, src->prev, REG_ITMP1);
2641 var_to_reg_int(s2, src, REG_ITMP2);
2642 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2643 if (iptr->op1 == 0) {
2644 gen_nullptr_check(s1);
2647 i386_fldl_memindex(OFFSET(java_doublearray, data[0]), s1, s2, 3);
2649 store_reg_to_var_flt(iptr->dst, d);
2652 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2654 var_to_reg_int(s1, src->prev, REG_ITMP1);
2655 var_to_reg_int(s2, src, REG_ITMP2);
2656 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2657 if (iptr->op1 == 0) {
2658 gen_nullptr_check(s1);
2661 i386_movzwl_memindex_reg(OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2662 store_reg_to_var_int(iptr->dst, d);
2665 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2667 var_to_reg_int(s1, src->prev, REG_ITMP1);
2668 var_to_reg_int(s2, src, REG_ITMP2);
2669 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2670 if (iptr->op1 == 0) {
2671 gen_nullptr_check(s1);
2674 i386_movswl_memindex_reg(OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2675 store_reg_to_var_int(iptr->dst, d);
2678 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2680 var_to_reg_int(s1, src->prev, REG_ITMP1);
2681 var_to_reg_int(s2, src, REG_ITMP2);
2682 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2683 if (iptr->op1 == 0) {
2684 gen_nullptr_check(s1);
2687 i386_movsbl_memindex_reg(OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2688 store_reg_to_var_int(iptr->dst, d);
2692 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2694 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2695 var_to_reg_int(s2, src->prev, REG_ITMP2);
2696 if (iptr->op1 == 0) {
2697 gen_nullptr_check(s1);
2700 var_to_reg_int(s3, src, REG_ITMP3);
2701 i386_mov_reg_memindex(s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2704 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2706 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2707 var_to_reg_int(s2, src->prev, REG_ITMP2);
2708 if (iptr->op1 == 0) {
2709 gen_nullptr_check(s1);
2713 if (src->flags & INMEMORY) {
2714 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP3);
2715 i386_mov_reg_memindex(REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2716 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2717 i386_mov_reg_memindex(REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2721 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2723 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2724 var_to_reg_int(s2, src->prev, REG_ITMP2);
2725 if (iptr->op1 == 0) {
2726 gen_nullptr_check(s1);
2729 var_to_reg_int(s3, src, REG_ITMP3);
2730 i386_mov_reg_memindex(s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2733 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2735 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2736 var_to_reg_int(s2, src->prev, REG_ITMP2);
2737 if (iptr->op1 == 0) {
2738 gen_nullptr_check(s1);
2741 var_to_reg_flt(s3, src, REG_FTMP1);
2742 i386_fstps_memindex(OFFSET(java_floatarray, data[0]), s1, s2, 2);
2746 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2748 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2749 var_to_reg_int(s2, src->prev, REG_ITMP2);
2750 if (iptr->op1 == 0) {
2751 gen_nullptr_check(s1);
2754 var_to_reg_flt(s3, src, REG_FTMP1);
2755 i386_fstpl_memindex(OFFSET(java_doublearray, data[0]), s1, s2, 3);
2759 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2762 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2763 var_to_reg_int(s2, src->prev, REG_ITMP2);
2764 if (iptr->op1 == 0) {
2765 gen_nullptr_check(s1);
2768 var_to_reg_int(s3, src, REG_ITMP3);
2769 i386_movw_reg_memindex(s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2772 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2774 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2775 var_to_reg_int(s2, src->prev, REG_ITMP2);
2776 if (iptr->op1 == 0) {
2777 gen_nullptr_check(s1);
2780 var_to_reg_int(s3, src, REG_ITMP3);
2781 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2782 M_INTMOVE(s3, REG_ITMP3);
2785 i386_movb_reg_memindex(s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2788 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2790 var_to_reg_int(s1, src->prev, REG_ITMP1);
2791 var_to_reg_int(s2, src, REG_ITMP2);
2792 if (iptr->op1 == 0) {
2793 gen_nullptr_check(s1);
2796 i386_mov_imm_memindex(iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 2);
2799 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2801 var_to_reg_int(s1, src->prev, REG_ITMP1);
2802 var_to_reg_int(s2, src, REG_ITMP2);
2803 if (iptr->op1 == 0) {
2804 gen_nullptr_check(s1);
2808 i386_mov_imm_memindex((u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2809 i386_mov_imm_memindex((u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2812 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2814 var_to_reg_int(s1, src->prev, REG_ITMP1);
2815 var_to_reg_int(s2, src, REG_ITMP2);
2816 if (iptr->op1 == 0) {
2817 gen_nullptr_check(s1);
2820 i386_mov_imm_memindex(0, OFFSET(java_bytearray, data[0]), s1, s2, 2);
2823 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2825 var_to_reg_int(s1, src->prev, REG_ITMP1);
2826 var_to_reg_int(s2, src, REG_ITMP2);
2827 if (iptr->op1 == 0) {
2828 gen_nullptr_check(s1);
2831 i386_movb_imm_memindex(iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2834 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2835 case ICMD_SASTORECONST:
2837 var_to_reg_int(s1, src->prev, REG_ITMP1);
2838 var_to_reg_int(s2, src, REG_ITMP2);
2839 if (iptr->op1 == 0) {
2840 gen_nullptr_check(s1);
2843 i386_movw_imm_memindex(iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 1);
2847 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2848 /* op1 = type, val.a = field address */
2850 /* if class isn't yet initialized, do it */
2851 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2852 /* call helper function which patches this code */
2853 i386_mov_imm_reg((s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2854 i386_mov_imm_reg((s4) asm_check_clinit, REG_ITMP2);
2855 i386_call_reg(REG_ITMP2);
2858 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2859 /* here it's slightly slower */
2860 i386_mov_imm_reg(0, REG_ITMP2);
2861 dseg_adddata(mcodeptr);
2862 i386_mov_membase_reg(REG_ITMP2, a, REG_ITMP2);
2863 switch (iptr->op1) {
2866 var_to_reg_int(s2, src, REG_ITMP1);
2867 i386_mov_reg_membase(s2, REG_ITMP2, 0);
2870 if (src->flags & INMEMORY) {
2871 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
2872 i386_mov_reg_membase(REG_ITMP1, REG_ITMP2, 0);
2873 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
2874 i386_mov_reg_membase(REG_ITMP1, REG_ITMP2, 0 + 4);
2876 panic("PUTSTATIC: longs have to be in memory");
2880 var_to_reg_flt(s2, src, REG_FTMP1);
2881 i386_fstps_membase(REG_ITMP2, 0);
2885 var_to_reg_flt(s2, src, REG_FTMP1);
2886 i386_fstpl_membase(REG_ITMP2, 0);
2889 default: panic ("internal error");
2893 case ICMD_GETSTATIC: /* ... ==> ..., value */
2894 /* op1 = type, val.a = field address */
2896 /* if class isn't yet initialized, do it */
2897 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2898 /* call helper function which patches this code */
2899 i386_mov_imm_reg((s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2900 i386_mov_imm_reg((s4) asm_check_clinit, REG_ITMP2);
2901 i386_call_reg(REG_ITMP2);
2904 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2905 i386_mov_imm_reg(0, REG_ITMP2);
2906 dseg_adddata(mcodeptr);
2907 i386_mov_membase_reg(REG_ITMP2, a, REG_ITMP2);
2908 switch (iptr->op1) {
2911 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2912 i386_mov_membase_reg(REG_ITMP2, 0, d);
2913 store_reg_to_var_int(iptr->dst, d);
2916 d = reg_of_var(m, iptr->dst, REG_NULL);
2917 if (iptr->dst->flags & INMEMORY) {
2918 i386_mov_membase_reg(REG_ITMP2, 0, REG_ITMP1);
2919 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2920 i386_mov_membase_reg(REG_ITMP2, 0 + 4, REG_ITMP1);
2921 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
2923 panic("GETSTATIC: longs have to be in memory");
2927 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2928 i386_flds_membase(REG_ITMP2, 0);
2930 store_reg_to_var_flt(iptr->dst, d);
2933 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2934 i386_fldl_membase(REG_ITMP2, 0);
2936 store_reg_to_var_flt(iptr->dst, d);
2938 default: panic ("internal error");
2942 case ICMD_PUTFIELD: /* ..., value ==> ... */
2943 /* op1 = type, val.i = field offset */
2945 a = ((fieldinfo *)(iptr->val.a))->offset;
2946 switch (iptr->op1) {
2949 var_to_reg_int(s1, src->prev, REG_ITMP1);
2950 var_to_reg_int(s2, src, REG_ITMP2);
2951 gen_nullptr_check(s1);
2952 i386_mov_reg_membase(s2, s1, a);
2955 var_to_reg_int(s1, src->prev, REG_ITMP1);
2956 gen_nullptr_check(s1);
2957 if (src->flags & INMEMORY) {
2958 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP2);
2959 i386_mov_reg_membase(REG_ITMP2, s1, a);
2960 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2961 i386_mov_reg_membase(REG_ITMP2, s1, a + 4);
2963 panic("PUTFIELD: longs have to be in memory");
2967 var_to_reg_int(s1, src->prev, REG_ITMP1);
2968 var_to_reg_flt(s2, src, REG_FTMP1);
2969 gen_nullptr_check(s1);
2970 i386_fstps_membase(s1, a);
2974 var_to_reg_int(s1, src->prev, REG_ITMP1);
2975 var_to_reg_flt(s2, src, REG_FTMP1);
2976 gen_nullptr_check(s1);
2977 i386_fstpl_membase(s1, a);
2980 default: panic ("internal error");
2984 case ICMD_GETFIELD: /* ... ==> ..., value */
2985 /* op1 = type, val.i = field offset */
2987 a = ((fieldinfo *)(iptr->val.a))->offset;
2988 switch (iptr->op1) {
2991 var_to_reg_int(s1, src, REG_ITMP1);
2992 d = reg_of_var(m, iptr->dst, REG_ITMP2);
2993 gen_nullptr_check(s1);
2994 i386_mov_membase_reg(s1, a, d);
2995 store_reg_to_var_int(iptr->dst, d);
2998 var_to_reg_int(s1, src, REG_ITMP1);
2999 d = reg_of_var(m, iptr->dst, REG_NULL);
3000 gen_nullptr_check(s1);
3001 i386_mov_membase_reg(s1, a, REG_ITMP2);
3002 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
3003 i386_mov_membase_reg(s1, a + 4, REG_ITMP2);
3004 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
3007 var_to_reg_int(s1, src, REG_ITMP1);
3008 d = reg_of_var(m, iptr->dst, REG_FTMP1);
3009 gen_nullptr_check(s1);
3010 i386_flds_membase(s1, a);
3012 store_reg_to_var_flt(iptr->dst, d);
3015 var_to_reg_int(s1, src, REG_ITMP1);
3016 d = reg_of_var(m, iptr->dst, REG_FTMP1);
3017 gen_nullptr_check(s1);
3018 i386_fldl_membase(s1, a);
3020 store_reg_to_var_flt(iptr->dst, d);
3022 default: panic ("internal error");
3027 /* branch operations **************************************************/
3030 /* #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}} */
3031 #define ALIGNCODENOP do {} while (0)
3033 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3035 var_to_reg_int(s1, src, REG_ITMP1);
3036 M_INTMOVE(s1, REG_ITMP1_XPTR);
3038 i386_call_imm(0); /* passing exception pointer */
3039 i386_pop_reg(REG_ITMP2_XPC);
3041 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
3042 i386_jmp_reg(REG_ITMP3);
3046 case ICMD_GOTO: /* ... ==> ... */
3047 /* op1 = target JavaVM pc */
3050 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3054 case ICMD_JSR: /* ... ==> ... */
3055 /* op1 = target JavaVM pc */
3058 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3061 case ICMD_RET: /* ... ==> ... */
3062 /* op1 = local variable */
3064 var = &(r->locals[iptr->op1][TYPE_ADR]);
3065 var_to_reg_int(s1, var, REG_ITMP1);
3069 case ICMD_IFNULL: /* ..., value ==> ... */
3070 /* op1 = target JavaVM pc */
3072 if (src->flags & INMEMORY) {
3073 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
3076 i386_test_reg_reg(src->regoff, src->regoff);
3078 i386_jcc(I386_CC_E, 0);
3079 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3082 case ICMD_IFNONNULL: /* ..., value ==> ... */
3083 /* op1 = target JavaVM pc */
3085 if (src->flags & INMEMORY) {
3086 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
3089 i386_test_reg_reg(src->regoff, src->regoff);
3091 i386_jcc(I386_CC_NE, 0);
3092 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3095 case ICMD_IFEQ: /* ..., value ==> ... */
3096 /* op1 = target JavaVM pc, val.i = constant */
3098 if (src->flags & INMEMORY) {
3099 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3102 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3104 i386_jcc(I386_CC_E, 0);
3105 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3108 case ICMD_IFLT: /* ..., value ==> ... */
3109 /* op1 = target JavaVM pc, val.i = constant */
3111 if (src->flags & INMEMORY) {
3112 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3115 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3117 i386_jcc(I386_CC_L, 0);
3118 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3121 case ICMD_IFLE: /* ..., value ==> ... */
3122 /* op1 = target JavaVM pc, val.i = constant */
3124 if (src->flags & INMEMORY) {
3125 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3128 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3130 i386_jcc(I386_CC_LE, 0);
3131 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3134 case ICMD_IFNE: /* ..., value ==> ... */
3135 /* op1 = target JavaVM pc, val.i = constant */
3137 if (src->flags & INMEMORY) {
3138 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3141 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3143 i386_jcc(I386_CC_NE, 0);
3144 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3147 case ICMD_IFGT: /* ..., value ==> ... */
3148 /* op1 = target JavaVM pc, val.i = constant */
3150 if (src->flags & INMEMORY) {
3151 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3154 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3156 i386_jcc(I386_CC_G, 0);
3157 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3160 case ICMD_IFGE: /* ..., value ==> ... */
3161 /* op1 = target JavaVM pc, val.i = constant */
3163 if (src->flags & INMEMORY) {
3164 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3167 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3169 i386_jcc(I386_CC_GE, 0);
3170 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3173 case ICMD_IF_LEQ: /* ..., value ==> ... */
3174 /* op1 = target JavaVM pc, val.l = constant */
3176 if (src->flags & INMEMORY) {
3177 if (iptr->val.l == 0) {
3178 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3179 i386_alu_membase_reg(I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3182 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3183 i386_alu_imm_reg(I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3184 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3185 i386_alu_imm_reg(I386_XOR, iptr->val.l, REG_ITMP1);
3186 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3189 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3190 i386_jcc(I386_CC_E, 0);
3191 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3194 case ICMD_IF_LLT: /* ..., value ==> ... */
3195 /* op1 = target JavaVM pc, val.l = constant */
3197 if (src->flags & INMEMORY) {
3198 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3199 i386_jcc(I386_CC_L, 0);
3200 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3203 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3204 CALCIMMEDIATEBYTES(a, iptr->val.l);
3206 i386_jcc(I386_CC_G, a);
3208 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3209 i386_jcc(I386_CC_B, 0);
3210 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3214 case ICMD_IF_LLE: /* ..., value ==> ... */
3215 /* op1 = target JavaVM pc, val.l = constant */
3217 if (src->flags & INMEMORY) {
3218 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3219 i386_jcc(I386_CC_L, 0);
3220 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3223 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3224 CALCIMMEDIATEBYTES(a, iptr->val.l);
3226 i386_jcc(I386_CC_G, a);
3228 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3229 i386_jcc(I386_CC_BE, 0);
3230 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3234 case ICMD_IF_LNE: /* ..., value ==> ... */
3235 /* op1 = target JavaVM pc, val.l = constant */
3237 if (src->flags & INMEMORY) {
3238 if (iptr->val.l == 0) {
3239 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3240 i386_alu_membase_reg(I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3243 i386_mov_imm_reg(iptr->val.l, REG_ITMP1);
3244 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3245 i386_mov_imm_reg(iptr->val.l >> 32, REG_ITMP2);
3246 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3247 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3250 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3251 i386_jcc(I386_CC_NE, 0);
3252 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3255 case ICMD_IF_LGT: /* ..., value ==> ... */
3256 /* op1 = target JavaVM pc, val.l = constant */
3258 if (src->flags & INMEMORY) {
3259 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3260 i386_jcc(I386_CC_G, 0);
3261 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3264 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3265 CALCIMMEDIATEBYTES(a, iptr->val.l);
3267 i386_jcc(I386_CC_L, a);
3269 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3270 i386_jcc(I386_CC_A, 0);
3271 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3275 case ICMD_IF_LGE: /* ..., value ==> ... */
3276 /* op1 = target JavaVM pc, val.l = constant */
3278 if (src->flags & INMEMORY) {
3279 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3280 i386_jcc(I386_CC_G, 0);
3281 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3284 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3285 CALCIMMEDIATEBYTES(a, iptr->val.l);
3287 i386_jcc(I386_CC_L, a);
3289 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3290 i386_jcc(I386_CC_AE, 0);
3291 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3295 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3296 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3298 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3299 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3300 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3302 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3303 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3305 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3306 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3309 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3311 i386_jcc(I386_CC_E, 0);
3312 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3315 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3316 /* op1 = target JavaVM pc */
3318 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3319 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3320 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3321 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3322 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3323 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3324 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3326 i386_jcc(I386_CC_E, 0);
3327 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3330 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3331 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3333 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3334 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3335 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3337 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3338 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3340 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3341 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3344 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3346 i386_jcc(I386_CC_NE, 0);
3347 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3350 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3351 /* op1 = target JavaVM pc */
3353 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3354 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3355 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3356 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3357 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3358 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3359 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3361 i386_jcc(I386_CC_NE, 0);
3362 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3365 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3366 /* op1 = target JavaVM pc */
3368 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3369 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3370 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3372 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3373 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3375 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3376 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3379 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3381 i386_jcc(I386_CC_L, 0);
3382 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3385 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3386 /* op1 = target JavaVM pc */
3388 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3389 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3390 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3391 i386_jcc(I386_CC_L, 0);
3392 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3395 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3396 CALCOFFSETBYTES(a, REG_SP, src->regoff);
3398 i386_jcc(I386_CC_G, a);
3400 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3401 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3402 i386_jcc(I386_CC_B, 0);
3403 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3407 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3408 /* op1 = target JavaVM pc */
3410 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3411 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3412 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3414 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3415 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3417 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3418 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3421 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3423 i386_jcc(I386_CC_G, 0);
3424 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3427 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3428 /* op1 = target JavaVM pc */
3430 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3431 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3432 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3433 i386_jcc(I386_CC_G, 0);
3434 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3437 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3438 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3440 i386_jcc(I386_CC_L, a);
3442 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3443 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3444 i386_jcc(I386_CC_A, 0);
3445 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3449 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3450 /* op1 = target JavaVM pc */
3452 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3453 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3454 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3456 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3457 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3459 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3460 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3463 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3465 i386_jcc(I386_CC_LE, 0);
3466 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3469 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3470 /* op1 = target JavaVM pc */
3472 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3473 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3474 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3475 i386_jcc(I386_CC_L, 0);
3476 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3479 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3480 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3482 i386_jcc(I386_CC_G, a);
3484 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3485 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3486 i386_jcc(I386_CC_BE, 0);
3487 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3491 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3492 /* op1 = target JavaVM pc */
3494 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3495 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3496 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3498 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3499 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3501 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3502 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3505 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3507 i386_jcc(I386_CC_GE, 0);
3508 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3511 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3512 /* op1 = target JavaVM pc */
3514 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3515 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3516 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3517 i386_jcc(I386_CC_G, 0);
3518 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3521 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3522 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3524 i386_jcc(I386_CC_L, a);
3526 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3527 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3528 i386_jcc(I386_CC_AE, 0);
3529 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3533 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3535 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3538 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3539 /* val.i = constant */
3541 d = reg_of_var(m, iptr->dst, REG_NULL);
3542 i386_emit_ifcc_iconst(I386_CC_NE, src, iptr);
3545 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3546 /* val.i = constant */
3548 d = reg_of_var(m, iptr->dst, REG_NULL);
3549 i386_emit_ifcc_iconst(I386_CC_E, src, iptr);
3552 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3553 /* val.i = constant */
3555 d = reg_of_var(m, iptr->dst, REG_NULL);
3556 i386_emit_ifcc_iconst(I386_CC_GE, src, iptr);
3559 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3560 /* val.i = constant */
3562 d = reg_of_var(m, iptr->dst, REG_NULL);
3563 i386_emit_ifcc_iconst(I386_CC_L, src, iptr);
3566 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3567 /* val.i = constant */
3569 d = reg_of_var(m, iptr->dst, REG_NULL);
3570 i386_emit_ifcc_iconst(I386_CC_LE, src, iptr);
3573 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3574 /* val.i = constant */
3576 d = reg_of_var(m, iptr->dst, REG_NULL);
3577 i386_emit_ifcc_iconst(I386_CC_G, src, iptr);
3581 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3584 var_to_reg_int(s1, src, REG_RESULT);
3585 M_INTMOVE(s1, REG_RESULT);
3587 goto nowperformreturn;
3589 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3591 if (src->flags & INMEMORY) {
3592 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_RESULT);
3593 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3596 panic("LRETURN: longs have to be in memory");
3599 goto nowperformreturn;
3601 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3602 case ICMD_DRETURN: /* ..., retvalue ==> ... */
3604 var_to_reg_flt(s1, src, REG_FRESULT);
3605 /* this may be an early return -- keep the offset correct for the
3609 goto nowperformreturn;
3611 case ICMD_RETURN: /* ... ==> ... */
3617 p = parentargs_base;
3619 /* call trace function */
3621 i386_alu_imm_reg(I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3623 i386_mov_imm_membase((s4) m, REG_SP, 0);
3625 i386_mov_reg_membase(REG_RESULT, REG_SP, 4);
3626 i386_mov_reg_membase(REG_RESULT2, REG_SP, 4 + 4);
3628 i386_fstl_membase(REG_SP, 4 + 8);
3629 i386_fsts_membase(REG_SP, 4 + 8 + 8);
3631 i386_mov_imm_reg((s4) builtin_displaymethodstop, REG_ITMP1);
3632 i386_call_reg(REG_ITMP1);
3634 i386_mov_membase_reg(REG_SP, 4, REG_RESULT);
3635 i386_mov_membase_reg(REG_SP, 4 + 4, REG_RESULT2);
3637 i386_alu_imm_reg(I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3640 #if defined(USE_THREADS)
3641 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3642 i386_mov_membase_reg(REG_SP, 8 * r->maxmemuse, REG_ITMP2);
3644 /* we need to save the proper return value */
3645 switch (iptr->opc) {
3648 i386_mov_reg_membase(REG_RESULT, REG_SP, r->maxmemuse * 8);
3652 i386_mov_reg_membase(REG_RESULT, REG_SP, r->maxmemuse * 8);
3653 i386_mov_reg_membase(REG_RESULT2, REG_SP, r->maxmemuse * 8 + 4);
3657 i386_fsts_membase(REG_SP, r->maxmemuse * 8);
3661 i386_fstl_membase(REG_SP, r->maxmemuse * 8);
3665 i386_alu_imm_reg(I386_SUB, 4, REG_SP);
3666 i386_mov_reg_membase(REG_ITMP2, REG_SP, 0);
3667 i386_mov_imm_reg((s4) builtin_monitorexit, REG_ITMP1);
3668 i386_call_reg(REG_ITMP1);
3669 i386_alu_imm_reg(I386_ADD, 4, REG_SP);
3671 /* and now restore the proper return value */
3672 switch (iptr->opc) {
3675 i386_mov_membase_reg(REG_SP, r->maxmemuse * 8, REG_RESULT);
3679 i386_mov_membase_reg(REG_SP, r->maxmemuse * 8, REG_RESULT);
3680 i386_mov_membase_reg(REG_SP, r->maxmemuse * 8 + 4, REG_RESULT2);
3684 i386_flds_membase(REG_SP, r->maxmemuse * 8);
3688 i386_fldl_membase(REG_SP, r->maxmemuse * 8);
3694 /* restore saved registers */
3695 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
3697 i386_mov_membase_reg(REG_SP, p * 8, r->savintregs[i]);
3699 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
3701 i386_fldl_membase(REG_SP, p * 8);
3703 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3704 i386_fstp_reg(r->savfltregs[i] + fpu_st_offset + 1);
3706 i386_fstp_reg(r->savfltregs[i] + fpu_st_offset);
3711 /* deallocate stack */
3712 if (parentargs_base) {
3713 i386_alu_imm_reg(I386_ADD, parentargs_base * 8, REG_SP);
3722 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3727 tptr = (void **) iptr->target;
3729 s4ptr = iptr->val.a;
3730 l = s4ptr[1]; /* low */
3731 i = s4ptr[2]; /* high */
3733 var_to_reg_int(s1, src, REG_ITMP1);
3734 M_INTMOVE(s1, REG_ITMP1);
3736 i386_alu_imm_reg(I386_SUB, l, REG_ITMP1);
3742 i386_alu_imm_reg(I386_CMP, i - 1, REG_ITMP1);
3743 i386_jcc(I386_CC_A, 0);
3745 /* codegen_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr); */
3746 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3748 /* build jump table top down and use address of lowest entry */
3750 /* s4ptr += 3 + i; */
3754 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3755 dseg_addtarget((basicblock *) tptr[0]);
3759 /* length of dataseg after last dseg_addtarget is used by load */
3761 i386_mov_imm_reg(0, REG_ITMP2);
3762 dseg_adddata(mcodeptr);
3763 i386_mov_memindex_reg(-dseglen, REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3764 i386_jmp_reg(REG_ITMP1);
3770 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3772 s4 i, l, val, *s4ptr;
3775 tptr = (void **) iptr->target;
3777 s4ptr = iptr->val.a;
3778 l = s4ptr[0]; /* default */
3779 i = s4ptr[1]; /* count */
3781 MCODECHECK((i<<2)+8);
3782 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3788 i386_alu_imm_reg(I386_CMP, val, s1);
3789 i386_jcc(I386_CC_E, 0);
3790 /* codegen_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr); */
3791 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3795 /* codegen_addreference(BlockPtrOfPC(l), mcodeptr); */
3797 tptr = (void **) iptr->target;
3798 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3805 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3806 /* op1 = return type, val.a = function pointer*/
3810 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3811 /* op1 = return type, val.a = function pointer*/
3815 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3816 /* op1 = return type, val.a = function pointer*/
3820 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3821 /* op1 = arg count, val.a = method pointer */
3823 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3824 /* op1 = arg count, val.a = method pointer */
3826 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3827 /* op1 = arg count, val.a = method pointer */
3829 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3830 /* op1 = arg count, val.a = method pointer */
3838 MCODECHECK((s3 << 1) + 64);
3840 /* copy arguments to registers or stack location */
3842 for (; --s3 >= 0; src = src->prev) {
3843 if (src->varkind == ARGVAR) {
3847 if (IS_INT_LNG_TYPE(src->type)) {
3848 if (s3 < r->intreg_argnum) {
3849 panic("No integer argument registers available!");
3852 if (!IS_2_WORD_TYPE(src->type)) {
3853 if (src->flags & INMEMORY) {
3854 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3855 i386_mov_reg_membase(REG_ITMP1, REG_SP, s3 * 8);
3858 i386_mov_reg_membase(src->regoff, REG_SP, s3 * 8);
3862 if (src->flags & INMEMORY) {
3863 M_LNGMEMMOVE(src->regoff, s3);
3866 panic("copy arguments: longs have to be in memory");
3872 if (s3 < r->fltreg_argnum) {
3873 panic("No float argument registers available!");
3876 var_to_reg_flt(d, src, REG_FTMP1);
3877 if (src->type == TYPE_FLT) {
3878 i386_fstps_membase(REG_SP, s3 * 8);
3881 i386_fstpl_membase(REG_SP, s3 * 8);
3888 switch (iptr->opc) {
3896 i386_mov_imm_reg(a, REG_ITMP1);
3897 i386_call_reg(REG_ITMP1);
3900 case ICMD_INVOKESTATIC:
3902 a = (u4) lm->stubroutine;
3905 i386_mov_imm_reg(a, REG_ITMP2);
3906 i386_call_reg(REG_ITMP2);
3909 case ICMD_INVOKESPECIAL:
3911 a = (u4) lm->stubroutine;
3914 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1);
3915 gen_nullptr_check(REG_ITMP1);
3916 i386_mov_membase_reg(REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
3918 i386_mov_imm_reg(a, REG_ITMP2);
3919 i386_call_reg(REG_ITMP2);
3922 case ICMD_INVOKEVIRTUAL:
3926 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1);
3927 gen_nullptr_check(REG_ITMP1);
3928 i386_mov_membase_reg(REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
3929 i386_mov_membase32_reg(REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
3931 i386_call_reg(REG_ITMP1);
3934 case ICMD_INVOKEINTERFACE:
3939 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1);
3940 gen_nullptr_check(REG_ITMP1);
3941 i386_mov_membase_reg(REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3942 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * ci->index, REG_ITMP2);
3943 i386_mov_membase32_reg(REG_ITMP2, sizeof(methodptr) * (lm - ci->methods), REG_ITMP1);
3945 i386_call_reg(REG_ITMP1);
3950 error("Unkown ICMD-Command: %d", iptr->opc);
3953 /* d contains return type */
3955 if (d != TYPE_VOID) {
3956 d = reg_of_var(m, iptr->dst, REG_NULL);
3958 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3959 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3960 if (iptr->dst->flags & INMEMORY) {
3961 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3962 i386_mov_reg_membase(REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
3965 panic("RETURN: longs have to be in memory");
3969 if (iptr->dst->flags & INMEMORY) {
3970 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3973 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
3978 /* fld from called function -- has other fpu_st_offset counter */
3980 store_reg_to_var_flt(iptr->dst, d);
3987 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3989 /* op1: 0 == array, 1 == class */
3990 /* val.a: (classinfo*) superclass */
3992 /* superclass is an interface:
3994 * return (sub != NULL) &&
3995 * (sub->vftbl->interfacetablelength > super->index) &&
3996 * (sub->vftbl->interfacetable[-super->index] != NULL);
3998 * superclass is a class:
4000 * return ((sub != NULL) && (0
4001 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4002 * super->vftbl->diffvall));
4006 classinfo *super = (classinfo*) iptr->val.a;
4008 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4009 codegen_threadcritrestart(mcodeptr - mcodebase);
4011 var_to_reg_int(s1, src, REG_ITMP1);
4012 d = reg_of_var(m, iptr->dst, REG_ITMP3);
4014 M_INTMOVE(s1, REG_ITMP1);
4017 i386_alu_reg_reg(I386_XOR, d, d);
4018 if (iptr->op1) { /* class/interface */
4019 if (super->flags & ACC_INTERFACE) { /* interface */
4020 i386_test_reg_reg(s1, s1);
4022 /* TODO: clean up this calculation */
4024 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4027 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4030 /* CALCOFFSETBYTES(a, super->index); */
4031 CALCIMMEDIATEBYTES(a, super->index);
4037 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4044 i386_jcc(I386_CC_E, a);
4046 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4047 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4048 i386_alu_imm_reg(I386_SUB, super->index, REG_ITMP2);
4050 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP2);
4052 /* TODO: clean up this calculation */
4055 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4062 i386_jcc(I386_CC_LE, a);
4063 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4065 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP1);
4066 /* i386_setcc_reg(I386_CC_A, d); */
4067 /* i386_jcc(I386_CC_BE, 5); */
4068 i386_jcc(I386_CC_E, 5);
4069 i386_mov_imm_reg(1, d);
4072 } else { /* class */
4073 i386_test_reg_reg(s1, s1);
4075 /* TODO: clean up this calculation */
4077 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4080 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4082 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4085 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4095 i386_jcc(I386_CC_E, a);
4097 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4098 i386_mov_imm_reg((s4) super->vftbl, REG_ITMP2);
4099 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4100 codegen_threadcritstart(mcodeptr - mcodebase);
4102 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4103 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4104 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4105 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4106 codegen_threadcritstop(mcodeptr - mcodebase);
4108 i386_alu_reg_reg(I386_SUB, REG_ITMP3, REG_ITMP1);
4109 i386_alu_reg_reg(I386_XOR, d, d);
4111 i386_alu_reg_reg(I386_CMP, REG_ITMP2, REG_ITMP1);
4112 i386_jcc(I386_CC_A, 5);
4113 i386_mov_imm_reg(1, d);
4117 panic ("internal error: no inlined array instanceof");
4119 store_reg_to_var_int(iptr->dst, d);
4122 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4124 /* op1: 0 == array, 1 == class */
4125 /* val.a: (classinfo*) superclass */
4127 /* superclass is an interface:
4129 * OK if ((sub == NULL) ||
4130 * (sub->vftbl->interfacetablelength > super->index) &&
4131 * (sub->vftbl->interfacetable[-super->index] != NULL));
4133 * superclass is a class:
4135 * OK if ((sub == NULL) || (0
4136 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4137 * super->vftbl->diffvall));
4141 classinfo *super = (classinfo*) iptr->val.a;
4143 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4144 codegen_threadcritrestart(mcodeptr - mcodebase);
4146 d = reg_of_var(m, iptr->dst, REG_ITMP3);
4147 var_to_reg_int(s1, src, d);
4148 if (iptr->op1) { /* class/interface */
4149 if (super->flags & ACC_INTERFACE) { /* interface */
4150 i386_test_reg_reg(s1, s1);
4152 /* TODO: clean up this calculation */
4154 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4157 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4160 /* CALCOFFSETBYTES(a, super->index); */
4161 CALCIMMEDIATEBYTES(a, super->index);
4167 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4172 i386_jcc(I386_CC_E, a);
4174 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4175 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4176 i386_alu_imm_reg(I386_SUB, super->index, REG_ITMP2);
4178 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP2);
4179 i386_jcc(I386_CC_LE, 0);
4180 codegen_addxcastrefs(mcodeptr);
4181 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
4183 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP2);
4184 i386_jcc(I386_CC_E, 0);
4185 codegen_addxcastrefs(mcodeptr);
4187 } else { /* class */
4188 i386_test_reg_reg(s1, s1);
4190 /* TODO: clean up this calculation */
4192 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4197 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4199 if (d != REG_ITMP3) {
4201 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4204 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4210 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4217 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4224 i386_jcc(I386_CC_E, a);
4226 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4227 i386_mov_imm_reg((s4) super->vftbl, REG_ITMP2);
4228 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4229 codegen_threadcritstart(mcodeptr - mcodebase);
4231 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4232 if (d != REG_ITMP3) {
4233 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4234 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4235 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4236 codegen_threadcritstop(mcodeptr - mcodebase);
4238 i386_alu_reg_reg(I386_SUB, REG_ITMP3, REG_ITMP1);
4241 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
4242 i386_alu_reg_reg(I386_SUB, REG_ITMP2, REG_ITMP1);
4243 i386_mov_imm_reg((s4) super->vftbl, REG_ITMP2);
4244 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4245 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4246 codegen_threadcritstop(mcodeptr - mcodebase);
4250 i386_alu_reg_reg(I386_CMP, REG_ITMP2, REG_ITMP1);
4251 i386_jcc(I386_CC_A, 0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
4252 codegen_addxcastrefs(mcodeptr);
4256 panic ("internal error: no inlined array checkcast");
4259 store_reg_to_var_int(iptr->dst, d);
4262 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4264 if (src->flags & INMEMORY) {
4265 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
4268 i386_test_reg_reg(src->regoff, src->regoff);
4270 i386_jcc(I386_CC_L, 0);
4271 codegen_addxcheckarefs(mcodeptr);
4274 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4276 i386_test_reg_reg(REG_RESULT, REG_RESULT);
4277 i386_jcc(I386_CC_E, 0);
4278 codegen_addxexceptionrefs(mcodeptr);
4281 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4282 /* op1 = dimension, val.a = array descriptor */
4284 /* check for negative sizes and copy sizes to stack if necessary */
4286 MCODECHECK((iptr->op1 << 1) + 64);
4288 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4289 if (src->flags & INMEMORY) {
4290 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
4293 i386_test_reg_reg(src->regoff, src->regoff);
4295 i386_jcc(I386_CC_L, 0);
4296 codegen_addxcheckarefs(mcodeptr);
4299 * copy sizes to new stack location, be cause native function
4300 * builtin_nmultianewarray access them as (int *)
4302 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
4303 i386_mov_reg_membase(REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);
4305 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
4307 if (src->varkind != ARGVAR) {
4308 if (src->flags & INMEMORY) {
4309 i386_mov_membase_reg(REG_SP, (src->regoff + INT_ARG_CNT) * 8, REG_ITMP1);
4310 i386_mov_reg_membase(REG_ITMP1, REG_SP, (s1 + INT_ARG_CNT) * 8);
4313 i386_mov_reg_membase(src->regoff, REG_SP, (s1 + INT_ARG_CNT) * 8);
4317 i386_alu_imm_reg(I386_SUB, iptr->op1 * 4, REG_SP);
4319 /* a0 = dimension count */
4321 /* save stack pointer */
4322 M_INTMOVE(REG_SP, REG_ITMP1);
4324 i386_alu_imm_reg(I386_SUB, 12, REG_SP);
4325 i386_mov_imm_membase(iptr->op1, REG_SP, 0);
4327 /* a1 = arraydescriptor */
4329 i386_mov_imm_membase((s4) iptr->val.a, REG_SP, 4);
4331 /* a2 = pointer to dimensions = stack pointer */
4333 i386_mov_reg_membase(REG_ITMP1, REG_SP, 8);
4335 i386_mov_imm_reg((s4) (builtin_nmultianewarray), REG_ITMP1);
4336 i386_call_reg(REG_ITMP1);
4337 i386_alu_imm_reg(I386_ADD, 12 + iptr->op1 * 4, REG_SP);
4339 s1 = reg_of_var(m, iptr->dst, REG_RESULT);
4340 M_INTMOVE(REG_RESULT, s1);
4341 store_reg_to_var_int(iptr->dst, s1);
4345 error ("Unknown pseudo command: %d", iptr->opc);
4348 } /* for instruction */
4350 /* copy values to interface registers */
4352 src = bptr->outstack;
4353 len = bptr->outdepth;
4357 if ((src->varkind != STACKVAR)) {
4359 if (IS_FLT_DBL_TYPE(s2)) {
4360 var_to_reg_flt(s1, src, REG_FTMP1);
4361 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
4362 M_FLTMOVE(s1, r->interfaces[len][s2].regoff);
4365 panic("double store");
4366 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4370 var_to_reg_int(s1, src, REG_ITMP1);
4371 if (!IS_2_WORD_TYPE(r->interfaces[len][s2].type)) {
4372 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
4373 M_INTMOVE(s1, r->interfaces[len][s2].regoff);
4376 i386_mov_reg_membase(s1, REG_SP, r->interfaces[len][s2].regoff * 8);
4380 if (r->interfaces[len][s2].flags & INMEMORY) {
4381 M_LNGMEMMOVE(s1, r->interfaces[len][s2].regoff);
4384 panic("copy interface registers: longs have to be in memory (end)");
4391 } /* if (bptr -> flags >= BBREACHED) */
4392 } /* for basic block */
4394 codegen_createlinenumbertable();
4396 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
4400 /* generate bound check stubs */
4402 u1 *xcodeptr = NULL;
4404 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
4405 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
4406 xboundrefs->branchpos,
4407 (u1*) mcodeptr - mcodebase);
4411 /* move index register into REG_ITMP1 */
4412 i386_mov_reg_reg(xboundrefs->reg, REG_ITMP1); /* 2 bytes */
4414 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4415 dseg_adddata(mcodeptr);
4416 i386_mov_imm_reg(xboundrefs->branchpos - 6, REG_ITMP3); /* 5 bytes */
4417 i386_alu_reg_reg(I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4419 if (xcodeptr != NULL) {
4420 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4423 xcodeptr = mcodeptr;
4425 i386_push_reg(REG_ITMP2_XPC);
4427 PREPARE_NATIVE_STACKINFO
4429 i386_alu_imm_reg(I386_SUB, 2 * 4, REG_SP);
4430 i386_mov_imm_membase((s4) string_java_lang_ArrayIndexOutOfBoundsException, REG_SP, 0 * 4);
4431 i386_mov_reg_membase(REG_ITMP1, REG_SP, 1 * 4);
4432 i386_mov_imm_reg((s4) new_exception_int, REG_ITMP1);
4433 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4434 i386_alu_imm_reg(I386_ADD, 2 * 4, REG_SP);
4436 REMOVE_NATIVE_STACKINFO
4438 i386_pop_reg(REG_ITMP2_XPC);
4440 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4441 i386_jmp_reg(REG_ITMP3);
4445 /* generate negative array size check stubs */
4449 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
4450 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4451 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
4452 xcheckarefs->branchpos,
4453 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4457 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
4458 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
4462 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4463 dseg_adddata(mcodeptr);
4464 i386_mov_imm_reg(xcheckarefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4465 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4467 if (xcodeptr != NULL) {
4468 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4471 xcodeptr = mcodeptr;
4473 i386_push_reg(REG_ITMP2_XPC);
4475 PREPARE_NATIVE_STACKINFO
4477 i386_alu_imm_reg(I386_SUB, 1 * 4, REG_SP);
4478 i386_mov_imm_membase((s4) string_java_lang_NegativeArraySizeException, REG_SP, 0 * 4);
4479 i386_mov_imm_reg((s4) new_exception, REG_ITMP1);
4480 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4481 i386_alu_imm_reg(I386_ADD, 1 * 4, REG_SP);
4484 REMOVE_NATIVE_STACKINFO
4486 i386_pop_reg(REG_ITMP2_XPC);
4488 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4489 i386_jmp_reg(REG_ITMP3);
4493 /* generate cast check stubs */
4497 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
4498 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4499 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
4500 xcastrefs->branchpos,
4501 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4505 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
4506 xcastrefs->branchpos, (u1*) mcodeptr - mcodebase);
4510 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4511 dseg_adddata(mcodeptr);
4512 i386_mov_imm_reg(xcastrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4513 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4515 if (xcodeptr != NULL) {
4516 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4519 xcodeptr = mcodeptr;
4521 i386_push_reg(REG_ITMP2_XPC);
4524 PREPARE_NATIVE_STACKINFO
4526 i386_alu_imm_reg(I386_SUB, 1 * 4, REG_SP);
4527 i386_mov_imm_membase((s4) string_java_lang_ClassCastException, REG_SP, 0 * 4);
4528 i386_mov_imm_reg((s4) new_exception, REG_ITMP1);
4529 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4530 i386_alu_imm_reg(I386_ADD, 1 * 4, REG_SP);
4533 REMOVE_NATIVE_STACKINFO
4535 i386_pop_reg(REG_ITMP2_XPC);
4537 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4538 i386_jmp_reg(REG_ITMP3);
4542 /* generate divide by zero check stubs */
4546 for (; xdivrefs != NULL; xdivrefs = xdivrefs->next) {
4547 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4548 gen_resolvebranch((u1*) mcodebase + xdivrefs->branchpos,
4549 xdivrefs->branchpos,
4550 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4554 gen_resolvebranch((u1*) mcodebase + xdivrefs->branchpos,
4555 xdivrefs->branchpos, (u1*) mcodeptr - mcodebase);
4559 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4560 dseg_adddata(mcodeptr);
4561 i386_mov_imm_reg(xdivrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4562 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4564 if (xcodeptr != NULL) {
4565 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4568 xcodeptr = mcodeptr;
4570 i386_push_reg(REG_ITMP2_XPC);
4572 PREPARE_NATIVE_STACKINFO
4574 i386_alu_imm_reg(I386_SUB, 2 * 4, REG_SP);
4575 i386_mov_imm_membase((s4) string_java_lang_ArithmeticException, REG_SP, 0 * 4);
4576 i386_mov_imm_membase((s4) string_java_lang_ArithmeticException_message, REG_SP, 1 * 4);
4577 i386_mov_imm_reg((s4) new_exception_message, REG_ITMP1);
4578 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4579 i386_alu_imm_reg(I386_ADD, 2 * 4, REG_SP);
4581 REMOVE_NATIVE_STACKINFO
4583 i386_pop_reg(REG_ITMP2_XPC);
4585 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4586 i386_jmp_reg(REG_ITMP3);
4590 /* generate exception check stubs */
4594 for (; xexceptionrefs != NULL; xexceptionrefs = xexceptionrefs->next) {
4595 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4596 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
4597 xexceptionrefs->branchpos,
4598 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4602 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
4603 xexceptionrefs->branchpos, (u1*) mcodeptr - mcodebase);
4607 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4608 dseg_adddata(mcodeptr);
4609 i386_mov_imm_reg(xexceptionrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4610 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4612 if (xcodeptr != NULL) {
4613 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4616 xcodeptr = mcodeptr;
4618 i386_push_reg(REG_ITMP2_XPC);
4620 PREPARE_NATIVE_STACKINFO
4622 i386_mov_imm_reg((s4) codegen_general_stubcalled,REG_ITMP1);
4623 i386_call_reg(REG_ITMP1);
4626 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4627 i386_mov_imm_reg((s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4628 i386_call_reg(REG_ITMP1);
4629 i386_mov_membase_reg(REG_RESULT, 0, REG_ITMP3);
4630 i386_mov_imm_membase(0, REG_RESULT, 0);
4631 i386_mov_reg_reg(REG_ITMP3, REG_ITMP1_XPTR);
4633 i386_mov_imm_reg((s4) &_exceptionptr, REG_ITMP3);
4634 i386_mov_membase_reg(REG_ITMP3, 0, REG_ITMP1_XPTR);
4635 i386_mov_imm_membase(0, REG_ITMP3, 0);
4638 i386_push_reg(REG_ITMP1_XPTR);
4640 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4641 java stack at this point*/
4642 i386_mov_membase_reg(REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4643 i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl_t,class), REG_ITMP1);
4644 i386_push_imm(utf_fillInStackTrace_desc);
4645 i386_push_imm(utf_fillInStackTrace_name);
4646 i386_push_reg(REG_ITMP1);
4647 i386_mov_imm_reg((s4) class_resolvemethod, REG_ITMP3);
4648 i386_call_reg(REG_ITMP3);
4649 /*cleanup parameters of class_resolvemethod*/
4650 i386_alu_imm_reg(I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4651 /*prepare call to asm_calljavafunction2 */
4653 i386_push_imm(TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
4654 i386_push_reg(REG_SP);
4655 i386_push_imm(sizeof(jni_callblock));
4657 i386_push_reg(REG_RESULT);
4659 i386_mov_imm_reg((s4) asm_calljavafunction2, REG_ITMP3);
4660 i386_call_reg(REG_ITMP3);
4662 /* check exceptionptr + fail (JOWENN)*/
4664 i386_alu_imm_reg(I386_ADD,6*4,REG_SP);
4666 i386_pop_reg(REG_ITMP1_XPTR);
4667 i386_pop_reg(REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4668 REMOVE_NATIVE_STACKINFO
4670 i386_pop_reg(REG_ITMP2_XPC);
4672 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4673 i386_jmp_reg(REG_ITMP3);
4677 /* generate null pointer check stubs */
4681 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
4682 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4683 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
4684 xnullrefs->branchpos,
4685 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4689 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
4690 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
4694 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4695 dseg_adddata(mcodeptr);
4696 i386_mov_imm_reg(xnullrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4697 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4699 if (xcodeptr != NULL) {
4700 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4703 xcodeptr = mcodeptr;
4705 i386_push_reg(REG_ITMP2_XPC);
4709 PREPARE_NATIVE_STACKINFO
4711 /* create native call block*/
4712 i386_alu_imm_reg(I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4715 i386_mov_imm_reg((s4) codegen_stubcalled,REG_ITMP1);
4716 i386_call_reg(REG_ITMP1); /*call codegen_stubcalled*/
4718 i386_mov_imm_reg((s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4719 i386_call_reg(REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
4720 i386_mov_imm_membase(0,REG_SP, 2*4); /* builtin */
4721 i386_mov_reg_membase(REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
4722 i386_mov_membase_reg(REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4723 i386_mov_reg_membase(REG_ITMP2,REG_SP,0*4); /* store value on stack */
4724 i386_mov_reg_membase(REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4730 /* create exception*/
4731 i386_alu_imm_reg(I386_SUB, 1 * 4, REG_SP);
4732 i386_mov_imm_membase((s4) string_java_lang_NullPointerException, REG_SP, 0 * 4);
4733 i386_mov_imm_reg((s4) new_exception, REG_ITMP1);
4734 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4735 i386_alu_imm_reg(I386_ADD, 1 * 4, REG_SP);
4738 REMOVE_NATIVE_STACKINFO
4740 /* restore native call stack */
4741 i386_mov_membase_reg(REG_SP,0,REG_ITMP2);
4742 i386_mov_membase_reg(REG_SP,4,REG_ITMP3);
4743 i386_mov_reg_membase(REG_ITMP2,REG_ITMP3,0);
4744 i386_alu_imm_reg(I386_ADD,3*4,REG_SP);
4748 i386_pop_reg(REG_ITMP2_XPC);
4750 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4751 i386_jmp_reg(REG_ITMP3);
4756 codegen_finish(m, (u4) ((u1 *) mcodeptr - mcodebase));
4760 /* function createcompilerstub *************************************************
4762 creates a stub routine which calls the compiler
4764 *******************************************************************************/
4766 #define COMPSTUBSIZE 12
4768 u1 *createcompilerstub(methodinfo *m)
4770 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
4771 mcodeptr = s; /* code generation pointer */
4773 /* code for the stub */
4774 i386_mov_imm_reg((u4) m, REG_ITMP1);/* pass method pointer to compiler */
4776 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
4777 i386_mov_imm_reg((u4) asm_call_jit_compiler, REG_ITMP3); /* load address */
4778 i386_jmp_reg(REG_ITMP3); /* jump to compiler */
4780 #if defined(STATISTICS)
4782 count_cstub_len += COMPSTUBSIZE;
4789 /* function removecompilerstub *************************************************
4791 deletes a compilerstub from memory (simply by freeing it)
4793 *******************************************************************************/
4795 void removecompilerstub(u1 *stub)
4797 CFREE(stub, COMPSTUBSIZE);
4801 /* function: createnativestub **************************************************
4803 creates a stub routine which calls a native method
4805 *******************************************************************************/
4807 #define NATIVESTUBSIZE 350
4809 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4810 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4813 void i386_native_stub_debug(void **p) {
4814 printf("Pos on stack: %p\n",p);
4815 printf("Return adress should be: %p\n",*p);
4818 void i386_native_stub_debug2(void **p) {
4819 printf("Pos on stack: %p\n",p);
4820 printf("Return for lookup is: %p\n",*p);
4823 void traverseStackInfo() {
4824 void **p=builtin_asm_get_stackframeinfo();
4828 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4829 m=*((methodinfo**)((*p)+8));
4830 utf_display(m->name);
4838 u1 *createnativestub(functionptr f, methodinfo *m)
4840 u1 *s = CNEW(u1, NATIVESTUBSIZE); /* memory to hold the stub */
4844 int stackframesize = 4+12; /* initial 4 bytes is space for jni env,
4845 + 4 byte thread pointer + 4 byte previous pointer + method info*/
4846 int stackframeoffset = 4;
4850 mcodeptr = s; /* make macros work */
4852 if (m->flags & ACC_STATIC) {
4853 stackframesize += 4;
4854 stackframeoffset += 4;
4858 descriptor2types(m); /* set paramcount and paramtypes */
4861 /* i386_push_reg(REG_SP);
4862 i386_mov_imm_reg((s4) i386_native_stub_debug, REG_ITMP1);
4863 i386_call_reg(REG_ITMP1);
4864 i386_pop_reg(REG_ITMP1);*/
4867 /* if function is static, check for initialized */
4869 if (m->flags & ACC_STATIC) {
4870 /* if class isn't yet initialized, do it */
4871 if (!m->class->initialized) {
4873 *header = 0;/*extablesize*/
4875 *header = 0;/*line number table start*/
4877 *header = 0;/*line number table size*/
4879 *header = 0;/*fltsave*/
4881 *header = 0;/*intsave*/
4883 *header = 0;/*isleaf*/
4885 *header = 0;/*issync*/
4887 *header = 0;/*framesize*/
4889 *header = m;/*methodpointer*/
4893 /* call helper function which patches this code */
4894 i386_mov_imm_reg((s4) m->class, REG_ITMP1);
4895 i386_mov_imm_reg((s4) asm_check_clinit, REG_ITMP2);
4896 i386_call_reg(REG_ITMP2);
4901 i386_alu_imm_reg(I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4903 for (p = 0; p < m->paramcount; p++) {
4904 t = m->paramtypes[p];
4905 if (IS_INT_LNG_TYPE(t)) {
4906 if (IS_2_WORD_TYPE(t)) {
4907 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4908 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
4909 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
4910 i386_mov_reg_membase(REG_ITMP2, REG_SP, p * 8 + 4);
4912 } else if (t == TYPE_ADR) {
4913 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4914 i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2);
4915 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
4916 i386_mov_reg_membase(REG_ITMP2, REG_SP, p * 8 + 4);
4919 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
4921 i386_mov_reg_membase(EAX, REG_SP, p * 8);
4922 i386_mov_reg_membase(EDX, REG_SP, p * 8 + 4);
4926 if (!IS_2_WORD_TYPE(t)) {
4927 i386_flds_membase(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4928 i386_fstps_membase(REG_SP, p * 8);
4929 i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2);
4930 i386_mov_reg_membase(REG_ITMP2, REG_SP, p * 8 + 4);
4933 i386_fldl_membase(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4934 i386_fstpl_membase(REG_SP, p * 8);
4939 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
4940 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
4941 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
4942 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
4945 i386_mov_imm_membase((s4) m, REG_SP, TRACE_ARGS_NUM * 8);
4947 i386_mov_imm_reg((s4) builtin_trace_args, REG_ITMP1);
4948 i386_call_reg(REG_ITMP1);
4950 i386_alu_imm_reg(I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4954 * mark the whole fpu stack as free for native functions
4955 * (only for saved register count == 0)
4966 /* calculate stackframe size for native function */
4967 tptr = m->paramtypes;
4968 for (i = 0; i < m->paramcount; i++) {
4973 stackframesize += 4;
4978 stackframesize += 8;
4982 panic("unknown parameter type in native function");
4986 i386_alu_imm_reg(I386_SUB, stackframesize, REG_SP);
4988 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
4989 i386_mov_imm_membase((s4) m, REG_SP,stackframesize-4);
4990 i386_mov_imm_reg((s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
4991 i386_call_reg(REG_ITMP1);
4992 i386_mov_reg_membase(REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
4993 i386_mov_membase_reg(REG_RESULT,0,REG_ITMP2);
4994 i386_mov_reg_membase(REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
4995 i386_mov_reg_reg(REG_SP,REG_ITMP2);
4996 i386_alu_imm_reg(I386_ADD,stackframesize-12,REG_ITMP2);
4997 i386_mov_reg_membase(REG_ITMP2,REG_RESULT,0);
5000 /* i386_mov_imm_membase((s4) m, REG_SP,stackframesize-4);
5001 i386_mov_imm_membase((s4) m, REG_SP,stackframesize-8);
5002 i386_mov_imm_membase((s4) m, REG_SP,stackframesize-12);*/
5004 /* CREATE DYNAMIC STACK INFO -- END*/
5007 tptr = m->paramtypes;
5008 for (i = 0; i < m->paramcount; i++) {
5013 i386_mov_membase_reg(REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5014 i386_mov_reg_membase(REG_ITMP1, REG_SP, stackframeoffset);
5015 stackframeoffset += 4;
5020 i386_mov_membase_reg(REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5021 i386_mov_membase_reg(REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5022 i386_mov_reg_membase(REG_ITMP1, REG_SP, stackframeoffset);
5023 i386_mov_reg_membase(REG_ITMP2, REG_SP, stackframeoffset + 4);
5024 stackframeoffset += 8;
5028 panic("unknown parameter type in native function");
5032 if (m->flags & ACC_STATIC) {
5033 /* put class into second argument */
5034 i386_mov_imm_membase((s4) m->class, REG_SP, 4);
5037 /* put env into first argument */
5038 i386_mov_imm_membase((s4) &env, REG_SP, 0);
5040 i386_mov_imm_reg((s4) f, REG_ITMP1);
5041 i386_call_reg(REG_ITMP1);
5042 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5043 i386_push_reg(REG_RESULT2);
5044 i386_mov_membase_reg(REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
5045 i386_mov_membase_reg(REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
5046 i386_mov_reg_membase(REG_ITMP2,REG_RESULT2,0);
5047 i386_pop_reg(REG_RESULT2);
5048 /*REMOVE DYNAMIC STACK INFO -END */
5050 i386_alu_imm_reg(I386_ADD, stackframesize, REG_SP);
5054 i386_alu_imm_reg(I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5056 i386_mov_imm_membase((s4) m, REG_SP, 0);
5058 i386_mov_reg_membase(REG_RESULT, REG_SP, 4);
5059 i386_mov_reg_membase(REG_RESULT2, REG_SP, 4 + 4);
5061 i386_fstl_membase(REG_SP, 4 + 8);
5062 i386_fsts_membase(REG_SP, 4 + 8 + 8);
5064 i386_mov_imm_reg((s4) builtin_displaymethodstop, REG_ITMP1);
5065 i386_call_reg(REG_ITMP1);
5067 i386_mov_membase_reg(REG_SP, 4, REG_RESULT);
5068 i386_mov_membase_reg(REG_SP, 4 + 4, REG_RESULT2);
5070 i386_alu_imm_reg(I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5074 /* we can't use REG_ITMP3 == REG_RESULT2 */
5075 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5076 i386_push_reg(REG_RESULT);
5077 i386_push_reg(REG_RESULT2);
5078 i386_call_mem((s4) &callgetexceptionptrptr);
5079 i386_mov_membase_reg(REG_RESULT, 0, REG_ITMP2);
5080 i386_test_reg_reg(REG_ITMP2, REG_ITMP2);
5081 i386_pop_reg(REG_RESULT2);
5082 i386_pop_reg(REG_RESULT);
5084 i386_mov_imm_reg((s4) &_exceptionptr, REG_ITMP2);
5085 i386_mov_membase_reg(REG_ITMP2, 0, REG_ITMP2);
5086 i386_test_reg_reg(REG_ITMP2, REG_ITMP2);
5088 i386_jcc(I386_CC_NE, 1);
5092 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5093 i386_push_reg(REG_ITMP2);
5094 i386_call_mem((s4) &callgetexceptionptrptr);
5095 i386_mov_imm_membase(0, REG_RESULT, 0);
5096 i386_pop_reg(REG_ITMP1_XPTR);
5098 i386_mov_reg_reg(REG_ITMP2, REG_ITMP1_XPTR);
5099 i386_mov_imm_reg((s4) &_exceptionptr, REG_ITMP2);
5100 i386_mov_imm_membase(0, REG_ITMP2, 0);
5102 i386_mov_membase_reg(REG_SP, 0, REG_ITMP2_XPC);
5103 i386_alu_imm_reg(I386_SUB, 2, REG_ITMP2_XPC);
5105 i386_mov_imm_reg((s4) asm_handle_nat_exception, REG_ITMP3);
5106 i386_jmp_reg(REG_ITMP3);
5109 codegen_insertNative(s,mcodeptr);
5113 dolog_plain("native stubentry: %p, stubsize: %x (for %d params) --", (s4)s,(s4) (mcodeptr - s), m->paramcount);
5114 utf_display(m->name);
5118 #if defined(STATISTICS)
5120 count_nstub_len += NATIVESTUBSIZE;
5127 /* function: removenativestub **************************************************
5129 removes a previously created native-stub from memory
5131 *******************************************************************************/
5133 void removenativestub(u1 *stub)
5135 CFREE(stub, NATIVESTUBSIZE);
5140 * These are local overrides for various environment variables in Emacs.
5141 * Please do not remove this and leave it at the end of the file, where
5142 * Emacs will automagically detect them.
5143 * ---------------------------------------------------------------------
5146 * indent-tabs-mode: t