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 1258 2004-06-30 21:35:11Z twisti $
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 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
349 if (m->flags & ACC_STATIC) {
350 i386_mov_imm_reg((s4) m->class, REG_ITMP1);
351 i386_mov_reg_membase(REG_ITMP1, REG_SP, r->maxmemuse * 8);
354 i386_mov_membase_reg(REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
355 i386_mov_reg_membase(REG_ITMP1, REG_SP, r->maxmemuse * 8);
358 /* call monitorenter function */
360 i386_alu_imm_reg(I386_SUB, 4, REG_SP);
361 i386_mov_reg_membase(REG_ITMP1, REG_SP, 0);
362 i386_mov_imm_reg((s4) builtin_monitorenter, REG_ITMP1);
363 i386_call_reg(REG_ITMP1);
364 i386_alu_imm_reg(I386_ADD, 4, REG_SP);
368 /* copy argument registers to stack and call trace function with pointer
369 to arguments on stack.
373 i386_alu_imm_reg(I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
375 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
376 t = m->paramtypes[p];
378 if (IS_INT_LNG_TYPE(t)) {
379 if (IS_2_WORD_TYPE(t)) {
380 i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
381 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
382 i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
383 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
385 /* } else if (t == TYPE_ADR) { */
387 i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
388 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
389 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
390 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
393 /* i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
395 /* i386_mov_reg_membase(EAX, REG_SP, p * 8); */
396 /* i386_mov_reg_membase(EDX, REG_SP, p * 8 + 4); */
400 if (!IS_2_WORD_TYPE(t)) {
401 i386_flds_membase(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
402 i386_fstps_membase(REG_SP, p * 8);
403 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
404 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
407 i386_fldl_membase(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
408 i386_fstpl_membase(REG_SP, p * 8);
413 /* fill up the remaining arguments */
414 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
415 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
416 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
417 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
420 i386_mov_imm_membase((s4) m, REG_SP, TRACE_ARGS_NUM * 8);
421 i386_mov_imm_reg((s4) builtin_trace_args, REG_ITMP1);
422 i386_call_reg(REG_ITMP1);
424 i386_alu_imm_reg(I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
427 /* take arguments out of register or stack frame */
429 for (p = 0, l = 0; p < m->paramcount; p++) {
430 t = m->paramtypes[p];
431 var = &(r->locals[l][t]);
433 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
437 if (IS_INT_LNG_TYPE(t)) { /* integer args */
438 if (p < r->intreg_argnum) { /* register arguments */
439 panic("integer register argument");
440 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
441 /* M_INTMOVE (argintregs[p], r); */
443 } else { /* reg arg -> spilled */
444 /* M_LST (argintregs[p], REG_SP, 8 * r); */
446 } else { /* stack arguments */
447 pa = p - r->intreg_argnum;
448 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
449 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, var->regoff); /* + 4 for return address */
450 } else { /* stack arg -> spilled */
451 if (!IS_2_WORD_TYPE(t)) {
452 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
453 i386_mov_reg_membase(REG_ITMP1, REG_SP, var->regoff * 8);
456 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
457 i386_mov_reg_membase(REG_ITMP1, REG_SP, var->regoff * 8);
458 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1); /* + 4 for return address */
459 i386_mov_reg_membase(REG_ITMP1, REG_SP, var->regoff * 8 + 4);
464 } else { /* floating args */
465 if (p < r->fltreg_argnum) { /* register arguments */
466 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
467 panic("There are no float argument registers!");
469 } else { /* reg arg -> spilled */
470 panic("There are no float argument registers!");
473 } else { /* stack arguments */
474 pa = p - r->fltreg_argnum;
475 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
477 i386_flds_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
479 i386_fstp_reg(var->regoff + fpu_st_offset);
483 i386_fldl_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
485 i386_fstp_reg(var->regoff + fpu_st_offset);
489 } else { /* stack-arg -> spilled */
490 /* i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
491 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, r * 8); */
493 i386_flds_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
494 i386_fstps_membase(REG_SP, var->regoff * 8);
497 i386_fldl_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
498 i386_fstpl_membase(REG_SP, var->regoff * 8);
507 /* end of header generation */
509 /* walk through all basic blocks */
510 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
512 bptr->mpc = (s4) ((u1 *) mcodeptr - mcodebase);
514 if (bptr->flags >= BBREACHED) {
516 /* branch resolving */
519 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
520 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
521 brefs->branchpos, bptr->mpc);
524 /* copy interface registers to their destination */
529 while (src != NULL) {
531 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
532 if (!IS_2_WORD_TYPE(src->type)) {
533 if (bptr->type == BBTYPE_SBR) {
534 d = reg_of_var(m, src, REG_ITMP1);
536 store_reg_to_var_int(src, d);
538 } else if (bptr->type == BBTYPE_EXH) {
539 d = reg_of_var(m, src, REG_ITMP1);
540 M_INTMOVE(REG_ITMP1, d);
541 store_reg_to_var_int(src, d);
545 panic("copy interface registers: longs have to me in memory (begin 1)");
549 d = reg_of_var(m, src, REG_ITMP1);
550 if ((src->varkind != STACKVAR)) {
552 if (IS_FLT_DBL_TYPE(s2)) {
553 s1 = r->interfaces[len][s2].regoff;
554 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
558 if (s2 == TYPE_FLT) {
559 i386_flds_membase(REG_SP, s1 * 8);
562 i386_fldl_membase(REG_SP, s1 * 8);
565 store_reg_to_var_flt(src, d);
568 s1 = r->interfaces[len][s2].regoff;
569 if (!IS_2_WORD_TYPE(r->interfaces[len][s2].type)) {
570 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
574 i386_mov_membase_reg(REG_SP, s1 * 8, d);
576 store_reg_to_var_int(src, d);
579 if (r->interfaces[len][s2].flags & INMEMORY) {
580 M_LNGMEMMOVE(s1, src->regoff);
583 panic("copy interface registers: longs have to be in memory (begin 2)");
592 /* walk through all instructions */
596 for (iptr = bptr->iinstr;
598 src = iptr->dst, len--, iptr++) {
600 if (iptr->line!=currentline) {
601 dseg_addlinenumber(iptr->line,mcodeptr);
602 currentline=iptr->line;
604 MCODECHECK(64); /* an instruction usually needs < 64 words */
607 case ICMD_NOP: /* ... ==> ... */
610 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
611 if (src->flags & INMEMORY) {
612 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
615 i386_test_reg_reg(src->regoff, src->regoff);
617 i386_jcc(I386_CC_E, 0);
618 codegen_addxnullrefs(mcodeptr);
621 /* constant operations ************************************************/
623 case ICMD_ICONST: /* ... ==> ..., constant */
624 /* op1 = 0, val.i = constant */
626 d = reg_of_var(m, iptr->dst, REG_ITMP1);
627 if (iptr->dst->flags & INMEMORY) {
628 i386_mov_imm_membase(iptr->val.i, REG_SP, iptr->dst->regoff * 8);
631 if (iptr->val.i == 0) {
632 i386_alu_reg_reg(I386_XOR, d, d);
635 i386_mov_imm_reg(iptr->val.i, d);
640 case ICMD_LCONST: /* ... ==> ..., constant */
641 /* op1 = 0, val.l = constant */
643 d = reg_of_var(m, iptr->dst, REG_ITMP1);
644 if (iptr->dst->flags & INMEMORY) {
645 i386_mov_imm_membase(iptr->val.l, REG_SP, iptr->dst->regoff * 8);
646 i386_mov_imm_membase(iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
649 panic("LCONST: longs have to be in memory");
653 case ICMD_FCONST: /* ... ==> ..., constant */
654 /* op1 = 0, val.f = constant */
656 d = reg_of_var(m, iptr->dst, REG_FTMP1);
657 if (iptr->val.f == 0.0) {
662 if (iptr->val.i == 0x80000000) {
666 } else if (iptr->val.f == 1.0) {
670 } else if (iptr->val.f == 2.0) {
677 a = dseg_addfloat(iptr->val.f);
678 i386_mov_imm_reg(0, REG_ITMP1);
679 dseg_adddata(mcodeptr);
680 i386_flds_membase(REG_ITMP1, a);
683 store_reg_to_var_flt(iptr->dst, d);
686 case ICMD_DCONST: /* ... ==> ..., constant */
687 /* op1 = 0, val.d = constant */
689 d = reg_of_var(m, iptr->dst, REG_FTMP1);
690 if (iptr->val.d == 0.0) {
695 if (iptr->val.l == 0x8000000000000000LL) {
699 } else if (iptr->val.d == 1.0) {
703 } else if (iptr->val.d == 2.0) {
710 a = dseg_adddouble(iptr->val.d);
711 i386_mov_imm_reg(0, REG_ITMP1);
712 dseg_adddata(mcodeptr);
713 i386_fldl_membase(REG_ITMP1, a);
716 store_reg_to_var_flt(iptr->dst, d);
719 case ICMD_ACONST: /* ... ==> ..., constant */
720 /* op1 = 0, val.a = constant */
722 d = reg_of_var(m, iptr->dst, REG_ITMP1);
723 if (iptr->dst->flags & INMEMORY) {
724 i386_mov_imm_membase((s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
727 if ((s4) iptr->val.a == 0) {
728 i386_alu_reg_reg(I386_XOR, d, d);
731 i386_mov_imm_reg((s4) iptr->val.a, d);
737 /* load/store operations **********************************************/
739 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
740 case ICMD_ALOAD: /* op1 = local variable */
742 d = reg_of_var(m, iptr->dst, REG_ITMP1);
743 if ((iptr->dst->varkind == LOCALVAR) &&
744 (iptr->dst->varnum == iptr->op1)) {
747 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
748 if (iptr->dst->flags & INMEMORY) {
749 if (var->flags & INMEMORY) {
750 i386_mov_membase_reg(REG_SP, var->regoff * 8, REG_ITMP1);
751 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
754 i386_mov_reg_membase(var->regoff, REG_SP, iptr->dst->regoff * 8);
758 if (var->flags & INMEMORY) {
759 i386_mov_membase_reg(REG_SP, var->regoff * 8, iptr->dst->regoff);
762 M_INTMOVE(var->regoff, iptr->dst->regoff);
767 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
768 /* op1 = local variable */
770 d = reg_of_var(m, iptr->dst, REG_ITMP1);
771 if ((iptr->dst->varkind == LOCALVAR) &&
772 (iptr->dst->varnum == iptr->op1)) {
775 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
776 if (iptr->dst->flags & INMEMORY) {
777 if (var->flags & INMEMORY) {
778 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
781 panic("LLOAD: longs have to be in memory");
785 panic("LLOAD: longs have to be in memory");
789 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
790 /* op1 = local variable */
792 d = reg_of_var(m, iptr->dst, REG_FTMP1);
793 if ((iptr->dst->varkind == LOCALVAR) &&
794 (iptr->dst->varnum == iptr->op1)) {
797 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
798 if (var->flags & INMEMORY) {
799 i386_flds_membase(REG_SP, var->regoff * 8);
802 i386_fld_reg(var->regoff + fpu_st_offset);
805 store_reg_to_var_flt(iptr->dst, d);
808 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
809 /* op1 = local variable */
811 d = reg_of_var(m, iptr->dst, REG_FTMP1);
812 if ((iptr->dst->varkind == LOCALVAR) &&
813 (iptr->dst->varnum == iptr->op1)) {
816 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
817 if (var->flags & INMEMORY) {
818 i386_fldl_membase(REG_SP, var->regoff * 8);
821 i386_fld_reg(var->regoff + fpu_st_offset);
824 store_reg_to_var_flt(iptr->dst, d);
827 case ICMD_ISTORE: /* ..., value ==> ... */
828 case ICMD_ASTORE: /* op1 = local variable */
830 if ((src->varkind == LOCALVAR) &&
831 (src->varnum == iptr->op1)) {
834 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
835 if (var->flags & INMEMORY) {
836 if (src->flags & INMEMORY) {
837 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
838 i386_mov_reg_membase(REG_ITMP1, REG_SP, var->regoff * 8);
841 i386_mov_reg_membase(src->regoff, REG_SP, var->regoff * 8);
845 var_to_reg_int(s1, src, var->regoff);
846 M_INTMOVE(s1, var->regoff);
850 case ICMD_LSTORE: /* ..., value ==> ... */
851 /* op1 = local variable */
853 if ((src->varkind == LOCALVAR) &&
854 (src->varnum == iptr->op1)) {
857 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
858 if (var->flags & INMEMORY) {
859 if (src->flags & INMEMORY) {
860 M_LNGMEMMOVE(src->regoff, var->regoff);
863 panic("LSTORE: longs have to be in memory");
867 panic("LSTORE: longs have to be in memory");
871 case ICMD_FSTORE: /* ..., value ==> ... */
872 /* op1 = local variable */
874 if ((src->varkind == LOCALVAR) &&
875 (src->varnum == iptr->op1)) {
878 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
879 if (var->flags & INMEMORY) {
880 var_to_reg_flt(s1, src, REG_FTMP1);
881 i386_fstps_membase(REG_SP, var->regoff * 8);
884 var_to_reg_flt(s1, src, var->regoff);
885 /* M_FLTMOVE(s1, var->regoff); */
886 i386_fstp_reg(var->regoff + fpu_st_offset);
891 case ICMD_DSTORE: /* ..., value ==> ... */
892 /* op1 = local variable */
894 if ((src->varkind == LOCALVAR) &&
895 (src->varnum == iptr->op1)) {
898 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
899 if (var->flags & INMEMORY) {
900 var_to_reg_flt(s1, src, REG_FTMP1);
901 i386_fstpl_membase(REG_SP, var->regoff * 8);
904 var_to_reg_flt(s1, src, var->regoff);
905 /* M_FLTMOVE(s1, var->regoff); */
906 i386_fstp_reg(var->regoff + fpu_st_offset);
912 /* pop/dup/swap operations ********************************************/
914 /* attention: double and longs are only one entry in CACAO ICMDs */
916 case ICMD_POP: /* ..., value ==> ... */
917 case ICMD_POP2: /* ..., value, value ==> ... */
920 #define M_COPY(from,to) \
921 d = reg_of_var(m, to, REG_ITMP1); \
922 if ((from->regoff != to->regoff) || \
923 ((from->flags ^ to->flags) & INMEMORY)) { \
924 if (IS_FLT_DBL_TYPE(from->type)) { \
925 var_to_reg_flt(s1, from, d); \
926 /* M_FLTMOVE(s1, d);*/ \
927 store_reg_to_var_flt(to, d); \
929 if (!IS_2_WORD_TYPE(from->type)) { \
930 if (to->flags & INMEMORY) { \
931 if (from->flags & INMEMORY) { \
932 i386_mov_membase_reg(REG_SP, from->regoff * 8, REG_ITMP1); \
933 i386_mov_reg_membase(REG_ITMP1, REG_SP, to->regoff * 8); \
935 i386_mov_reg_membase(from->regoff, REG_SP, to->regoff * 8); \
938 if (from->flags & INMEMORY) { \
939 i386_mov_membase_reg(REG_SP, from->regoff * 8, to->regoff); \
941 i386_mov_reg_reg(from->regoff, to->regoff); \
945 M_LNGMEMMOVE(from->regoff, to->regoff); \
950 case ICMD_DUP: /* ..., a ==> ..., a, a */
951 M_COPY(src, iptr->dst);
954 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
956 M_COPY(src, iptr->dst->prev->prev);
958 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
960 M_COPY(src, iptr->dst);
961 M_COPY(src->prev, iptr->dst->prev);
964 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
966 M_COPY(src->prev, iptr->dst->prev->prev->prev);
968 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
970 M_COPY(src, iptr->dst);
971 M_COPY(src->prev, iptr->dst->prev);
972 M_COPY(src->prev->prev, iptr->dst->prev->prev);
973 M_COPY(src, iptr->dst->prev->prev->prev);
976 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
978 M_COPY(src, iptr->dst);
979 M_COPY(src->prev, iptr->dst->prev);
980 M_COPY(src->prev->prev, iptr->dst->prev->prev);
981 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
982 M_COPY(src, iptr->dst->prev->prev->prev->prev);
983 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
986 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
988 M_COPY(src, iptr->dst->prev);
989 M_COPY(src->prev, iptr->dst);
993 /* integer operations *************************************************/
995 case ICMD_INEG: /* ..., value ==> ..., - value */
997 d = reg_of_var(m, iptr->dst, REG_NULL);
998 if (iptr->dst->flags & INMEMORY) {
999 if (src->flags & INMEMORY) {
1000 if (src->regoff == iptr->dst->regoff) {
1001 i386_neg_membase(REG_SP, iptr->dst->regoff * 8);
1004 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1005 i386_neg_reg(REG_ITMP1);
1006 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1010 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1011 i386_neg_membase(REG_SP, iptr->dst->regoff * 8);
1015 if (src->flags & INMEMORY) {
1016 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1017 i386_neg_reg(iptr->dst->regoff);
1020 M_INTMOVE(src->regoff, iptr->dst->regoff);
1021 i386_neg_reg(iptr->dst->regoff);
1026 case ICMD_LNEG: /* ..., value ==> ..., - value */
1028 d = reg_of_var(m, iptr->dst, REG_NULL);
1029 if (iptr->dst->flags & INMEMORY) {
1030 if (src->flags & INMEMORY) {
1031 if (src->regoff == iptr->dst->regoff) {
1032 i386_neg_membase(REG_SP, iptr->dst->regoff * 8);
1033 i386_alu_imm_membase(I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1034 i386_neg_membase(REG_SP, iptr->dst->regoff * 8 + 4);
1037 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1038 i386_neg_reg(REG_ITMP1);
1039 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1040 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1041 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP1);
1042 i386_neg_reg(REG_ITMP1);
1043 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1049 case ICMD_I2L: /* ..., value ==> ..., value */
1051 d = reg_of_var(m, iptr->dst, REG_NULL);
1052 if (iptr->dst->flags & INMEMORY) {
1053 if (src->flags & INMEMORY) {
1054 i386_mov_membase_reg(REG_SP, src->regoff * 8, EAX);
1056 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1057 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1060 M_INTMOVE(src->regoff, EAX);
1062 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1063 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1068 case ICMD_L2I: /* ..., value ==> ..., value */
1070 d = reg_of_var(m, iptr->dst, REG_NULL);
1071 if (iptr->dst->flags & INMEMORY) {
1072 if (src->flags & INMEMORY) {
1073 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1074 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1078 if (src->flags & INMEMORY) {
1079 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1084 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1086 d = reg_of_var(m, iptr->dst, REG_NULL);
1087 if (iptr->dst->flags & INMEMORY) {
1088 if (src->flags & INMEMORY) {
1089 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1090 i386_shift_imm_reg(I386_SHL, 24, REG_ITMP1);
1091 i386_shift_imm_reg(I386_SAR, 24, REG_ITMP1);
1092 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1095 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1096 i386_shift_imm_membase(I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1097 i386_shift_imm_membase(I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1101 if (src->flags & INMEMORY) {
1102 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1103 i386_shift_imm_reg(I386_SHL, 24, iptr->dst->regoff);
1104 i386_shift_imm_reg(I386_SAR, 24, iptr->dst->regoff);
1107 M_INTMOVE(src->regoff, iptr->dst->regoff);
1108 i386_shift_imm_reg(I386_SHL, 24, iptr->dst->regoff);
1109 i386_shift_imm_reg(I386_SAR, 24, iptr->dst->regoff);
1114 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1116 d = reg_of_var(m, iptr->dst, REG_NULL);
1117 if (iptr->dst->flags & INMEMORY) {
1118 if (src->flags & INMEMORY) {
1119 if (src->regoff == iptr->dst->regoff) {
1120 i386_alu_imm_membase(I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1123 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1124 i386_alu_imm_reg(I386_AND, 0x0000ffff, REG_ITMP1);
1125 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1129 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1130 i386_alu_imm_membase(I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1134 if (src->flags & INMEMORY) {
1135 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1136 i386_alu_imm_reg(I386_AND, 0x0000ffff, iptr->dst->regoff);
1139 M_INTMOVE(src->regoff, iptr->dst->regoff);
1140 i386_alu_imm_reg(I386_AND, 0x0000ffff, iptr->dst->regoff);
1145 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1147 d = reg_of_var(m, iptr->dst, REG_NULL);
1148 if (iptr->dst->flags & INMEMORY) {
1149 if (src->flags & INMEMORY) {
1150 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1151 i386_shift_imm_reg(I386_SHL, 16, REG_ITMP1);
1152 i386_shift_imm_reg(I386_SAR, 16, REG_ITMP1);
1153 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1156 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1157 i386_shift_imm_membase(I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1158 i386_shift_imm_membase(I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1162 if (src->flags & INMEMORY) {
1163 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1164 i386_shift_imm_reg(I386_SHL, 16, iptr->dst->regoff);
1165 i386_shift_imm_reg(I386_SAR, 16, iptr->dst->regoff);
1168 M_INTMOVE(src->regoff, iptr->dst->regoff);
1169 i386_shift_imm_reg(I386_SHL, 16, iptr->dst->regoff);
1170 i386_shift_imm_reg(I386_SAR, 16, iptr->dst->regoff);
1176 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1178 d = reg_of_var(m, iptr->dst, REG_NULL);
1179 i386_emit_ialu(I386_ADD, src, iptr);
1182 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1183 /* val.i = constant */
1185 d = reg_of_var(m, iptr->dst, REG_NULL);
1186 /* should we use a inc optimization for smaller code size? */
1187 i386_emit_ialuconst(I386_ADD, src, iptr);
1190 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1192 d = reg_of_var(m, iptr->dst, REG_NULL);
1193 if (iptr->dst->flags & INMEMORY) {
1194 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1195 if (src->regoff == iptr->dst->regoff) {
1196 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1197 i386_alu_reg_membase(I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1198 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1199 i386_alu_reg_membase(I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1201 } else if (src->prev->regoff == iptr->dst->regoff) {
1202 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1203 i386_alu_reg_membase(I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1204 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1205 i386_alu_reg_membase(I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1208 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1209 i386_alu_membase_reg(I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1210 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1211 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1212 i386_alu_membase_reg(I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1213 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1220 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1221 /* val.l = constant */
1223 d = reg_of_var(m, iptr->dst, REG_NULL);
1224 if (iptr->dst->flags & INMEMORY) {
1225 if (src->flags & INMEMORY) {
1226 if (src->regoff == iptr->dst->regoff) {
1227 i386_alu_imm_membase(I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1228 i386_alu_imm_membase(I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1231 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1232 i386_alu_imm_reg(I386_ADD, iptr->val.l, REG_ITMP1);
1233 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1234 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1235 i386_alu_imm_reg(I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1236 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1242 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1244 d = reg_of_var(m, iptr->dst, REG_NULL);
1245 if (iptr->dst->flags & INMEMORY) {
1246 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1247 if (src->prev->regoff == iptr->dst->regoff) {
1248 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1249 i386_alu_reg_membase(I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1252 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1253 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1254 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1257 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1258 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1259 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1260 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1262 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1263 if (src->prev->regoff == iptr->dst->regoff) {
1264 i386_alu_reg_membase(I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1267 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1268 i386_alu_reg_reg(I386_SUB, src->regoff, REG_ITMP1);
1269 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1273 i386_mov_reg_membase(src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1274 i386_alu_reg_membase(I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1278 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1279 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, d);
1280 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, d);
1282 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1283 M_INTMOVE(src->prev->regoff, d);
1284 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, d);
1286 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1287 /* workaround for reg alloc */
1288 if (src->regoff == iptr->dst->regoff) {
1289 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1290 i386_alu_reg_reg(I386_SUB, src->regoff, REG_ITMP1);
1291 M_INTMOVE(REG_ITMP1, d);
1294 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, d);
1295 i386_alu_reg_reg(I386_SUB, src->regoff, d);
1299 /* workaround for reg alloc */
1300 if (src->regoff == iptr->dst->regoff) {
1301 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1302 i386_alu_reg_reg(I386_SUB, src->regoff, REG_ITMP1);
1303 M_INTMOVE(REG_ITMP1, d);
1306 M_INTMOVE(src->prev->regoff, d);
1307 i386_alu_reg_reg(I386_SUB, src->regoff, d);
1313 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1314 /* val.i = constant */
1316 d = reg_of_var(m, iptr->dst, REG_NULL);
1317 i386_emit_ialuconst(I386_SUB, src, iptr);
1320 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1322 d = reg_of_var(m, iptr->dst, REG_NULL);
1323 if (iptr->dst->flags & INMEMORY) {
1324 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1325 if (src->prev->regoff == iptr->dst->regoff) {
1326 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1327 i386_alu_reg_membase(I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1328 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1329 i386_alu_reg_membase(I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1332 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1333 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1334 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1335 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1336 i386_alu_membase_reg(I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1337 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1343 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1344 /* val.l = constant */
1346 d = reg_of_var(m, iptr->dst, REG_NULL);
1347 if (iptr->dst->flags & INMEMORY) {
1348 if (src->flags & INMEMORY) {
1349 if (src->regoff == iptr->dst->regoff) {
1350 i386_alu_imm_membase(I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1351 i386_alu_imm_membase(I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1354 /* TODO: could be size optimized with lea -- see gcc output */
1355 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1356 i386_alu_imm_reg(I386_SUB, iptr->val.l, REG_ITMP1);
1357 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1358 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1359 i386_alu_imm_reg(I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1360 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1366 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1368 d = reg_of_var(m, iptr->dst, REG_NULL);
1369 if (iptr->dst->flags & INMEMORY) {
1370 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1371 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1372 i386_imul_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1373 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1375 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1376 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1377 i386_imul_reg_reg(src->prev->regoff, REG_ITMP1);
1378 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1380 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1381 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1382 i386_imul_reg_reg(src->regoff, REG_ITMP1);
1383 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1386 i386_mov_reg_reg(src->prev->regoff, REG_ITMP1);
1387 i386_imul_reg_reg(src->regoff, REG_ITMP1);
1388 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1392 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1393 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1394 i386_imul_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1396 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1397 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1398 i386_imul_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1400 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1401 M_INTMOVE(src->regoff, iptr->dst->regoff);
1402 i386_imul_membase_reg(REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1405 if (src->regoff == iptr->dst->regoff) {
1406 i386_imul_reg_reg(src->prev->regoff, iptr->dst->regoff);
1409 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1410 i386_imul_reg_reg(src->regoff, iptr->dst->regoff);
1416 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1417 /* val.i = constant */
1419 d = reg_of_var(m, iptr->dst, REG_NULL);
1420 if (iptr->dst->flags & INMEMORY) {
1421 if (src->flags & INMEMORY) {
1422 i386_imul_imm_membase_reg(iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1423 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1426 i386_imul_imm_reg_reg(iptr->val.i, src->regoff, REG_ITMP1);
1427 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1431 if (src->flags & INMEMORY) {
1432 i386_imul_imm_membase_reg(iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1435 i386_imul_imm_reg_reg(iptr->val.i, src->regoff, iptr->dst->regoff);
1440 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1442 d = reg_of_var(m, iptr->dst, REG_NULL);
1443 if (iptr->dst->flags & INMEMORY) {
1444 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1445 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, EAX); /* mem -> EAX */
1446 /* optimize move EAX -> REG_ITMP3 is slower??? */
1447 /* i386_mov_reg_reg(EAX, REG_ITMP3); */
1448 i386_mul_membase(REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1450 /* TODO: optimize move EAX -> REG_ITMP3 */
1451 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); /* mem -> ITMP3 */
1452 i386_imul_membase_reg(REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1453 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1455 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP2); /* mem -> ITMP3 */
1456 i386_imul_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1458 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1459 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1460 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1465 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1466 /* val.l = constant */
1468 d = reg_of_var(m, iptr->dst, REG_NULL);
1469 if (iptr->dst->flags & INMEMORY) {
1470 if (src->flags & INMEMORY) {
1471 i386_mov_imm_reg(iptr->val.l, EAX); /* imm -> EAX */
1472 i386_mul_membase(REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1473 /* TODO: optimize move EAX -> REG_ITMP3 */
1474 i386_mov_imm_reg(iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1475 i386_imul_membase_reg(REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1477 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1478 i386_mov_imm_reg(iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1479 i386_imul_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1481 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1482 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1483 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1488 #define gen_div_check(v) \
1490 if ((v)->flags & INMEMORY) { \
1491 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8); \
1493 i386_test_reg_reg(src->regoff, src->regoff); \
1495 i386_jcc(I386_CC_E, 0); \
1496 codegen_addxdivrefs(mcodeptr); \
1499 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1501 d = reg_of_var(m, iptr->dst, REG_NULL);
1502 var_to_reg_int(s1, src, REG_ITMP2);
1504 if (src->prev->flags & INMEMORY) {
1505 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, EAX);
1508 M_INTMOVE(src->prev->regoff, EAX);
1511 i386_alu_imm_reg(I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1512 i386_jcc(I386_CC_NE, 3 + 6);
1513 i386_alu_imm_reg(I386_CMP, -1, s1);
1514 i386_jcc(I386_CC_E, 1 + 2);
1519 if (iptr->dst->flags & INMEMORY) {
1520 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1523 M_INTMOVE(EAX, iptr->dst->regoff);
1527 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1529 d = reg_of_var(m, iptr->dst, REG_NULL);
1530 var_to_reg_int(s1, src, REG_ITMP2);
1532 if (src->prev->flags & INMEMORY) {
1533 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, EAX);
1536 M_INTMOVE(src->prev->regoff, EAX);
1539 i386_alu_imm_reg(I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1540 i386_jcc(I386_CC_NE, 2 + 3 + 6);
1541 i386_alu_reg_reg(I386_XOR, EDX, EDX);
1542 i386_alu_imm_reg(I386_CMP, -1, s1);
1543 i386_jcc(I386_CC_E, 1 + 2);
1548 if (iptr->dst->flags & INMEMORY) {
1549 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8);
1552 M_INTMOVE(EDX, iptr->dst->regoff);
1556 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1557 /* val.i = constant */
1559 /* TODO: optimize for `/ 2' */
1560 var_to_reg_int(s1, src, REG_ITMP1);
1561 d = reg_of_var(m, iptr->dst, REG_ITMP1);
1564 i386_test_reg_reg(d, d);
1566 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1567 i386_jcc(I386_CC_NS, a);
1568 i386_alu_imm_reg(I386_ADD, (1 << iptr->val.i) - 1, d);
1570 i386_shift_imm_reg(I386_SAR, iptr->val.i, d);
1571 store_reg_to_var_int(iptr->dst, d);
1574 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1575 /* val.i = constant */
1577 d = reg_of_var(m, iptr->dst, REG_NULL);
1578 if (iptr->dst->flags & INMEMORY) {
1579 if (src->flags & INMEMORY) {
1581 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1583 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1584 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1586 i386_test_reg_reg(REG_ITMP2, REG_ITMP2);
1587 i386_jcc(I386_CC_NS, a);
1588 i386_alu_imm_reg(I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1589 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP2);
1590 i386_shrd_imm_reg_reg(iptr->val.i, REG_ITMP2, REG_ITMP1);
1591 i386_shift_imm_reg(I386_SAR, iptr->val.i, REG_ITMP2);
1593 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1594 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1599 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1600 /* val.i = constant */
1602 var_to_reg_int(s1, src, REG_ITMP1);
1603 d = reg_of_var(m, iptr->dst, REG_ITMP2);
1605 M_INTMOVE(s1, REG_ITMP1);
1612 CALCIMMEDIATEBYTES(a, iptr->val.i);
1615 /* TODO: optimize */
1617 i386_alu_imm_reg(I386_AND, iptr->val.i, d);
1618 i386_test_reg_reg(s1, s1);
1619 i386_jcc(I386_CC_GE, a);
1620 i386_mov_reg_reg(s1, d);
1622 i386_alu_imm_reg(I386_AND, iptr->val.i, d);
1625 /* M_INTMOVE(s1, EAX); */
1627 /* i386_alu_reg_reg(I386_XOR, EDX, EAX); */
1628 /* i386_alu_reg_reg(I386_SUB, EDX, EAX); */
1629 /* i386_alu_reg_reg(I386_AND, iptr->val.i, EAX); */
1630 /* i386_alu_reg_reg(I386_XOR, EDX, EAX); */
1631 /* i386_alu_reg_reg(I386_SUB, EDX, EAX); */
1632 /* M_INTMOVE(EAX, d); */
1634 /* i386_alu_reg_reg(I386_XOR, d, d); */
1635 /* i386_mov_imm_reg(iptr->val.i, ECX); */
1636 /* i386_shrd_reg_reg(s1, d); */
1637 /* i386_shift_imm_reg(I386_SHR, 32 - iptr->val.i, d); */
1639 store_reg_to_var_int(iptr->dst, d);
1642 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1643 /* val.l = constant */
1645 d = reg_of_var(m, iptr->dst, REG_NULL);
1646 if (iptr->dst->flags & INMEMORY) {
1647 if (src->flags & INMEMORY) {
1648 /* Intel algorithm -- does not work, because constant is wrong */
1649 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1); */
1650 /* i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1652 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1653 /* i386_test_reg_reg(REG_ITMP3, REG_ITMP3); */
1654 /* i386_jcc(I386_CC_NS, offset); */
1655 /* i386_alu_imm_reg(I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1656 /* i386_alu_imm_reg(I386_ADC, 0, REG_ITMP3); */
1658 /* i386_shrd_imm_reg_reg(iptr->val.l, REG_ITMP3, REG_ITMP2); */
1659 /* i386_shift_imm_reg(I386_SAR, iptr->val.l, REG_ITMP3); */
1660 /* i386_shld_imm_reg_reg(iptr->val.l, REG_ITMP2, REG_ITMP3); */
1662 /* i386_shift_imm_reg(I386_SHL, iptr->val.l, REG_ITMP2); */
1664 /* i386_alu_reg_reg(I386_SUB, REG_ITMP2, REG_ITMP1); */
1665 /* i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1666 /* i386_alu_reg_reg(I386_SBB, REG_ITMP3, REG_ITMP2); */
1668 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1669 /* i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1671 /* Alpha algorithm */
1673 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1675 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1681 /* TODO: hmm, don't know if this is always correct */
1683 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1685 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1691 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1692 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1694 i386_alu_imm_reg(I386_AND, iptr->val.l, REG_ITMP1);
1695 i386_alu_imm_reg(I386_AND, iptr->val.l >> 32, REG_ITMP2);
1696 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1697 i386_jcc(I386_CC_GE, a);
1699 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1700 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1702 i386_neg_reg(REG_ITMP1);
1703 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP2);
1704 i386_neg_reg(REG_ITMP2);
1706 i386_alu_imm_reg(I386_AND, iptr->val.l, REG_ITMP1);
1707 i386_alu_imm_reg(I386_AND, iptr->val.l >> 32, REG_ITMP2);
1709 i386_neg_reg(REG_ITMP1);
1710 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP2);
1711 i386_neg_reg(REG_ITMP2);
1713 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1714 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1719 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1721 d = reg_of_var(m, iptr->dst, REG_NULL);
1722 i386_emit_ishift(I386_SHL, src, iptr);
1725 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1726 /* val.i = constant */
1728 d = reg_of_var(m, iptr->dst, REG_NULL);
1729 i386_emit_ishiftconst(I386_SHL, src, iptr);
1732 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1734 d = reg_of_var(m, iptr->dst, REG_NULL);
1735 i386_emit_ishift(I386_SAR, src, iptr);
1738 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1739 /* val.i = constant */
1741 d = reg_of_var(m, iptr->dst, REG_NULL);
1742 i386_emit_ishiftconst(I386_SAR, src, iptr);
1745 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1747 d = reg_of_var(m, iptr->dst, REG_NULL);
1748 i386_emit_ishift(I386_SHR, src, iptr);
1751 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1752 /* val.i = constant */
1754 d = reg_of_var(m, iptr->dst, REG_NULL);
1755 i386_emit_ishiftconst(I386_SHR, src, iptr);
1758 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1760 d = reg_of_var(m, iptr->dst, REG_NULL);
1761 if (iptr->dst->flags & INMEMORY ){
1762 if (src->prev->flags & INMEMORY) {
1763 /* if (src->prev->regoff == iptr->dst->regoff) { */
1764 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1766 /* if (src->flags & INMEMORY) { */
1767 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX); */
1769 /* M_INTMOVE(src->regoff, ECX); */
1772 /* i386_test_imm_reg(32, ECX); */
1773 /* i386_jcc(I386_CC_E, 2 + 2); */
1774 /* i386_mov_reg_reg(REG_ITMP1, REG_ITMP2); */
1775 /* i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1); */
1777 /* i386_shld_reg_membase(REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1778 /* i386_shift_membase(I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1781 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1782 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1784 if (src->flags & INMEMORY) {
1785 i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX);
1787 M_INTMOVE(src->regoff, ECX);
1790 i386_test_imm_reg(32, ECX);
1791 i386_jcc(I386_CC_E, 2 + 2);
1792 i386_mov_reg_reg(REG_ITMP1, REG_ITMP3);
1793 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
1795 i386_shld_reg_reg(REG_ITMP1, REG_ITMP3);
1796 i386_shift_reg(I386_SHL, REG_ITMP1);
1797 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1798 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1804 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1805 /* val.i = constant */
1807 d = reg_of_var(m, iptr->dst, REG_NULL);
1808 if (iptr->dst->flags & INMEMORY ) {
1809 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1810 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1812 if (iptr->val.i & 0x20) {
1813 i386_mov_reg_reg(REG_ITMP1, REG_ITMP2);
1814 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
1815 i386_shld_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1818 i386_shld_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1819 i386_shift_imm_reg(I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1822 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1823 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1827 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1829 d = reg_of_var(m, iptr->dst, REG_NULL);
1830 if (iptr->dst->flags & INMEMORY ){
1831 if (src->prev->flags & INMEMORY) {
1832 /* if (src->prev->regoff == iptr->dst->regoff) { */
1833 /* TODO: optimize */
1834 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1835 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1837 /* if (src->flags & INMEMORY) { */
1838 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX); */
1840 /* M_INTMOVE(src->regoff, ECX); */
1843 /* i386_test_imm_reg(32, ECX); */
1844 /* i386_jcc(I386_CC_E, 2 + 3); */
1845 /* i386_mov_reg_reg(REG_ITMP2, REG_ITMP1); */
1846 /* i386_shift_imm_reg(I386_SAR, 31, REG_ITMP2); */
1848 /* i386_shrd_reg_reg(REG_ITMP2, REG_ITMP1); */
1849 /* i386_shift_reg(I386_SAR, REG_ITMP2); */
1850 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1851 /* i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1854 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1855 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1857 if (src->flags & INMEMORY) {
1858 i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX);
1860 M_INTMOVE(src->regoff, ECX);
1863 i386_test_imm_reg(32, ECX);
1864 i386_jcc(I386_CC_E, 2 + 3);
1865 i386_mov_reg_reg(REG_ITMP3, REG_ITMP1);
1866 i386_shift_imm_reg(I386_SAR, 31, REG_ITMP3);
1868 i386_shrd_reg_reg(REG_ITMP3, REG_ITMP1);
1869 i386_shift_reg(I386_SAR, REG_ITMP3);
1870 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1871 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1877 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1878 /* val.i = constant */
1880 d = reg_of_var(m, iptr->dst, REG_NULL);
1881 if (iptr->dst->flags & INMEMORY ) {
1882 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1883 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1885 if (iptr->val.i & 0x20) {
1886 i386_mov_reg_reg(REG_ITMP2, REG_ITMP1);
1887 i386_shift_imm_reg(I386_SAR, 31, REG_ITMP2);
1888 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1891 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1892 i386_shift_imm_reg(I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1895 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1896 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1900 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1902 d = reg_of_var(m, iptr->dst, REG_NULL);
1903 if (iptr->dst->flags & INMEMORY ){
1904 if (src->prev->flags & INMEMORY) {
1905 /* if (src->prev->regoff == iptr->dst->regoff) { */
1906 /* TODO: optimize */
1907 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1908 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1910 /* if (src->flags & INMEMORY) { */
1911 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX); */
1913 /* M_INTMOVE(src->regoff, ECX); */
1916 /* i386_test_imm_reg(32, ECX); */
1917 /* i386_jcc(I386_CC_E, 2 + 2); */
1918 /* i386_mov_reg_reg(REG_ITMP2, REG_ITMP1); */
1919 /* i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2); */
1921 /* i386_shrd_reg_reg(REG_ITMP2, REG_ITMP1); */
1922 /* i386_shift_reg(I386_SHR, REG_ITMP2); */
1923 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1924 /* i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1927 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1928 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1930 if (src->flags & INMEMORY) {
1931 i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX);
1933 M_INTMOVE(src->regoff, ECX);
1936 i386_test_imm_reg(32, ECX);
1937 i386_jcc(I386_CC_E, 2 + 2);
1938 i386_mov_reg_reg(REG_ITMP3, REG_ITMP1);
1939 i386_alu_reg_reg(I386_XOR, REG_ITMP3, REG_ITMP3);
1941 i386_shrd_reg_reg(REG_ITMP3, REG_ITMP1);
1942 i386_shift_reg(I386_SHR, REG_ITMP3);
1943 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1944 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1950 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1951 /* val.l = constant */
1953 d = reg_of_var(m, iptr->dst, REG_NULL);
1954 if (iptr->dst->flags & INMEMORY ) {
1955 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1956 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1958 if (iptr->val.i & 0x20) {
1959 i386_mov_reg_reg(REG_ITMP2, REG_ITMP1);
1960 i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2);
1961 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1964 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1965 i386_shift_imm_reg(I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
1968 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1969 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1973 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1975 d = reg_of_var(m, iptr->dst, REG_NULL);
1976 i386_emit_ialu(I386_AND, src, iptr);
1979 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1980 /* val.i = constant */
1982 d = reg_of_var(m, iptr->dst, REG_NULL);
1983 i386_emit_ialuconst(I386_AND, src, iptr);
1986 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1988 d = reg_of_var(m, iptr->dst, REG_NULL);
1989 i386_emit_lalu(I386_AND, src, iptr);
1992 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1993 /* val.l = constant */
1995 d = reg_of_var(m, iptr->dst, REG_NULL);
1996 i386_emit_laluconst(I386_AND, src, iptr);
1999 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2001 d = reg_of_var(m, iptr->dst, REG_NULL);
2002 i386_emit_ialu(I386_OR, src, iptr);
2005 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2006 /* val.i = constant */
2008 d = reg_of_var(m, iptr->dst, REG_NULL);
2009 i386_emit_ialuconst(I386_OR, src, iptr);
2012 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2014 d = reg_of_var(m, iptr->dst, REG_NULL);
2015 i386_emit_lalu(I386_OR, src, iptr);
2018 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2019 /* val.l = constant */
2021 d = reg_of_var(m, iptr->dst, REG_NULL);
2022 i386_emit_laluconst(I386_OR, src, iptr);
2025 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2027 d = reg_of_var(m, iptr->dst, REG_NULL);
2028 i386_emit_ialu(I386_XOR, src, iptr);
2031 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2032 /* val.i = constant */
2034 d = reg_of_var(m, iptr->dst, REG_NULL);
2035 i386_emit_ialuconst(I386_XOR, src, iptr);
2038 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2040 d = reg_of_var(m, iptr->dst, REG_NULL);
2041 i386_emit_lalu(I386_XOR, src, iptr);
2044 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2045 /* val.l = constant */
2047 d = reg_of_var(m, iptr->dst, REG_NULL);
2048 i386_emit_laluconst(I386_XOR, src, iptr);
2051 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2052 /* op1 = variable, val.i = constant */
2054 var = &(r->locals[iptr->op1][TYPE_INT]);
2055 if (var->flags & INMEMORY) {
2056 i386_alu_imm_membase(I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2059 i386_alu_imm_reg(I386_ADD, iptr->val.i, var->regoff);
2064 /* floating operations ************************************************/
2066 #define ROUND_TO_SINGLE \
2067 i386_fstps_membase(REG_SP, -8); \
2068 i386_flds_membase(REG_SP, -8);
2070 #define ROUND_TO_DOUBLE \
2071 i386_fstpl_membase(REG_SP, -8); \
2072 i386_fldl_membase(REG_SP, -8);
2074 #define FPU_SET_24BIT_MODE \
2075 if (!fpu_in_24bit_mode) { \
2076 i386_fldcw_mem(&fpu_ctrlwrd_24bit); \
2077 fpu_in_24bit_mode = 1; \
2080 #define FPU_SET_53BIT_MODE \
2081 if (fpu_in_24bit_mode) { \
2082 i386_fldcw_mem(&fpu_ctrlwrd_53bit); \
2083 fpu_in_24bit_mode = 0; \
2086 #define ROUND_TO_SINGLE
2087 #define ROUND_TO_DOUBLE
2088 #define FPU_SET_24BIT_MODE
2089 #define FPU_SET_53BIT_MODE
2091 case ICMD_FNEG: /* ..., value ==> ..., - value */
2094 var_to_reg_flt(s1, src, REG_FTMP1);
2095 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2097 store_reg_to_var_flt(iptr->dst, d);
2100 case ICMD_DNEG: /* ..., value ==> ..., - value */
2103 var_to_reg_flt(s1, src, REG_FTMP1);
2104 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2106 store_reg_to_var_flt(iptr->dst, d);
2109 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2112 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2113 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2114 var_to_reg_flt(s2, src, REG_FTMP2);
2117 store_reg_to_var_flt(iptr->dst, d);
2120 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2123 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2124 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2125 var_to_reg_flt(s2, src, REG_FTMP2);
2128 store_reg_to_var_flt(iptr->dst, d);
2131 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2134 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2135 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2136 var_to_reg_flt(s2, src, REG_FTMP2);
2139 store_reg_to_var_flt(iptr->dst, d);
2142 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2145 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2146 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2147 var_to_reg_flt(s2, src, REG_FTMP2);
2150 store_reg_to_var_flt(iptr->dst, d);
2153 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2156 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2157 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2158 var_to_reg_flt(s2, src, REG_FTMP2);
2162 store_reg_to_var_flt(iptr->dst, d);
2165 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2168 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2169 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2171 /* i386_fldt_mem(subnormal_bias1); */
2174 var_to_reg_flt(s2, src, REG_FTMP2);
2179 /* i386_fldt_mem(subnormal_bias2); */
2182 store_reg_to_var_flt(iptr->dst, d);
2185 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2188 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2189 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2190 var_to_reg_flt(s2, src, REG_FTMP2);
2194 store_reg_to_var_flt(iptr->dst, d);
2197 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2200 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2201 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2203 /* i386_fldt_mem(subnormal_bias1); */
2206 var_to_reg_flt(s2, src, REG_FTMP2);
2211 /* i386_fldt_mem(subnormal_bias2); */
2214 store_reg_to_var_flt(iptr->dst, d);
2217 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2220 /* exchanged to skip fxch */
2221 var_to_reg_flt(s2, src, REG_FTMP2);
2222 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2223 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2229 i386_jcc(I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2230 store_reg_to_var_flt(iptr->dst, d);
2236 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2239 /* exchanged to skip fxch */
2240 var_to_reg_flt(s2, src, REG_FTMP2);
2241 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2242 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2248 i386_jcc(I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2249 store_reg_to_var_flt(iptr->dst, d);
2255 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2256 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2258 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2259 if (src->flags & INMEMORY) {
2260 i386_fildl_membase(REG_SP, src->regoff * 8);
2265 i386_mov_imm_reg(0, REG_ITMP1);
2266 dseg_adddata(mcodeptr);
2267 i386_mov_reg_membase(src->regoff, REG_ITMP1, a);
2268 i386_fildl_membase(REG_ITMP1, a);
2271 store_reg_to_var_flt(iptr->dst, d);
2274 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2275 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2277 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2278 if (src->flags & INMEMORY) {
2279 i386_fildll_membase(REG_SP, src->regoff * 8);
2283 panic("L2F: longs have to be in memory");
2285 store_reg_to_var_flt(iptr->dst, d);
2288 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2290 var_to_reg_flt(s1, src, REG_FTMP1);
2291 d = reg_of_var(m, iptr->dst, REG_NULL);
2293 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2294 i386_mov_imm_reg(0, REG_ITMP1);
2295 dseg_adddata(mcodeptr);
2296 i386_fldcw_membase(REG_ITMP1, a);
2298 if (iptr->dst->flags & INMEMORY) {
2299 i386_fistpl_membase(REG_SP, iptr->dst->regoff * 8);
2302 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2303 i386_fldcw_membase(REG_ITMP1, a);
2305 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2308 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2310 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2314 i386_fistpl_membase(REG_ITMP1, a);
2316 i386_mov_membase_reg(REG_ITMP1, a, iptr->dst->regoff);
2318 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2319 i386_fldcw_membase(REG_ITMP1, a);
2321 i386_alu_imm_reg(I386_CMP, 0x80000000, iptr->dst->regoff);
2324 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2325 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2328 i386_jcc(I386_CC_NE, a);
2330 /* XXX: change this when we use registers */
2331 i386_flds_membase(REG_SP, src->regoff * 8);
2332 i386_mov_imm_reg((s4) asm_builtin_f2i, REG_ITMP1);
2333 i386_call_reg(REG_ITMP1);
2335 if (iptr->dst->flags & INMEMORY) {
2336 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2339 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2343 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2345 var_to_reg_flt(s1, src, REG_FTMP1);
2346 d = reg_of_var(m, iptr->dst, REG_NULL);
2348 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2349 i386_mov_imm_reg(0, REG_ITMP1);
2350 dseg_adddata(mcodeptr);
2351 i386_fldcw_membase(REG_ITMP1, a);
2353 if (iptr->dst->flags & INMEMORY) {
2354 i386_fistpl_membase(REG_SP, iptr->dst->regoff * 8);
2357 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2358 i386_fldcw_membase(REG_ITMP1, a);
2360 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2363 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2365 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2369 i386_fistpl_membase(REG_ITMP1, a);
2371 i386_mov_membase_reg(REG_ITMP1, a, iptr->dst->regoff);
2373 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2374 i386_fldcw_membase(REG_ITMP1, a);
2376 i386_alu_imm_reg(I386_CMP, 0x80000000, iptr->dst->regoff);
2379 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2380 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2383 i386_jcc(I386_CC_NE, a);
2385 /* XXX: change this when we use registers */
2386 i386_fldl_membase(REG_SP, src->regoff * 8);
2387 i386_mov_imm_reg((s4) asm_builtin_d2i, REG_ITMP1);
2388 i386_call_reg(REG_ITMP1);
2390 if (iptr->dst->flags & INMEMORY) {
2391 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2393 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2397 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2399 var_to_reg_flt(s1, src, REG_FTMP1);
2400 d = reg_of_var(m, iptr->dst, REG_NULL);
2402 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2403 i386_mov_imm_reg(0, REG_ITMP1);
2404 dseg_adddata(mcodeptr);
2405 i386_fldcw_membase(REG_ITMP1, a);
2407 if (iptr->dst->flags & INMEMORY) {
2408 i386_fistpll_membase(REG_SP, iptr->dst->regoff * 8);
2411 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2412 i386_fldcw_membase(REG_ITMP1, a);
2414 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2417 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2419 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2422 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2424 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2426 i386_jcc(I386_CC_NE, a);
2428 i386_alu_imm_membase(I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2431 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2433 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2435 i386_jcc(I386_CC_NE, a);
2437 /* XXX: change this when we use registers */
2438 i386_flds_membase(REG_SP, src->regoff * 8);
2439 i386_mov_imm_reg((s4) asm_builtin_f2l, REG_ITMP1);
2440 i386_call_reg(REG_ITMP1);
2441 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2442 i386_mov_reg_membase(REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2445 panic("F2L: longs have to be in memory");
2449 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2451 var_to_reg_flt(s1, src, REG_FTMP1);
2452 d = reg_of_var(m, iptr->dst, REG_NULL);
2454 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2455 i386_mov_imm_reg(0, REG_ITMP1);
2456 dseg_adddata(mcodeptr);
2457 i386_fldcw_membase(REG_ITMP1, a);
2459 if (iptr->dst->flags & INMEMORY) {
2460 i386_fistpll_membase(REG_SP, iptr->dst->regoff * 8);
2463 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2464 i386_fldcw_membase(REG_ITMP1, a);
2466 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2469 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2471 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2474 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2476 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2478 i386_jcc(I386_CC_NE, a);
2480 i386_alu_imm_membase(I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2483 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2485 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2487 i386_jcc(I386_CC_NE, a);
2489 /* XXX: change this when we use registers */
2490 i386_fldl_membase(REG_SP, src->regoff * 8);
2491 i386_mov_imm_reg((s4) asm_builtin_d2l, REG_ITMP1);
2492 i386_call_reg(REG_ITMP1);
2493 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2494 i386_mov_reg_membase(REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2497 panic("D2L: longs have to be in memory");
2501 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2503 var_to_reg_flt(s1, src, REG_FTMP1);
2504 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2506 store_reg_to_var_flt(iptr->dst, d);
2509 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2511 var_to_reg_flt(s1, src, REG_FTMP1);
2512 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2514 store_reg_to_var_flt(iptr->dst, d);
2517 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2520 /* exchanged to skip fxch */
2521 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2522 var_to_reg_flt(s1, src, REG_FTMP2);
2523 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2528 i386_test_imm_reg(0x400, EAX); /* unordered treat as GT */
2529 i386_jcc(I386_CC_E, 6);
2530 i386_alu_imm_reg(I386_AND, 0x000000ff, EAX);
2532 i386_mov_imm_reg(0, d); /* does not affect flags */
2533 i386_jcc(I386_CC_E, 6 + 3 + 5 + 3);
2534 i386_jcc(I386_CC_B, 3 + 5);
2535 i386_alu_imm_reg(I386_SUB, 1, d);
2537 i386_alu_imm_reg(I386_ADD, 1, d);
2538 store_reg_to_var_int(iptr->dst, d);
2541 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2544 /* exchanged to skip fxch */
2545 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2546 var_to_reg_flt(s1, src, REG_FTMP2);
2547 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2552 i386_test_imm_reg(0x400, EAX); /* unordered treat as LT */
2553 i386_jcc(I386_CC_E, 3);
2554 i386_movb_imm_reg(1, I386_AH);
2556 i386_mov_imm_reg(0, d); /* does not affect flags */
2557 i386_jcc(I386_CC_E, 6 + 3 + 5 + 3);
2558 i386_jcc(I386_CC_B, 3 + 5);
2559 i386_alu_imm_reg(I386_SUB, 1, d);
2561 i386_alu_imm_reg(I386_ADD, 1, d);
2562 store_reg_to_var_int(iptr->dst, d);
2566 /* memory operations **************************************************/
2568 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2570 var_to_reg_int(s1, src, REG_ITMP1);
2571 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2572 gen_nullptr_check(s1);
2573 i386_mov_membase_reg(s1, OFFSET(java_arrayheader, size), d);
2574 store_reg_to_var_int(iptr->dst, d);
2577 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2579 var_to_reg_int(s1, src->prev, REG_ITMP1);
2580 var_to_reg_int(s2, src, REG_ITMP2);
2581 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2582 if (iptr->op1 == 0) {
2583 gen_nullptr_check(s1);
2586 i386_mov_memindex_reg(OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2587 store_reg_to_var_int(iptr->dst, d);
2590 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2592 var_to_reg_int(s1, src->prev, REG_ITMP1);
2593 var_to_reg_int(s2, src, REG_ITMP2);
2594 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2595 if (iptr->op1 == 0) {
2596 gen_nullptr_check(s1);
2600 if (iptr->dst->flags & INMEMORY) {
2601 i386_mov_memindex_reg(OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2602 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2603 i386_mov_memindex_reg(OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2604 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2608 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2610 var_to_reg_int(s1, src->prev, REG_ITMP1);
2611 var_to_reg_int(s2, src, REG_ITMP2);
2612 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2613 if (iptr->op1 == 0) {
2614 gen_nullptr_check(s1);
2617 i386_mov_memindex_reg(OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2618 store_reg_to_var_int(iptr->dst, d);
2621 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2623 var_to_reg_int(s1, src->prev, REG_ITMP1);
2624 var_to_reg_int(s2, src, REG_ITMP2);
2625 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2626 if (iptr->op1 == 0) {
2627 gen_nullptr_check(s1);
2630 i386_flds_memindex(OFFSET(java_floatarray, data[0]), s1, s2, 2);
2632 store_reg_to_var_flt(iptr->dst, d);
2635 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2637 var_to_reg_int(s1, src->prev, REG_ITMP1);
2638 var_to_reg_int(s2, src, REG_ITMP2);
2639 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2640 if (iptr->op1 == 0) {
2641 gen_nullptr_check(s1);
2644 i386_fldl_memindex(OFFSET(java_doublearray, data[0]), s1, s2, 3);
2646 store_reg_to_var_flt(iptr->dst, d);
2649 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2651 var_to_reg_int(s1, src->prev, REG_ITMP1);
2652 var_to_reg_int(s2, src, REG_ITMP2);
2653 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2654 if (iptr->op1 == 0) {
2655 gen_nullptr_check(s1);
2658 i386_movzwl_memindex_reg(OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2659 store_reg_to_var_int(iptr->dst, d);
2662 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2664 var_to_reg_int(s1, src->prev, REG_ITMP1);
2665 var_to_reg_int(s2, src, REG_ITMP2);
2666 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2667 if (iptr->op1 == 0) {
2668 gen_nullptr_check(s1);
2671 i386_movswl_memindex_reg(OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2672 store_reg_to_var_int(iptr->dst, d);
2675 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2677 var_to_reg_int(s1, src->prev, REG_ITMP1);
2678 var_to_reg_int(s2, src, REG_ITMP2);
2679 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2680 if (iptr->op1 == 0) {
2681 gen_nullptr_check(s1);
2684 i386_movsbl_memindex_reg(OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2685 store_reg_to_var_int(iptr->dst, d);
2689 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2691 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2692 var_to_reg_int(s2, src->prev, REG_ITMP2);
2693 if (iptr->op1 == 0) {
2694 gen_nullptr_check(s1);
2697 var_to_reg_int(s3, src, REG_ITMP3);
2698 i386_mov_reg_memindex(s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2701 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2703 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2704 var_to_reg_int(s2, src->prev, REG_ITMP2);
2705 if (iptr->op1 == 0) {
2706 gen_nullptr_check(s1);
2710 if (src->flags & INMEMORY) {
2711 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP3);
2712 i386_mov_reg_memindex(REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2713 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2714 i386_mov_reg_memindex(REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2718 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2720 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2721 var_to_reg_int(s2, src->prev, REG_ITMP2);
2722 if (iptr->op1 == 0) {
2723 gen_nullptr_check(s1);
2726 var_to_reg_int(s3, src, REG_ITMP3);
2727 i386_mov_reg_memindex(s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2730 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2732 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2733 var_to_reg_int(s2, src->prev, REG_ITMP2);
2734 if (iptr->op1 == 0) {
2735 gen_nullptr_check(s1);
2738 var_to_reg_flt(s3, src, REG_FTMP1);
2739 i386_fstps_memindex(OFFSET(java_floatarray, data[0]), s1, s2, 2);
2743 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2745 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2746 var_to_reg_int(s2, src->prev, REG_ITMP2);
2747 if (iptr->op1 == 0) {
2748 gen_nullptr_check(s1);
2751 var_to_reg_flt(s3, src, REG_FTMP1);
2752 i386_fstpl_memindex(OFFSET(java_doublearray, data[0]), s1, s2, 3);
2756 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2759 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2760 var_to_reg_int(s2, src->prev, REG_ITMP2);
2761 if (iptr->op1 == 0) {
2762 gen_nullptr_check(s1);
2765 var_to_reg_int(s3, src, REG_ITMP3);
2766 i386_movw_reg_memindex(s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2769 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2771 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2772 var_to_reg_int(s2, src->prev, REG_ITMP2);
2773 if (iptr->op1 == 0) {
2774 gen_nullptr_check(s1);
2777 var_to_reg_int(s3, src, REG_ITMP3);
2778 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2779 M_INTMOVE(s3, REG_ITMP3);
2782 i386_movb_reg_memindex(s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2785 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2787 var_to_reg_int(s1, src->prev, REG_ITMP1);
2788 var_to_reg_int(s2, src, REG_ITMP2);
2789 if (iptr->op1 == 0) {
2790 gen_nullptr_check(s1);
2793 i386_mov_imm_memindex(iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 2);
2796 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2798 var_to_reg_int(s1, src->prev, REG_ITMP1);
2799 var_to_reg_int(s2, src, REG_ITMP2);
2800 if (iptr->op1 == 0) {
2801 gen_nullptr_check(s1);
2805 i386_mov_imm_memindex((u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2806 i386_mov_imm_memindex((u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2809 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2811 var_to_reg_int(s1, src->prev, REG_ITMP1);
2812 var_to_reg_int(s2, src, REG_ITMP2);
2813 if (iptr->op1 == 0) {
2814 gen_nullptr_check(s1);
2817 i386_mov_imm_memindex(0, OFFSET(java_bytearray, data[0]), s1, s2, 2);
2820 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2822 var_to_reg_int(s1, src->prev, REG_ITMP1);
2823 var_to_reg_int(s2, src, REG_ITMP2);
2824 if (iptr->op1 == 0) {
2825 gen_nullptr_check(s1);
2828 i386_movb_imm_memindex(iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2831 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2832 case ICMD_SASTORECONST:
2834 var_to_reg_int(s1, src->prev, REG_ITMP1);
2835 var_to_reg_int(s2, src, REG_ITMP2);
2836 if (iptr->op1 == 0) {
2837 gen_nullptr_check(s1);
2840 i386_movw_imm_memindex(iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 1);
2844 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2845 /* op1 = type, val.a = field address */
2847 /* if class isn't yet initialized, do it */
2848 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2849 /* call helper function which patches this code */
2850 i386_mov_imm_reg((s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2851 i386_mov_imm_reg((s4) asm_check_clinit, REG_ITMP2);
2852 i386_call_reg(REG_ITMP2);
2855 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2856 /* here it's slightly slower */
2857 i386_mov_imm_reg(0, REG_ITMP2);
2858 dseg_adddata(mcodeptr);
2859 i386_mov_membase_reg(REG_ITMP2, a, REG_ITMP2);
2860 switch (iptr->op1) {
2863 var_to_reg_int(s2, src, REG_ITMP1);
2864 i386_mov_reg_membase(s2, REG_ITMP2, 0);
2867 if (src->flags & INMEMORY) {
2868 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
2869 i386_mov_reg_membase(REG_ITMP1, REG_ITMP2, 0);
2870 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
2871 i386_mov_reg_membase(REG_ITMP1, REG_ITMP2, 0 + 4);
2873 panic("PUTSTATIC: longs have to be in memory");
2877 var_to_reg_flt(s2, src, REG_FTMP1);
2878 i386_fstps_membase(REG_ITMP2, 0);
2882 var_to_reg_flt(s2, src, REG_FTMP1);
2883 i386_fstpl_membase(REG_ITMP2, 0);
2886 default: panic ("internal error");
2890 case ICMD_GETSTATIC: /* ... ==> ..., value */
2891 /* op1 = type, val.a = field address */
2893 /* if class isn't yet initialized, do it */
2894 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2895 /* call helper function which patches this code */
2896 i386_mov_imm_reg((s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2897 i386_mov_imm_reg((s4) asm_check_clinit, REG_ITMP2);
2898 i386_call_reg(REG_ITMP2);
2901 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2902 i386_mov_imm_reg(0, REG_ITMP2);
2903 dseg_adddata(mcodeptr);
2904 i386_mov_membase_reg(REG_ITMP2, a, REG_ITMP2);
2905 switch (iptr->op1) {
2908 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2909 i386_mov_membase_reg(REG_ITMP2, 0, d);
2910 store_reg_to_var_int(iptr->dst, d);
2913 d = reg_of_var(m, iptr->dst, REG_NULL);
2914 if (iptr->dst->flags & INMEMORY) {
2915 i386_mov_membase_reg(REG_ITMP2, 0, REG_ITMP1);
2916 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2917 i386_mov_membase_reg(REG_ITMP2, 0 + 4, REG_ITMP1);
2918 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
2920 panic("GETSTATIC: longs have to be in memory");
2924 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2925 i386_flds_membase(REG_ITMP2, 0);
2927 store_reg_to_var_flt(iptr->dst, d);
2930 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2931 i386_fldl_membase(REG_ITMP2, 0);
2933 store_reg_to_var_flt(iptr->dst, d);
2935 default: panic ("internal error");
2939 case ICMD_PUTFIELD: /* ..., value ==> ... */
2940 /* op1 = type, val.i = field offset */
2942 a = ((fieldinfo *)(iptr->val.a))->offset;
2943 switch (iptr->op1) {
2946 var_to_reg_int(s1, src->prev, REG_ITMP1);
2947 var_to_reg_int(s2, src, REG_ITMP2);
2948 gen_nullptr_check(s1);
2949 i386_mov_reg_membase(s2, s1, a);
2952 var_to_reg_int(s1, src->prev, REG_ITMP1);
2953 gen_nullptr_check(s1);
2954 if (src->flags & INMEMORY) {
2955 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP2);
2956 i386_mov_reg_membase(REG_ITMP2, s1, a);
2957 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2958 i386_mov_reg_membase(REG_ITMP2, s1, a + 4);
2960 panic("PUTFIELD: longs have to be in memory");
2964 var_to_reg_int(s1, src->prev, REG_ITMP1);
2965 var_to_reg_flt(s2, src, REG_FTMP1);
2966 gen_nullptr_check(s1);
2967 i386_fstps_membase(s1, a);
2971 var_to_reg_int(s1, src->prev, REG_ITMP1);
2972 var_to_reg_flt(s2, src, REG_FTMP1);
2973 gen_nullptr_check(s1);
2974 i386_fstpl_membase(s1, a);
2977 default: panic ("internal error");
2981 case ICMD_GETFIELD: /* ... ==> ..., value */
2982 /* op1 = type, val.i = field offset */
2984 a = ((fieldinfo *)(iptr->val.a))->offset;
2985 switch (iptr->op1) {
2988 var_to_reg_int(s1, src, REG_ITMP1);
2989 d = reg_of_var(m, iptr->dst, REG_ITMP2);
2990 gen_nullptr_check(s1);
2991 i386_mov_membase_reg(s1, a, d);
2992 store_reg_to_var_int(iptr->dst, d);
2995 var_to_reg_int(s1, src, REG_ITMP1);
2996 d = reg_of_var(m, iptr->dst, REG_NULL);
2997 gen_nullptr_check(s1);
2998 i386_mov_membase_reg(s1, a, REG_ITMP2);
2999 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
3000 i386_mov_membase_reg(s1, a + 4, REG_ITMP2);
3001 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
3004 var_to_reg_int(s1, src, REG_ITMP1);
3005 d = reg_of_var(m, iptr->dst, REG_FTMP1);
3006 gen_nullptr_check(s1);
3007 i386_flds_membase(s1, a);
3009 store_reg_to_var_flt(iptr->dst, d);
3012 var_to_reg_int(s1, src, REG_ITMP1);
3013 d = reg_of_var(m, iptr->dst, REG_FTMP1);
3014 gen_nullptr_check(s1);
3015 i386_fldl_membase(s1, a);
3017 store_reg_to_var_flt(iptr->dst, d);
3019 default: panic ("internal error");
3024 /* branch operations **************************************************/
3027 /* #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}} */
3028 #define ALIGNCODENOP do {} while (0)
3030 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3032 var_to_reg_int(s1, src, REG_ITMP1);
3033 M_INTMOVE(s1, REG_ITMP1_XPTR);
3035 i386_call_imm(0); /* passing exception pointer */
3036 i386_pop_reg(REG_ITMP2_XPC);
3038 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
3039 i386_jmp_reg(REG_ITMP3);
3043 case ICMD_GOTO: /* ... ==> ... */
3044 /* op1 = target JavaVM pc */
3047 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3051 case ICMD_JSR: /* ... ==> ... */
3052 /* op1 = target JavaVM pc */
3055 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3058 case ICMD_RET: /* ... ==> ... */
3059 /* op1 = local variable */
3061 var = &(r->locals[iptr->op1][TYPE_ADR]);
3062 var_to_reg_int(s1, var, REG_ITMP1);
3066 case ICMD_IFNULL: /* ..., value ==> ... */
3067 /* op1 = target JavaVM pc */
3069 if (src->flags & INMEMORY) {
3070 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
3073 i386_test_reg_reg(src->regoff, src->regoff);
3075 i386_jcc(I386_CC_E, 0);
3076 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3079 case ICMD_IFNONNULL: /* ..., value ==> ... */
3080 /* op1 = target JavaVM pc */
3082 if (src->flags & INMEMORY) {
3083 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
3086 i386_test_reg_reg(src->regoff, src->regoff);
3088 i386_jcc(I386_CC_NE, 0);
3089 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3092 case ICMD_IFEQ: /* ..., value ==> ... */
3093 /* op1 = target JavaVM pc, val.i = constant */
3095 if (src->flags & INMEMORY) {
3096 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3099 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3101 i386_jcc(I386_CC_E, 0);
3102 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3105 case ICMD_IFLT: /* ..., value ==> ... */
3106 /* op1 = target JavaVM pc, val.i = constant */
3108 if (src->flags & INMEMORY) {
3109 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3112 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3114 i386_jcc(I386_CC_L, 0);
3115 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3118 case ICMD_IFLE: /* ..., value ==> ... */
3119 /* op1 = target JavaVM pc, val.i = constant */
3121 if (src->flags & INMEMORY) {
3122 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3125 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3127 i386_jcc(I386_CC_LE, 0);
3128 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3131 case ICMD_IFNE: /* ..., value ==> ... */
3132 /* op1 = target JavaVM pc, val.i = constant */
3134 if (src->flags & INMEMORY) {
3135 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3138 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3140 i386_jcc(I386_CC_NE, 0);
3141 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3144 case ICMD_IFGT: /* ..., value ==> ... */
3145 /* op1 = target JavaVM pc, val.i = constant */
3147 if (src->flags & INMEMORY) {
3148 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3151 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3153 i386_jcc(I386_CC_G, 0);
3154 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3157 case ICMD_IFGE: /* ..., value ==> ... */
3158 /* op1 = target JavaVM pc, val.i = constant */
3160 if (src->flags & INMEMORY) {
3161 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3164 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3166 i386_jcc(I386_CC_GE, 0);
3167 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3170 case ICMD_IF_LEQ: /* ..., value ==> ... */
3171 /* op1 = target JavaVM pc, val.l = constant */
3173 if (src->flags & INMEMORY) {
3174 if (iptr->val.l == 0) {
3175 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3176 i386_alu_membase_reg(I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3179 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3180 i386_alu_imm_reg(I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3181 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3182 i386_alu_imm_reg(I386_XOR, iptr->val.l, REG_ITMP1);
3183 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3186 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3187 i386_jcc(I386_CC_E, 0);
3188 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3191 case ICMD_IF_LLT: /* ..., value ==> ... */
3192 /* op1 = target JavaVM pc, val.l = constant */
3194 if (src->flags & INMEMORY) {
3195 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3196 i386_jcc(I386_CC_L, 0);
3197 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3200 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3201 CALCIMMEDIATEBYTES(a, iptr->val.l);
3203 i386_jcc(I386_CC_G, a);
3205 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3206 i386_jcc(I386_CC_B, 0);
3207 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3211 case ICMD_IF_LLE: /* ..., value ==> ... */
3212 /* op1 = target JavaVM pc, val.l = constant */
3214 if (src->flags & INMEMORY) {
3215 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3216 i386_jcc(I386_CC_L, 0);
3217 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3220 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3221 CALCIMMEDIATEBYTES(a, iptr->val.l);
3223 i386_jcc(I386_CC_G, a);
3225 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3226 i386_jcc(I386_CC_BE, 0);
3227 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3231 case ICMD_IF_LNE: /* ..., value ==> ... */
3232 /* op1 = target JavaVM pc, val.l = constant */
3234 if (src->flags & INMEMORY) {
3235 if (iptr->val.l == 0) {
3236 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3237 i386_alu_membase_reg(I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3240 i386_mov_imm_reg(iptr->val.l, REG_ITMP1);
3241 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3242 i386_mov_imm_reg(iptr->val.l >> 32, REG_ITMP2);
3243 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3244 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3247 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3248 i386_jcc(I386_CC_NE, 0);
3249 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3252 case ICMD_IF_LGT: /* ..., value ==> ... */
3253 /* op1 = target JavaVM pc, val.l = constant */
3255 if (src->flags & INMEMORY) {
3256 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3257 i386_jcc(I386_CC_G, 0);
3258 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3261 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3262 CALCIMMEDIATEBYTES(a, iptr->val.l);
3264 i386_jcc(I386_CC_L, a);
3266 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3267 i386_jcc(I386_CC_A, 0);
3268 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3272 case ICMD_IF_LGE: /* ..., value ==> ... */
3273 /* op1 = target JavaVM pc, val.l = constant */
3275 if (src->flags & INMEMORY) {
3276 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3277 i386_jcc(I386_CC_G, 0);
3278 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3281 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3282 CALCIMMEDIATEBYTES(a, iptr->val.l);
3284 i386_jcc(I386_CC_L, a);
3286 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3287 i386_jcc(I386_CC_AE, 0);
3288 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3292 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3293 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3295 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3296 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3297 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3299 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3300 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3302 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3303 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3306 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3308 i386_jcc(I386_CC_E, 0);
3309 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3312 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3313 /* op1 = target JavaVM pc */
3315 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3316 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3317 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3318 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3319 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3320 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3321 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3323 i386_jcc(I386_CC_E, 0);
3324 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3327 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3328 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3330 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3331 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3332 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3334 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3335 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3337 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3338 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3341 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3343 i386_jcc(I386_CC_NE, 0);
3344 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3347 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3348 /* op1 = target JavaVM pc */
3350 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3351 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3352 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3353 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3354 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3355 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3356 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3358 i386_jcc(I386_CC_NE, 0);
3359 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3362 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3363 /* op1 = target JavaVM pc */
3365 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3366 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3367 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3369 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3370 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3372 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3373 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3376 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3378 i386_jcc(I386_CC_L, 0);
3379 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3382 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3383 /* op1 = target JavaVM pc */
3385 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3386 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3387 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3388 i386_jcc(I386_CC_L, 0);
3389 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3392 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3393 CALCOFFSETBYTES(a, REG_SP, src->regoff);
3395 i386_jcc(I386_CC_G, a);
3397 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3398 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3399 i386_jcc(I386_CC_B, 0);
3400 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3404 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3405 /* op1 = target JavaVM pc */
3407 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3408 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3409 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3411 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3412 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3414 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3415 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3418 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3420 i386_jcc(I386_CC_G, 0);
3421 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3424 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3425 /* op1 = target JavaVM pc */
3427 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3428 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3429 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3430 i386_jcc(I386_CC_G, 0);
3431 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3434 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3435 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3437 i386_jcc(I386_CC_L, a);
3439 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3440 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3441 i386_jcc(I386_CC_A, 0);
3442 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3446 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3447 /* op1 = target JavaVM pc */
3449 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3450 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3451 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3453 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3454 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3456 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3457 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3460 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3462 i386_jcc(I386_CC_LE, 0);
3463 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3466 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3467 /* op1 = target JavaVM pc */
3469 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3470 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3471 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3472 i386_jcc(I386_CC_L, 0);
3473 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3476 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3477 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3479 i386_jcc(I386_CC_G, a);
3481 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3482 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3483 i386_jcc(I386_CC_BE, 0);
3484 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3488 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3489 /* op1 = target JavaVM pc */
3491 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3492 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3493 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3495 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3496 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3498 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3499 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3502 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3504 i386_jcc(I386_CC_GE, 0);
3505 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3508 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3509 /* op1 = target JavaVM pc */
3511 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3512 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3513 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3514 i386_jcc(I386_CC_G, 0);
3515 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3518 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3519 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3521 i386_jcc(I386_CC_L, a);
3523 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3524 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3525 i386_jcc(I386_CC_AE, 0);
3526 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3530 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3532 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3535 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3536 /* val.i = constant */
3538 d = reg_of_var(m, iptr->dst, REG_NULL);
3539 i386_emit_ifcc_iconst(I386_CC_NE, src, iptr);
3542 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3543 /* val.i = constant */
3545 d = reg_of_var(m, iptr->dst, REG_NULL);
3546 i386_emit_ifcc_iconst(I386_CC_E, src, iptr);
3549 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3550 /* val.i = constant */
3552 d = reg_of_var(m, iptr->dst, REG_NULL);
3553 i386_emit_ifcc_iconst(I386_CC_GE, src, iptr);
3556 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3557 /* val.i = constant */
3559 d = reg_of_var(m, iptr->dst, REG_NULL);
3560 i386_emit_ifcc_iconst(I386_CC_L, src, iptr);
3563 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3564 /* val.i = constant */
3566 d = reg_of_var(m, iptr->dst, REG_NULL);
3567 i386_emit_ifcc_iconst(I386_CC_LE, src, iptr);
3570 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3571 /* val.i = constant */
3573 d = reg_of_var(m, iptr->dst, REG_NULL);
3574 i386_emit_ifcc_iconst(I386_CC_G, src, iptr);
3578 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3581 var_to_reg_int(s1, src, REG_RESULT);
3582 M_INTMOVE(s1, REG_RESULT);
3584 goto nowperformreturn;
3586 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3588 if (src->flags & INMEMORY) {
3589 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_RESULT);
3590 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3593 panic("LRETURN: longs have to be in memory");
3596 goto nowperformreturn;
3598 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3599 case ICMD_DRETURN: /* ..., retvalue ==> ... */
3601 var_to_reg_flt(s1, src, REG_FRESULT);
3602 /* this may be an early return -- keep the offset correct for the
3606 goto nowperformreturn;
3608 case ICMD_RETURN: /* ... ==> ... */
3614 p = parentargs_base;
3616 /* call trace function */
3618 i386_alu_imm_reg(I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3620 i386_mov_imm_membase((s4) m, REG_SP, 0);
3622 i386_mov_reg_membase(REG_RESULT, REG_SP, 4);
3623 i386_mov_reg_membase(REG_RESULT2, REG_SP, 4 + 4);
3625 i386_fstl_membase(REG_SP, 4 + 8);
3626 i386_fsts_membase(REG_SP, 4 + 8 + 8);
3628 i386_mov_imm_reg((s4) builtin_displaymethodstop, REG_ITMP1);
3629 i386_call_reg(REG_ITMP1);
3631 i386_mov_membase_reg(REG_SP, 4, REG_RESULT);
3632 i386_mov_membase_reg(REG_SP, 4 + 4, REG_RESULT2);
3634 i386_alu_imm_reg(I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3637 #if defined(USE_THREADS)
3638 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3639 i386_mov_membase_reg(REG_SP, 8 * r->maxmemuse, REG_ITMP2);
3641 /* we need to save the proper return value */
3642 switch (iptr->opc) {
3645 i386_mov_reg_membase(REG_RESULT, REG_SP, r->maxmemuse * 8);
3649 i386_mov_reg_membase(REG_RESULT, REG_SP, r->maxmemuse * 8);
3650 i386_mov_reg_membase(REG_RESULT2, REG_SP, r->maxmemuse * 8 + 4);
3654 i386_fsts_membase(REG_SP, r->maxmemuse * 8);
3658 i386_fstl_membase(REG_SP, r->maxmemuse * 8);
3662 i386_alu_imm_reg(I386_SUB, 4, REG_SP);
3663 i386_mov_reg_membase(REG_ITMP2, REG_SP, 0);
3664 i386_mov_imm_reg((s4) builtin_monitorexit, REG_ITMP1);
3665 i386_call_reg(REG_ITMP1);
3666 i386_alu_imm_reg(I386_ADD, 4, REG_SP);
3668 /* and now restore the proper return value */
3669 switch (iptr->opc) {
3672 i386_mov_membase_reg(REG_SP, r->maxmemuse * 8, REG_RESULT);
3676 i386_mov_membase_reg(REG_SP, r->maxmemuse * 8, REG_RESULT);
3677 i386_mov_membase_reg(REG_SP, r->maxmemuse * 8 + 4, REG_RESULT2);
3681 i386_flds_membase(REG_SP, r->maxmemuse * 8);
3685 i386_fldl_membase(REG_SP, r->maxmemuse * 8);
3691 /* restore saved registers */
3692 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
3694 i386_mov_membase_reg(REG_SP, p * 8, r->savintregs[i]);
3696 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
3698 i386_fldl_membase(REG_SP, p * 8);
3700 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3701 i386_fstp_reg(r->savfltregs[i] + fpu_st_offset + 1);
3703 i386_fstp_reg(r->savfltregs[i] + fpu_st_offset);
3708 /* deallocate stack */
3709 if (parentargs_base) {
3710 i386_alu_imm_reg(I386_ADD, parentargs_base * 8, REG_SP);
3719 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3724 tptr = (void **) iptr->target;
3726 s4ptr = iptr->val.a;
3727 l = s4ptr[1]; /* low */
3728 i = s4ptr[2]; /* high */
3730 var_to_reg_int(s1, src, REG_ITMP1);
3731 M_INTMOVE(s1, REG_ITMP1);
3733 i386_alu_imm_reg(I386_SUB, l, REG_ITMP1);
3739 i386_alu_imm_reg(I386_CMP, i - 1, REG_ITMP1);
3740 i386_jcc(I386_CC_A, 0);
3742 /* codegen_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr); */
3743 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3745 /* build jump table top down and use address of lowest entry */
3747 /* s4ptr += 3 + i; */
3751 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3752 dseg_addtarget((basicblock *) tptr[0]);
3756 /* length of dataseg after last dseg_addtarget is used by load */
3758 i386_mov_imm_reg(0, REG_ITMP2);
3759 dseg_adddata(mcodeptr);
3760 i386_mov_memindex_reg(-dseglen, REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3761 i386_jmp_reg(REG_ITMP1);
3767 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3769 s4 i, l, val, *s4ptr;
3772 tptr = (void **) iptr->target;
3774 s4ptr = iptr->val.a;
3775 l = s4ptr[0]; /* default */
3776 i = s4ptr[1]; /* count */
3778 MCODECHECK((i<<2)+8);
3779 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3785 i386_alu_imm_reg(I386_CMP, val, s1);
3786 i386_jcc(I386_CC_E, 0);
3787 /* codegen_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr); */
3788 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3792 /* codegen_addreference(BlockPtrOfPC(l), mcodeptr); */
3794 tptr = (void **) iptr->target;
3795 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3802 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3803 /* op1 = return type, val.a = function pointer*/
3807 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3808 /* op1 = return type, val.a = function pointer*/
3812 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3813 /* op1 = return type, val.a = function pointer*/
3817 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3818 /* op1 = arg count, val.a = method pointer */
3820 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3821 /* op1 = arg count, val.a = method pointer */
3823 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3824 /* op1 = arg count, val.a = method pointer */
3826 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3827 /* op1 = arg count, val.a = method pointer */
3835 MCODECHECK((s3 << 1) + 64);
3837 /* copy arguments to registers or stack location */
3839 for (; --s3 >= 0; src = src->prev) {
3840 if (src->varkind == ARGVAR) {
3844 if (IS_INT_LNG_TYPE(src->type)) {
3845 if (s3 < r->intreg_argnum) {
3846 panic("No integer argument registers available!");
3849 if (!IS_2_WORD_TYPE(src->type)) {
3850 if (src->flags & INMEMORY) {
3851 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3852 i386_mov_reg_membase(REG_ITMP1, REG_SP, s3 * 8);
3855 i386_mov_reg_membase(src->regoff, REG_SP, s3 * 8);
3859 if (src->flags & INMEMORY) {
3860 M_LNGMEMMOVE(src->regoff, s3);
3863 panic("copy arguments: longs have to be in memory");
3869 if (s3 < r->fltreg_argnum) {
3870 panic("No float argument registers available!");
3873 var_to_reg_flt(d, src, REG_FTMP1);
3874 if (src->type == TYPE_FLT) {
3875 i386_fstps_membase(REG_SP, s3 * 8);
3878 i386_fstpl_membase(REG_SP, s3 * 8);
3885 switch (iptr->opc) {
3893 i386_mov_imm_reg(a, REG_ITMP1);
3894 i386_call_reg(REG_ITMP1);
3897 case ICMD_INVOKESTATIC:
3899 a = (u4) lm->stubroutine;
3902 i386_mov_imm_reg(a, REG_ITMP2);
3903 i386_call_reg(REG_ITMP2);
3906 case ICMD_INVOKESPECIAL:
3908 a = (u4) lm->stubroutine;
3911 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1);
3912 gen_nullptr_check(REG_ITMP1);
3913 i386_mov_membase_reg(REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
3915 i386_mov_imm_reg(a, REG_ITMP2);
3916 i386_call_reg(REG_ITMP2);
3919 case ICMD_INVOKEVIRTUAL:
3923 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1);
3924 gen_nullptr_check(REG_ITMP1);
3925 i386_mov_membase_reg(REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
3926 i386_mov_membase32_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
3928 i386_call_reg(REG_ITMP1);
3931 case ICMD_INVOKEINTERFACE:
3936 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1);
3937 gen_nullptr_check(REG_ITMP1);
3938 i386_mov_membase_reg(REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3939 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - sizeof(methodptr) * ci->index, REG_ITMP2);
3940 i386_mov_membase32_reg(REG_ITMP2, sizeof(methodptr) * (lm - ci->methods), REG_ITMP1);
3942 i386_call_reg(REG_ITMP1);
3947 error("Unkown ICMD-Command: %d", iptr->opc);
3950 /* d contains return type */
3952 if (d != TYPE_VOID) {
3953 d = reg_of_var(m, iptr->dst, REG_NULL);
3955 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3956 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3957 if (iptr->dst->flags & INMEMORY) {
3958 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3959 i386_mov_reg_membase(REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
3962 panic("RETURN: longs have to be in memory");
3966 if (iptr->dst->flags & INMEMORY) {
3967 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3970 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
3975 /* fld from called function -- has other fpu_st_offset counter */
3977 store_reg_to_var_flt(iptr->dst, d);
3984 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3986 /* op1: 0 == array, 1 == class */
3987 /* val.a: (classinfo*) superclass */
3989 /* superclass is an interface:
3991 * return (sub != NULL) &&
3992 * (sub->vftbl->interfacetablelength > super->index) &&
3993 * (sub->vftbl->interfacetable[-super->index] != NULL);
3995 * superclass is a class:
3997 * return ((sub != NULL) && (0
3998 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3999 * super->vftbl->diffvall));
4003 classinfo *super = (classinfo*) iptr->val.a;
4005 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4006 codegen_threadcritrestart(mcodeptr - mcodebase);
4008 var_to_reg_int(s1, src, REG_ITMP1);
4009 d = reg_of_var(m, iptr->dst, REG_ITMP3);
4011 M_INTMOVE(s1, REG_ITMP1);
4014 i386_alu_reg_reg(I386_XOR, d, d);
4015 if (iptr->op1) { /* class/interface */
4016 if (super->flags & ACC_INTERFACE) { /* interface */
4017 i386_test_reg_reg(s1, s1);
4019 /* TODO: clean up this calculation */
4021 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4024 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
4027 /* CALCOFFSETBYTES(a, super->index); */
4028 CALCIMMEDIATEBYTES(a, super->index);
4034 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*));
4041 i386_jcc(I386_CC_E, a);
4043 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4044 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetablelength), REG_ITMP2);
4045 i386_alu_imm_reg(I386_SUB, super->index, REG_ITMP2);
4047 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP2);
4049 /* TODO: clean up this calculation */
4052 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*));
4059 i386_jcc(I386_CC_LE, a);
4060 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4062 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP1);
4063 /* i386_setcc_reg(I386_CC_A, d); */
4064 /* i386_jcc(I386_CC_BE, 5); */
4065 i386_jcc(I386_CC_E, 5);
4066 i386_mov_imm_reg(1, d);
4069 } else { /* class */
4070 i386_test_reg_reg(s1, s1);
4072 /* TODO: clean up this calculation */
4074 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4077 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, baseval));
4079 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, baseval));
4082 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, diffval));
4092 i386_jcc(I386_CC_E, a);
4094 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4095 i386_mov_imm_reg((s4) super->vftbl, REG_ITMP2);
4096 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4097 codegen_threadcritstart(mcodeptr - mcodebase);
4099 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, baseval), REG_ITMP1);
4100 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, baseval), REG_ITMP3);
4101 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, diffval), REG_ITMP2);
4102 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4103 codegen_threadcritstop(mcodeptr - mcodebase);
4105 i386_alu_reg_reg(I386_SUB, REG_ITMP3, REG_ITMP1);
4106 i386_alu_reg_reg(I386_XOR, d, d);
4108 i386_alu_reg_reg(I386_CMP, REG_ITMP2, REG_ITMP1);
4109 i386_jcc(I386_CC_A, 5);
4110 i386_mov_imm_reg(1, d);
4114 panic ("internal error: no inlined array instanceof");
4116 store_reg_to_var_int(iptr->dst, d);
4119 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4121 /* op1: 0 == array, 1 == class */
4122 /* val.a: (classinfo*) superclass */
4124 /* superclass is an interface:
4126 * OK if ((sub == NULL) ||
4127 * (sub->vftbl->interfacetablelength > super->index) &&
4128 * (sub->vftbl->interfacetable[-super->index] != NULL));
4130 * superclass is a class:
4132 * OK if ((sub == NULL) || (0
4133 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4134 * super->vftbl->diffvall));
4138 classinfo *super = (classinfo*) iptr->val.a;
4140 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4141 codegen_threadcritrestart(mcodeptr - mcodebase);
4143 d = reg_of_var(m, iptr->dst, REG_ITMP3);
4144 var_to_reg_int(s1, src, d);
4145 if (iptr->op1) { /* class/interface */
4146 if (super->flags & ACC_INTERFACE) { /* interface */
4147 i386_test_reg_reg(s1, s1);
4149 /* TODO: clean up this calculation */
4151 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4154 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
4157 /* CALCOFFSETBYTES(a, super->index); */
4158 CALCIMMEDIATEBYTES(a, super->index);
4164 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*));
4169 i386_jcc(I386_CC_E, a);
4171 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4172 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetablelength), REG_ITMP2);
4173 i386_alu_imm_reg(I386_SUB, super->index, REG_ITMP2);
4175 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP2);
4176 i386_jcc(I386_CC_LE, 0);
4177 codegen_addxcastrefs(mcodeptr);
4178 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
4180 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP2);
4181 i386_jcc(I386_CC_E, 0);
4182 codegen_addxcastrefs(mcodeptr);
4184 } else { /* class */
4185 i386_test_reg_reg(s1, s1);
4187 /* TODO: clean up this calculation */
4189 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4194 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, baseval));
4196 if (d != REG_ITMP3) {
4198 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, baseval));
4201 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, diffval));
4207 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, baseval));
4214 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, diffval));
4221 i386_jcc(I386_CC_E, a);
4223 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4224 i386_mov_imm_reg((s4) super->vftbl, REG_ITMP2);
4225 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4226 codegen_threadcritstart(mcodeptr - mcodebase);
4228 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, baseval), REG_ITMP1);
4229 if (d != REG_ITMP3) {
4230 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, baseval), REG_ITMP3);
4231 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, diffval), REG_ITMP2);
4232 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4233 codegen_threadcritstop(mcodeptr - mcodebase);
4235 i386_alu_reg_reg(I386_SUB, REG_ITMP3, REG_ITMP1);
4238 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, baseval), REG_ITMP2);
4239 i386_alu_reg_reg(I386_SUB, REG_ITMP2, REG_ITMP1);
4240 i386_mov_imm_reg((s4) super->vftbl, REG_ITMP2);
4241 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, diffval), REG_ITMP2);
4242 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4243 codegen_threadcritstop(mcodeptr - mcodebase);
4247 i386_alu_reg_reg(I386_CMP, REG_ITMP2, REG_ITMP1);
4248 i386_jcc(I386_CC_A, 0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
4249 codegen_addxcastrefs(mcodeptr);
4253 panic ("internal error: no inlined array checkcast");
4256 store_reg_to_var_int(iptr->dst, d);
4259 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4261 if (src->flags & INMEMORY) {
4262 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
4265 i386_test_reg_reg(src->regoff, src->regoff);
4267 i386_jcc(I386_CC_L, 0);
4268 codegen_addxcheckarefs(mcodeptr);
4271 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4273 i386_test_reg_reg(REG_RESULT, REG_RESULT);
4274 i386_jcc(I386_CC_E, 0);
4275 codegen_addxexceptionrefs(mcodeptr);
4278 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4279 /* op1 = dimension, val.a = array descriptor */
4281 /* check for negative sizes and copy sizes to stack if necessary */
4283 MCODECHECK((iptr->op1 << 1) + 64);
4285 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4286 if (src->flags & INMEMORY) {
4287 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
4290 i386_test_reg_reg(src->regoff, src->regoff);
4292 i386_jcc(I386_CC_L, 0);
4293 codegen_addxcheckarefs(mcodeptr);
4296 * copy sizes to new stack location, be cause native function
4297 * builtin_nmultianewarray access them as (int *)
4299 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
4300 i386_mov_reg_membase(REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);
4302 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
4304 if (src->varkind != ARGVAR) {
4305 if (src->flags & INMEMORY) {
4306 i386_mov_membase_reg(REG_SP, (src->regoff + INT_ARG_CNT) * 8, REG_ITMP1);
4307 i386_mov_reg_membase(REG_ITMP1, REG_SP, (s1 + INT_ARG_CNT) * 8);
4310 i386_mov_reg_membase(src->regoff, REG_SP, (s1 + INT_ARG_CNT) * 8);
4314 i386_alu_imm_reg(I386_SUB, iptr->op1 * 4, REG_SP);
4316 /* a0 = dimension count */
4318 /* save stack pointer */
4319 M_INTMOVE(REG_SP, REG_ITMP1);
4321 i386_alu_imm_reg(I386_SUB, 12, REG_SP);
4322 i386_mov_imm_membase(iptr->op1, REG_SP, 0);
4324 /* a1 = arraydescriptor */
4326 i386_mov_imm_membase((s4) iptr->val.a, REG_SP, 4);
4328 /* a2 = pointer to dimensions = stack pointer */
4330 i386_mov_reg_membase(REG_ITMP1, REG_SP, 8);
4332 i386_mov_imm_reg((s4) (builtin_nmultianewarray), REG_ITMP1);
4333 i386_call_reg(REG_ITMP1);
4334 i386_alu_imm_reg(I386_ADD, 12 + iptr->op1 * 4, REG_SP);
4336 s1 = reg_of_var(m, iptr->dst, REG_RESULT);
4337 M_INTMOVE(REG_RESULT, s1);
4338 store_reg_to_var_int(iptr->dst, s1);
4342 error ("Unknown pseudo command: %d", iptr->opc);
4345 } /* for instruction */
4347 /* copy values to interface registers */
4349 src = bptr->outstack;
4350 len = bptr->outdepth;
4354 if ((src->varkind != STACKVAR)) {
4356 if (IS_FLT_DBL_TYPE(s2)) {
4357 var_to_reg_flt(s1, src, REG_FTMP1);
4358 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
4359 M_FLTMOVE(s1, r->interfaces[len][s2].regoff);
4362 panic("double store");
4363 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4367 var_to_reg_int(s1, src, REG_ITMP1);
4368 if (!IS_2_WORD_TYPE(r->interfaces[len][s2].type)) {
4369 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
4370 M_INTMOVE(s1, r->interfaces[len][s2].regoff);
4373 i386_mov_reg_membase(s1, REG_SP, r->interfaces[len][s2].regoff * 8);
4377 if (r->interfaces[len][s2].flags & INMEMORY) {
4378 M_LNGMEMMOVE(s1, r->interfaces[len][s2].regoff);
4381 panic("copy interface registers: longs have to be in memory (end)");
4388 } /* if (bptr -> flags >= BBREACHED) */
4389 } /* for basic block */
4391 codegen_createlinenumbertable();
4393 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
4397 /* generate bound check stubs */
4399 u1 *xcodeptr = NULL;
4401 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
4402 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
4403 xboundrefs->branchpos,
4404 (u1*) mcodeptr - mcodebase);
4408 /* move index register into REG_ITMP1 */
4409 i386_mov_reg_reg(xboundrefs->reg, REG_ITMP1); /* 2 bytes */
4411 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4412 dseg_adddata(mcodeptr);
4413 i386_mov_imm_reg(xboundrefs->branchpos - 6, REG_ITMP3); /* 5 bytes */
4414 i386_alu_reg_reg(I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4416 if (xcodeptr != NULL) {
4417 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4420 xcodeptr = mcodeptr;
4422 i386_push_reg(REG_ITMP2_XPC);
4424 PREPARE_NATIVE_STACKINFO
4426 i386_alu_imm_reg(I386_SUB, 2 * 4, REG_SP);
4427 i386_mov_imm_membase((s4) string_java_lang_ArrayIndexOutOfBoundsException, REG_SP, 0 * 4);
4428 i386_mov_reg_membase(REG_ITMP1, REG_SP, 1 * 4);
4429 i386_mov_imm_reg((s4) new_exception_int, REG_ITMP1);
4430 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4431 i386_alu_imm_reg(I386_ADD, 2 * 4, REG_SP);
4433 REMOVE_NATIVE_STACKINFO
4435 i386_pop_reg(REG_ITMP2_XPC);
4437 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4438 i386_jmp_reg(REG_ITMP3);
4442 /* generate negative array size check stubs */
4446 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
4447 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4448 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
4449 xcheckarefs->branchpos,
4450 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4454 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
4455 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
4459 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4460 dseg_adddata(mcodeptr);
4461 i386_mov_imm_reg(xcheckarefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4462 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4464 if (xcodeptr != NULL) {
4465 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4468 xcodeptr = mcodeptr;
4470 i386_push_reg(REG_ITMP2_XPC);
4472 PREPARE_NATIVE_STACKINFO
4474 i386_alu_imm_reg(I386_SUB, 1 * 4, REG_SP);
4475 i386_mov_imm_membase((s4) string_java_lang_NegativeArraySizeException, REG_SP, 0 * 4);
4476 i386_mov_imm_reg((s4) new_exception, REG_ITMP1);
4477 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4478 i386_alu_imm_reg(I386_ADD, 1 * 4, REG_SP);
4481 REMOVE_NATIVE_STACKINFO
4483 i386_pop_reg(REG_ITMP2_XPC);
4485 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4486 i386_jmp_reg(REG_ITMP3);
4490 /* generate cast check stubs */
4494 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
4495 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4496 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
4497 xcastrefs->branchpos,
4498 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4502 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
4503 xcastrefs->branchpos, (u1*) mcodeptr - mcodebase);
4507 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4508 dseg_adddata(mcodeptr);
4509 i386_mov_imm_reg(xcastrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4510 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4512 if (xcodeptr != NULL) {
4513 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4516 xcodeptr = mcodeptr;
4518 i386_push_reg(REG_ITMP2_XPC);
4521 PREPARE_NATIVE_STACKINFO
4523 i386_alu_imm_reg(I386_SUB, 1 * 4, REG_SP);
4524 i386_mov_imm_membase((s4) string_java_lang_ClassCastException, REG_SP, 0 * 4);
4525 i386_mov_imm_reg((s4) new_exception, REG_ITMP1);
4526 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4527 i386_alu_imm_reg(I386_ADD, 1 * 4, REG_SP);
4530 REMOVE_NATIVE_STACKINFO
4532 i386_pop_reg(REG_ITMP2_XPC);
4534 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4535 i386_jmp_reg(REG_ITMP3);
4539 /* generate divide by zero check stubs */
4543 for (; xdivrefs != NULL; xdivrefs = xdivrefs->next) {
4544 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4545 gen_resolvebranch((u1*) mcodebase + xdivrefs->branchpos,
4546 xdivrefs->branchpos,
4547 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4551 gen_resolvebranch((u1*) mcodebase + xdivrefs->branchpos,
4552 xdivrefs->branchpos, (u1*) mcodeptr - mcodebase);
4556 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4557 dseg_adddata(mcodeptr);
4558 i386_mov_imm_reg(xdivrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4559 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4561 if (xcodeptr != NULL) {
4562 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4565 xcodeptr = mcodeptr;
4567 i386_push_reg(REG_ITMP2_XPC);
4569 PREPARE_NATIVE_STACKINFO
4571 i386_alu_imm_reg(I386_SUB, 2 * 4, REG_SP);
4572 i386_mov_imm_membase((s4) string_java_lang_ArithmeticException, REG_SP, 0 * 4);
4573 i386_mov_imm_membase((s4) string_java_lang_ArithmeticException_message, REG_SP, 1 * 4);
4574 i386_mov_imm_reg((s4) new_exception_message, REG_ITMP1);
4575 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4576 i386_alu_imm_reg(I386_ADD, 2 * 4, REG_SP);
4578 REMOVE_NATIVE_STACKINFO
4580 i386_pop_reg(REG_ITMP2_XPC);
4582 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4583 i386_jmp_reg(REG_ITMP3);
4587 /* generate exception check stubs */
4591 for (; xexceptionrefs != NULL; xexceptionrefs = xexceptionrefs->next) {
4592 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4593 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
4594 xexceptionrefs->branchpos,
4595 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4599 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
4600 xexceptionrefs->branchpos, (u1*) mcodeptr - mcodebase);
4604 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4605 dseg_adddata(mcodeptr);
4606 i386_mov_imm_reg(xexceptionrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4607 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4609 if (xcodeptr != NULL) {
4610 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4613 xcodeptr = mcodeptr;
4615 i386_push_reg(REG_ITMP2_XPC);
4617 PREPARE_NATIVE_STACKINFO
4619 i386_mov_imm_reg((s4) codegen_general_stubcalled,REG_ITMP1);
4620 i386_call_reg(REG_ITMP1);
4623 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4624 i386_mov_imm_reg((s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4625 i386_call_reg(REG_ITMP1);
4626 i386_mov_membase_reg(REG_RESULT, 0, REG_ITMP3);
4627 i386_mov_imm_membase(0, REG_RESULT, 0);
4628 i386_mov_reg_reg(REG_ITMP3, REG_ITMP1_XPTR);
4630 i386_mov_imm_reg((s4) &_exceptionptr, REG_ITMP3);
4631 i386_mov_membase_reg(REG_ITMP3, 0, REG_ITMP1_XPTR);
4632 i386_mov_imm_membase(0, REG_ITMP3, 0);
4635 i386_push_reg(REG_ITMP1_XPTR);
4637 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4638 java stack at this point*/
4639 i386_mov_membase_reg(REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4640 i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl,class), REG_ITMP1);
4641 i386_push_imm(utf_fillInStackTrace_desc);
4642 i386_push_imm(utf_fillInStackTrace_name);
4643 i386_push_reg(REG_ITMP1);
4644 i386_mov_imm_reg((s4) class_resolvemethod, REG_ITMP3);
4645 i386_call_reg(REG_ITMP3);
4646 /*cleanup parameters of class_resolvemethod*/
4647 i386_alu_imm_reg(I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4648 /*prepare call to asm_calljavafunction2 */
4650 i386_push_imm(TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
4651 i386_push_reg(REG_SP);
4652 i386_push_imm(sizeof(jni_callblock));
4654 i386_push_reg(REG_RESULT);
4656 i386_mov_imm_reg((s4) asm_calljavafunction2, REG_ITMP3);
4657 i386_call_reg(REG_ITMP3);
4659 /* check exceptionptr + fail (JOWENN)*/
4661 i386_alu_imm_reg(I386_ADD,6*4,REG_SP);
4663 i386_pop_reg(REG_ITMP1_XPTR);
4664 i386_pop_reg(REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4665 REMOVE_NATIVE_STACKINFO
4667 i386_pop_reg(REG_ITMP2_XPC);
4669 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4670 i386_jmp_reg(REG_ITMP3);
4674 /* generate null pointer check stubs */
4678 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
4679 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4680 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
4681 xnullrefs->branchpos,
4682 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4686 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
4687 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
4691 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4692 dseg_adddata(mcodeptr);
4693 i386_mov_imm_reg(xnullrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4694 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4696 if (xcodeptr != NULL) {
4697 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4700 xcodeptr = mcodeptr;
4702 i386_push_reg(REG_ITMP2_XPC);
4706 PREPARE_NATIVE_STACKINFO
4708 /* create native call block*/
4709 i386_alu_imm_reg(I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4712 i386_mov_imm_reg((s4) codegen_stubcalled,REG_ITMP1);
4713 i386_call_reg(REG_ITMP1); /*call codegen_stubcalled*/
4715 i386_mov_imm_reg((s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4716 i386_call_reg(REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
4717 i386_mov_imm_membase(0,REG_SP, 2*4); /* builtin */
4718 i386_mov_reg_membase(REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
4719 i386_mov_membase_reg(REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4720 i386_mov_reg_membase(REG_ITMP2,REG_SP,0*4); /* store value on stack */
4721 i386_mov_reg_membase(REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4727 /* create exception*/
4728 i386_alu_imm_reg(I386_SUB, 1 * 4, REG_SP);
4729 i386_mov_imm_membase((s4) string_java_lang_NullPointerException, REG_SP, 0 * 4);
4730 i386_mov_imm_reg((s4) new_exception, REG_ITMP1);
4731 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4732 i386_alu_imm_reg(I386_ADD, 1 * 4, REG_SP);
4735 REMOVE_NATIVE_STACKINFO
4737 /* restore native call stack */
4738 i386_mov_membase_reg(REG_SP,0,REG_ITMP2);
4739 i386_mov_membase_reg(REG_SP,4,REG_ITMP3);
4740 i386_mov_reg_membase(REG_ITMP2,REG_ITMP3,0);
4741 i386_alu_imm_reg(I386_ADD,3*4,REG_SP);
4745 i386_pop_reg(REG_ITMP2_XPC);
4747 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4748 i386_jmp_reg(REG_ITMP3);
4753 codegen_finish(m, (u4) ((u1 *) mcodeptr - mcodebase));
4757 /* function createcompilerstub *************************************************
4759 creates a stub routine which calls the compiler
4761 *******************************************************************************/
4763 #define COMPSTUBSIZE 12
4765 u1 *createcompilerstub(methodinfo *m)
4767 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
4768 mcodeptr = s; /* code generation pointer */
4770 /* code for the stub */
4771 i386_mov_imm_reg((u4) m, REG_ITMP1);/* pass method pointer to compiler */
4773 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
4774 i386_mov_imm_reg((u4) asm_call_jit_compiler, REG_ITMP3); /* load address */
4775 i386_jmp_reg(REG_ITMP3); /* jump to compiler */
4777 #if defined(STATISTICS)
4779 count_cstub_len += COMPSTUBSIZE;
4786 /* function removecompilerstub *************************************************
4788 deletes a compilerstub from memory (simply by freeing it)
4790 *******************************************************************************/
4792 void removecompilerstub(u1 *stub)
4794 CFREE(stub, COMPSTUBSIZE);
4798 /* function: createnativestub **************************************************
4800 creates a stub routine which calls a native method
4802 *******************************************************************************/
4804 #define NATIVESTUBSIZE 350
4806 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4807 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4810 void i386_native_stub_debug(void **p) {
4811 printf("Pos on stack: %p\n",p);
4812 printf("Return adress should be: %p\n",*p);
4815 void i386_native_stub_debug2(void **p) {
4816 printf("Pos on stack: %p\n",p);
4817 printf("Return for lookup is: %p\n",*p);
4820 void traverseStackInfo() {
4821 void **p=builtin_asm_get_stackframeinfo();
4825 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4826 m=*((methodinfo**)((*p)+8));
4827 utf_display(m->name);
4835 u1 *createnativestub(functionptr f, methodinfo *m)
4837 u1 *s = CNEW(u1, NATIVESTUBSIZE); /* memory to hold the stub */
4841 int stackframesize = 4+12; /* initial 4 bytes is space for jni env,
4842 + 4 byte thread pointer + 4 byte previous pointer + method info*/
4843 int stackframeoffset = 4;
4847 mcodeptr = s; /* make macros work */
4849 if (m->flags & ACC_STATIC) {
4850 stackframesize += 4;
4851 stackframeoffset += 4;
4855 descriptor2types(m); /* set paramcount and paramtypes */
4858 /* i386_push_reg(REG_SP);
4859 i386_mov_imm_reg((s4) i386_native_stub_debug, REG_ITMP1);
4860 i386_call_reg(REG_ITMP1);
4861 i386_pop_reg(REG_ITMP1);*/
4864 /* if function is static, check for initialized */
4866 if (m->flags & ACC_STATIC) {
4867 /* if class isn't yet initialized, do it */
4868 if (!m->class->initialized) {
4870 *header = 0;/*extablesize*/
4872 *header = 0;/*line number table start*/
4874 *header = 0;/*line number table size*/
4876 *header = 0;/*fltsave*/
4878 *header = 0;/*intsave*/
4880 *header = 0;/*isleaf*/
4882 *header = 0;/*issync*/
4884 *header = 0;/*framesize*/
4886 *header = m;/*methodpointer*/
4890 /* call helper function which patches this code */
4891 i386_mov_imm_reg((s4) m->class, REG_ITMP1);
4892 i386_mov_imm_reg((s4) asm_check_clinit, REG_ITMP2);
4893 i386_call_reg(REG_ITMP2);
4898 i386_alu_imm_reg(I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4900 for (p = 0; p < m->paramcount; p++) {
4901 t = m->paramtypes[p];
4902 if (IS_INT_LNG_TYPE(t)) {
4903 if (IS_2_WORD_TYPE(t)) {
4904 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4905 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
4906 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
4907 i386_mov_reg_membase(REG_ITMP2, REG_SP, p * 8 + 4);
4909 } else if (t == TYPE_ADR) {
4910 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4911 i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2);
4912 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
4913 i386_mov_reg_membase(REG_ITMP2, REG_SP, p * 8 + 4);
4916 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
4918 i386_mov_reg_membase(EAX, REG_SP, p * 8);
4919 i386_mov_reg_membase(EDX, REG_SP, p * 8 + 4);
4923 if (!IS_2_WORD_TYPE(t)) {
4924 i386_flds_membase(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4925 i386_fstps_membase(REG_SP, p * 8);
4926 i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2);
4927 i386_mov_reg_membase(REG_ITMP2, REG_SP, p * 8 + 4);
4930 i386_fldl_membase(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4931 i386_fstpl_membase(REG_SP, p * 8);
4936 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
4937 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
4938 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
4939 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
4942 i386_mov_imm_membase((s4) m, REG_SP, TRACE_ARGS_NUM * 8);
4944 i386_mov_imm_reg((s4) builtin_trace_args, REG_ITMP1);
4945 i386_call_reg(REG_ITMP1);
4947 i386_alu_imm_reg(I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4951 * mark the whole fpu stack as free for native functions
4952 * (only for saved register count == 0)
4963 /* calculate stackframe size for native function */
4964 tptr = m->paramtypes;
4965 for (i = 0; i < m->paramcount; i++) {
4970 stackframesize += 4;
4975 stackframesize += 8;
4979 panic("unknown parameter type in native function");
4983 i386_alu_imm_reg(I386_SUB, stackframesize, REG_SP);
4985 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
4986 i386_mov_imm_membase((s4) m, REG_SP,stackframesize-4);
4987 i386_mov_imm_reg((s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
4988 i386_call_reg(REG_ITMP1);
4989 i386_mov_reg_membase(REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
4990 i386_mov_membase_reg(REG_RESULT,0,REG_ITMP2);
4991 i386_mov_reg_membase(REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
4992 i386_mov_reg_reg(REG_SP,REG_ITMP2);
4993 i386_alu_imm_reg(I386_ADD,stackframesize-12,REG_ITMP2);
4994 i386_mov_reg_membase(REG_ITMP2,REG_RESULT,0);
4997 /* i386_mov_imm_membase((s4) m, REG_SP,stackframesize-4);
4998 i386_mov_imm_membase((s4) m, REG_SP,stackframesize-8);
4999 i386_mov_imm_membase((s4) m, REG_SP,stackframesize-12);*/
5001 /* CREATE DYNAMIC STACK INFO -- END*/
5004 tptr = m->paramtypes;
5005 for (i = 0; i < m->paramcount; i++) {
5010 i386_mov_membase_reg(REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5011 i386_mov_reg_membase(REG_ITMP1, REG_SP, stackframeoffset);
5012 stackframeoffset += 4;
5017 i386_mov_membase_reg(REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5018 i386_mov_membase_reg(REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5019 i386_mov_reg_membase(REG_ITMP1, REG_SP, stackframeoffset);
5020 i386_mov_reg_membase(REG_ITMP2, REG_SP, stackframeoffset + 4);
5021 stackframeoffset += 8;
5025 panic("unknown parameter type in native function");
5029 if (m->flags & ACC_STATIC) {
5030 /* put class into second argument */
5031 i386_mov_imm_membase((s4) m->class, REG_SP, 4);
5034 /* put env into first argument */
5035 i386_mov_imm_membase((s4) &env, REG_SP, 0);
5037 i386_mov_imm_reg((s4) f, REG_ITMP1);
5038 i386_call_reg(REG_ITMP1);
5039 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5040 i386_push_reg(REG_RESULT2);
5041 i386_mov_membase_reg(REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
5042 i386_mov_membase_reg(REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
5043 i386_mov_reg_membase(REG_ITMP2,REG_RESULT2,0);
5044 i386_pop_reg(REG_RESULT2);
5045 /*REMOVE DYNAMIC STACK INFO -END */
5047 i386_alu_imm_reg(I386_ADD, stackframesize, REG_SP);
5051 i386_alu_imm_reg(I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5053 i386_mov_imm_membase((s4) m, REG_SP, 0);
5055 i386_mov_reg_membase(REG_RESULT, REG_SP, 4);
5056 i386_mov_reg_membase(REG_RESULT2, REG_SP, 4 + 4);
5058 i386_fstl_membase(REG_SP, 4 + 8);
5059 i386_fsts_membase(REG_SP, 4 + 8 + 8);
5061 i386_mov_imm_reg((s4) builtin_displaymethodstop, REG_ITMP1);
5062 i386_call_reg(REG_ITMP1);
5064 i386_mov_membase_reg(REG_SP, 4, REG_RESULT);
5065 i386_mov_membase_reg(REG_SP, 4 + 4, REG_RESULT2);
5067 i386_alu_imm_reg(I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5071 /* we can't use REG_ITMP3 == REG_RESULT2 */
5072 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5073 i386_push_reg(REG_RESULT);
5074 i386_push_reg(REG_RESULT2);
5075 i386_call_mem((s4) &callgetexceptionptrptr);
5076 i386_mov_membase_reg(REG_RESULT, 0, REG_ITMP2);
5077 i386_test_reg_reg(REG_ITMP2, REG_ITMP2);
5078 i386_pop_reg(REG_RESULT2);
5079 i386_pop_reg(REG_RESULT);
5081 i386_mov_imm_reg((s4) &_exceptionptr, REG_ITMP2);
5082 i386_mov_membase_reg(REG_ITMP2, 0, REG_ITMP2);
5083 i386_test_reg_reg(REG_ITMP2, REG_ITMP2);
5085 i386_jcc(I386_CC_NE, 1);
5089 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5090 i386_push_reg(REG_ITMP2);
5091 i386_call_mem((s4) &callgetexceptionptrptr);
5092 i386_mov_imm_membase(0, REG_RESULT, 0);
5093 i386_pop_reg(REG_ITMP1_XPTR);
5095 i386_mov_reg_reg(REG_ITMP2, REG_ITMP1_XPTR);
5096 i386_mov_imm_reg((s4) &_exceptionptr, REG_ITMP2);
5097 i386_mov_imm_membase(0, REG_ITMP2, 0);
5099 i386_mov_membase_reg(REG_SP, 0, REG_ITMP2_XPC);
5100 i386_alu_imm_reg(I386_SUB, 2, REG_ITMP2_XPC);
5102 i386_mov_imm_reg((s4) asm_handle_nat_exception, REG_ITMP3);
5103 i386_jmp_reg(REG_ITMP3);
5106 codegen_insertNative(s,mcodeptr);
5110 dolog_plain("native stubentry: %p, stubsize: %x (for %d params) --", (s4)s,(s4) (mcodeptr - s), m->paramcount);
5111 utf_display(m->name);
5115 #if defined(STATISTICS)
5117 count_nstub_len += NATIVESTUBSIZE;
5124 /* function: removenativestub **************************************************
5126 removes a previously created native-stub from memory
5128 *******************************************************************************/
5130 void removenativestub(u1 *stub)
5132 CFREE(stub, NATIVESTUBSIZE);
5137 * These are local overrides for various environment variables in Emacs.
5138 * Please do not remove this and leave it at the end of the file, where
5139 * Emacs will automagically detect them.
5140 * ---------------------------------------------------------------------
5143 * indent-tabs-mode: t