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 1362 2004-07-28 11:34:45Z 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(cd, REG_ITMP1); /*save itmp1, needed by some stubs */ \
113 i386_alu_imm_reg(cd, I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \
114 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1); \
115 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/ \
116 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \
117 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/ \
118 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/ \
119 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \
120 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */ \
121 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \
122 i386_mov_membase_reg(cd, REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \
123 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
126 #define REMOVE_NATIVE_STACKINFO \
127 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2); \
128 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3); \
129 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0); \
130 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
133 /* NullPointerException signal handler for hardware null pointer check */
135 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
138 /* long faultaddr; */
140 struct ucontext *_uc = (struct ucontext *) _p;
141 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
142 struct sigaction act;
144 /* Reset signal handler - necessary for SysV, does no harm for BSD */
146 /* instr = *((int*)(sigctx->eip)); */
147 /* faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f]; */
149 /* fprintf(stderr, "null=%d %p addr=%p\n", sig, sigctx, sigctx->eip);*/
151 /* if (faultaddr == 0) { */
152 /* signal(sig, (void *) catch_NullPointerException); */
153 act.sa_sigaction = (void *) catch_NullPointerException;
154 act.sa_flags = SA_SIGINFO;
155 sigaction(sig, &act, NULL); /* reinstall handler */
158 sigaddset(&nsig, sig);
159 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
161 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
162 sigctx->eax = (u4) string_java_lang_NullPointerException;
163 sigctx->eip = (u4) asm_throw_and_handle_exception;
168 /* faultaddr += (long) ((instr << 16) >> 16); */
169 /* fprintf(stderr, "faulting address: 0x%08x\n", faultaddr); */
170 /* panic("Stack overflow"); */
175 /* ArithmeticException signal handler for hardware divide by zero check */
177 void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p)
181 /* void **_p = (void **) &sig; */
182 /* struct sigcontext *sigctx = (struct sigcontext *) ++_p; */
183 struct ucontext *_uc = (struct ucontext *) _p;
184 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
185 struct sigaction act;
187 /* Reset signal handler - necessary for SysV, does no harm for BSD */
189 /* signal(sig, (void *) catch_ArithmeticException); */
190 act.sa_sigaction = (void *) catch_ArithmeticException;
191 act.sa_flags = SA_SIGINFO;
192 sigaction(sig, &act, NULL); /* reinstall handler */
195 sigaddset(&nsig, sig);
196 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
198 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
199 sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
205 void init_exceptions(void)
207 struct sigaction act;
209 /* install signal handlers we need to convert to exceptions */
213 /* signal(SIGSEGV, (void *) catch_NullPointerException); */
214 act.sa_sigaction = (void *) catch_NullPointerException;
215 act.sa_flags = SA_SIGINFO;
216 sigaction(SIGSEGV, &act, NULL);
220 /* signal(SIGBUS, (void *) catch_NullPointerException); */
221 act.sa_sigaction = (void *) catch_NullPointerException;
222 act.sa_flags = SA_SIGINFO;
223 sigaction(SIGBUS, &act, NULL);
227 /* signal(SIGFPE, (void *) catch_ArithmeticException); */
228 act.sa_sigaction = (void *) catch_ArithmeticException;
229 act.sa_flags = SA_SIGINFO;
230 sigaction(SIGFPE, &act, NULL);
234 /* function codegen ************************************************************
236 generates machine code
238 *******************************************************************************/
240 void codegen(methodinfo *m)
242 int len, s1, s2, s3, d;
252 s4 fpu_st_offset = 0;
258 s4 savedregs_num = 0;
260 /* keep code size smaller */
264 /* space to save used callee saved registers */
266 savedregs_num += (r->savintregcnt - r->maxsavintreguse);
267 savedregs_num += (r->savfltregcnt - r->maxsavfltreguse);
269 parentargs_base = r->maxmemuse + savedregs_num;
271 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
273 if (checksync && (m->flags & ACC_SYNCHRONIZED))
278 /* create method header */
280 (void) dseg_addaddress(m, m); /* MethodPointer */
281 (void) dseg_adds4(m, parentargs_base * 8); /* FrameSize */
283 #if defined(USE_THREADS)
285 /* IsSync contains the offset relative to the stack pointer for the
286 argument of monitor_exit used in the exception handler. Since the
287 offset could be zero and give a wrong meaning of the flag it is
291 if (checksync && (m->flags & ACC_SYNCHRONIZED))
292 (void) dseg_adds4(m, (r->maxmemuse + 1) * 8); /* IsSync */
297 (void) dseg_adds4(m, 0); /* IsSync */
299 (void) dseg_adds4(m, m->isleafmethod); /* IsLeaf */
300 (void) dseg_adds4(m, r->savintregcnt - r->maxsavintreguse); /* IntSave */
301 (void) dseg_adds4(m, r->savfltregcnt - r->maxsavfltreguse); /* FltSave */
303 /* adds a reference for the length of the line number counter. We don't
304 know the size yet, since we evaluate the information during code
305 generation, to save one additional iteration over the whole
306 instructions. During code optimization the position could have changed
307 to the information gotten from the class file */
308 (void) dseg_addlinenumbertablesize(m);
310 (void) dseg_adds4(m, m->exceptiontablelength); /* ExTableSize */
312 /* create exception table */
314 for (ex = m->exceptiontable; ex != NULL; ex = ex->down) {
315 dseg_addtarget(m, ex->start);
316 dseg_addtarget(m, ex->end);
317 dseg_addtarget(m, ex->handler);
318 (void) dseg_addaddress(m, ex->catchtype);
322 /* initialize mcode variables */
324 cd->mcodeptr = cd->mcodebase;
325 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
326 MCODECHECK(128 + m->paramcount);
328 /* create stack frame (if necessary) */
330 if (parentargs_base) {
331 i386_alu_imm_reg(cd, I386_SUB, parentargs_base * 8, REG_SP);
334 /* save return address and used callee saved registers */
337 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
338 p--; i386_mov_reg_membase(cd, r->savintregs[i], REG_SP, p * 8);
340 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
341 p--; i386_fld_reg(cd, r->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 8);
344 /* save monitorenter argument */
346 #if defined(USE_THREADS)
347 s4 func_enter = (m->flags & ACC_STATIC) ?
348 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
350 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
351 if (m->flags & ACC_STATIC) {
352 i386_mov_imm_reg(cd, (s4) m->class, REG_ITMP1);
353 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r->maxmemuse * 8);
356 i386_mov_membase_reg(cd, REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
357 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r->maxmemuse * 8);
360 /* call monitorenter function */
362 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
363 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
364 i386_mov_imm_reg(cd, func_enter, REG_ITMP1);
365 i386_call_reg(cd, REG_ITMP1);
366 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
370 /* copy argument registers to stack and call trace function with pointer
371 to arguments on stack.
375 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
377 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
378 t = m->paramtypes[p];
380 if (IS_INT_LNG_TYPE(t)) {
381 if (IS_2_WORD_TYPE(t)) {
382 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
383 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
384 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
385 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
387 /* } else if (t == TYPE_ADR) { */
389 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
390 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
391 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
392 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
395 /* i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
397 /* i386_mov_reg_membase(cd, EAX, REG_SP, p * 8); */
398 /* i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4); */
402 if (!IS_2_WORD_TYPE(t)) {
403 i386_flds_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
404 i386_fstps_membase(cd, REG_SP, p * 8);
405 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
406 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
409 i386_fldl_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
410 i386_fstpl_membase(cd, REG_SP, p * 8);
415 /* fill up the remaining arguments */
416 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
417 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
418 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
419 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
422 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
423 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
424 i386_call_reg(cd, REG_ITMP1);
426 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
429 /* take arguments out of register or stack frame */
431 for (p = 0, l = 0; p < m->paramcount; p++) {
432 t = m->paramtypes[p];
433 var = &(r->locals[l][t]);
435 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
439 if (IS_INT_LNG_TYPE(t)) { /* integer args */
440 if (p < r->intreg_argnum) { /* register arguments */
441 panic("integer register argument");
442 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
443 /* M_INTMOVE (argintregs[p], r); */
445 } else { /* reg arg -> spilled */
446 /* M_LST (argintregs[p], REG_SP, 8 * r); */
448 } else { /* stack arguments */
449 pa = p - r->intreg_argnum;
450 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
451 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, var->regoff); /* + 4 for return address */
452 } else { /* stack arg -> spilled */
453 if (!IS_2_WORD_TYPE(t)) {
454 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
455 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
458 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
459 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
460 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1); /* + 4 for return address */
461 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8 + 4);
466 } else { /* floating args */
467 if (p < r->fltreg_argnum) { /* register arguments */
468 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
469 panic("There are no float argument registers!");
471 } else { /* reg arg -> spilled */
472 panic("There are no float argument registers!");
475 } else { /* stack arguments */
476 pa = p - r->fltreg_argnum;
477 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
479 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
481 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
485 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
487 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
491 } else { /* stack-arg -> spilled */
492 /* i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
493 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r * 8); */
495 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
496 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
499 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
500 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
509 /* end of header generation */
511 /* walk through all basic blocks */
512 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
514 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
516 if (bptr->flags >= BBREACHED) {
518 /* branch resolving */
521 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
522 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
527 /* copy interface registers to their destination */
532 while (src != NULL) {
534 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
535 if (!IS_2_WORD_TYPE(src->type)) {
536 if (bptr->type == BBTYPE_SBR) {
537 d = reg_of_var(m, src, REG_ITMP1);
539 store_reg_to_var_int(src, d);
541 } else if (bptr->type == BBTYPE_EXH) {
542 d = reg_of_var(m, src, REG_ITMP1);
543 M_INTMOVE(REG_ITMP1, d);
544 store_reg_to_var_int(src, d);
548 panic("copy interface registers: longs have to me in memory (begin 1)");
552 d = reg_of_var(m, src, REG_ITMP1);
553 if ((src->varkind != STACKVAR)) {
555 if (IS_FLT_DBL_TYPE(s2)) {
556 s1 = r->interfaces[len][s2].regoff;
557 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
561 if (s2 == TYPE_FLT) {
562 i386_flds_membase(cd, REG_SP, s1 * 8);
565 i386_fldl_membase(cd, REG_SP, s1 * 8);
568 store_reg_to_var_flt(src, d);
571 s1 = r->interfaces[len][s2].regoff;
572 if (!IS_2_WORD_TYPE(r->interfaces[len][s2].type)) {
573 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
577 i386_mov_membase_reg(cd, REG_SP, s1 * 8, d);
579 store_reg_to_var_int(src, d);
582 if (r->interfaces[len][s2].flags & INMEMORY) {
583 M_LNGMEMMOVE(s1, src->regoff);
586 panic("copy interface registers: longs have to be in memory (begin 2)");
595 /* walk through all instructions */
600 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
601 if (iptr->line != currentline) {
602 dseg_addlinenumber(m, iptr->line, cd->mcodeptr);
603 currentline = iptr->line;
606 MCODECHECK(64); /* an instruction usually needs < 64 words */
609 case ICMD_NOP: /* ... ==> ... */
612 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
613 if (src->flags & INMEMORY) {
614 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
617 i386_test_reg_reg(cd, src->regoff, src->regoff);
619 i386_jcc(cd, I386_CC_E, 0);
620 codegen_addxnullrefs(m, cd->mcodeptr);
623 /* constant operations ************************************************/
625 case ICMD_ICONST: /* ... ==> ..., constant */
626 /* op1 = 0, val.i = constant */
628 d = reg_of_var(m, iptr->dst, REG_ITMP1);
629 if (iptr->dst->flags & INMEMORY) {
630 i386_mov_imm_membase(cd, iptr->val.i, REG_SP, iptr->dst->regoff * 8);
633 if (iptr->val.i == 0) {
634 i386_alu_reg_reg(cd, I386_XOR, d, d);
637 i386_mov_imm_reg(cd, iptr->val.i, d);
642 case ICMD_LCONST: /* ... ==> ..., constant */
643 /* op1 = 0, val.l = constant */
645 d = reg_of_var(m, iptr->dst, REG_ITMP1);
646 if (iptr->dst->flags & INMEMORY) {
647 i386_mov_imm_membase(cd, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
648 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
651 panic("LCONST: longs have to be in memory");
655 case ICMD_FCONST: /* ... ==> ..., constant */
656 /* op1 = 0, val.f = constant */
658 d = reg_of_var(m, iptr->dst, REG_FTMP1);
659 if (iptr->val.f == 0.0) {
664 if (iptr->val.i == 0x80000000) {
668 } else if (iptr->val.f == 1.0) {
672 } else if (iptr->val.f == 2.0) {
679 a = dseg_addfloat(m, iptr->val.f);
680 i386_mov_imm_reg(cd, 0, REG_ITMP1);
681 dseg_adddata(m, cd->mcodeptr);
682 i386_flds_membase(cd, REG_ITMP1, a);
685 store_reg_to_var_flt(iptr->dst, d);
688 case ICMD_DCONST: /* ... ==> ..., constant */
689 /* op1 = 0, val.d = constant */
691 d = reg_of_var(m, iptr->dst, REG_FTMP1);
692 if (iptr->val.d == 0.0) {
697 if (iptr->val.l == 0x8000000000000000LL) {
701 } else if (iptr->val.d == 1.0) {
705 } else if (iptr->val.d == 2.0) {
712 a = dseg_adddouble(m, iptr->val.d);
713 i386_mov_imm_reg(cd, 0, REG_ITMP1);
714 dseg_adddata(m, cd->mcodeptr);
715 i386_fldl_membase(cd, REG_ITMP1, a);
718 store_reg_to_var_flt(iptr->dst, d);
721 case ICMD_ACONST: /* ... ==> ..., constant */
722 /* op1 = 0, val.a = constant */
724 d = reg_of_var(m, iptr->dst, REG_ITMP1);
725 if (iptr->dst->flags & INMEMORY) {
726 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
729 if ((s4) iptr->val.a == 0) {
730 i386_alu_reg_reg(cd, I386_XOR, d, d);
733 i386_mov_imm_reg(cd, (s4) iptr->val.a, d);
739 /* load/store operations **********************************************/
741 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
742 case ICMD_ALOAD: /* op1 = local variable */
744 d = reg_of_var(m, iptr->dst, REG_ITMP1);
745 if ((iptr->dst->varkind == LOCALVAR) &&
746 (iptr->dst->varnum == iptr->op1)) {
749 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
750 if (iptr->dst->flags & INMEMORY) {
751 if (var->flags & INMEMORY) {
752 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, REG_ITMP1);
753 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
756 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
760 if (var->flags & INMEMORY) {
761 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, iptr->dst->regoff);
764 M_INTMOVE(var->regoff, iptr->dst->regoff);
769 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
770 /* op1 = local variable */
772 d = reg_of_var(m, iptr->dst, REG_ITMP1);
773 if ((iptr->dst->varkind == LOCALVAR) &&
774 (iptr->dst->varnum == iptr->op1)) {
777 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
778 if (iptr->dst->flags & INMEMORY) {
779 if (var->flags & INMEMORY) {
780 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
783 panic("LLOAD: longs have to be in memory");
787 panic("LLOAD: longs have to be in memory");
791 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
792 /* op1 = local variable */
794 d = reg_of_var(m, iptr->dst, REG_FTMP1);
795 if ((iptr->dst->varkind == LOCALVAR) &&
796 (iptr->dst->varnum == iptr->op1)) {
799 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
800 if (var->flags & INMEMORY) {
801 i386_flds_membase(cd, REG_SP, var->regoff * 8);
804 i386_fld_reg(cd, var->regoff + fpu_st_offset);
807 store_reg_to_var_flt(iptr->dst, d);
810 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
811 /* op1 = local variable */
813 d = reg_of_var(m, iptr->dst, REG_FTMP1);
814 if ((iptr->dst->varkind == LOCALVAR) &&
815 (iptr->dst->varnum == iptr->op1)) {
818 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
819 if (var->flags & INMEMORY) {
820 i386_fldl_membase(cd, REG_SP, var->regoff * 8);
823 i386_fld_reg(cd, var->regoff + fpu_st_offset);
826 store_reg_to_var_flt(iptr->dst, d);
829 case ICMD_ISTORE: /* ..., value ==> ... */
830 case ICMD_ASTORE: /* op1 = local variable */
832 if ((src->varkind == LOCALVAR) &&
833 (src->varnum == iptr->op1)) {
836 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
837 if (var->flags & INMEMORY) {
838 if (src->flags & INMEMORY) {
839 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
840 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
843 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 8);
847 var_to_reg_int(s1, src, var->regoff);
848 M_INTMOVE(s1, var->regoff);
852 case ICMD_LSTORE: /* ..., value ==> ... */
853 /* op1 = local variable */
855 if ((src->varkind == LOCALVAR) &&
856 (src->varnum == iptr->op1)) {
859 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
860 if (var->flags & INMEMORY) {
861 if (src->flags & INMEMORY) {
862 M_LNGMEMMOVE(src->regoff, var->regoff);
865 panic("LSTORE: longs have to be in memory");
869 panic("LSTORE: longs have to be in memory");
873 case ICMD_FSTORE: /* ..., value ==> ... */
874 /* op1 = local variable */
876 if ((src->varkind == LOCALVAR) &&
877 (src->varnum == iptr->op1)) {
880 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
881 if (var->flags & INMEMORY) {
882 var_to_reg_flt(s1, src, REG_FTMP1);
883 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
886 var_to_reg_flt(s1, src, var->regoff);
887 /* M_FLTMOVE(s1, var->regoff); */
888 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
893 case ICMD_DSTORE: /* ..., value ==> ... */
894 /* op1 = local variable */
896 if ((src->varkind == LOCALVAR) &&
897 (src->varnum == iptr->op1)) {
900 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
901 if (var->flags & INMEMORY) {
902 var_to_reg_flt(s1, src, REG_FTMP1);
903 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
906 var_to_reg_flt(s1, src, var->regoff);
907 /* M_FLTMOVE(s1, var->regoff); */
908 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
914 /* pop/dup/swap operations ********************************************/
916 /* attention: double and longs are only one entry in CACAO ICMDs */
918 case ICMD_POP: /* ..., value ==> ... */
919 case ICMD_POP2: /* ..., value, value ==> ... */
922 case ICMD_DUP: /* ..., a ==> ..., a, a */
923 M_COPY(src, iptr->dst);
926 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
928 M_COPY(src, iptr->dst);
929 M_COPY(src->prev, iptr->dst->prev);
932 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
934 M_COPY(src, iptr->dst);
935 M_COPY(src->prev, iptr->dst->prev);
936 M_COPY(iptr->dst, iptr->dst->prev->prev);
939 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
941 M_COPY(src, iptr->dst);
942 M_COPY(src->prev, iptr->dst->prev);
943 M_COPY(src->prev->prev, iptr->dst->prev->prev);
944 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
947 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
949 M_COPY(src, iptr->dst);
950 M_COPY(src->prev, iptr->dst->prev);
951 M_COPY(src->prev->prev, iptr->dst->prev->prev);
952 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
953 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev);
956 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
958 M_COPY(src, iptr->dst);
959 M_COPY(src->prev, iptr->dst->prev);
960 M_COPY(src->prev->prev, iptr->dst->prev->prev);
961 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
962 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
963 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
966 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
968 M_COPY(src, iptr->dst->prev);
969 M_COPY(src->prev, iptr->dst);
973 /* integer operations *************************************************/
975 case ICMD_INEG: /* ..., value ==> ..., - value */
977 d = reg_of_var(m, iptr->dst, REG_NULL);
978 if (iptr->dst->flags & INMEMORY) {
979 if (src->flags & INMEMORY) {
980 if (src->regoff == iptr->dst->regoff) {
981 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
984 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
985 i386_neg_reg(cd, REG_ITMP1);
986 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
990 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
991 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
995 if (src->flags & INMEMORY) {
996 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
997 i386_neg_reg(cd, iptr->dst->regoff);
1000 M_INTMOVE(src->regoff, iptr->dst->regoff);
1001 i386_neg_reg(cd, iptr->dst->regoff);
1006 case ICMD_LNEG: /* ..., value ==> ..., - value */
1008 d = reg_of_var(m, iptr->dst, REG_NULL);
1009 if (iptr->dst->flags & INMEMORY) {
1010 if (src->flags & INMEMORY) {
1011 if (src->regoff == iptr->dst->regoff) {
1012 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1013 i386_alu_imm_membase(cd, I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1014 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8 + 4);
1017 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1018 i386_neg_reg(cd, REG_ITMP1);
1019 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1020 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1021 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP1);
1022 i386_neg_reg(cd, REG_ITMP1);
1023 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1029 case ICMD_I2L: /* ..., value ==> ..., value */
1031 d = reg_of_var(m, iptr->dst, REG_NULL);
1032 if (iptr->dst->flags & INMEMORY) {
1033 if (src->flags & INMEMORY) {
1034 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, EAX);
1036 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1037 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1040 M_INTMOVE(src->regoff, EAX);
1042 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1043 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1048 case ICMD_L2I: /* ..., value ==> ..., value */
1050 d = reg_of_var(m, iptr->dst, REG_NULL);
1051 if (iptr->dst->flags & INMEMORY) {
1052 if (src->flags & INMEMORY) {
1053 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1054 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1058 if (src->flags & INMEMORY) {
1059 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1064 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1066 d = reg_of_var(m, iptr->dst, REG_NULL);
1067 if (iptr->dst->flags & INMEMORY) {
1068 if (src->flags & INMEMORY) {
1069 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1070 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1071 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1072 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1075 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1076 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1077 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1081 if (src->flags & INMEMORY) {
1082 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1083 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1084 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1087 M_INTMOVE(src->regoff, iptr->dst->regoff);
1088 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1089 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1094 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1096 d = reg_of_var(m, iptr->dst, REG_NULL);
1097 if (iptr->dst->flags & INMEMORY) {
1098 if (src->flags & INMEMORY) {
1099 if (src->regoff == iptr->dst->regoff) {
1100 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1103 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1104 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, REG_ITMP1);
1105 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1109 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1110 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1114 if (src->flags & INMEMORY) {
1115 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1116 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1119 M_INTMOVE(src->regoff, iptr->dst->regoff);
1120 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1125 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1127 d = reg_of_var(m, iptr->dst, REG_NULL);
1128 if (iptr->dst->flags & INMEMORY) {
1129 if (src->flags & INMEMORY) {
1130 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1131 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1132 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1133 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1136 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1137 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1138 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1142 if (src->flags & INMEMORY) {
1143 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1144 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1145 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1148 M_INTMOVE(src->regoff, iptr->dst->regoff);
1149 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1150 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1156 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1158 d = reg_of_var(m, iptr->dst, REG_NULL);
1159 i386_emit_ialu(cd, I386_ADD, src, iptr);
1162 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1163 /* val.i = constant */
1165 d = reg_of_var(m, iptr->dst, REG_NULL);
1166 /* should we use a inc optimization for smaller code size? */
1167 i386_emit_ialuconst(cd, I386_ADD, src, iptr);
1170 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1172 d = reg_of_var(m, iptr->dst, REG_NULL);
1173 if (iptr->dst->flags & INMEMORY) {
1174 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1175 if (src->regoff == iptr->dst->regoff) {
1176 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1177 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1178 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1179 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1181 } else if (src->prev->regoff == iptr->dst->regoff) {
1182 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1183 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1184 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1185 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1188 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1189 i386_alu_membase_reg(cd, I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1190 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1191 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1192 i386_alu_membase_reg(cd, I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1193 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1200 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1201 /* val.l = constant */
1203 d = reg_of_var(m, iptr->dst, REG_NULL);
1204 if (iptr->dst->flags & INMEMORY) {
1205 if (src->flags & INMEMORY) {
1206 if (src->regoff == iptr->dst->regoff) {
1207 i386_alu_imm_membase(cd, I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1208 i386_alu_imm_membase(cd, I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1211 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1212 i386_alu_imm_reg(cd, I386_ADD, iptr->val.l, REG_ITMP1);
1213 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1214 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1215 i386_alu_imm_reg(cd, I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1216 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1222 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1224 d = reg_of_var(m, iptr->dst, REG_NULL);
1225 if (iptr->dst->flags & INMEMORY) {
1226 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1227 if (src->prev->regoff == iptr->dst->regoff) {
1228 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1229 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1232 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1233 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1234 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1237 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1238 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1239 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1240 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1242 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1243 if (src->prev->regoff == iptr->dst->regoff) {
1244 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1247 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1248 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1249 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1253 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1254 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1258 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1259 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1260 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1262 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1263 M_INTMOVE(src->prev->regoff, d);
1264 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1266 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1267 /* workaround for reg alloc */
1268 if (src->regoff == iptr->dst->regoff) {
1269 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1270 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1271 M_INTMOVE(REG_ITMP1, d);
1274 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1275 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1279 /* workaround for reg alloc */
1280 if (src->regoff == iptr->dst->regoff) {
1281 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1282 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1283 M_INTMOVE(REG_ITMP1, d);
1286 M_INTMOVE(src->prev->regoff, d);
1287 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1293 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1294 /* val.i = constant */
1296 d = reg_of_var(m, iptr->dst, REG_NULL);
1297 i386_emit_ialuconst(cd, I386_SUB, src, iptr);
1300 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1302 d = reg_of_var(m, iptr->dst, REG_NULL);
1303 if (iptr->dst->flags & INMEMORY) {
1304 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1305 if (src->prev->regoff == iptr->dst->regoff) {
1306 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1307 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1308 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1309 i386_alu_reg_membase(cd, I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1312 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1313 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1314 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1315 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1316 i386_alu_membase_reg(cd, I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1317 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1323 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1324 /* val.l = constant */
1326 d = reg_of_var(m, iptr->dst, REG_NULL);
1327 if (iptr->dst->flags & INMEMORY) {
1328 if (src->flags & INMEMORY) {
1329 if (src->regoff == iptr->dst->regoff) {
1330 i386_alu_imm_membase(cd, I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1331 i386_alu_imm_membase(cd, I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1334 /* TODO: could be size optimized with lea -- see gcc output */
1335 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1336 i386_alu_imm_reg(cd, I386_SUB, iptr->val.l, REG_ITMP1);
1337 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1338 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1339 i386_alu_imm_reg(cd, I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1340 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1346 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1348 d = reg_of_var(m, iptr->dst, REG_NULL);
1349 if (iptr->dst->flags & INMEMORY) {
1350 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1351 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1352 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1353 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1355 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1356 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1357 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1358 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1360 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1361 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1362 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1363 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1366 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1367 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1368 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1372 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1373 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1374 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1376 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1377 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1378 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1380 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1381 M_INTMOVE(src->regoff, iptr->dst->regoff);
1382 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1385 if (src->regoff == iptr->dst->regoff) {
1386 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1389 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1390 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1396 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1397 /* val.i = constant */
1399 d = reg_of_var(m, iptr->dst, REG_NULL);
1400 if (iptr->dst->flags & INMEMORY) {
1401 if (src->flags & INMEMORY) {
1402 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1403 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1406 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1407 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1411 if (src->flags & INMEMORY) {
1412 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1415 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1420 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1422 d = reg_of_var(m, iptr->dst, REG_NULL);
1423 if (iptr->dst->flags & INMEMORY) {
1424 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1425 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX); /* mem -> EAX */
1426 /* optimize move EAX -> REG_ITMP3 is slower??? */
1427 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1428 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1430 /* TODO: optimize move EAX -> REG_ITMP3 */
1431 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); /* mem -> ITMP3 */
1432 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1433 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1435 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP2); /* mem -> ITMP3 */
1436 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1438 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1439 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1440 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1445 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1446 /* val.l = constant */
1448 d = reg_of_var(m, iptr->dst, REG_NULL);
1449 if (iptr->dst->flags & INMEMORY) {
1450 if (src->flags & INMEMORY) {
1451 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1452 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1453 /* TODO: optimize move EAX -> REG_ITMP3 */
1454 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1455 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1457 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1458 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1459 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1461 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1462 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1463 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1468 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1470 d = reg_of_var(m, iptr->dst, REG_NULL);
1471 var_to_reg_int(s1, src, REG_ITMP2);
1473 if (src->prev->flags & INMEMORY) {
1474 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1477 M_INTMOVE(src->prev->regoff, EAX);
1480 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1481 i386_jcc(cd, I386_CC_NE, 3 + 6);
1482 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1483 i386_jcc(cd, I386_CC_E, 1 + 2);
1486 i386_idiv_reg(cd, s1);
1488 if (iptr->dst->flags & INMEMORY) {
1489 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1492 M_INTMOVE(EAX, iptr->dst->regoff);
1496 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1498 d = reg_of_var(m, iptr->dst, REG_NULL);
1499 var_to_reg_int(s1, src, REG_ITMP2);
1501 if (src->prev->flags & INMEMORY) {
1502 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1505 M_INTMOVE(src->prev->regoff, EAX);
1508 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1509 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1510 i386_alu_reg_reg(cd, I386_XOR, EDX, EDX);
1511 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1512 i386_jcc(cd, I386_CC_E, 1 + 2);
1515 i386_idiv_reg(cd, s1);
1517 if (iptr->dst->flags & INMEMORY) {
1518 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8);
1521 M_INTMOVE(EDX, iptr->dst->regoff);
1525 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1526 /* val.i = constant */
1528 /* TODO: optimize for `/ 2' */
1529 var_to_reg_int(s1, src, REG_ITMP1);
1530 d = reg_of_var(m, iptr->dst, REG_ITMP1);
1533 i386_test_reg_reg(cd, d, d);
1535 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1536 i386_jcc(cd, I386_CC_NS, a);
1537 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, d);
1539 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1540 store_reg_to_var_int(iptr->dst, d);
1543 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1544 /* val.i = constant */
1546 d = reg_of_var(m, iptr->dst, REG_NULL);
1547 if (iptr->dst->flags & INMEMORY) {
1548 if (src->flags & INMEMORY) {
1550 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1552 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1553 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1555 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1556 i386_jcc(cd, I386_CC_NS, a);
1557 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1558 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1559 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1560 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1562 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1563 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1568 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1569 /* val.i = constant */
1571 var_to_reg_int(s1, src, REG_ITMP1);
1572 d = reg_of_var(m, iptr->dst, REG_ITMP2);
1574 M_INTMOVE(s1, REG_ITMP1);
1581 CALCIMMEDIATEBYTES(a, iptr->val.i);
1584 /* TODO: optimize */
1586 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1587 i386_test_reg_reg(cd, s1, s1);
1588 i386_jcc(cd, I386_CC_GE, a);
1589 i386_mov_reg_reg(cd, s1, d);
1590 i386_neg_reg(cd, d);
1591 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1592 i386_neg_reg(cd, d);
1594 /* M_INTMOVE(s1, EAX); */
1595 /* i386_cltd(cd); */
1596 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1597 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1598 /* i386_alu_reg_reg(cd, I386_AND, iptr->val.i, EAX); */
1599 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1600 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1601 /* M_INTMOVE(EAX, d); */
1603 /* i386_alu_reg_reg(cd, I386_XOR, d, d); */
1604 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1605 /* i386_shrd_reg_reg(cd, s1, d); */
1606 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1608 store_reg_to_var_int(iptr->dst, d);
1611 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1612 /* val.l = constant */
1614 d = reg_of_var(m, iptr->dst, REG_NULL);
1615 if (iptr->dst->flags & INMEMORY) {
1616 if (src->flags & INMEMORY) {
1617 /* Intel algorithm -- does not work, because constant is wrong */
1618 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1); */
1619 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1621 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1622 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1623 /* i386_jcc(cd, I386_CC_NS, offset); */
1624 /* i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1625 /* i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP3); */
1627 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1628 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1629 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1631 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1633 /* i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1); */
1634 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1635 /* i386_alu_reg_reg(cd, I386_SBB, REG_ITMP3, REG_ITMP2); */
1637 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1638 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1640 /* Alpha algorithm */
1642 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1644 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1650 /* TODO: hmm, don't know if this is always correct */
1652 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1654 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1660 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1661 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1663 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1664 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1665 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1666 i386_jcc(cd, I386_CC_GE, a);
1668 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1669 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1671 i386_neg_reg(cd, REG_ITMP1);
1672 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1673 i386_neg_reg(cd, REG_ITMP2);
1675 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1676 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1678 i386_neg_reg(cd, REG_ITMP1);
1679 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1680 i386_neg_reg(cd, REG_ITMP2);
1682 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1683 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1688 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1690 d = reg_of_var(m, iptr->dst, REG_NULL);
1691 i386_emit_ishift(cd, I386_SHL, src, iptr);
1694 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1695 /* val.i = constant */
1697 d = reg_of_var(m, iptr->dst, REG_NULL);
1698 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1701 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1703 d = reg_of_var(m, iptr->dst, REG_NULL);
1704 i386_emit_ishift(cd, I386_SAR, src, iptr);
1707 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1708 /* val.i = constant */
1710 d = reg_of_var(m, iptr->dst, REG_NULL);
1711 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1714 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1716 d = reg_of_var(m, iptr->dst, REG_NULL);
1717 i386_emit_ishift(cd, I386_SHR, src, iptr);
1720 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1721 /* val.i = constant */
1723 d = reg_of_var(m, iptr->dst, REG_NULL);
1724 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1727 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1729 d = reg_of_var(m, iptr->dst, REG_NULL);
1730 if (iptr->dst->flags & INMEMORY ){
1731 if (src->prev->flags & INMEMORY) {
1732 /* if (src->prev->regoff == iptr->dst->regoff) { */
1733 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1735 /* if (src->flags & INMEMORY) { */
1736 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1738 /* M_INTMOVE(src->regoff, ECX); */
1741 /* i386_test_imm_reg(cd, 32, ECX); */
1742 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1743 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1744 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1); */
1746 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1747 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1750 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1751 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1753 if (src->flags & INMEMORY) {
1754 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1756 M_INTMOVE(src->regoff, ECX);
1759 i386_test_imm_reg(cd, 32, ECX);
1760 i386_jcc(cd, I386_CC_E, 2 + 2);
1761 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1762 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1764 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1765 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1766 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1767 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1773 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1774 /* val.i = constant */
1776 d = reg_of_var(m, iptr->dst, REG_NULL);
1777 if (iptr->dst->flags & INMEMORY ) {
1778 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1779 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1781 if (iptr->val.i & 0x20) {
1782 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1783 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1784 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1787 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1788 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1791 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1792 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1796 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1798 d = reg_of_var(m, iptr->dst, REG_NULL);
1799 if (iptr->dst->flags & INMEMORY ){
1800 if (src->prev->flags & INMEMORY) {
1801 /* if (src->prev->regoff == iptr->dst->regoff) { */
1802 /* TODO: optimize */
1803 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1804 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1806 /* if (src->flags & INMEMORY) { */
1807 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1809 /* M_INTMOVE(src->regoff, ECX); */
1812 /* i386_test_imm_reg(cd, 32, ECX); */
1813 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1814 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1815 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1817 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1818 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1819 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1820 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1823 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1824 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1826 if (src->flags & INMEMORY) {
1827 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1829 M_INTMOVE(src->regoff, ECX);
1832 i386_test_imm_reg(cd, 32, ECX);
1833 i386_jcc(cd, I386_CC_E, 2 + 3);
1834 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1835 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1837 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1838 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1839 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1840 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1846 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1847 /* val.i = constant */
1849 d = reg_of_var(m, iptr->dst, REG_NULL);
1850 if (iptr->dst->flags & INMEMORY ) {
1851 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1852 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1854 if (iptr->val.i & 0x20) {
1855 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1856 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
1857 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1860 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1861 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1864 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1865 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1869 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1871 d = reg_of_var(m, iptr->dst, REG_NULL);
1872 if (iptr->dst->flags & INMEMORY ){
1873 if (src->prev->flags & INMEMORY) {
1874 /* if (src->prev->regoff == iptr->dst->regoff) { */
1875 /* TODO: optimize */
1876 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1877 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1879 /* if (src->flags & INMEMORY) { */
1880 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1882 /* M_INTMOVE(src->regoff, ECX); */
1885 /* i386_test_imm_reg(cd, 32, ECX); */
1886 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1887 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1888 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2); */
1890 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1891 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
1892 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1893 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1896 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1897 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1899 if (src->flags & INMEMORY) {
1900 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1902 M_INTMOVE(src->regoff, ECX);
1905 i386_test_imm_reg(cd, 32, ECX);
1906 i386_jcc(cd, I386_CC_E, 2 + 2);
1907 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1908 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP3, REG_ITMP3);
1910 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1911 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
1912 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1913 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1919 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1920 /* val.l = constant */
1922 d = reg_of_var(m, iptr->dst, REG_NULL);
1923 if (iptr->dst->flags & INMEMORY ) {
1924 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1925 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1927 if (iptr->val.i & 0x20) {
1928 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1929 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
1930 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1933 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1934 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
1937 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1938 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1942 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1944 d = reg_of_var(m, iptr->dst, REG_NULL);
1945 i386_emit_ialu(cd, I386_AND, src, iptr);
1948 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1949 /* val.i = constant */
1951 d = reg_of_var(m, iptr->dst, REG_NULL);
1952 i386_emit_ialuconst(cd, I386_AND, src, iptr);
1955 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1957 d = reg_of_var(m, iptr->dst, REG_NULL);
1958 i386_emit_lalu(cd, I386_AND, src, iptr);
1961 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1962 /* val.l = constant */
1964 d = reg_of_var(m, iptr->dst, REG_NULL);
1965 i386_emit_laluconst(cd, I386_AND, src, iptr);
1968 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1970 d = reg_of_var(m, iptr->dst, REG_NULL);
1971 i386_emit_ialu(cd, I386_OR, src, iptr);
1974 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1975 /* val.i = constant */
1977 d = reg_of_var(m, iptr->dst, REG_NULL);
1978 i386_emit_ialuconst(cd, I386_OR, src, iptr);
1981 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1983 d = reg_of_var(m, iptr->dst, REG_NULL);
1984 i386_emit_lalu(cd, I386_OR, src, iptr);
1987 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1988 /* val.l = constant */
1990 d = reg_of_var(m, iptr->dst, REG_NULL);
1991 i386_emit_laluconst(cd, I386_OR, src, iptr);
1994 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1996 d = reg_of_var(m, iptr->dst, REG_NULL);
1997 i386_emit_ialu(cd, I386_XOR, src, iptr);
2000 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2001 /* val.i = constant */
2003 d = reg_of_var(m, iptr->dst, REG_NULL);
2004 i386_emit_ialuconst(cd, I386_XOR, src, iptr);
2007 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2009 d = reg_of_var(m, iptr->dst, REG_NULL);
2010 i386_emit_lalu(cd, I386_XOR, src, iptr);
2013 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2014 /* val.l = constant */
2016 d = reg_of_var(m, iptr->dst, REG_NULL);
2017 i386_emit_laluconst(cd, I386_XOR, src, iptr);
2020 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2021 /* op1 = variable, val.i = constant */
2023 var = &(r->locals[iptr->op1][TYPE_INT]);
2024 if (var->flags & INMEMORY) {
2025 i386_alu_imm_membase(cd, I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2028 i386_alu_imm_reg(cd, I386_ADD, iptr->val.i, var->regoff);
2033 /* floating operations ************************************************/
2035 #define ROUND_TO_SINGLE \
2036 i386_fstps_membase(cd, REG_SP, -8); \
2037 i386_flds_membase(cd, REG_SP, -8);
2039 #define ROUND_TO_DOUBLE \
2040 i386_fstpl_membase(cd, REG_SP, -8); \
2041 i386_fldl_membase(cd, REG_SP, -8);
2043 #define FPU_SET_24BIT_MODE \
2044 if (!fpu_in_24bit_mode) { \
2045 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2046 fpu_in_24bit_mode = 1; \
2049 #define FPU_SET_53BIT_MODE \
2050 if (fpu_in_24bit_mode) { \
2051 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2052 fpu_in_24bit_mode = 0; \
2055 #define ROUND_TO_SINGLE
2056 #define ROUND_TO_DOUBLE
2057 #define FPU_SET_24BIT_MODE
2058 #define FPU_SET_53BIT_MODE
2060 case ICMD_FNEG: /* ..., value ==> ..., - value */
2063 var_to_reg_flt(s1, src, REG_FTMP1);
2064 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2066 store_reg_to_var_flt(iptr->dst, d);
2069 case ICMD_DNEG: /* ..., value ==> ..., - value */
2072 var_to_reg_flt(s1, src, REG_FTMP1);
2073 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2075 store_reg_to_var_flt(iptr->dst, d);
2078 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2081 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2082 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2083 var_to_reg_flt(s2, src, REG_FTMP2);
2086 store_reg_to_var_flt(iptr->dst, d);
2089 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2092 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2093 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2094 var_to_reg_flt(s2, src, REG_FTMP2);
2097 store_reg_to_var_flt(iptr->dst, d);
2100 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2103 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2104 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2105 var_to_reg_flt(s2, src, REG_FTMP2);
2108 store_reg_to_var_flt(iptr->dst, d);
2111 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2114 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2115 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2116 var_to_reg_flt(s2, src, REG_FTMP2);
2119 store_reg_to_var_flt(iptr->dst, d);
2122 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2125 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2126 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2127 var_to_reg_flt(s2, src, REG_FTMP2);
2131 store_reg_to_var_flt(iptr->dst, d);
2134 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2137 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2138 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2140 /* i386_fldt_mem(cd, subnormal_bias1); */
2141 /* i386_fmulp(cd); */
2143 var_to_reg_flt(s2, src, REG_FTMP2);
2148 /* i386_fldt_mem(cd, subnormal_bias2); */
2149 /* i386_fmulp(cd); */
2151 store_reg_to_var_flt(iptr->dst, d);
2154 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2157 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2158 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2159 var_to_reg_flt(s2, src, REG_FTMP2);
2163 store_reg_to_var_flt(iptr->dst, d);
2166 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2169 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2170 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2172 /* i386_fldt_mem(cd, subnormal_bias1); */
2173 /* i386_fmulp(cd); */
2175 var_to_reg_flt(s2, src, REG_FTMP2);
2180 /* i386_fldt_mem(cd, subnormal_bias2); */
2181 /* i386_fmulp(cd); */
2183 store_reg_to_var_flt(iptr->dst, d);
2186 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2189 /* exchanged to skip fxch */
2190 var_to_reg_flt(s2, src, REG_FTMP2);
2191 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2192 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2193 /* i386_fxch(cd); */
2198 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2199 store_reg_to_var_flt(iptr->dst, d);
2200 i386_ffree_reg(cd, 0);
2205 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2208 /* exchanged to skip fxch */
2209 var_to_reg_flt(s2, src, REG_FTMP2);
2210 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2211 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2212 /* i386_fxch(cd); */
2217 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2218 store_reg_to_var_flt(iptr->dst, d);
2219 i386_ffree_reg(cd, 0);
2224 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2225 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2227 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2228 if (src->flags & INMEMORY) {
2229 i386_fildl_membase(cd, REG_SP, src->regoff * 8);
2233 a = dseg_adds4(m, 0);
2234 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2235 dseg_adddata(m, cd->mcodeptr);
2236 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, a);
2237 i386_fildl_membase(cd, REG_ITMP1, a);
2240 store_reg_to_var_flt(iptr->dst, d);
2243 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2244 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2246 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2247 if (src->flags & INMEMORY) {
2248 i386_fildll_membase(cd, REG_SP, src->regoff * 8);
2252 panic("L2F: longs have to be in memory");
2254 store_reg_to_var_flt(iptr->dst, d);
2257 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2259 var_to_reg_flt(s1, src, REG_FTMP1);
2260 d = reg_of_var(m, iptr->dst, REG_NULL);
2262 a = dseg_adds4(m, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2263 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2264 dseg_adddata(m, cd->mcodeptr);
2265 i386_fldcw_membase(cd, REG_ITMP1, a);
2267 if (iptr->dst->flags & INMEMORY) {
2268 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2271 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2272 i386_fldcw_membase(cd, REG_ITMP1, a);
2274 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2277 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2279 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2282 a = dseg_adds4(m, 0);
2283 i386_fistpl_membase(cd, REG_ITMP1, a);
2285 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2287 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2288 i386_fldcw_membase(cd, REG_ITMP1, a);
2290 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2293 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2294 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2297 i386_jcc(cd, I386_CC_NE, a);
2299 /* XXX: change this when we use registers */
2300 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2301 i386_mov_imm_reg(cd, (s4) asm_builtin_f2i, REG_ITMP1);
2302 i386_call_reg(cd, REG_ITMP1);
2304 if (iptr->dst->flags & INMEMORY) {
2305 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2308 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2312 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2314 var_to_reg_flt(s1, src, REG_FTMP1);
2315 d = reg_of_var(m, iptr->dst, REG_NULL);
2317 a = dseg_adds4(m, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2318 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2319 dseg_adddata(m, cd->mcodeptr);
2320 i386_fldcw_membase(cd, REG_ITMP1, a);
2322 if (iptr->dst->flags & INMEMORY) {
2323 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2326 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2327 i386_fldcw_membase(cd, REG_ITMP1, a);
2329 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2332 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2334 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2337 a = dseg_adds4(m, 0);
2338 i386_fistpl_membase(cd, REG_ITMP1, a);
2340 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2342 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2343 i386_fldcw_membase(cd, REG_ITMP1, a);
2345 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2348 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2349 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2352 i386_jcc(cd, I386_CC_NE, a);
2354 /* XXX: change this when we use registers */
2355 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2356 i386_mov_imm_reg(cd, (s4) asm_builtin_d2i, REG_ITMP1);
2357 i386_call_reg(cd, REG_ITMP1);
2359 if (iptr->dst->flags & INMEMORY) {
2360 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2362 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2366 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2368 var_to_reg_flt(s1, src, REG_FTMP1);
2369 d = reg_of_var(m, iptr->dst, REG_NULL);
2371 a = dseg_adds4(m, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2372 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2373 dseg_adddata(m, cd->mcodeptr);
2374 i386_fldcw_membase(cd, REG_ITMP1, a);
2376 if (iptr->dst->flags & INMEMORY) {
2377 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2380 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2381 i386_fldcw_membase(cd, REG_ITMP1, a);
2383 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2386 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2388 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2391 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2393 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2395 i386_jcc(cd, I386_CC_NE, a);
2397 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2400 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2402 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2404 i386_jcc(cd, I386_CC_NE, a);
2406 /* XXX: change this when we use registers */
2407 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2408 i386_mov_imm_reg(cd, (s4) asm_builtin_f2l, REG_ITMP1);
2409 i386_call_reg(cd, REG_ITMP1);
2410 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2411 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2414 panic("F2L: longs have to be in memory");
2418 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2420 var_to_reg_flt(s1, src, REG_FTMP1);
2421 d = reg_of_var(m, iptr->dst, REG_NULL);
2423 a = dseg_adds4(m, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2424 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2425 dseg_adddata(m, cd->mcodeptr);
2426 i386_fldcw_membase(cd, REG_ITMP1, a);
2428 if (iptr->dst->flags & INMEMORY) {
2429 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2432 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2433 i386_fldcw_membase(cd, REG_ITMP1, a);
2435 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2438 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2440 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2443 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2445 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2447 i386_jcc(cd, I386_CC_NE, a);
2449 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2452 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2454 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2456 i386_jcc(cd, I386_CC_NE, a);
2458 /* XXX: change this when we use registers */
2459 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2460 i386_mov_imm_reg(cd, (s4) asm_builtin_d2l, REG_ITMP1);
2461 i386_call_reg(cd, REG_ITMP1);
2462 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2463 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2466 panic("D2L: longs have to be in memory");
2470 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2472 var_to_reg_flt(s1, src, REG_FTMP1);
2473 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2475 store_reg_to_var_flt(iptr->dst, d);
2478 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2480 var_to_reg_flt(s1, src, REG_FTMP1);
2481 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2483 store_reg_to_var_flt(iptr->dst, d);
2486 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2489 /* exchanged to skip fxch */
2490 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2491 var_to_reg_flt(s1, src, REG_FTMP2);
2492 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2493 /* i386_fxch(cd); */
2497 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2498 i386_jcc(cd, I386_CC_E, 6);
2499 i386_alu_imm_reg(cd, I386_AND, 0x000000ff, EAX);
2501 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2502 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2503 i386_jcc(cd, I386_CC_B, 3 + 5);
2504 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2505 i386_jmp_imm(cd, 3);
2506 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2507 store_reg_to_var_int(iptr->dst, d);
2510 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2513 /* exchanged to skip fxch */
2514 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2515 var_to_reg_flt(s1, src, REG_FTMP2);
2516 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2517 /* i386_fxch(cd); */
2521 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2522 i386_jcc(cd, I386_CC_E, 3);
2523 i386_movb_imm_reg(cd, 1, I386_AH);
2525 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2526 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2527 i386_jcc(cd, I386_CC_B, 3 + 5);
2528 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2529 i386_jmp_imm(cd, 3);
2530 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2531 store_reg_to_var_int(iptr->dst, d);
2535 /* memory operations **************************************************/
2537 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2539 var_to_reg_int(s1, src, REG_ITMP1);
2540 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2541 gen_nullptr_check(s1);
2542 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2543 store_reg_to_var_int(iptr->dst, d);
2546 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2548 var_to_reg_int(s1, src->prev, REG_ITMP1);
2549 var_to_reg_int(s2, src, REG_ITMP2);
2550 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2551 if (iptr->op1 == 0) {
2552 gen_nullptr_check(s1);
2555 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2556 store_reg_to_var_int(iptr->dst, d);
2559 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2561 var_to_reg_int(s1, src->prev, REG_ITMP1);
2562 var_to_reg_int(s2, src, REG_ITMP2);
2563 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2564 if (iptr->op1 == 0) {
2565 gen_nullptr_check(s1);
2569 if (iptr->dst->flags & INMEMORY) {
2570 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2571 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2572 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2573 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2577 case ICMD_IALOAD: /* ..., 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(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2587 store_reg_to_var_int(iptr->dst, d);
2590 case ICMD_FALOAD: /* ..., 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_FTMP1);
2595 if (iptr->op1 == 0) {
2596 gen_nullptr_check(s1);
2599 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2601 store_reg_to_var_flt(iptr->dst, d);
2604 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2606 var_to_reg_int(s1, src->prev, REG_ITMP1);
2607 var_to_reg_int(s2, src, REG_ITMP2);
2608 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2609 if (iptr->op1 == 0) {
2610 gen_nullptr_check(s1);
2613 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2615 store_reg_to_var_flt(iptr->dst, d);
2618 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2620 var_to_reg_int(s1, src->prev, REG_ITMP1);
2621 var_to_reg_int(s2, src, REG_ITMP2);
2622 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2623 if (iptr->op1 == 0) {
2624 gen_nullptr_check(s1);
2627 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2628 store_reg_to_var_int(iptr->dst, d);
2631 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2633 var_to_reg_int(s1, src->prev, REG_ITMP1);
2634 var_to_reg_int(s2, src, REG_ITMP2);
2635 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2636 if (iptr->op1 == 0) {
2637 gen_nullptr_check(s1);
2640 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2641 store_reg_to_var_int(iptr->dst, d);
2644 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2646 var_to_reg_int(s1, src->prev, REG_ITMP1);
2647 var_to_reg_int(s2, src, REG_ITMP2);
2648 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2649 if (iptr->op1 == 0) {
2650 gen_nullptr_check(s1);
2653 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2654 store_reg_to_var_int(iptr->dst, d);
2658 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2660 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2661 var_to_reg_int(s2, src->prev, REG_ITMP2);
2662 if (iptr->op1 == 0) {
2663 gen_nullptr_check(s1);
2666 var_to_reg_int(s3, src, REG_ITMP3);
2667 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2670 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2672 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2673 var_to_reg_int(s2, src->prev, REG_ITMP2);
2674 if (iptr->op1 == 0) {
2675 gen_nullptr_check(s1);
2679 if (src->flags & INMEMORY) {
2680 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
2681 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2682 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2683 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2687 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2689 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2690 var_to_reg_int(s2, src->prev, REG_ITMP2);
2691 if (iptr->op1 == 0) {
2692 gen_nullptr_check(s1);
2695 var_to_reg_int(s3, src, REG_ITMP3);
2696 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2699 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2701 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2702 var_to_reg_int(s2, src->prev, REG_ITMP2);
2703 if (iptr->op1 == 0) {
2704 gen_nullptr_check(s1);
2707 var_to_reg_flt(s3, src, REG_FTMP1);
2708 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2712 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2714 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2715 var_to_reg_int(s2, src->prev, REG_ITMP2);
2716 if (iptr->op1 == 0) {
2717 gen_nullptr_check(s1);
2720 var_to_reg_flt(s3, src, REG_FTMP1);
2721 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2725 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2727 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2728 var_to_reg_int(s2, src->prev, REG_ITMP2);
2729 if (iptr->op1 == 0) {
2730 gen_nullptr_check(s1);
2733 var_to_reg_int(s3, src, REG_ITMP3);
2734 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2737 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2739 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2740 var_to_reg_int(s2, src->prev, REG_ITMP2);
2741 if (iptr->op1 == 0) {
2742 gen_nullptr_check(s1);
2745 var_to_reg_int(s3, src, REG_ITMP3);
2746 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2749 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2751 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2752 var_to_reg_int(s2, src->prev, REG_ITMP2);
2753 if (iptr->op1 == 0) {
2754 gen_nullptr_check(s1);
2757 var_to_reg_int(s3, src, REG_ITMP3);
2758 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2759 M_INTMOVE(s3, REG_ITMP3);
2762 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2765 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2767 var_to_reg_int(s1, src->prev, REG_ITMP1);
2768 var_to_reg_int(s2, src, REG_ITMP2);
2769 if (iptr->op1 == 0) {
2770 gen_nullptr_check(s1);
2773 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2776 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2778 var_to_reg_int(s1, src->prev, REG_ITMP1);
2779 var_to_reg_int(s2, src, REG_ITMP2);
2780 if (iptr->op1 == 0) {
2781 gen_nullptr_check(s1);
2785 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2786 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2789 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2791 var_to_reg_int(s1, src->prev, REG_ITMP1);
2792 var_to_reg_int(s2, src, REG_ITMP2);
2793 if (iptr->op1 == 0) {
2794 gen_nullptr_check(s1);
2797 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2800 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2802 var_to_reg_int(s1, src->prev, REG_ITMP1);
2803 var_to_reg_int(s2, src, REG_ITMP2);
2804 if (iptr->op1 == 0) {
2805 gen_nullptr_check(s1);
2808 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2811 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2813 var_to_reg_int(s1, src->prev, REG_ITMP1);
2814 var_to_reg_int(s2, src, REG_ITMP2);
2815 if (iptr->op1 == 0) {
2816 gen_nullptr_check(s1);
2819 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2822 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2824 var_to_reg_int(s1, src->prev, REG_ITMP1);
2825 var_to_reg_int(s2, src, REG_ITMP2);
2826 if (iptr->op1 == 0) {
2827 gen_nullptr_check(s1);
2830 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2834 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2835 /* op1 = type, val.a = field address */
2837 /* if class isn't yet initialized, do it */
2838 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2839 /* call helper function which patches this code */
2840 i386_mov_imm_reg(cd, (s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2841 i386_mov_imm_reg(cd, (s4) asm_check_clinit, REG_ITMP2);
2842 i386_call_reg(cd, REG_ITMP2);
2845 a = dseg_addaddress(m, &(((fieldinfo *) iptr->val.a)->value));
2846 /* here it's slightly slower */
2847 i386_mov_imm_reg(cd, 0, REG_ITMP2);
2848 dseg_adddata(m, cd->mcodeptr);
2849 i386_mov_membase_reg(cd, REG_ITMP2, a, REG_ITMP2);
2850 switch (iptr->op1) {
2853 var_to_reg_int(s2, src, REG_ITMP1);
2854 i386_mov_reg_membase(cd, s2, REG_ITMP2, 0);
2857 if (src->flags & INMEMORY) {
2858 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
2859 i386_mov_reg_membase(cd, REG_ITMP1, REG_ITMP2, 0);
2860 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
2861 i386_mov_reg_membase(cd, REG_ITMP1, REG_ITMP2, 0 + 4);
2863 panic("PUTSTATIC: longs have to be in memory");
2867 var_to_reg_flt(s2, src, REG_FTMP1);
2868 i386_fstps_membase(cd, REG_ITMP2, 0);
2872 var_to_reg_flt(s2, src, REG_FTMP1);
2873 i386_fstpl_membase(cd, REG_ITMP2, 0);
2876 default: panic ("internal error");
2880 case ICMD_GETSTATIC: /* ... ==> ..., value */
2881 /* op1 = type, val.a = field address */
2883 /* if class isn't yet initialized, do it */
2884 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2885 /* call helper function which patches this code */
2886 i386_mov_imm_reg(cd, (s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2887 i386_mov_imm_reg(cd, (s4) asm_check_clinit, REG_ITMP2);
2888 i386_call_reg(cd, REG_ITMP2);
2891 a = dseg_addaddress(m, &(((fieldinfo *) iptr->val.a)->value));
2892 i386_mov_imm_reg(cd, 0, REG_ITMP2);
2893 dseg_adddata(m, cd->mcodeptr);
2894 i386_mov_membase_reg(cd, REG_ITMP2, a, REG_ITMP2);
2895 switch (iptr->op1) {
2898 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2899 i386_mov_membase_reg(cd, REG_ITMP2, 0, d);
2900 store_reg_to_var_int(iptr->dst, d);
2903 d = reg_of_var(m, iptr->dst, REG_NULL);
2904 if (iptr->dst->flags & INMEMORY) {
2905 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP1);
2906 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2907 i386_mov_membase_reg(cd, REG_ITMP2, 0 + 4, REG_ITMP1);
2908 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
2910 panic("GETSTATIC: longs have to be in memory");
2914 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2915 i386_flds_membase(cd, REG_ITMP2, 0);
2917 store_reg_to_var_flt(iptr->dst, d);
2920 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2921 i386_fldl_membase(cd, REG_ITMP2, 0);
2923 store_reg_to_var_flt(iptr->dst, d);
2925 default: panic ("internal error");
2929 case ICMD_PUTFIELD: /* ..., value ==> ... */
2930 /* op1 = type, val.i = field offset */
2932 a = ((fieldinfo *)(iptr->val.a))->offset;
2933 switch (iptr->op1) {
2936 var_to_reg_int(s1, src->prev, REG_ITMP1);
2937 var_to_reg_int(s2, src, REG_ITMP2);
2938 gen_nullptr_check(s1);
2939 i386_mov_reg_membase(cd, s2, s1, a);
2942 var_to_reg_int(s1, src->prev, REG_ITMP1);
2943 gen_nullptr_check(s1);
2944 if (src->flags & INMEMORY) {
2945 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);
2946 i386_mov_reg_membase(cd, REG_ITMP2, s1, a);
2947 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2948 i386_mov_reg_membase(cd, REG_ITMP2, s1, a + 4);
2950 panic("PUTFIELD: longs have to be in memory");
2954 var_to_reg_int(s1, src->prev, REG_ITMP1);
2955 var_to_reg_flt(s2, src, REG_FTMP1);
2956 gen_nullptr_check(s1);
2957 i386_fstps_membase(cd, s1, a);
2961 var_to_reg_int(s1, src->prev, REG_ITMP1);
2962 var_to_reg_flt(s2, src, REG_FTMP1);
2963 gen_nullptr_check(s1);
2964 i386_fstpl_membase(cd, s1, a);
2967 default: panic ("internal error");
2971 case ICMD_GETFIELD: /* ... ==> ..., value */
2972 /* op1 = type, val.i = field offset */
2974 a = ((fieldinfo *)(iptr->val.a))->offset;
2975 switch (iptr->op1) {
2978 var_to_reg_int(s1, src, REG_ITMP1);
2979 d = reg_of_var(m, iptr->dst, REG_ITMP2);
2980 gen_nullptr_check(s1);
2981 i386_mov_membase_reg(cd, s1, a, d);
2982 store_reg_to_var_int(iptr->dst, d);
2985 var_to_reg_int(s1, src, REG_ITMP1);
2986 d = reg_of_var(m, iptr->dst, REG_NULL);
2987 gen_nullptr_check(s1);
2988 i386_mov_membase_reg(cd, s1, a, REG_ITMP2);
2989 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
2990 i386_mov_membase_reg(cd, s1, a + 4, REG_ITMP2);
2991 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2994 var_to_reg_int(s1, src, REG_ITMP1);
2995 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2996 gen_nullptr_check(s1);
2997 i386_flds_membase(cd, s1, a);
2999 store_reg_to_var_flt(iptr->dst, d);
3002 var_to_reg_int(s1, src, REG_ITMP1);
3003 d = reg_of_var(m, iptr->dst, REG_FTMP1);
3004 gen_nullptr_check(s1);
3005 i386_fldl_membase(cd, s1, a);
3007 store_reg_to_var_flt(iptr->dst, d);
3009 default: panic ("internal error");
3014 /* branch operations **************************************************/
3017 /* #define ALIGNCODENOP {if((int)((long)cd->mcodeptr&7)){M_NOP;}} */
3018 #define ALIGNCODENOP do {} while (0)
3020 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3022 var_to_reg_int(s1, src, REG_ITMP1);
3023 M_INTMOVE(s1, REG_ITMP1_XPTR);
3025 i386_call_imm(cd, 0); /* passing exception pointer */
3026 i386_pop_reg(cd, REG_ITMP2_XPC);
3028 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
3029 i386_jmp_reg(cd, REG_ITMP3);
3033 case ICMD_GOTO: /* ... ==> ... */
3034 /* op1 = target JavaVM pc */
3036 i386_jmp_imm(cd, 0);
3037 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3041 case ICMD_JSR: /* ... ==> ... */
3042 /* op1 = target JavaVM pc */
3044 i386_call_imm(cd, 0);
3045 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3048 case ICMD_RET: /* ... ==> ... */
3049 /* op1 = local variable */
3051 var = &(r->locals[iptr->op1][TYPE_ADR]);
3052 var_to_reg_int(s1, var, REG_ITMP1);
3053 i386_jmp_reg(cd, s1);
3056 case ICMD_IFNULL: /* ..., value ==> ... */
3057 /* op1 = target JavaVM pc */
3059 if (src->flags & INMEMORY) {
3060 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3063 i386_test_reg_reg(cd, src->regoff, src->regoff);
3065 i386_jcc(cd, I386_CC_E, 0);
3066 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3069 case ICMD_IFNONNULL: /* ..., value ==> ... */
3070 /* op1 = target JavaVM pc */
3072 if (src->flags & INMEMORY) {
3073 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3076 i386_test_reg_reg(cd, src->regoff, src->regoff);
3078 i386_jcc(cd, I386_CC_NE, 0);
3079 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3082 case ICMD_IFEQ: /* ..., value ==> ... */
3083 /* op1 = target JavaVM pc, val.i = constant */
3085 if (src->flags & INMEMORY) {
3086 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3089 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3091 i386_jcc(cd, I386_CC_E, 0);
3092 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3095 case ICMD_IFLT: /* ..., value ==> ... */
3096 /* op1 = target JavaVM pc, val.i = constant */
3098 if (src->flags & INMEMORY) {
3099 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3102 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3104 i386_jcc(cd, I386_CC_L, 0);
3105 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3108 case ICMD_IFLE: /* ..., value ==> ... */
3109 /* op1 = target JavaVM pc, val.i = constant */
3111 if (src->flags & INMEMORY) {
3112 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3115 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3117 i386_jcc(cd, I386_CC_LE, 0);
3118 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3121 case ICMD_IFNE: /* ..., value ==> ... */
3122 /* op1 = target JavaVM pc, val.i = constant */
3124 if (src->flags & INMEMORY) {
3125 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3128 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3130 i386_jcc(cd, I386_CC_NE, 0);
3131 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3134 case ICMD_IFGT: /* ..., value ==> ... */
3135 /* op1 = target JavaVM pc, val.i = constant */
3137 if (src->flags & INMEMORY) {
3138 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3141 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3143 i386_jcc(cd, I386_CC_G, 0);
3144 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3147 case ICMD_IFGE: /* ..., value ==> ... */
3148 /* op1 = target JavaVM pc, val.i = constant */
3150 if (src->flags & INMEMORY) {
3151 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3154 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3156 i386_jcc(cd, I386_CC_GE, 0);
3157 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3160 case ICMD_IF_LEQ: /* ..., value ==> ... */
3161 /* op1 = target JavaVM pc, val.l = constant */
3163 if (src->flags & INMEMORY) {
3164 if (iptr->val.l == 0) {
3165 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3166 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3169 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3170 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3171 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3172 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l, REG_ITMP1);
3173 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3176 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3177 i386_jcc(cd, I386_CC_E, 0);
3178 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3181 case ICMD_IF_LLT: /* ..., value ==> ... */
3182 /* op1 = target JavaVM pc, val.l = constant */
3184 if (src->flags & INMEMORY) {
3185 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3186 i386_jcc(cd, I386_CC_L, 0);
3187 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3190 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3191 CALCIMMEDIATEBYTES(a, iptr->val.l);
3193 i386_jcc(cd, I386_CC_G, a);
3195 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3196 i386_jcc(cd, I386_CC_B, 0);
3197 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3201 case ICMD_IF_LLE: /* ..., value ==> ... */
3202 /* op1 = target JavaVM pc, val.l = constant */
3204 if (src->flags & INMEMORY) {
3205 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3206 i386_jcc(cd, I386_CC_L, 0);
3207 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3210 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3211 CALCIMMEDIATEBYTES(a, iptr->val.l);
3213 i386_jcc(cd, I386_CC_G, a);
3215 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3216 i386_jcc(cd, I386_CC_BE, 0);
3217 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3221 case ICMD_IF_LNE: /* ..., value ==> ... */
3222 /* op1 = target JavaVM pc, val.l = constant */
3224 if (src->flags & INMEMORY) {
3225 if (iptr->val.l == 0) {
3226 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3227 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3230 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3231 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3232 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3233 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3234 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3237 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3238 i386_jcc(cd, I386_CC_NE, 0);
3239 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3242 case ICMD_IF_LGT: /* ..., value ==> ... */
3243 /* op1 = target JavaVM pc, val.l = constant */
3245 if (src->flags & INMEMORY) {
3246 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3247 i386_jcc(cd, I386_CC_G, 0);
3248 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3251 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3252 CALCIMMEDIATEBYTES(a, iptr->val.l);
3254 i386_jcc(cd, I386_CC_L, a);
3256 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3257 i386_jcc(cd, I386_CC_A, 0);
3258 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3262 case ICMD_IF_LGE: /* ..., value ==> ... */
3263 /* op1 = target JavaVM pc, val.l = constant */
3265 if (src->flags & INMEMORY) {
3266 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3267 i386_jcc(cd, I386_CC_G, 0);
3268 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3271 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3272 CALCIMMEDIATEBYTES(a, iptr->val.l);
3274 i386_jcc(cd, I386_CC_L, a);
3276 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3277 i386_jcc(cd, I386_CC_AE, 0);
3278 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3282 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3283 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3285 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3286 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3287 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3289 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3290 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3292 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3293 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3296 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3298 i386_jcc(cd, I386_CC_E, 0);
3299 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3302 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3303 /* op1 = target JavaVM pc */
3305 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3306 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3307 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3308 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3309 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3310 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3311 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3313 i386_jcc(cd, I386_CC_E, 0);
3314 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3317 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3318 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3320 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3321 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3322 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3324 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3325 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3327 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3328 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3331 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3333 i386_jcc(cd, I386_CC_NE, 0);
3334 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3337 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3338 /* op1 = target JavaVM pc */
3340 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3341 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3342 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3343 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3344 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3345 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3346 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3348 i386_jcc(cd, I386_CC_NE, 0);
3349 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3352 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3353 /* op1 = target JavaVM pc */
3355 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3356 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3357 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3359 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3360 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3362 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3363 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3366 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3368 i386_jcc(cd, I386_CC_L, 0);
3369 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3372 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3373 /* op1 = target JavaVM pc */
3375 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3376 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3377 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3378 i386_jcc(cd, I386_CC_L, 0);
3379 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3382 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3383 CALCOFFSETBYTES(a, REG_SP, src->regoff);
3385 i386_jcc(cd, I386_CC_G, a);
3387 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3388 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3389 i386_jcc(cd, I386_CC_B, 0);
3390 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3394 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3395 /* op1 = target JavaVM pc */
3397 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3398 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3399 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3401 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3402 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3404 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3405 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3408 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3410 i386_jcc(cd, I386_CC_G, 0);
3411 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3414 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3415 /* op1 = target JavaVM pc */
3417 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3418 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3419 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3420 i386_jcc(cd, I386_CC_G, 0);
3421 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3424 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3425 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3427 i386_jcc(cd, I386_CC_L, a);
3429 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3430 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3431 i386_jcc(cd, I386_CC_A, 0);
3432 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3436 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3437 /* op1 = target JavaVM pc */
3439 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3440 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3441 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3443 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3444 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3446 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3447 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3450 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3452 i386_jcc(cd, I386_CC_LE, 0);
3453 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3456 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3457 /* op1 = target JavaVM pc */
3459 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3460 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3461 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3462 i386_jcc(cd, I386_CC_L, 0);
3463 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3466 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3467 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3469 i386_jcc(cd, I386_CC_G, a);
3471 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3472 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3473 i386_jcc(cd, I386_CC_BE, 0);
3474 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3478 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3479 /* op1 = target JavaVM pc */
3481 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3482 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3483 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3485 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3486 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3488 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3489 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3492 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3494 i386_jcc(cd, I386_CC_GE, 0);
3495 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3498 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3499 /* op1 = target JavaVM pc */
3501 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3502 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3503 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3504 i386_jcc(cd, I386_CC_G, 0);
3505 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3508 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3509 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3511 i386_jcc(cd, I386_CC_L, a);
3513 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3514 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3515 i386_jcc(cd, I386_CC_AE, 0);
3516 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3520 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3522 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3525 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3526 /* val.i = constant */
3528 d = reg_of_var(m, iptr->dst, REG_NULL);
3529 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
3532 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3533 /* val.i = constant */
3535 d = reg_of_var(m, iptr->dst, REG_NULL);
3536 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
3539 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3540 /* val.i = constant */
3542 d = reg_of_var(m, iptr->dst, REG_NULL);
3543 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
3546 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3547 /* val.i = constant */
3549 d = reg_of_var(m, iptr->dst, REG_NULL);
3550 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
3553 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3554 /* val.i = constant */
3556 d = reg_of_var(m, iptr->dst, REG_NULL);
3557 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
3560 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3561 /* val.i = constant */
3563 d = reg_of_var(m, iptr->dst, REG_NULL);
3564 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
3568 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3571 var_to_reg_int(s1, src, REG_RESULT);
3572 M_INTMOVE(s1, REG_RESULT);
3574 goto nowperformreturn;
3576 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3578 if (src->flags & INMEMORY) {
3579 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_RESULT);
3580 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3583 panic("LRETURN: longs have to be in memory");
3586 goto nowperformreturn;
3588 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3589 case ICMD_DRETURN: /* ..., retvalue ==> ... */
3591 var_to_reg_flt(s1, src, REG_FRESULT);
3592 /* this may be an early return -- keep the offset correct for the
3596 goto nowperformreturn;
3598 case ICMD_RETURN: /* ... ==> ... */
3604 p = parentargs_base;
3606 /* call trace function */
3608 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3610 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3612 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3613 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3615 i386_fstl_membase(cd, REG_SP, 4 + 8);
3616 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3618 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3619 i386_call_reg(cd, REG_ITMP1);
3621 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3622 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3624 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3627 #if defined(USE_THREADS)
3628 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3629 i386_mov_membase_reg(cd, REG_SP, 8 * r->maxmemuse, REG_ITMP2);
3631 /* we need to save the proper return value */
3632 switch (iptr->opc) {
3635 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, r->maxmemuse * 8);
3639 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, r->maxmemuse * 8);
3640 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, r->maxmemuse * 8 + 4);
3644 i386_fsts_membase(cd, REG_SP, r->maxmemuse * 8);
3648 i386_fstl_membase(cd, REG_SP, r->maxmemuse * 8);
3652 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
3653 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, 0);
3654 i386_mov_imm_reg(cd, (s4) builtin_monitorexit, REG_ITMP1);
3655 i386_call_reg(cd, REG_ITMP1);
3656 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
3658 /* and now restore the proper return value */
3659 switch (iptr->opc) {
3662 i386_mov_membase_reg(cd, REG_SP, r->maxmemuse * 8, REG_RESULT);
3666 i386_mov_membase_reg(cd, REG_SP, r->maxmemuse * 8, REG_RESULT);
3667 i386_mov_membase_reg(cd, REG_SP, r->maxmemuse * 8 + 4, REG_RESULT2);
3671 i386_flds_membase(cd, REG_SP, r->maxmemuse * 8);
3675 i386_fldl_membase(cd, REG_SP, r->maxmemuse * 8);
3681 /* restore saved registers */
3682 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
3684 i386_mov_membase_reg(cd, REG_SP, p * 8, r->savintregs[i]);
3686 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
3688 i386_fldl_membase(cd, REG_SP, p * 8);
3690 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3691 i386_fstp_reg(cd, r->savfltregs[i] + fpu_st_offset + 1);
3693 i386_fstp_reg(cd, r->savfltregs[i] + fpu_st_offset);
3698 /* deallocate stack */
3699 if (parentargs_base) {
3700 i386_alu_imm_reg(cd, I386_ADD, parentargs_base * 8, REG_SP);
3709 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3714 tptr = (void **) iptr->target;
3716 s4ptr = iptr->val.a;
3717 l = s4ptr[1]; /* low */
3718 i = s4ptr[2]; /* high */
3720 var_to_reg_int(s1, src, REG_ITMP1);
3721 M_INTMOVE(s1, REG_ITMP1);
3723 i386_alu_imm_reg(cd, I386_SUB, l, REG_ITMP1);
3729 i386_alu_imm_reg(cd, I386_CMP, i - 1, REG_ITMP1);
3730 i386_jcc(cd, I386_CC_A, 0);
3732 /* codegen_addreference(m, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
3733 codegen_addreference(m, (basicblock *) tptr[0], cd->mcodeptr);
3735 /* build jump table top down and use address of lowest entry */
3737 /* s4ptr += 3 + i; */
3741 /* dseg_addtarget(m, BlockPtrOfPC(*--s4ptr)); */
3742 dseg_addtarget(m, (basicblock *) tptr[0]);
3746 /* length of dataseg after last dseg_addtarget is used by load */
3748 i386_mov_imm_reg(cd, 0, REG_ITMP2);
3749 dseg_adddata(m, cd->mcodeptr);
3750 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3751 i386_jmp_reg(cd, REG_ITMP1);
3757 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3759 s4 i, l, val, *s4ptr;
3762 tptr = (void **) iptr->target;
3764 s4ptr = iptr->val.a;
3765 l = s4ptr[0]; /* default */
3766 i = s4ptr[1]; /* count */
3768 MCODECHECK((i<<2)+8);
3769 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3775 i386_alu_imm_reg(cd, I386_CMP, val, s1);
3776 i386_jcc(cd, I386_CC_E, 0);
3777 /* codegen_addreference(m, BlockPtrOfPC(s4ptr[1]), cd->mcodeptr); */
3778 codegen_addreference(m, (basicblock *) tptr[0], cd->mcodeptr);
3781 i386_jmp_imm(cd, 0);
3782 /* codegen_addreference(m, BlockPtrOfPC(l), cd->mcodeptr); */
3784 tptr = (void **) iptr->target;
3785 codegen_addreference(m, (basicblock *) tptr[0], cd->mcodeptr);
3792 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3793 /* op1 = return type, val.a = function pointer*/
3797 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3798 /* op1 = return type, val.a = function pointer*/
3802 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3803 /* op1 = return type, val.a = function pointer*/
3807 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3808 /* op1 = arg count, val.a = method pointer */
3810 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3811 /* op1 = arg count, val.a = method pointer */
3813 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3814 /* op1 = arg count, val.a = method pointer */
3816 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3817 /* op1 = arg count, val.a = method pointer */
3824 MCODECHECK((s3 << 1) + 64);
3826 /* copy arguments to registers or stack location */
3828 for (; --s3 >= 0; src = src->prev) {
3829 if (src->varkind == ARGVAR) {
3833 if (IS_INT_LNG_TYPE(src->type)) {
3834 if (s3 < r->intreg_argnum) {
3835 panic("No integer argument registers available!");
3838 if (!IS_2_WORD_TYPE(src->type)) {
3839 if (src->flags & INMEMORY) {
3840 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3841 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s3 * 8);
3844 i386_mov_reg_membase(cd, src->regoff, REG_SP, s3 * 8);
3848 if (src->flags & INMEMORY) {
3849 M_LNGMEMMOVE(src->regoff, s3);
3852 panic("copy arguments: longs have to be in memory");
3858 if (s3 < r->fltreg_argnum) {
3859 panic("No float argument registers available!");
3862 var_to_reg_flt(d, src, REG_FTMP1);
3863 if (src->type == TYPE_FLT) {
3864 i386_fstps_membase(cd, REG_SP, s3 * 8);
3867 i386_fstpl_membase(cd, REG_SP, s3 * 8);
3874 switch (iptr->opc) {
3881 i386_mov_imm_reg(cd, a, REG_ITMP1);
3882 i386_call_reg(cd, REG_ITMP1);
3885 case ICMD_INVOKESTATIC:
3886 a = (u4) lm->stubroutine;
3889 i386_mov_imm_reg(cd, a, REG_ITMP2);
3890 i386_call_reg(cd, REG_ITMP2);
3893 case ICMD_INVOKESPECIAL:
3894 a = (u4) lm->stubroutine;
3897 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3898 gen_nullptr_check(REG_ITMP1);
3899 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
3901 i386_mov_imm_reg(cd, a, REG_ITMP2);
3902 i386_call_reg(cd, REG_ITMP2);
3905 case ICMD_INVOKEVIRTUAL:
3908 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3909 gen_nullptr_check(REG_ITMP1);
3910 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
3911 i386_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
3913 i386_call_reg(cd, REG_ITMP1);
3916 case ICMD_INVOKEINTERFACE:
3919 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3920 gen_nullptr_check(REG_ITMP1);
3921 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3922 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * lm->class->index, REG_ITMP2);
3923 i386_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - lm->class->methods), REG_ITMP1);
3925 i386_call_reg(cd, REG_ITMP1);
3929 /* d contains return type */
3931 if (d != TYPE_VOID) {
3932 d = reg_of_var(m, iptr->dst, REG_NULL);
3934 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3935 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3936 if (iptr->dst->flags & INMEMORY) {
3937 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3938 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
3941 panic("RETURN: longs have to be in memory");
3945 if (iptr->dst->flags & INMEMORY) {
3946 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3949 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
3954 /* fld from called function -- has other fpu_st_offset counter */
3956 store_reg_to_var_flt(iptr->dst, d);
3963 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3965 /* op1: 0 == array, 1 == class */
3966 /* val.a: (classinfo*) superclass */
3968 /* superclass is an interface:
3970 * return (sub != NULL) &&
3971 * (sub->vftbl->interfacetablelength > super->index) &&
3972 * (sub->vftbl->interfacetable[-super->index] != NULL);
3974 * superclass is a class:
3976 * return ((sub != NULL) && (0
3977 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3978 * super->vftbl->diffvall));
3982 classinfo *super = (classinfo*) iptr->val.a;
3984 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3985 codegen_threadcritrestart(m, cd->mcodeptr - cd->mcodebase);
3987 var_to_reg_int(s1, src, REG_ITMP1);
3988 d = reg_of_var(m, iptr->dst, REG_ITMP3);
3990 M_INTMOVE(s1, REG_ITMP1);
3993 i386_alu_reg_reg(cd, I386_XOR, d, d);
3994 if (iptr->op1) { /* class/interface */
3995 if (super->flags & ACC_INTERFACE) { /* interface */
3996 i386_test_reg_reg(cd, s1, s1);
3998 /* TODO: clean up this calculation */
4000 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4003 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4006 /* CALCOFFSETBYTES(a, super->index); */
4007 CALCIMMEDIATEBYTES(a, super->index);
4013 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4020 i386_jcc(cd, I386_CC_E, a);
4022 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4023 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4024 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4026 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4028 /* TODO: clean up this calculation */
4031 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4038 i386_jcc(cd, I386_CC_LE, a);
4039 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4041 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP1);
4042 /* i386_setcc_reg(cd, I386_CC_A, d); */
4043 /* i386_jcc(cd, I386_CC_BE, 5); */
4044 i386_jcc(cd, I386_CC_E, 5);
4045 i386_mov_imm_reg(cd, 1, d);
4048 } else { /* class */
4049 i386_test_reg_reg(cd, s1, s1);
4051 /* TODO: clean up this calculation */
4053 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4056 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4058 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4061 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4071 i386_jcc(cd, I386_CC_E, a);
4073 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4074 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4075 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4076 codegen_threadcritstart(m, cd->mcodeptr - cd->mcodebase);
4078 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4079 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4080 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4081 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4082 codegen_threadcritstop(m, cd->mcodeptr - cd->mcodebase);
4084 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4085 i386_alu_reg_reg(cd, I386_XOR, d, d);
4087 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4088 i386_jcc(cd, I386_CC_A, 5);
4089 i386_mov_imm_reg(cd, 1, d);
4093 panic ("internal error: no inlined array instanceof");
4095 store_reg_to_var_int(iptr->dst, d);
4098 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4100 /* op1: 0 == array, 1 == class */
4101 /* val.a: (classinfo*) superclass */
4103 /* superclass is an interface:
4105 * OK if ((sub == NULL) ||
4106 * (sub->vftbl->interfacetablelength > super->index) &&
4107 * (sub->vftbl->interfacetable[-super->index] != NULL));
4109 * superclass is a class:
4111 * OK if ((sub == NULL) || (0
4112 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4113 * super->vftbl->diffvall));
4117 classinfo *super = (classinfo*) iptr->val.a;
4119 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4120 codegen_threadcritrestart(m, cd->mcodeptr - cd->mcodebase);
4122 d = reg_of_var(m, iptr->dst, REG_ITMP3);
4123 var_to_reg_int(s1, src, d);
4124 if (iptr->op1) { /* class/interface */
4125 if (super->flags & ACC_INTERFACE) { /* interface */
4126 i386_test_reg_reg(cd, s1, s1);
4128 /* TODO: clean up this calculation */
4130 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4133 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4136 /* CALCOFFSETBYTES(a, super->index); */
4137 CALCIMMEDIATEBYTES(a, super->index);
4143 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4148 i386_jcc(cd, I386_CC_E, a);
4150 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4151 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4152 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4154 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4155 i386_jcc(cd, I386_CC_LE, 0);
4156 codegen_addxcastrefs(m, cd->mcodeptr);
4157 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
4159 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4160 i386_jcc(cd, I386_CC_E, 0);
4161 codegen_addxcastrefs(m, cd->mcodeptr);
4163 } else { /* class */
4164 i386_test_reg_reg(cd, s1, s1);
4166 /* TODO: clean up this calculation */
4168 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4173 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4175 if (d != REG_ITMP3) {
4177 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4180 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4186 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4193 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4200 i386_jcc(cd, I386_CC_E, a);
4202 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4203 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4204 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4205 codegen_threadcritstart(m, cd->mcodeptr - cd->mcodebase);
4207 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4208 if (d != REG_ITMP3) {
4209 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4210 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4211 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4212 codegen_threadcritstop(m, cd->mcodeptr - cd->mcodebase);
4214 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4217 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
4218 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1);
4219 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4220 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4221 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4222 codegen_threadcritstop(m, cd->mcodeptr - cd->mcodebase);
4226 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4227 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
4228 codegen_addxcastrefs(m, cd->mcodeptr);
4232 panic ("internal error: no inlined array checkcast");
4235 store_reg_to_var_int(iptr->dst, d);
4238 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4240 if (src->flags & INMEMORY) {
4241 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4244 i386_test_reg_reg(cd, src->regoff, src->regoff);
4246 i386_jcc(cd, I386_CC_L, 0);
4247 codegen_addxcheckarefs(m, cd->mcodeptr);
4250 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4252 i386_test_reg_reg(cd, REG_RESULT, REG_RESULT);
4253 i386_jcc(cd, I386_CC_E, 0);
4254 codegen_addxexceptionrefs(m, cd->mcodeptr);
4257 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4258 /* op1 = dimension, val.a = array descriptor */
4260 /* check for negative sizes and copy sizes to stack if necessary */
4262 MCODECHECK((iptr->op1 << 1) + 64);
4264 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4265 if (src->flags & INMEMORY) {
4266 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4269 i386_test_reg_reg(cd, src->regoff, src->regoff);
4271 i386_jcc(cd, I386_CC_L, 0);
4272 codegen_addxcheckarefs(m, cd->mcodeptr);
4275 * copy sizes to new stack location, be cause native function
4276 * builtin_nmultianewarray access them as (int *)
4278 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
4279 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);
4281 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
4283 if (src->varkind != ARGVAR) {
4284 if (src->flags & INMEMORY) {
4285 i386_mov_membase_reg(cd, REG_SP, (src->regoff + INT_ARG_CNT) * 8, REG_ITMP1);
4286 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, (s1 + INT_ARG_CNT) * 8);
4289 i386_mov_reg_membase(cd, src->regoff, REG_SP, (s1 + INT_ARG_CNT) * 8);
4293 i386_alu_imm_reg(cd, I386_SUB, iptr->op1 * 4, REG_SP);
4295 /* a0 = dimension count */
4297 /* save stack pointer */
4298 M_INTMOVE(REG_SP, REG_ITMP1);
4300 i386_alu_imm_reg(cd, I386_SUB, 12, REG_SP);
4301 i386_mov_imm_membase(cd, iptr->op1, REG_SP, 0);
4303 /* a1 = arraydescriptor */
4305 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, 4);
4307 /* a2 = pointer to dimensions = stack pointer */
4309 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 8);
4311 i386_mov_imm_reg(cd, (s4) (builtin_nmultianewarray), REG_ITMP1);
4312 i386_call_reg(cd, REG_ITMP1);
4313 i386_alu_imm_reg(cd, I386_ADD, 12 + iptr->op1 * 4, REG_SP);
4315 s1 = reg_of_var(m, iptr->dst, REG_RESULT);
4316 M_INTMOVE(REG_RESULT, s1);
4317 store_reg_to_var_int(iptr->dst, s1);
4321 error ("Unknown pseudo command: %d", iptr->opc);
4324 } /* for instruction */
4326 /* copy values to interface registers */
4328 src = bptr->outstack;
4329 len = bptr->outdepth;
4333 if ((src->varkind != STACKVAR)) {
4335 if (IS_FLT_DBL_TYPE(s2)) {
4336 var_to_reg_flt(s1, src, REG_FTMP1);
4337 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
4338 M_FLTMOVE(s1, r->interfaces[len][s2].regoff);
4341 panic("double store");
4342 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4346 var_to_reg_int(s1, src, REG_ITMP1);
4347 if (!IS_2_WORD_TYPE(r->interfaces[len][s2].type)) {
4348 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
4349 M_INTMOVE(s1, r->interfaces[len][s2].regoff);
4352 i386_mov_reg_membase(cd, s1, REG_SP, r->interfaces[len][s2].regoff * 8);
4356 if (r->interfaces[len][s2].flags & INMEMORY) {
4357 M_LNGMEMMOVE(s1, r->interfaces[len][s2].regoff);
4360 panic("copy interface registers: longs have to be in memory (end)");
4367 } /* if (bptr -> flags >= BBREACHED) */
4368 } /* for basic block */
4370 codegen_createlinenumbertable(m);
4374 /* generate bound check stubs */
4376 u1 *xcodeptr = NULL;
4379 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
4380 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4382 cd->mcodeptr - cd->mcodebase);
4386 /* move index register into REG_ITMP1 */
4387 i386_mov_reg_reg(cd, bref->reg, REG_ITMP1); /* 2 bytes */
4389 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4390 dseg_adddata(m, cd->mcodeptr);
4391 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3); /* 5 bytes */
4392 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4394 if (xcodeptr != NULL) {
4395 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4398 xcodeptr = cd->mcodeptr;
4400 i386_push_reg(cd, REG_ITMP2_XPC);
4402 PREPARE_NATIVE_STACKINFO;
4404 i386_alu_imm_reg(cd, I386_SUB, 2 * 4, REG_SP);
4405 i386_mov_imm_membase(cd, (s4) string_java_lang_ArrayIndexOutOfBoundsException, REG_SP, 0 * 4);
4406 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 1 * 4);
4407 i386_mov_imm_reg(cd, (s4) new_exception_int, REG_ITMP1);
4408 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4409 i386_alu_imm_reg(cd, I386_ADD, 2 * 4, REG_SP);
4411 REMOVE_NATIVE_STACKINFO;
4413 i386_pop_reg(cd, REG_ITMP2_XPC);
4415 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4416 i386_jmp_reg(cd, REG_ITMP3);
4420 /* generate negative array size check stubs */
4424 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
4425 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4426 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4428 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4432 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4434 cd->mcodeptr - cd->mcodebase);
4438 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4439 dseg_adddata(m, cd->mcodeptr);
4440 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4441 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4443 if (xcodeptr != NULL) {
4444 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4447 xcodeptr = cd->mcodeptr;
4449 i386_push_reg(cd, REG_ITMP2_XPC);
4451 PREPARE_NATIVE_STACKINFO;
4453 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4454 i386_mov_imm_membase(cd, (s4) string_java_lang_NegativeArraySizeException, REG_SP, 0 * 4);
4455 i386_mov_imm_reg(cd, (s4) new_exception, REG_ITMP1);
4456 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4457 i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4460 REMOVE_NATIVE_STACKINFO;
4462 i386_pop_reg(cd, REG_ITMP2_XPC);
4464 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4465 i386_jmp_reg(cd, REG_ITMP3);
4469 /* generate cast check stubs */
4473 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
4474 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4475 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4477 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4481 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4483 cd->mcodeptr - cd->mcodebase);
4487 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4488 dseg_adddata(m, cd->mcodeptr);
4489 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4490 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4492 if (xcodeptr != NULL) {
4493 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4496 xcodeptr = cd->mcodeptr;
4498 i386_push_reg(cd, REG_ITMP2_XPC);
4501 PREPARE_NATIVE_STACKINFO;
4503 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4504 i386_mov_imm_membase(cd, (s4) string_java_lang_ClassCastException, REG_SP, 0 * 4);
4505 i386_mov_imm_reg(cd, (s4) new_exception, REG_ITMP1);
4506 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4507 i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4510 REMOVE_NATIVE_STACKINFO;
4512 i386_pop_reg(cd, REG_ITMP2_XPC);
4514 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4515 i386_jmp_reg(cd, REG_ITMP3);
4519 /* generate divide by zero check stubs */
4523 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
4524 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4525 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4527 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4531 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4533 cd->mcodeptr - cd->mcodebase);
4537 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4538 dseg_adddata(m, cd->mcodeptr);
4539 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4540 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4542 if (xcodeptr != NULL) {
4543 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4546 xcodeptr = cd->mcodeptr;
4548 i386_push_reg(cd, REG_ITMP2_XPC);
4550 PREPARE_NATIVE_STACKINFO;
4552 i386_alu_imm_reg(cd, I386_SUB, 2 * 4, REG_SP);
4553 i386_mov_imm_membase(cd, (s4) string_java_lang_ArithmeticException, REG_SP, 0 * 4);
4554 i386_mov_imm_membase(cd, (s4) string_java_lang_ArithmeticException_message, REG_SP, 1 * 4);
4555 i386_mov_imm_reg(cd, (s4) new_exception_message, REG_ITMP1);
4556 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4557 i386_alu_imm_reg(cd, I386_ADD, 2 * 4, REG_SP);
4559 REMOVE_NATIVE_STACKINFO;
4561 i386_pop_reg(cd, REG_ITMP2_XPC);
4563 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4564 i386_jmp_reg(cd, REG_ITMP3);
4568 /* generate exception check stubs */
4572 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
4573 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4574 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4576 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4580 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4582 cd->mcodeptr - cd->mcodebase);
4586 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4587 dseg_adddata(m, cd->mcodeptr);
4588 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4589 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4591 if (xcodeptr != NULL) {
4592 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4595 xcodeptr = cd->mcodeptr;
4597 i386_push_reg(cd, REG_ITMP2_XPC);
4599 PREPARE_NATIVE_STACKINFO;
4601 i386_mov_imm_reg(cd, (s4) codegen_general_stubcalled, REG_ITMP1);
4602 i386_call_reg(cd, REG_ITMP1);
4604 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4605 i386_mov_imm_reg(cd, (s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4606 i386_call_reg(cd, REG_ITMP1);
4607 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP3);
4608 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
4609 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1_XPTR);
4611 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP3);
4612 i386_mov_membase_reg(cd, REG_ITMP3, 0, REG_ITMP1_XPTR);
4613 i386_mov_imm_membase(cd, 0, REG_ITMP3, 0);
4615 i386_push_imm(cd, 0);
4616 i386_push_reg(cd, REG_ITMP1_XPTR);
4618 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4619 java stack at this point*/
4620 i386_mov_membase_reg(cd, REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4621 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, class), REG_ITMP1);
4622 i386_push_imm(cd, (u4) utf_fillInStackTrace_desc);
4623 i386_push_imm(cd, (u4) utf_fillInStackTrace_name);
4624 i386_push_reg(cd, REG_ITMP1);
4625 i386_mov_imm_reg(cd, (s4) class_resolvemethod, REG_ITMP3);
4626 i386_call_reg(cd, REG_ITMP3);
4627 /*cleanup parameters of class_resolvemethod*/
4628 i386_alu_imm_reg(cd, I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4629 /*prepare call to asm_calljavafunction2 */
4630 i386_push_imm(cd, 0);
4631 i386_push_imm(cd, TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
4632 i386_push_reg(cd, REG_SP);
4633 i386_push_imm(cd, sizeof(jni_callblock));
4634 i386_push_imm(cd, 1);
4635 i386_push_reg(cd, REG_RESULT);
4637 i386_mov_imm_reg(cd, (s4) asm_calljavafunction2, REG_ITMP3);
4638 i386_call_reg(cd, REG_ITMP3);
4640 /* check exceptionptr + fail (JOWENN)*/
4642 i386_alu_imm_reg(cd, I386_ADD,6*4,REG_SP);
4644 i386_pop_reg(cd, REG_ITMP1_XPTR);
4645 i386_pop_reg(cd, REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4647 REMOVE_NATIVE_STACKINFO;
4649 i386_pop_reg(cd, REG_ITMP2_XPC);
4651 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4652 i386_jmp_reg(cd, REG_ITMP3);
4656 /* generate null pointer check stubs */
4660 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
4661 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4662 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4664 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4668 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4670 cd->mcodeptr - cd->mcodebase);
4674 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4675 dseg_adddata(m, cd->mcodeptr);
4676 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4677 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4679 if (xcodeptr != NULL) {
4680 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4683 xcodeptr = cd->mcodeptr;
4685 i386_push_reg(cd, REG_ITMP2_XPC);
4687 PREPARE_NATIVE_STACKINFO;
4690 /* create native call block*/
4691 i386_alu_imm_reg(cd, I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4694 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1);
4695 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/
4697 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4698 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
4699 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
4700 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
4701 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4702 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */
4703 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4706 /* create exception*/
4707 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4708 i386_mov_imm_membase(cd, (s4) string_java_lang_NullPointerException, REG_SP, 0 * 4);
4709 i386_mov_imm_reg(cd, (s4) new_exception, REG_ITMP1);
4710 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4711 i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4713 REMOVE_NATIVE_STACKINFO;
4716 /* restore native call stack */
4717 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2);
4718 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3);
4719 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0);
4720 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
4723 i386_pop_reg(cd, REG_ITMP2_XPC);
4725 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4726 i386_jmp_reg(cd, REG_ITMP3);
4731 codegen_finish(m, (u4) (cd->mcodeptr - cd->mcodebase));
4735 /* function createcompilerstub *************************************************
4737 creates a stub routine which calls the compiler
4739 *******************************************************************************/
4741 #define COMPSTUBSIZE 12
4743 u1 *createcompilerstub(methodinfo *m)
4745 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
4748 /* setup codegendata structure */
4751 cd = m->codegendata;
4754 /* code for the stub */
4755 i386_mov_imm_reg(cd, (u4) m, REG_ITMP1);/* pass method pointer to compiler*/
4757 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
4758 i386_mov_imm_reg(cd, (u4) asm_call_jit_compiler, REG_ITMP3);
4759 i386_jmp_reg(cd, REG_ITMP3); /* jump to compiler */
4761 /* free codegendata memory */
4764 #if defined(STATISTICS)
4766 count_cstub_len += COMPSTUBSIZE;
4773 /* function removecompilerstub *************************************************
4775 deletes a compilerstub from memory (simply by freeing it)
4777 *******************************************************************************/
4779 void removecompilerstub(u1 *stub)
4781 CFREE(stub, COMPSTUBSIZE);
4785 /* function: createnativestub **************************************************
4787 creates a stub routine which calls a native method
4789 *******************************************************************************/
4791 #define NATIVESTUBSIZE 350
4793 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4794 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4797 void i386_native_stub_debug(void **p) {
4798 printf("Pos on stack: %p\n",p);
4799 printf("Return adress should be: %p\n",*p);
4802 void i386_native_stub_debug2(void **p) {
4803 printf("Pos on stack: %p\n",p);
4804 printf("Return for lookup is: %p\n",*p);
4807 void traverseStackInfo() {
4808 void **p=builtin_asm_get_stackframeinfo();
4812 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4813 m=*((methodinfo**)((*p)+8));
4814 utf_display(m->name);
4822 u1 *createnativestub(functionptr f, methodinfo *m)
4824 u1 *s = CNEW(u1, NATIVESTUBSIZE); /* memory to hold the stub */
4828 int stackframesize = 4+12; /* initial 4 bytes is space for jni env,
4829 + 4 byte thread pointer + 4 byte previous pointer + method info*/
4830 int stackframeoffset = 4;
4835 /* setup codegendata structure */
4838 cd = m->codegendata;
4841 if (m->flags & ACC_STATIC) {
4842 stackframesize += 4;
4843 stackframeoffset += 4;
4847 descriptor2types(m); /* set paramcount and paramtypes */
4850 /* i386_push_reg(cd, REG_SP);
4851 i386_mov_imm_reg(cd, (s4) i386_native_stub_debug, REG_ITMP1);
4852 i386_call_reg(cd, REG_ITMP1);
4853 i386_pop_reg(cd, REG_ITMP1);*/
4856 /* if function is static, check for initialized */
4858 if (m->flags & ACC_STATIC) {
4859 /* if class isn't yet initialized, do it */
4860 if (!m->class->initialized) {
4861 s4 *header = (s4 *) s;
4862 *header = 0;/*extablesize*/
4864 *header = 0;/*line number table start*/
4866 *header = 0;/*line number table size*/
4868 *header = 0;/*fltsave*/
4870 *header = 0;/*intsave*/
4872 *header = 0;/*isleaf*/
4874 *header = 0;/*issync*/
4876 *header = 0;/*framesize*/
4878 *header = (u4) m;/*methodpointer*/
4880 cd->mcodeptr = s = (u1 *) header;
4883 /* call helper function which patches this code */
4884 i386_mov_imm_reg(cd, (u4) m->class, REG_ITMP1);
4885 i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP2);
4886 i386_call_reg(cd, REG_ITMP2);
4891 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4893 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
4894 t = m->paramtypes[p];
4895 if (IS_INT_LNG_TYPE(t)) {
4896 if (IS_2_WORD_TYPE(t)) {
4897 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4898 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
4899 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4900 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4902 } else if (t == TYPE_ADR) {
4903 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4904 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
4905 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4906 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4909 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
4911 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
4912 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
4916 if (!IS_2_WORD_TYPE(t)) {
4917 i386_flds_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4918 i386_fstps_membase(cd, REG_SP, p * 8);
4919 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
4920 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4923 i386_fldl_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4924 i386_fstpl_membase(cd, REG_SP, p * 8);
4929 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
4930 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
4931 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4932 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
4935 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
4937 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
4938 i386_call_reg(cd, REG_ITMP1);
4940 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4944 * mark the whole fpu stack as free for native functions
4945 * (only for saved register count == 0)
4947 i386_ffree_reg(cd, 0);
4948 i386_ffree_reg(cd, 1);
4949 i386_ffree_reg(cd, 2);
4950 i386_ffree_reg(cd, 3);
4951 i386_ffree_reg(cd, 4);
4952 i386_ffree_reg(cd, 5);
4953 i386_ffree_reg(cd, 6);
4954 i386_ffree_reg(cd, 7);
4956 /* calculate stackframe size for native function */
4957 tptr = m->paramtypes;
4958 for (i = 0; i < m->paramcount; i++) {
4963 stackframesize += 4;
4968 stackframesize += 8;
4972 panic("unknown parameter type in native function");
4976 i386_alu_imm_reg(cd, I386_SUB, stackframesize, REG_SP);
4978 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
4979 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
4980 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
4981 i386_call_reg(cd, REG_ITMP1);
4982 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
4983 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2);
4984 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
4985 i386_mov_reg_reg(cd, REG_SP,REG_ITMP2);
4986 i386_alu_imm_reg(cd, I386_ADD,stackframesize-12,REG_ITMP2);
4987 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0);
4990 /* i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
4991 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
4992 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-12);*/
4994 /* CREATE DYNAMIC STACK INFO -- END*/
4997 tptr = m->paramtypes;
4998 for (i = 0; i < m->paramcount; i++) {
5003 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5004 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5005 stackframeoffset += 4;
5010 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5011 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5012 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5013 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, stackframeoffset + 4);
5014 stackframeoffset += 8;
5018 panic("unknown parameter type in native function");
5022 if (m->flags & ACC_STATIC) {
5023 /* put class into second argument */
5024 i386_mov_imm_membase(cd, (s4) m->class, REG_SP, 4);
5027 /* put env into first argument */
5028 i386_mov_imm_membase(cd, (s4) &env, REG_SP, 0);
5030 i386_mov_imm_reg(cd, (s4) f, REG_ITMP1);
5031 i386_call_reg(cd, REG_ITMP1);
5032 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5033 i386_push_reg(cd, REG_RESULT2);
5034 i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
5035 i386_mov_membase_reg(cd, REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
5036 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT2,0);
5037 i386_pop_reg(cd, REG_RESULT2);
5038 /*REMOVE DYNAMIC STACK INFO -END */
5040 i386_alu_imm_reg(cd, I386_ADD, stackframesize, REG_SP);
5044 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5046 i386_mov_imm_membase(cd, (u4) m, REG_SP, 0);
5048 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
5049 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
5051 i386_fstl_membase(cd, REG_SP, 4 + 8);
5052 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5054 i386_mov_imm_reg(cd, (u4) builtin_displaymethodstop, REG_ITMP1);
5055 i386_call_reg(cd, REG_ITMP1);
5057 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
5058 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
5060 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5064 /* we can't use REG_ITMP3 == REG_RESULT2 */
5065 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5066 i386_push_reg(cd, REG_RESULT);
5067 i386_push_reg(cd, REG_RESULT2);
5068 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5069 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP2);
5070 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5071 i386_pop_reg(cd, REG_RESULT2);
5072 i386_pop_reg(cd, REG_RESULT);
5074 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5075 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP2);
5076 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5078 i386_jcc(cd, I386_CC_NE, 1);
5082 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5083 i386_push_reg(cd, REG_ITMP2);
5084 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5085 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5086 i386_pop_reg(cd, REG_ITMP1_XPTR);
5088 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1_XPTR);
5089 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5090 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5092 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP2_XPC);
5093 i386_alu_imm_reg(cd, I386_SUB, 2, REG_ITMP2_XPC);
5095 i386_mov_imm_reg(cd, (s4) asm_handle_nat_exception, REG_ITMP3);
5096 i386_jmp_reg(cd, REG_ITMP3);
5099 codegen_insertmethod(s, cd->mcodeptr);
5103 dolog_plain("native stubentry: %p, stubsize: %x (for %d params) --", (s4)s,(s4) (cd->mcodeptr - s), m->paramcount);
5104 utf_display(m->name);
5108 /* free codegendata memory */
5111 #if defined(STATISTICS)
5113 count_nstub_len += NATIVESTUBSIZE;
5120 /* function: removenativestub **************************************************
5122 removes a previously created native-stub from memory
5124 *******************************************************************************/
5126 void removenativestub(u1 *stub)
5128 CFREE(stub, NATIVESTUBSIZE);
5133 * These are local overrides for various environment variables in Emacs.
5134 * Please do not remove this and leave it at the end of the file, where
5135 * Emacs will automagically detect them.
5136 * ---------------------------------------------------------------------
5139 * indent-tabs-mode: t