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 1367 2004-08-01 07:29:50Z stefan $
40 #include <sys/ucontext.h>
50 #include "jit/parse.h"
52 #include "jit/i386/codegen.h"
53 #include "jit/i386/emitfuncs.h"
55 /* include independent code generation stuff */
56 #include "jit/codegen.inc"
57 #include "jit/reg.inc"
60 /* register descripton - array ************************************************/
62 /* #define REG_RES 0 reserved register for OS or code generator */
63 /* #define REG_RET 1 return value register */
64 /* #define REG_EXC 2 exception value register (only old jit) */
65 /* #define REG_SAV 3 (callee) saved register */
66 /* #define REG_TMP 4 scratch temporary register (caller saved) */
67 /* #define REG_ARG 5 argument register (caller saved) */
69 /* #define REG_END -1 last entry in tables */
72 we initially try to use %edx as scratch register, it cannot be used if we
73 have one of these ICMDs:
74 LMUL, LMULCONST, IDIV, IREM, LALOAD, AASTORE, LASTORE, IASTORE, CASTORE,
75 SASTORE, BASTORE, INSTANCEOF, CHECKCAST, I2L, F2L, D2L
78 REG_RET, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV,
83 int nregdescfloat[] = {
84 /* rounding problems with callee saved registers */
85 /* REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_RES, REG_RES, */
86 /* REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, */
87 REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
92 void codegen_stubcalled() {
93 log_text("Stub has been called");
96 void codegen_general_stubcalled() {
97 log_text("general exception stub has been called");
101 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
102 void thread_restartcriticalsection(ucontext_t *uc)
105 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL)
106 uc->uc_mcontext.gregs[REG_EIP] = (u4) critical;
111 #define PREPARE_NATIVE_STACKINFO \
112 i386_push_reg(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 */
210 sigemptyset(&act.sa_mask);
214 /* signal(SIGSEGV, (void *) catch_NullPointerException); */
215 act.sa_sigaction = (void *) catch_NullPointerException;
216 act.sa_flags = SA_SIGINFO;
217 sigaction(SIGSEGV, &act, NULL);
221 /* signal(SIGBUS, (void *) catch_NullPointerException); */
222 act.sa_sigaction = (void *) catch_NullPointerException;
223 act.sa_flags = SA_SIGINFO;
224 sigaction(SIGBUS, &act, NULL);
228 /* signal(SIGFPE, (void *) catch_ArithmeticException); */
229 act.sa_sigaction = (void *) catch_ArithmeticException;
230 act.sa_flags = SA_SIGINFO;
231 sigaction(SIGFPE, &act, NULL);
235 /* function codegen ************************************************************
237 generates machine code
239 *******************************************************************************/
241 void codegen(methodinfo *m)
243 int len, s1, s2, s3, d;
253 s4 fpu_st_offset = 0;
259 s4 savedregs_num = 0;
261 /* keep code size smaller */
265 /* space to save used callee saved registers */
267 savedregs_num += (r->savintregcnt - r->maxsavintreguse);
268 savedregs_num += (r->savfltregcnt - r->maxsavfltreguse);
270 parentargs_base = r->maxmemuse + savedregs_num;
272 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
274 if (checksync && (m->flags & ACC_SYNCHRONIZED))
279 /* create method header */
281 (void) dseg_addaddress(m, m); /* MethodPointer */
282 (void) dseg_adds4(m, parentargs_base * 8); /* FrameSize */
284 #if defined(USE_THREADS)
286 /* IsSync contains the offset relative to the stack pointer for the
287 argument of monitor_exit used in the exception handler. Since the
288 offset could be zero and give a wrong meaning of the flag it is
292 if (checksync && (m->flags & ACC_SYNCHRONIZED))
293 (void) dseg_adds4(m, (r->maxmemuse + 1) * 8); /* IsSync */
298 (void) dseg_adds4(m, 0); /* IsSync */
300 (void) dseg_adds4(m, m->isleafmethod); /* IsLeaf */
301 (void) dseg_adds4(m, r->savintregcnt - r->maxsavintreguse); /* IntSave */
302 (void) dseg_adds4(m, r->savfltregcnt - r->maxsavfltreguse); /* FltSave */
304 /* adds a reference for the length of the line number counter. We don't
305 know the size yet, since we evaluate the information during code
306 generation, to save one additional iteration over the whole
307 instructions. During code optimization the position could have changed
308 to the information gotten from the class file */
309 (void) dseg_addlinenumbertablesize(m);
311 (void) dseg_adds4(m, m->exceptiontablelength); /* ExTableSize */
313 /* create exception table */
315 for (ex = m->exceptiontable; ex != NULL; ex = ex->down) {
316 dseg_addtarget(m, ex->start);
317 dseg_addtarget(m, ex->end);
318 dseg_addtarget(m, ex->handler);
319 (void) dseg_addaddress(m, ex->catchtype);
323 /* initialize mcode variables */
325 cd->mcodeptr = cd->mcodebase;
326 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
327 MCODECHECK(128 + m->paramcount);
329 /* create stack frame (if necessary) */
331 if (parentargs_base) {
332 i386_alu_imm_reg(cd, I386_SUB, parentargs_base * 8, REG_SP);
335 /* save return address and used callee saved registers */
338 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
339 p--; i386_mov_reg_membase(cd, r->savintregs[i], REG_SP, p * 8);
341 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
342 p--; i386_fld_reg(cd, r->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 8);
345 /* save monitorenter argument */
347 #if defined(USE_THREADS)
348 s4 func_enter = (m->flags & ACC_STATIC) ?
349 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
351 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
352 if (m->flags & ACC_STATIC) {
353 i386_mov_imm_reg(cd, (s4) m->class, REG_ITMP1);
354 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r->maxmemuse * 8);
357 i386_mov_membase_reg(cd, REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
358 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r->maxmemuse * 8);
361 /* call monitorenter function */
363 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
364 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
365 i386_mov_imm_reg(cd, func_enter, REG_ITMP1);
366 i386_call_reg(cd, REG_ITMP1);
367 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
371 /* copy argument registers to stack and call trace function with pointer
372 to arguments on stack.
376 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
378 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
379 t = m->paramtypes[p];
381 if (IS_INT_LNG_TYPE(t)) {
382 if (IS_2_WORD_TYPE(t)) {
383 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
384 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
385 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
386 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
388 /* } else if (t == TYPE_ADR) { */
390 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
391 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
392 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
393 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
396 /* i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
398 /* i386_mov_reg_membase(cd, EAX, REG_SP, p * 8); */
399 /* i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4); */
403 if (!IS_2_WORD_TYPE(t)) {
404 i386_flds_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
405 i386_fstps_membase(cd, REG_SP, p * 8);
406 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
407 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
410 i386_fldl_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
411 i386_fstpl_membase(cd, REG_SP, p * 8);
416 /* fill up the remaining arguments */
417 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
418 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
419 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
420 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
423 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
424 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
425 i386_call_reg(cd, REG_ITMP1);
427 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
430 /* take arguments out of register or stack frame */
432 for (p = 0, l = 0; p < m->paramcount; p++) {
433 t = m->paramtypes[p];
434 var = &(r->locals[l][t]);
436 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
440 if (IS_INT_LNG_TYPE(t)) { /* integer args */
441 if (p < r->intreg_argnum) { /* register arguments */
442 panic("integer register argument");
443 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
444 /* M_INTMOVE (argintregs[p], r); */
446 } else { /* reg arg -> spilled */
447 /* M_LST (argintregs[p], REG_SP, 8 * r); */
449 } else { /* stack arguments */
450 pa = p - r->intreg_argnum;
451 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
452 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, var->regoff); /* + 4 for return address */
453 } else { /* stack arg -> spilled */
454 if (!IS_2_WORD_TYPE(t)) {
455 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
456 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
459 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
460 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
461 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1); /* + 4 for return address */
462 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8 + 4);
467 } else { /* floating args */
468 if (p < r->fltreg_argnum) { /* register arguments */
469 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
470 panic("There are no float argument registers!");
472 } else { /* reg arg -> spilled */
473 panic("There are no float argument registers!");
476 } else { /* stack arguments */
477 pa = p - r->fltreg_argnum;
478 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
480 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
482 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
486 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
488 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
492 } else { /* stack-arg -> spilled */
493 /* i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
494 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r * 8); */
496 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
497 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
500 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
501 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
510 /* end of header generation */
512 /* walk through all basic blocks */
513 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
515 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
517 if (bptr->flags >= BBREACHED) {
519 /* branch resolving */
522 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
523 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
528 /* copy interface registers to their destination */
533 while (src != NULL) {
535 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
536 if (!IS_2_WORD_TYPE(src->type)) {
537 if (bptr->type == BBTYPE_SBR) {
538 d = reg_of_var(m, src, REG_ITMP1);
540 store_reg_to_var_int(src, d);
542 } else if (bptr->type == BBTYPE_EXH) {
543 d = reg_of_var(m, src, REG_ITMP1);
544 M_INTMOVE(REG_ITMP1, d);
545 store_reg_to_var_int(src, d);
549 panic("copy interface registers: longs have to me in memory (begin 1)");
553 d = reg_of_var(m, src, REG_ITMP1);
554 if ((src->varkind != STACKVAR)) {
556 if (IS_FLT_DBL_TYPE(s2)) {
557 s1 = r->interfaces[len][s2].regoff;
558 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
562 if (s2 == TYPE_FLT) {
563 i386_flds_membase(cd, REG_SP, s1 * 8);
566 i386_fldl_membase(cd, REG_SP, s1 * 8);
569 store_reg_to_var_flt(src, d);
572 s1 = r->interfaces[len][s2].regoff;
573 if (!IS_2_WORD_TYPE(r->interfaces[len][s2].type)) {
574 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
578 i386_mov_membase_reg(cd, REG_SP, s1 * 8, d);
580 store_reg_to_var_int(src, d);
583 if (r->interfaces[len][s2].flags & INMEMORY) {
584 M_LNGMEMMOVE(s1, src->regoff);
587 panic("copy interface registers: longs have to be in memory (begin 2)");
596 /* walk through all instructions */
601 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
602 if (iptr->line != currentline) {
603 dseg_addlinenumber(m, iptr->line, cd->mcodeptr);
604 currentline = iptr->line;
607 MCODECHECK(64); /* an instruction usually needs < 64 words */
610 case ICMD_NOP: /* ... ==> ... */
613 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
614 if (src->flags & INMEMORY) {
615 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
618 i386_test_reg_reg(cd, src->regoff, src->regoff);
620 i386_jcc(cd, I386_CC_E, 0);
621 codegen_addxnullrefs(m, cd->mcodeptr);
624 /* constant operations ************************************************/
626 case ICMD_ICONST: /* ... ==> ..., constant */
627 /* op1 = 0, val.i = constant */
629 d = reg_of_var(m, iptr->dst, REG_ITMP1);
630 if (iptr->dst->flags & INMEMORY) {
631 i386_mov_imm_membase(cd, iptr->val.i, REG_SP, iptr->dst->regoff * 8);
634 if (iptr->val.i == 0) {
635 i386_alu_reg_reg(cd, I386_XOR, d, d);
638 i386_mov_imm_reg(cd, iptr->val.i, d);
643 case ICMD_LCONST: /* ... ==> ..., constant */
644 /* op1 = 0, val.l = constant */
646 d = reg_of_var(m, iptr->dst, REG_ITMP1);
647 if (iptr->dst->flags & INMEMORY) {
648 i386_mov_imm_membase(cd, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
649 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
652 panic("LCONST: longs have to be in memory");
656 case ICMD_FCONST: /* ... ==> ..., constant */
657 /* op1 = 0, val.f = constant */
659 d = reg_of_var(m, iptr->dst, REG_FTMP1);
660 if (iptr->val.f == 0.0) {
665 if (iptr->val.i == 0x80000000) {
669 } else if (iptr->val.f == 1.0) {
673 } else if (iptr->val.f == 2.0) {
680 a = dseg_addfloat(m, iptr->val.f);
681 i386_mov_imm_reg(cd, 0, REG_ITMP1);
682 dseg_adddata(m, cd->mcodeptr);
683 i386_flds_membase(cd, REG_ITMP1, a);
686 store_reg_to_var_flt(iptr->dst, d);
689 case ICMD_DCONST: /* ... ==> ..., constant */
690 /* op1 = 0, val.d = constant */
692 d = reg_of_var(m, iptr->dst, REG_FTMP1);
693 if (iptr->val.d == 0.0) {
698 if (iptr->val.l == 0x8000000000000000LL) {
702 } else if (iptr->val.d == 1.0) {
706 } else if (iptr->val.d == 2.0) {
713 a = dseg_adddouble(m, iptr->val.d);
714 i386_mov_imm_reg(cd, 0, REG_ITMP1);
715 dseg_adddata(m, cd->mcodeptr);
716 i386_fldl_membase(cd, REG_ITMP1, a);
719 store_reg_to_var_flt(iptr->dst, d);
722 case ICMD_ACONST: /* ... ==> ..., constant */
723 /* op1 = 0, val.a = constant */
725 d = reg_of_var(m, iptr->dst, REG_ITMP1);
726 if (iptr->dst->flags & INMEMORY) {
727 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
730 if ((s4) iptr->val.a == 0) {
731 i386_alu_reg_reg(cd, I386_XOR, d, d);
734 i386_mov_imm_reg(cd, (s4) iptr->val.a, d);
740 /* load/store operations **********************************************/
742 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
743 case ICMD_ALOAD: /* op1 = local variable */
745 d = reg_of_var(m, iptr->dst, REG_ITMP1);
746 if ((iptr->dst->varkind == LOCALVAR) &&
747 (iptr->dst->varnum == iptr->op1)) {
750 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
751 if (iptr->dst->flags & INMEMORY) {
752 if (var->flags & INMEMORY) {
753 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, REG_ITMP1);
754 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
757 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
761 if (var->flags & INMEMORY) {
762 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, iptr->dst->regoff);
765 M_INTMOVE(var->regoff, iptr->dst->regoff);
770 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
771 /* op1 = local variable */
773 d = reg_of_var(m, iptr->dst, REG_ITMP1);
774 if ((iptr->dst->varkind == LOCALVAR) &&
775 (iptr->dst->varnum == iptr->op1)) {
778 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
779 if (iptr->dst->flags & INMEMORY) {
780 if (var->flags & INMEMORY) {
781 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
784 panic("LLOAD: longs have to be in memory");
788 panic("LLOAD: longs have to be in memory");
792 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
793 /* op1 = local variable */
795 d = reg_of_var(m, iptr->dst, REG_FTMP1);
796 if ((iptr->dst->varkind == LOCALVAR) &&
797 (iptr->dst->varnum == iptr->op1)) {
800 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
801 if (var->flags & INMEMORY) {
802 i386_flds_membase(cd, REG_SP, var->regoff * 8);
805 i386_fld_reg(cd, var->regoff + fpu_st_offset);
808 store_reg_to_var_flt(iptr->dst, d);
811 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
812 /* op1 = local variable */
814 d = reg_of_var(m, iptr->dst, REG_FTMP1);
815 if ((iptr->dst->varkind == LOCALVAR) &&
816 (iptr->dst->varnum == iptr->op1)) {
819 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
820 if (var->flags & INMEMORY) {
821 i386_fldl_membase(cd, REG_SP, var->regoff * 8);
824 i386_fld_reg(cd, var->regoff + fpu_st_offset);
827 store_reg_to_var_flt(iptr->dst, d);
830 case ICMD_ISTORE: /* ..., value ==> ... */
831 case ICMD_ASTORE: /* op1 = local variable */
833 if ((src->varkind == LOCALVAR) &&
834 (src->varnum == iptr->op1)) {
837 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
838 if (var->flags & INMEMORY) {
839 if (src->flags & INMEMORY) {
840 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
841 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
844 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 8);
848 var_to_reg_int(s1, src, var->regoff);
849 M_INTMOVE(s1, var->regoff);
853 case ICMD_LSTORE: /* ..., value ==> ... */
854 /* op1 = local variable */
856 if ((src->varkind == LOCALVAR) &&
857 (src->varnum == iptr->op1)) {
860 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
861 if (var->flags & INMEMORY) {
862 if (src->flags & INMEMORY) {
863 M_LNGMEMMOVE(src->regoff, var->regoff);
866 panic("LSTORE: longs have to be in memory");
870 panic("LSTORE: longs have to be in memory");
874 case ICMD_FSTORE: /* ..., value ==> ... */
875 /* op1 = local variable */
877 if ((src->varkind == LOCALVAR) &&
878 (src->varnum == iptr->op1)) {
881 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
882 if (var->flags & INMEMORY) {
883 var_to_reg_flt(s1, src, REG_FTMP1);
884 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
887 var_to_reg_flt(s1, src, var->regoff);
888 /* M_FLTMOVE(s1, var->regoff); */
889 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
894 case ICMD_DSTORE: /* ..., value ==> ... */
895 /* op1 = local variable */
897 if ((src->varkind == LOCALVAR) &&
898 (src->varnum == iptr->op1)) {
901 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
902 if (var->flags & INMEMORY) {
903 var_to_reg_flt(s1, src, REG_FTMP1);
904 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
907 var_to_reg_flt(s1, src, var->regoff);
908 /* M_FLTMOVE(s1, var->regoff); */
909 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
915 /* pop/dup/swap operations ********************************************/
917 /* attention: double and longs are only one entry in CACAO ICMDs */
919 case ICMD_POP: /* ..., value ==> ... */
920 case ICMD_POP2: /* ..., value, value ==> ... */
923 case ICMD_DUP: /* ..., a ==> ..., a, a */
924 M_COPY(src, iptr->dst);
927 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
929 M_COPY(src, iptr->dst);
930 M_COPY(src->prev, iptr->dst->prev);
933 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
935 M_COPY(src, iptr->dst);
936 M_COPY(src->prev, iptr->dst->prev);
937 M_COPY(iptr->dst, iptr->dst->prev->prev);
940 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
942 M_COPY(src, iptr->dst);
943 M_COPY(src->prev, iptr->dst->prev);
944 M_COPY(src->prev->prev, iptr->dst->prev->prev);
945 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
948 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
950 M_COPY(src, iptr->dst);
951 M_COPY(src->prev, iptr->dst->prev);
952 M_COPY(src->prev->prev, iptr->dst->prev->prev);
953 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
954 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev);
957 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
959 M_COPY(src, iptr->dst);
960 M_COPY(src->prev, iptr->dst->prev);
961 M_COPY(src->prev->prev, iptr->dst->prev->prev);
962 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
963 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
964 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
967 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
969 M_COPY(src, iptr->dst->prev);
970 M_COPY(src->prev, iptr->dst);
974 /* integer operations *************************************************/
976 case ICMD_INEG: /* ..., value ==> ..., - value */
978 d = reg_of_var(m, iptr->dst, REG_NULL);
979 if (iptr->dst->flags & INMEMORY) {
980 if (src->flags & INMEMORY) {
981 if (src->regoff == iptr->dst->regoff) {
982 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
985 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
986 i386_neg_reg(cd, REG_ITMP1);
987 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
991 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
992 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
996 if (src->flags & INMEMORY) {
997 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
998 i386_neg_reg(cd, iptr->dst->regoff);
1001 M_INTMOVE(src->regoff, iptr->dst->regoff);
1002 i386_neg_reg(cd, iptr->dst->regoff);
1007 case ICMD_LNEG: /* ..., value ==> ..., - value */
1009 d = reg_of_var(m, iptr->dst, REG_NULL);
1010 if (iptr->dst->flags & INMEMORY) {
1011 if (src->flags & INMEMORY) {
1012 if (src->regoff == iptr->dst->regoff) {
1013 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1014 i386_alu_imm_membase(cd, I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1015 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8 + 4);
1018 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1019 i386_neg_reg(cd, REG_ITMP1);
1020 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1021 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1022 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP1);
1023 i386_neg_reg(cd, REG_ITMP1);
1024 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1030 case ICMD_I2L: /* ..., value ==> ..., value */
1032 d = reg_of_var(m, iptr->dst, REG_NULL);
1033 if (iptr->dst->flags & INMEMORY) {
1034 if (src->flags & INMEMORY) {
1035 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, EAX);
1037 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1038 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1041 M_INTMOVE(src->regoff, EAX);
1043 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1044 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1049 case ICMD_L2I: /* ..., value ==> ..., value */
1051 d = reg_of_var(m, iptr->dst, REG_NULL);
1052 if (iptr->dst->flags & INMEMORY) {
1053 if (src->flags & INMEMORY) {
1054 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1055 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1059 if (src->flags & INMEMORY) {
1060 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1065 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1067 d = reg_of_var(m, iptr->dst, REG_NULL);
1068 if (iptr->dst->flags & INMEMORY) {
1069 if (src->flags & INMEMORY) {
1070 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1071 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1072 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1073 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1076 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1077 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1078 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1082 if (src->flags & INMEMORY) {
1083 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1084 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1085 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1088 M_INTMOVE(src->regoff, iptr->dst->regoff);
1089 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1090 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1095 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1097 d = reg_of_var(m, iptr->dst, REG_NULL);
1098 if (iptr->dst->flags & INMEMORY) {
1099 if (src->flags & INMEMORY) {
1100 if (src->regoff == iptr->dst->regoff) {
1101 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1104 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1105 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, REG_ITMP1);
1106 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1110 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1111 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1115 if (src->flags & INMEMORY) {
1116 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1117 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1120 M_INTMOVE(src->regoff, iptr->dst->regoff);
1121 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1126 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1128 d = reg_of_var(m, iptr->dst, REG_NULL);
1129 if (iptr->dst->flags & INMEMORY) {
1130 if (src->flags & INMEMORY) {
1131 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1132 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1133 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1134 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1137 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1138 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1139 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1143 if (src->flags & INMEMORY) {
1144 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1145 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1146 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1149 M_INTMOVE(src->regoff, iptr->dst->regoff);
1150 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1151 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1157 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1159 d = reg_of_var(m, iptr->dst, REG_NULL);
1160 i386_emit_ialu(cd, I386_ADD, src, iptr);
1163 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1164 /* val.i = constant */
1166 d = reg_of_var(m, iptr->dst, REG_NULL);
1167 /* should we use a inc optimization for smaller code size? */
1168 i386_emit_ialuconst(cd, I386_ADD, src, iptr);
1171 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1173 d = reg_of_var(m, iptr->dst, REG_NULL);
1174 if (iptr->dst->flags & INMEMORY) {
1175 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1176 if (src->regoff == iptr->dst->regoff) {
1177 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1178 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1179 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1180 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1182 } else if (src->prev->regoff == iptr->dst->regoff) {
1183 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1184 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1185 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1186 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1189 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1190 i386_alu_membase_reg(cd, I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1191 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1192 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1193 i386_alu_membase_reg(cd, I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1194 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1201 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1202 /* val.l = constant */
1204 d = reg_of_var(m, iptr->dst, REG_NULL);
1205 if (iptr->dst->flags & INMEMORY) {
1206 if (src->flags & INMEMORY) {
1207 if (src->regoff == iptr->dst->regoff) {
1208 i386_alu_imm_membase(cd, I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1209 i386_alu_imm_membase(cd, I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1212 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1213 i386_alu_imm_reg(cd, I386_ADD, iptr->val.l, REG_ITMP1);
1214 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1215 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1216 i386_alu_imm_reg(cd, I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1217 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1223 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1225 d = reg_of_var(m, iptr->dst, REG_NULL);
1226 if (iptr->dst->flags & INMEMORY) {
1227 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1228 if (src->prev->regoff == iptr->dst->regoff) {
1229 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1230 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1233 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1234 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1235 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1238 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1239 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1240 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1241 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1243 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1244 if (src->prev->regoff == iptr->dst->regoff) {
1245 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1248 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1249 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1250 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1254 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1255 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1259 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1260 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1261 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1263 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1264 M_INTMOVE(src->prev->regoff, d);
1265 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1267 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1268 /* workaround for reg alloc */
1269 if (src->regoff == iptr->dst->regoff) {
1270 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1271 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1272 M_INTMOVE(REG_ITMP1, d);
1275 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1276 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1280 /* workaround for reg alloc */
1281 if (src->regoff == iptr->dst->regoff) {
1282 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1283 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1284 M_INTMOVE(REG_ITMP1, d);
1287 M_INTMOVE(src->prev->regoff, d);
1288 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1294 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1295 /* val.i = constant */
1297 d = reg_of_var(m, iptr->dst, REG_NULL);
1298 i386_emit_ialuconst(cd, I386_SUB, src, iptr);
1301 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1303 d = reg_of_var(m, iptr->dst, REG_NULL);
1304 if (iptr->dst->flags & INMEMORY) {
1305 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1306 if (src->prev->regoff == iptr->dst->regoff) {
1307 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1308 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1309 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1310 i386_alu_reg_membase(cd, I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1313 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1314 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1315 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1316 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1317 i386_alu_membase_reg(cd, I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1318 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1324 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1325 /* val.l = constant */
1327 d = reg_of_var(m, iptr->dst, REG_NULL);
1328 if (iptr->dst->flags & INMEMORY) {
1329 if (src->flags & INMEMORY) {
1330 if (src->regoff == iptr->dst->regoff) {
1331 i386_alu_imm_membase(cd, I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1332 i386_alu_imm_membase(cd, I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1335 /* TODO: could be size optimized with lea -- see gcc output */
1336 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1337 i386_alu_imm_reg(cd, I386_SUB, iptr->val.l, REG_ITMP1);
1338 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1339 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1340 i386_alu_imm_reg(cd, I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1341 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1347 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1349 d = reg_of_var(m, iptr->dst, REG_NULL);
1350 if (iptr->dst->flags & INMEMORY) {
1351 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1352 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1353 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1354 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1356 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1357 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1358 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1359 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1361 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1362 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1363 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1364 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1367 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1368 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1369 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1373 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1374 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1375 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1377 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1378 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1379 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1381 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1382 M_INTMOVE(src->regoff, iptr->dst->regoff);
1383 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1386 if (src->regoff == iptr->dst->regoff) {
1387 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1390 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1391 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1397 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1398 /* val.i = constant */
1400 d = reg_of_var(m, iptr->dst, REG_NULL);
1401 if (iptr->dst->flags & INMEMORY) {
1402 if (src->flags & INMEMORY) {
1403 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1404 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1407 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1408 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1412 if (src->flags & INMEMORY) {
1413 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1416 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1421 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1423 d = reg_of_var(m, iptr->dst, REG_NULL);
1424 if (iptr->dst->flags & INMEMORY) {
1425 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1426 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX); /* mem -> EAX */
1427 /* optimize move EAX -> REG_ITMP3 is slower??? */
1428 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1429 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1431 /* TODO: optimize move EAX -> REG_ITMP3 */
1432 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); /* mem -> ITMP3 */
1433 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1434 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1436 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP2); /* mem -> ITMP3 */
1437 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1439 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1440 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1441 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1446 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1447 /* val.l = constant */
1449 d = reg_of_var(m, iptr->dst, REG_NULL);
1450 if (iptr->dst->flags & INMEMORY) {
1451 if (src->flags & INMEMORY) {
1452 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1453 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1454 /* TODO: optimize move EAX -> REG_ITMP3 */
1455 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1456 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1458 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1459 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1460 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1462 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1463 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1464 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1469 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1471 d = reg_of_var(m, iptr->dst, REG_NULL);
1472 var_to_reg_int(s1, src, REG_ITMP2);
1474 if (src->prev->flags & INMEMORY) {
1475 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1478 M_INTMOVE(src->prev->regoff, EAX);
1481 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1482 i386_jcc(cd, I386_CC_NE, 3 + 6);
1483 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1484 i386_jcc(cd, I386_CC_E, 1 + 2);
1487 i386_idiv_reg(cd, s1);
1489 if (iptr->dst->flags & INMEMORY) {
1490 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1493 M_INTMOVE(EAX, iptr->dst->regoff);
1497 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1499 d = reg_of_var(m, iptr->dst, REG_NULL);
1500 var_to_reg_int(s1, src, REG_ITMP2);
1502 if (src->prev->flags & INMEMORY) {
1503 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1506 M_INTMOVE(src->prev->regoff, EAX);
1509 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1510 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1511 i386_alu_reg_reg(cd, I386_XOR, EDX, EDX);
1512 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1513 i386_jcc(cd, I386_CC_E, 1 + 2);
1516 i386_idiv_reg(cd, s1);
1518 if (iptr->dst->flags & INMEMORY) {
1519 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8);
1522 M_INTMOVE(EDX, iptr->dst->regoff);
1526 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1527 /* val.i = constant */
1529 /* TODO: optimize for `/ 2' */
1530 var_to_reg_int(s1, src, REG_ITMP1);
1531 d = reg_of_var(m, iptr->dst, REG_ITMP1);
1534 i386_test_reg_reg(cd, d, d);
1536 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1537 i386_jcc(cd, I386_CC_NS, a);
1538 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, d);
1540 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1541 store_reg_to_var_int(iptr->dst, d);
1544 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1545 /* val.i = constant */
1547 d = reg_of_var(m, iptr->dst, REG_NULL);
1548 if (iptr->dst->flags & INMEMORY) {
1549 if (src->flags & INMEMORY) {
1551 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1553 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1554 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1556 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1557 i386_jcc(cd, I386_CC_NS, a);
1558 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1559 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1560 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1561 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1563 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1564 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1569 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1570 /* val.i = constant */
1572 var_to_reg_int(s1, src, REG_ITMP1);
1573 d = reg_of_var(m, iptr->dst, REG_ITMP2);
1575 M_INTMOVE(s1, REG_ITMP1);
1582 CALCIMMEDIATEBYTES(a, iptr->val.i);
1585 /* TODO: optimize */
1587 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1588 i386_test_reg_reg(cd, s1, s1);
1589 i386_jcc(cd, I386_CC_GE, a);
1590 i386_mov_reg_reg(cd, s1, d);
1591 i386_neg_reg(cd, d);
1592 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1593 i386_neg_reg(cd, d);
1595 /* M_INTMOVE(s1, EAX); */
1596 /* i386_cltd(cd); */
1597 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1598 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1599 /* i386_alu_reg_reg(cd, I386_AND, iptr->val.i, EAX); */
1600 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1601 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1602 /* M_INTMOVE(EAX, d); */
1604 /* i386_alu_reg_reg(cd, I386_XOR, d, d); */
1605 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1606 /* i386_shrd_reg_reg(cd, s1, d); */
1607 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1609 store_reg_to_var_int(iptr->dst, d);
1612 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1613 /* val.l = constant */
1615 d = reg_of_var(m, iptr->dst, REG_NULL);
1616 if (iptr->dst->flags & INMEMORY) {
1617 if (src->flags & INMEMORY) {
1618 /* Intel algorithm -- does not work, because constant is wrong */
1619 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1); */
1620 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1622 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1623 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1624 /* i386_jcc(cd, I386_CC_NS, offset); */
1625 /* i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1626 /* i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP3); */
1628 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1629 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1630 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1632 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1634 /* i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1); */
1635 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1636 /* i386_alu_reg_reg(cd, I386_SBB, REG_ITMP3, REG_ITMP2); */
1638 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1639 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1641 /* Alpha algorithm */
1643 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1645 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1651 /* TODO: hmm, don't know if this is always correct */
1653 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1655 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1661 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1662 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1664 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1665 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1666 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1667 i386_jcc(cd, I386_CC_GE, a);
1669 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1670 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1672 i386_neg_reg(cd, REG_ITMP1);
1673 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1674 i386_neg_reg(cd, REG_ITMP2);
1676 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1677 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1679 i386_neg_reg(cd, REG_ITMP1);
1680 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1681 i386_neg_reg(cd, REG_ITMP2);
1683 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1684 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1689 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1691 d = reg_of_var(m, iptr->dst, REG_NULL);
1692 i386_emit_ishift(cd, I386_SHL, src, iptr);
1695 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1696 /* val.i = constant */
1698 d = reg_of_var(m, iptr->dst, REG_NULL);
1699 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1702 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1704 d = reg_of_var(m, iptr->dst, REG_NULL);
1705 i386_emit_ishift(cd, I386_SAR, src, iptr);
1708 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1709 /* val.i = constant */
1711 d = reg_of_var(m, iptr->dst, REG_NULL);
1712 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1715 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1717 d = reg_of_var(m, iptr->dst, REG_NULL);
1718 i386_emit_ishift(cd, I386_SHR, src, iptr);
1721 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1722 /* val.i = constant */
1724 d = reg_of_var(m, iptr->dst, REG_NULL);
1725 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1728 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1730 d = reg_of_var(m, iptr->dst, REG_NULL);
1731 if (iptr->dst->flags & INMEMORY ){
1732 if (src->prev->flags & INMEMORY) {
1733 /* if (src->prev->regoff == iptr->dst->regoff) { */
1734 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1736 /* if (src->flags & INMEMORY) { */
1737 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1739 /* M_INTMOVE(src->regoff, ECX); */
1742 /* i386_test_imm_reg(cd, 32, ECX); */
1743 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1744 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1745 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1); */
1747 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1748 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1751 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1752 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1754 if (src->flags & INMEMORY) {
1755 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1757 M_INTMOVE(src->regoff, ECX);
1760 i386_test_imm_reg(cd, 32, ECX);
1761 i386_jcc(cd, I386_CC_E, 2 + 2);
1762 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1763 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1765 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1766 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1767 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1768 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1774 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1775 /* val.i = constant */
1777 d = reg_of_var(m, iptr->dst, REG_NULL);
1778 if (iptr->dst->flags & INMEMORY ) {
1779 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1780 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1782 if (iptr->val.i & 0x20) {
1783 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1784 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1785 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1788 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1789 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1792 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1793 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1797 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1799 d = reg_of_var(m, iptr->dst, REG_NULL);
1800 if (iptr->dst->flags & INMEMORY ){
1801 if (src->prev->flags & INMEMORY) {
1802 /* if (src->prev->regoff == iptr->dst->regoff) { */
1803 /* TODO: optimize */
1804 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1805 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1807 /* if (src->flags & INMEMORY) { */
1808 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1810 /* M_INTMOVE(src->regoff, ECX); */
1813 /* i386_test_imm_reg(cd, 32, ECX); */
1814 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1815 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1816 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1818 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1819 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1820 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1821 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1824 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1825 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1827 if (src->flags & INMEMORY) {
1828 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1830 M_INTMOVE(src->regoff, ECX);
1833 i386_test_imm_reg(cd, 32, ECX);
1834 i386_jcc(cd, I386_CC_E, 2 + 3);
1835 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1836 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1838 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1839 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1840 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1841 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1847 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1848 /* val.i = constant */
1850 d = reg_of_var(m, iptr->dst, REG_NULL);
1851 if (iptr->dst->flags & INMEMORY ) {
1852 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1853 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1855 if (iptr->val.i & 0x20) {
1856 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1857 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
1858 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1861 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1862 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1865 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1866 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1870 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1872 d = reg_of_var(m, iptr->dst, REG_NULL);
1873 if (iptr->dst->flags & INMEMORY ){
1874 if (src->prev->flags & INMEMORY) {
1875 /* if (src->prev->regoff == iptr->dst->regoff) { */
1876 /* TODO: optimize */
1877 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1878 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1880 /* if (src->flags & INMEMORY) { */
1881 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1883 /* M_INTMOVE(src->regoff, ECX); */
1886 /* i386_test_imm_reg(cd, 32, ECX); */
1887 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1888 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1889 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2); */
1891 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1892 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
1893 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1894 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1897 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1898 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1900 if (src->flags & INMEMORY) {
1901 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1903 M_INTMOVE(src->regoff, ECX);
1906 i386_test_imm_reg(cd, 32, ECX);
1907 i386_jcc(cd, I386_CC_E, 2 + 2);
1908 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1909 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP3, REG_ITMP3);
1911 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1912 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
1913 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1914 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1920 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1921 /* val.l = constant */
1923 d = reg_of_var(m, iptr->dst, REG_NULL);
1924 if (iptr->dst->flags & INMEMORY ) {
1925 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1926 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1928 if (iptr->val.i & 0x20) {
1929 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1930 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
1931 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1934 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1935 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
1938 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1939 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1943 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1945 d = reg_of_var(m, iptr->dst, REG_NULL);
1946 i386_emit_ialu(cd, I386_AND, src, iptr);
1949 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1950 /* val.i = constant */
1952 d = reg_of_var(m, iptr->dst, REG_NULL);
1953 i386_emit_ialuconst(cd, I386_AND, src, iptr);
1956 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1958 d = reg_of_var(m, iptr->dst, REG_NULL);
1959 i386_emit_lalu(cd, I386_AND, src, iptr);
1962 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1963 /* val.l = constant */
1965 d = reg_of_var(m, iptr->dst, REG_NULL);
1966 i386_emit_laluconst(cd, I386_AND, src, iptr);
1969 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1971 d = reg_of_var(m, iptr->dst, REG_NULL);
1972 i386_emit_ialu(cd, I386_OR, src, iptr);
1975 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1976 /* val.i = constant */
1978 d = reg_of_var(m, iptr->dst, REG_NULL);
1979 i386_emit_ialuconst(cd, I386_OR, src, iptr);
1982 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1984 d = reg_of_var(m, iptr->dst, REG_NULL);
1985 i386_emit_lalu(cd, I386_OR, src, iptr);
1988 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1989 /* val.l = constant */
1991 d = reg_of_var(m, iptr->dst, REG_NULL);
1992 i386_emit_laluconst(cd, I386_OR, src, iptr);
1995 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1997 d = reg_of_var(m, iptr->dst, REG_NULL);
1998 i386_emit_ialu(cd, I386_XOR, src, iptr);
2001 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2002 /* val.i = constant */
2004 d = reg_of_var(m, iptr->dst, REG_NULL);
2005 i386_emit_ialuconst(cd, I386_XOR, src, iptr);
2008 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2010 d = reg_of_var(m, iptr->dst, REG_NULL);
2011 i386_emit_lalu(cd, I386_XOR, src, iptr);
2014 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2015 /* val.l = constant */
2017 d = reg_of_var(m, iptr->dst, REG_NULL);
2018 i386_emit_laluconst(cd, I386_XOR, src, iptr);
2021 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2022 /* op1 = variable, val.i = constant */
2024 var = &(r->locals[iptr->op1][TYPE_INT]);
2025 if (var->flags & INMEMORY) {
2026 i386_alu_imm_membase(cd, I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2029 i386_alu_imm_reg(cd, I386_ADD, iptr->val.i, var->regoff);
2034 /* floating operations ************************************************/
2036 #define ROUND_TO_SINGLE \
2037 i386_fstps_membase(cd, REG_SP, -8); \
2038 i386_flds_membase(cd, REG_SP, -8);
2040 #define ROUND_TO_DOUBLE \
2041 i386_fstpl_membase(cd, REG_SP, -8); \
2042 i386_fldl_membase(cd, REG_SP, -8);
2044 #define FPU_SET_24BIT_MODE \
2045 if (!fpu_in_24bit_mode) { \
2046 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2047 fpu_in_24bit_mode = 1; \
2050 #define FPU_SET_53BIT_MODE \
2051 if (fpu_in_24bit_mode) { \
2052 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2053 fpu_in_24bit_mode = 0; \
2056 #define ROUND_TO_SINGLE
2057 #define ROUND_TO_DOUBLE
2058 #define FPU_SET_24BIT_MODE
2059 #define FPU_SET_53BIT_MODE
2061 case ICMD_FNEG: /* ..., value ==> ..., - value */
2064 var_to_reg_flt(s1, src, REG_FTMP1);
2065 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2067 store_reg_to_var_flt(iptr->dst, d);
2070 case ICMD_DNEG: /* ..., value ==> ..., - value */
2073 var_to_reg_flt(s1, src, REG_FTMP1);
2074 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2076 store_reg_to_var_flt(iptr->dst, d);
2079 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2082 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2083 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2084 var_to_reg_flt(s2, src, REG_FTMP2);
2087 store_reg_to_var_flt(iptr->dst, d);
2090 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2093 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2094 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2095 var_to_reg_flt(s2, src, REG_FTMP2);
2098 store_reg_to_var_flt(iptr->dst, d);
2101 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2104 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2105 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2106 var_to_reg_flt(s2, src, REG_FTMP2);
2109 store_reg_to_var_flt(iptr->dst, d);
2112 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2115 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2116 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2117 var_to_reg_flt(s2, src, REG_FTMP2);
2120 store_reg_to_var_flt(iptr->dst, d);
2123 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2126 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2127 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2128 var_to_reg_flt(s2, src, REG_FTMP2);
2132 store_reg_to_var_flt(iptr->dst, d);
2135 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2138 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2139 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2141 /* i386_fldt_mem(cd, subnormal_bias1); */
2142 /* i386_fmulp(cd); */
2144 var_to_reg_flt(s2, src, REG_FTMP2);
2149 /* i386_fldt_mem(cd, subnormal_bias2); */
2150 /* i386_fmulp(cd); */
2152 store_reg_to_var_flt(iptr->dst, d);
2155 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2158 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2159 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2160 var_to_reg_flt(s2, src, REG_FTMP2);
2164 store_reg_to_var_flt(iptr->dst, d);
2167 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2170 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2171 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2173 /* i386_fldt_mem(cd, subnormal_bias1); */
2174 /* i386_fmulp(cd); */
2176 var_to_reg_flt(s2, src, REG_FTMP2);
2181 /* i386_fldt_mem(cd, subnormal_bias2); */
2182 /* i386_fmulp(cd); */
2184 store_reg_to_var_flt(iptr->dst, d);
2187 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2190 /* exchanged to skip fxch */
2191 var_to_reg_flt(s2, src, REG_FTMP2);
2192 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2193 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2194 /* i386_fxch(cd); */
2199 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2200 store_reg_to_var_flt(iptr->dst, d);
2201 i386_ffree_reg(cd, 0);
2206 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2209 /* exchanged to skip fxch */
2210 var_to_reg_flt(s2, src, REG_FTMP2);
2211 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2212 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2213 /* i386_fxch(cd); */
2218 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2219 store_reg_to_var_flt(iptr->dst, d);
2220 i386_ffree_reg(cd, 0);
2225 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2226 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2228 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2229 if (src->flags & INMEMORY) {
2230 i386_fildl_membase(cd, REG_SP, src->regoff * 8);
2234 a = dseg_adds4(m, 0);
2235 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2236 dseg_adddata(m, cd->mcodeptr);
2237 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, a);
2238 i386_fildl_membase(cd, REG_ITMP1, a);
2241 store_reg_to_var_flt(iptr->dst, d);
2244 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2245 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2247 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2248 if (src->flags & INMEMORY) {
2249 i386_fildll_membase(cd, REG_SP, src->regoff * 8);
2253 panic("L2F: longs have to be in memory");
2255 store_reg_to_var_flt(iptr->dst, d);
2258 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2260 var_to_reg_flt(s1, src, REG_FTMP1);
2261 d = reg_of_var(m, iptr->dst, REG_NULL);
2263 a = dseg_adds4(m, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2264 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2265 dseg_adddata(m, cd->mcodeptr);
2266 i386_fldcw_membase(cd, REG_ITMP1, a);
2268 if (iptr->dst->flags & INMEMORY) {
2269 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2272 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2273 i386_fldcw_membase(cd, REG_ITMP1, a);
2275 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2278 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2280 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2283 a = dseg_adds4(m, 0);
2284 i386_fistpl_membase(cd, REG_ITMP1, a);
2286 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2288 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2289 i386_fldcw_membase(cd, REG_ITMP1, a);
2291 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2294 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2295 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2298 i386_jcc(cd, I386_CC_NE, a);
2300 /* XXX: change this when we use registers */
2301 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2302 i386_mov_imm_reg(cd, (s4) asm_builtin_f2i, REG_ITMP1);
2303 i386_call_reg(cd, REG_ITMP1);
2305 if (iptr->dst->flags & INMEMORY) {
2306 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2309 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2313 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2315 var_to_reg_flt(s1, src, REG_FTMP1);
2316 d = reg_of_var(m, iptr->dst, REG_NULL);
2318 a = dseg_adds4(m, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2319 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2320 dseg_adddata(m, cd->mcodeptr);
2321 i386_fldcw_membase(cd, REG_ITMP1, a);
2323 if (iptr->dst->flags & INMEMORY) {
2324 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2327 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2328 i386_fldcw_membase(cd, REG_ITMP1, a);
2330 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2333 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2335 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2338 a = dseg_adds4(m, 0);
2339 i386_fistpl_membase(cd, REG_ITMP1, a);
2341 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2343 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2344 i386_fldcw_membase(cd, REG_ITMP1, a);
2346 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2349 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2350 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2353 i386_jcc(cd, I386_CC_NE, a);
2355 /* XXX: change this when we use registers */
2356 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2357 i386_mov_imm_reg(cd, (s4) asm_builtin_d2i, REG_ITMP1);
2358 i386_call_reg(cd, REG_ITMP1);
2360 if (iptr->dst->flags & INMEMORY) {
2361 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2363 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2367 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2369 var_to_reg_flt(s1, src, REG_FTMP1);
2370 d = reg_of_var(m, iptr->dst, REG_NULL);
2372 a = dseg_adds4(m, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2373 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2374 dseg_adddata(m, cd->mcodeptr);
2375 i386_fldcw_membase(cd, REG_ITMP1, a);
2377 if (iptr->dst->flags & INMEMORY) {
2378 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2381 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2382 i386_fldcw_membase(cd, REG_ITMP1, a);
2384 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2387 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2389 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2392 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2394 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2396 i386_jcc(cd, I386_CC_NE, a);
2398 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2401 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2403 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2405 i386_jcc(cd, I386_CC_NE, a);
2407 /* XXX: change this when we use registers */
2408 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2409 i386_mov_imm_reg(cd, (s4) asm_builtin_f2l, REG_ITMP1);
2410 i386_call_reg(cd, REG_ITMP1);
2411 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2412 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2415 panic("F2L: longs have to be in memory");
2419 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2421 var_to_reg_flt(s1, src, REG_FTMP1);
2422 d = reg_of_var(m, iptr->dst, REG_NULL);
2424 a = dseg_adds4(m, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2425 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2426 dseg_adddata(m, cd->mcodeptr);
2427 i386_fldcw_membase(cd, REG_ITMP1, a);
2429 if (iptr->dst->flags & INMEMORY) {
2430 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2433 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2434 i386_fldcw_membase(cd, REG_ITMP1, a);
2436 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2439 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2441 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2444 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2446 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2448 i386_jcc(cd, I386_CC_NE, a);
2450 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2453 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2455 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2457 i386_jcc(cd, I386_CC_NE, a);
2459 /* XXX: change this when we use registers */
2460 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2461 i386_mov_imm_reg(cd, (s4) asm_builtin_d2l, REG_ITMP1);
2462 i386_call_reg(cd, REG_ITMP1);
2463 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2464 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2467 panic("D2L: longs have to be in memory");
2471 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2473 var_to_reg_flt(s1, src, REG_FTMP1);
2474 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2476 store_reg_to_var_flt(iptr->dst, d);
2479 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2481 var_to_reg_flt(s1, src, REG_FTMP1);
2482 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2484 store_reg_to_var_flt(iptr->dst, d);
2487 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2490 /* exchanged to skip fxch */
2491 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2492 var_to_reg_flt(s1, src, REG_FTMP2);
2493 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2494 /* i386_fxch(cd); */
2498 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2499 i386_jcc(cd, I386_CC_E, 6);
2500 i386_alu_imm_reg(cd, I386_AND, 0x000000ff, EAX);
2502 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2503 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2504 i386_jcc(cd, I386_CC_B, 3 + 5);
2505 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2506 i386_jmp_imm(cd, 3);
2507 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2508 store_reg_to_var_int(iptr->dst, d);
2511 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2514 /* exchanged to skip fxch */
2515 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2516 var_to_reg_flt(s1, src, REG_FTMP2);
2517 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2518 /* i386_fxch(cd); */
2522 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2523 i386_jcc(cd, I386_CC_E, 3);
2524 i386_movb_imm_reg(cd, 1, I386_AH);
2526 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2527 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2528 i386_jcc(cd, I386_CC_B, 3 + 5);
2529 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2530 i386_jmp_imm(cd, 3);
2531 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2532 store_reg_to_var_int(iptr->dst, d);
2536 /* memory operations **************************************************/
2538 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2540 var_to_reg_int(s1, src, REG_ITMP1);
2541 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2542 gen_nullptr_check(s1);
2543 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2544 store_reg_to_var_int(iptr->dst, d);
2547 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2549 var_to_reg_int(s1, src->prev, REG_ITMP1);
2550 var_to_reg_int(s2, src, REG_ITMP2);
2551 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2552 if (iptr->op1 == 0) {
2553 gen_nullptr_check(s1);
2556 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2557 store_reg_to_var_int(iptr->dst, d);
2560 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2562 var_to_reg_int(s1, src->prev, REG_ITMP1);
2563 var_to_reg_int(s2, src, REG_ITMP2);
2564 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2565 if (iptr->op1 == 0) {
2566 gen_nullptr_check(s1);
2570 if (iptr->dst->flags & INMEMORY) {
2571 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2572 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2573 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2574 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2578 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2580 var_to_reg_int(s1, src->prev, REG_ITMP1);
2581 var_to_reg_int(s2, src, REG_ITMP2);
2582 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2583 if (iptr->op1 == 0) {
2584 gen_nullptr_check(s1);
2587 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2588 store_reg_to_var_int(iptr->dst, d);
2591 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2593 var_to_reg_int(s1, src->prev, REG_ITMP1);
2594 var_to_reg_int(s2, src, REG_ITMP2);
2595 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2596 if (iptr->op1 == 0) {
2597 gen_nullptr_check(s1);
2600 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2602 store_reg_to_var_flt(iptr->dst, d);
2605 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2607 var_to_reg_int(s1, src->prev, REG_ITMP1);
2608 var_to_reg_int(s2, src, REG_ITMP2);
2609 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2610 if (iptr->op1 == 0) {
2611 gen_nullptr_check(s1);
2614 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2616 store_reg_to_var_flt(iptr->dst, d);
2619 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2621 var_to_reg_int(s1, src->prev, REG_ITMP1);
2622 var_to_reg_int(s2, src, REG_ITMP2);
2623 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2624 if (iptr->op1 == 0) {
2625 gen_nullptr_check(s1);
2628 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2629 store_reg_to_var_int(iptr->dst, d);
2632 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2634 var_to_reg_int(s1, src->prev, REG_ITMP1);
2635 var_to_reg_int(s2, src, REG_ITMP2);
2636 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2637 if (iptr->op1 == 0) {
2638 gen_nullptr_check(s1);
2641 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2642 store_reg_to_var_int(iptr->dst, d);
2645 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2647 var_to_reg_int(s1, src->prev, REG_ITMP1);
2648 var_to_reg_int(s2, src, REG_ITMP2);
2649 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2650 if (iptr->op1 == 0) {
2651 gen_nullptr_check(s1);
2654 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2655 store_reg_to_var_int(iptr->dst, d);
2659 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2661 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2662 var_to_reg_int(s2, src->prev, REG_ITMP2);
2663 if (iptr->op1 == 0) {
2664 gen_nullptr_check(s1);
2667 var_to_reg_int(s3, src, REG_ITMP3);
2668 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2671 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2673 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2674 var_to_reg_int(s2, src->prev, REG_ITMP2);
2675 if (iptr->op1 == 0) {
2676 gen_nullptr_check(s1);
2680 if (src->flags & INMEMORY) {
2681 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
2682 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2683 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2684 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2688 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2690 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2691 var_to_reg_int(s2, src->prev, REG_ITMP2);
2692 if (iptr->op1 == 0) {
2693 gen_nullptr_check(s1);
2696 var_to_reg_int(s3, src, REG_ITMP3);
2697 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2700 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2702 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2703 var_to_reg_int(s2, src->prev, REG_ITMP2);
2704 if (iptr->op1 == 0) {
2705 gen_nullptr_check(s1);
2708 var_to_reg_flt(s3, src, REG_FTMP1);
2709 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2713 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2715 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2716 var_to_reg_int(s2, src->prev, REG_ITMP2);
2717 if (iptr->op1 == 0) {
2718 gen_nullptr_check(s1);
2721 var_to_reg_flt(s3, src, REG_FTMP1);
2722 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2726 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2728 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2729 var_to_reg_int(s2, src->prev, REG_ITMP2);
2730 if (iptr->op1 == 0) {
2731 gen_nullptr_check(s1);
2734 var_to_reg_int(s3, src, REG_ITMP3);
2735 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2738 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2740 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2741 var_to_reg_int(s2, src->prev, REG_ITMP2);
2742 if (iptr->op1 == 0) {
2743 gen_nullptr_check(s1);
2746 var_to_reg_int(s3, src, REG_ITMP3);
2747 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2750 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2752 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2753 var_to_reg_int(s2, src->prev, REG_ITMP2);
2754 if (iptr->op1 == 0) {
2755 gen_nullptr_check(s1);
2758 var_to_reg_int(s3, src, REG_ITMP3);
2759 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2760 M_INTMOVE(s3, REG_ITMP3);
2763 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2766 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2768 var_to_reg_int(s1, src->prev, REG_ITMP1);
2769 var_to_reg_int(s2, src, REG_ITMP2);
2770 if (iptr->op1 == 0) {
2771 gen_nullptr_check(s1);
2774 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2777 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2779 var_to_reg_int(s1, src->prev, REG_ITMP1);
2780 var_to_reg_int(s2, src, REG_ITMP2);
2781 if (iptr->op1 == 0) {
2782 gen_nullptr_check(s1);
2786 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2787 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2790 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2792 var_to_reg_int(s1, src->prev, REG_ITMP1);
2793 var_to_reg_int(s2, src, REG_ITMP2);
2794 if (iptr->op1 == 0) {
2795 gen_nullptr_check(s1);
2798 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2801 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2803 var_to_reg_int(s1, src->prev, REG_ITMP1);
2804 var_to_reg_int(s2, src, REG_ITMP2);
2805 if (iptr->op1 == 0) {
2806 gen_nullptr_check(s1);
2809 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2812 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2814 var_to_reg_int(s1, src->prev, REG_ITMP1);
2815 var_to_reg_int(s2, src, REG_ITMP2);
2816 if (iptr->op1 == 0) {
2817 gen_nullptr_check(s1);
2820 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2823 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2825 var_to_reg_int(s1, src->prev, REG_ITMP1);
2826 var_to_reg_int(s2, src, REG_ITMP2);
2827 if (iptr->op1 == 0) {
2828 gen_nullptr_check(s1);
2831 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2835 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2836 /* op1 = type, val.a = field address */
2838 /* if class isn't yet initialized, do it */
2839 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2840 /* call helper function which patches this code */
2841 i386_mov_imm_reg(cd, (s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2842 i386_mov_imm_reg(cd, (s4) asm_check_clinit, REG_ITMP2);
2843 i386_call_reg(cd, REG_ITMP2);
2846 a = dseg_addaddress(m, &(((fieldinfo *) iptr->val.a)->value));
2847 /* here it's slightly slower */
2848 i386_mov_imm_reg(cd, 0, REG_ITMP2);
2849 dseg_adddata(m, cd->mcodeptr);
2850 i386_mov_membase_reg(cd, REG_ITMP2, a, REG_ITMP2);
2851 switch (iptr->op1) {
2854 var_to_reg_int(s2, src, REG_ITMP1);
2855 i386_mov_reg_membase(cd, s2, REG_ITMP2, 0);
2858 if (src->flags & INMEMORY) {
2859 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
2860 i386_mov_reg_membase(cd, REG_ITMP1, REG_ITMP2, 0);
2861 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
2862 i386_mov_reg_membase(cd, REG_ITMP1, REG_ITMP2, 0 + 4);
2864 panic("PUTSTATIC: longs have to be in memory");
2868 var_to_reg_flt(s2, src, REG_FTMP1);
2869 i386_fstps_membase(cd, REG_ITMP2, 0);
2873 var_to_reg_flt(s2, src, REG_FTMP1);
2874 i386_fstpl_membase(cd, REG_ITMP2, 0);
2877 default: panic ("internal error");
2881 case ICMD_GETSTATIC: /* ... ==> ..., value */
2882 /* op1 = type, val.a = field address */
2884 /* if class isn't yet initialized, do it */
2885 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2886 /* call helper function which patches this code */
2887 i386_mov_imm_reg(cd, (s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2888 i386_mov_imm_reg(cd, (s4) asm_check_clinit, REG_ITMP2);
2889 i386_call_reg(cd, REG_ITMP2);
2892 a = dseg_addaddress(m, &(((fieldinfo *) iptr->val.a)->value));
2893 i386_mov_imm_reg(cd, 0, REG_ITMP2);
2894 dseg_adddata(m, cd->mcodeptr);
2895 i386_mov_membase_reg(cd, REG_ITMP2, a, REG_ITMP2);
2896 switch (iptr->op1) {
2899 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2900 i386_mov_membase_reg(cd, REG_ITMP2, 0, d);
2901 store_reg_to_var_int(iptr->dst, d);
2904 d = reg_of_var(m, iptr->dst, REG_NULL);
2905 if (iptr->dst->flags & INMEMORY) {
2906 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP1);
2907 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2908 i386_mov_membase_reg(cd, REG_ITMP2, 0 + 4, REG_ITMP1);
2909 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
2911 panic("GETSTATIC: longs have to be in memory");
2915 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2916 i386_flds_membase(cd, REG_ITMP2, 0);
2918 store_reg_to_var_flt(iptr->dst, d);
2921 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2922 i386_fldl_membase(cd, REG_ITMP2, 0);
2924 store_reg_to_var_flt(iptr->dst, d);
2926 default: panic ("internal error");
2930 case ICMD_PUTFIELD: /* ..., value ==> ... */
2931 /* op1 = type, val.i = field offset */
2933 a = ((fieldinfo *)(iptr->val.a))->offset;
2934 switch (iptr->op1) {
2937 var_to_reg_int(s1, src->prev, REG_ITMP1);
2938 var_to_reg_int(s2, src, REG_ITMP2);
2939 gen_nullptr_check(s1);
2940 i386_mov_reg_membase(cd, s2, s1, a);
2943 var_to_reg_int(s1, src->prev, REG_ITMP1);
2944 gen_nullptr_check(s1);
2945 if (src->flags & INMEMORY) {
2946 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);
2947 i386_mov_reg_membase(cd, REG_ITMP2, s1, a);
2948 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2949 i386_mov_reg_membase(cd, REG_ITMP2, s1, a + 4);
2951 panic("PUTFIELD: longs have to be in memory");
2955 var_to_reg_int(s1, src->prev, REG_ITMP1);
2956 var_to_reg_flt(s2, src, REG_FTMP1);
2957 gen_nullptr_check(s1);
2958 i386_fstps_membase(cd, s1, a);
2962 var_to_reg_int(s1, src->prev, REG_ITMP1);
2963 var_to_reg_flt(s2, src, REG_FTMP1);
2964 gen_nullptr_check(s1);
2965 i386_fstpl_membase(cd, s1, a);
2968 default: panic ("internal error");
2972 case ICMD_GETFIELD: /* ... ==> ..., value */
2973 /* op1 = type, val.i = field offset */
2975 a = ((fieldinfo *)(iptr->val.a))->offset;
2976 switch (iptr->op1) {
2979 var_to_reg_int(s1, src, REG_ITMP1);
2980 d = reg_of_var(m, iptr->dst, REG_ITMP2);
2981 gen_nullptr_check(s1);
2982 i386_mov_membase_reg(cd, s1, a, d);
2983 store_reg_to_var_int(iptr->dst, d);
2986 var_to_reg_int(s1, src, REG_ITMP1);
2987 d = reg_of_var(m, iptr->dst, REG_NULL);
2988 gen_nullptr_check(s1);
2989 i386_mov_membase_reg(cd, s1, a, REG_ITMP2);
2990 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
2991 i386_mov_membase_reg(cd, s1, a + 4, REG_ITMP2);
2992 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2995 var_to_reg_int(s1, src, REG_ITMP1);
2996 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2997 gen_nullptr_check(s1);
2998 i386_flds_membase(cd, s1, a);
3000 store_reg_to_var_flt(iptr->dst, d);
3003 var_to_reg_int(s1, src, REG_ITMP1);
3004 d = reg_of_var(m, iptr->dst, REG_FTMP1);
3005 gen_nullptr_check(s1);
3006 i386_fldl_membase(cd, s1, a);
3008 store_reg_to_var_flt(iptr->dst, d);
3010 default: panic ("internal error");
3015 /* branch operations **************************************************/
3018 /* #define ALIGNCODENOP {if((int)((long)cd->mcodeptr&7)){M_NOP;}} */
3019 #define ALIGNCODENOP do {} while (0)
3021 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3023 var_to_reg_int(s1, src, REG_ITMP1);
3024 M_INTMOVE(s1, REG_ITMP1_XPTR);
3026 i386_call_imm(cd, 0); /* passing exception pointer */
3027 i386_pop_reg(cd, REG_ITMP2_XPC);
3029 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
3030 i386_jmp_reg(cd, REG_ITMP3);
3034 case ICMD_GOTO: /* ... ==> ... */
3035 /* op1 = target JavaVM pc */
3037 i386_jmp_imm(cd, 0);
3038 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3042 case ICMD_JSR: /* ... ==> ... */
3043 /* op1 = target JavaVM pc */
3045 i386_call_imm(cd, 0);
3046 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3049 case ICMD_RET: /* ... ==> ... */
3050 /* op1 = local variable */
3052 var = &(r->locals[iptr->op1][TYPE_ADR]);
3053 var_to_reg_int(s1, var, REG_ITMP1);
3054 i386_jmp_reg(cd, s1);
3057 case ICMD_IFNULL: /* ..., value ==> ... */
3058 /* op1 = target JavaVM pc */
3060 if (src->flags & INMEMORY) {
3061 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3064 i386_test_reg_reg(cd, src->regoff, src->regoff);
3066 i386_jcc(cd, I386_CC_E, 0);
3067 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3070 case ICMD_IFNONNULL: /* ..., value ==> ... */
3071 /* op1 = target JavaVM pc */
3073 if (src->flags & INMEMORY) {
3074 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3077 i386_test_reg_reg(cd, src->regoff, src->regoff);
3079 i386_jcc(cd, I386_CC_NE, 0);
3080 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3083 case ICMD_IFEQ: /* ..., value ==> ... */
3084 /* op1 = target JavaVM pc, val.i = constant */
3086 if (src->flags & INMEMORY) {
3087 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3090 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3092 i386_jcc(cd, I386_CC_E, 0);
3093 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3096 case ICMD_IFLT: /* ..., value ==> ... */
3097 /* op1 = target JavaVM pc, val.i = constant */
3099 if (src->flags & INMEMORY) {
3100 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3103 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3105 i386_jcc(cd, I386_CC_L, 0);
3106 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3109 case ICMD_IFLE: /* ..., value ==> ... */
3110 /* op1 = target JavaVM pc, val.i = constant */
3112 if (src->flags & INMEMORY) {
3113 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3116 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3118 i386_jcc(cd, I386_CC_LE, 0);
3119 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3122 case ICMD_IFNE: /* ..., value ==> ... */
3123 /* op1 = target JavaVM pc, val.i = constant */
3125 if (src->flags & INMEMORY) {
3126 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3129 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3131 i386_jcc(cd, I386_CC_NE, 0);
3132 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3135 case ICMD_IFGT: /* ..., value ==> ... */
3136 /* op1 = target JavaVM pc, val.i = constant */
3138 if (src->flags & INMEMORY) {
3139 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3142 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3144 i386_jcc(cd, I386_CC_G, 0);
3145 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3148 case ICMD_IFGE: /* ..., value ==> ... */
3149 /* op1 = target JavaVM pc, val.i = constant */
3151 if (src->flags & INMEMORY) {
3152 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3155 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3157 i386_jcc(cd, I386_CC_GE, 0);
3158 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3161 case ICMD_IF_LEQ: /* ..., value ==> ... */
3162 /* op1 = target JavaVM pc, val.l = constant */
3164 if (src->flags & INMEMORY) {
3165 if (iptr->val.l == 0) {
3166 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3167 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3170 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3171 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3172 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3173 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l, REG_ITMP1);
3174 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3177 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3178 i386_jcc(cd, I386_CC_E, 0);
3179 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3182 case ICMD_IF_LLT: /* ..., value ==> ... */
3183 /* op1 = target JavaVM pc, val.l = constant */
3185 if (src->flags & INMEMORY) {
3186 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3187 i386_jcc(cd, I386_CC_L, 0);
3188 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3191 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3192 CALCIMMEDIATEBYTES(a, iptr->val.l);
3194 i386_jcc(cd, I386_CC_G, a);
3196 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3197 i386_jcc(cd, I386_CC_B, 0);
3198 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3202 case ICMD_IF_LLE: /* ..., value ==> ... */
3203 /* op1 = target JavaVM pc, val.l = constant */
3205 if (src->flags & INMEMORY) {
3206 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3207 i386_jcc(cd, I386_CC_L, 0);
3208 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3211 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3212 CALCIMMEDIATEBYTES(a, iptr->val.l);
3214 i386_jcc(cd, I386_CC_G, a);
3216 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3217 i386_jcc(cd, I386_CC_BE, 0);
3218 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3222 case ICMD_IF_LNE: /* ..., value ==> ... */
3223 /* op1 = target JavaVM pc, val.l = constant */
3225 if (src->flags & INMEMORY) {
3226 if (iptr->val.l == 0) {
3227 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3228 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3231 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3232 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3233 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3234 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3235 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3238 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3239 i386_jcc(cd, I386_CC_NE, 0);
3240 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3243 case ICMD_IF_LGT: /* ..., value ==> ... */
3244 /* op1 = target JavaVM pc, val.l = constant */
3246 if (src->flags & INMEMORY) {
3247 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3248 i386_jcc(cd, I386_CC_G, 0);
3249 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3252 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3253 CALCIMMEDIATEBYTES(a, iptr->val.l);
3255 i386_jcc(cd, I386_CC_L, a);
3257 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3258 i386_jcc(cd, I386_CC_A, 0);
3259 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3263 case ICMD_IF_LGE: /* ..., value ==> ... */
3264 /* op1 = target JavaVM pc, val.l = constant */
3266 if (src->flags & INMEMORY) {
3267 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3268 i386_jcc(cd, I386_CC_G, 0);
3269 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3272 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3273 CALCIMMEDIATEBYTES(a, iptr->val.l);
3275 i386_jcc(cd, I386_CC_L, a);
3277 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3278 i386_jcc(cd, I386_CC_AE, 0);
3279 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3283 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3284 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3286 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3287 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3288 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3290 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3291 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3293 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3294 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3297 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3299 i386_jcc(cd, I386_CC_E, 0);
3300 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3303 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3304 /* op1 = target JavaVM pc */
3306 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3307 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3308 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3309 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3310 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3311 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3312 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3314 i386_jcc(cd, I386_CC_E, 0);
3315 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3318 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3319 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3321 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3322 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3323 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3325 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3326 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3328 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3329 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3332 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3334 i386_jcc(cd, I386_CC_NE, 0);
3335 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3338 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3339 /* op1 = target JavaVM pc */
3341 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3342 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3343 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3344 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3345 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3346 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3347 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3349 i386_jcc(cd, I386_CC_NE, 0);
3350 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3353 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3354 /* op1 = target JavaVM pc */
3356 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3357 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3358 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3360 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3361 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3363 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3364 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3367 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3369 i386_jcc(cd, I386_CC_L, 0);
3370 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3373 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3374 /* op1 = target JavaVM pc */
3376 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3377 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3378 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3379 i386_jcc(cd, I386_CC_L, 0);
3380 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3383 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3384 CALCOFFSETBYTES(a, REG_SP, src->regoff);
3386 i386_jcc(cd, I386_CC_G, a);
3388 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3389 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3390 i386_jcc(cd, I386_CC_B, 0);
3391 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3395 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3396 /* op1 = target JavaVM pc */
3398 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3399 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3400 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3402 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3403 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3405 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3406 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3409 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3411 i386_jcc(cd, I386_CC_G, 0);
3412 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3415 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3416 /* op1 = target JavaVM pc */
3418 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3419 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3420 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3421 i386_jcc(cd, I386_CC_G, 0);
3422 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3425 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3426 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3428 i386_jcc(cd, I386_CC_L, a);
3430 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3431 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3432 i386_jcc(cd, I386_CC_A, 0);
3433 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3437 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3438 /* op1 = target JavaVM pc */
3440 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3441 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3442 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3444 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3445 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3447 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3448 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3451 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3453 i386_jcc(cd, I386_CC_LE, 0);
3454 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3457 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3458 /* op1 = target JavaVM pc */
3460 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3461 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3462 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3463 i386_jcc(cd, I386_CC_L, 0);
3464 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3467 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3468 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3470 i386_jcc(cd, I386_CC_G, a);
3472 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3473 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3474 i386_jcc(cd, I386_CC_BE, 0);
3475 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3479 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3480 /* op1 = target JavaVM pc */
3482 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3483 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3484 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3486 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3487 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3489 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3490 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3493 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3495 i386_jcc(cd, I386_CC_GE, 0);
3496 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3499 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3500 /* op1 = target JavaVM pc */
3502 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3503 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3504 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3505 i386_jcc(cd, I386_CC_G, 0);
3506 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3509 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3510 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3512 i386_jcc(cd, I386_CC_L, a);
3514 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3515 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3516 i386_jcc(cd, I386_CC_AE, 0);
3517 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3521 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3523 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3526 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3527 /* val.i = constant */
3529 d = reg_of_var(m, iptr->dst, REG_NULL);
3530 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
3533 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3534 /* val.i = constant */
3536 d = reg_of_var(m, iptr->dst, REG_NULL);
3537 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
3540 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3541 /* val.i = constant */
3543 d = reg_of_var(m, iptr->dst, REG_NULL);
3544 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
3547 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3548 /* val.i = constant */
3550 d = reg_of_var(m, iptr->dst, REG_NULL);
3551 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
3554 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3555 /* val.i = constant */
3557 d = reg_of_var(m, iptr->dst, REG_NULL);
3558 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
3561 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3562 /* val.i = constant */
3564 d = reg_of_var(m, iptr->dst, REG_NULL);
3565 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
3569 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3572 var_to_reg_int(s1, src, REG_RESULT);
3573 M_INTMOVE(s1, REG_RESULT);
3575 goto nowperformreturn;
3577 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3579 if (src->flags & INMEMORY) {
3580 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_RESULT);
3581 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3584 panic("LRETURN: longs have to be in memory");
3587 goto nowperformreturn;
3589 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3590 case ICMD_DRETURN: /* ..., retvalue ==> ... */
3592 var_to_reg_flt(s1, src, REG_FRESULT);
3593 /* this may be an early return -- keep the offset correct for the
3597 goto nowperformreturn;
3599 case ICMD_RETURN: /* ... ==> ... */
3605 p = parentargs_base;
3607 /* call trace function */
3609 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3611 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3613 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3614 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3616 i386_fstl_membase(cd, REG_SP, 4 + 8);
3617 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3619 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3620 i386_call_reg(cd, REG_ITMP1);
3622 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3623 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3625 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3628 #if defined(USE_THREADS)
3629 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3630 i386_mov_membase_reg(cd, REG_SP, 8 * r->maxmemuse, REG_ITMP2);
3632 /* we need to save the proper return value */
3633 switch (iptr->opc) {
3636 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, r->maxmemuse * 8);
3640 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, r->maxmemuse * 8);
3641 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, r->maxmemuse * 8 + 4);
3645 i386_fsts_membase(cd, REG_SP, r->maxmemuse * 8);
3649 i386_fstl_membase(cd, REG_SP, r->maxmemuse * 8);
3653 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
3654 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, 0);
3655 i386_mov_imm_reg(cd, (s4) builtin_monitorexit, REG_ITMP1);
3656 i386_call_reg(cd, REG_ITMP1);
3657 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
3659 /* and now restore the proper return value */
3660 switch (iptr->opc) {
3663 i386_mov_membase_reg(cd, REG_SP, r->maxmemuse * 8, REG_RESULT);
3667 i386_mov_membase_reg(cd, REG_SP, r->maxmemuse * 8, REG_RESULT);
3668 i386_mov_membase_reg(cd, REG_SP, r->maxmemuse * 8 + 4, REG_RESULT2);
3672 i386_flds_membase(cd, REG_SP, r->maxmemuse * 8);
3676 i386_fldl_membase(cd, REG_SP, r->maxmemuse * 8);
3682 /* restore saved registers */
3683 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
3685 i386_mov_membase_reg(cd, REG_SP, p * 8, r->savintregs[i]);
3687 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
3689 i386_fldl_membase(cd, REG_SP, p * 8);
3691 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3692 i386_fstp_reg(cd, r->savfltregs[i] + fpu_st_offset + 1);
3694 i386_fstp_reg(cd, r->savfltregs[i] + fpu_st_offset);
3699 /* deallocate stack */
3700 if (parentargs_base) {
3701 i386_alu_imm_reg(cd, I386_ADD, parentargs_base * 8, REG_SP);
3710 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3715 tptr = (void **) iptr->target;
3717 s4ptr = iptr->val.a;
3718 l = s4ptr[1]; /* low */
3719 i = s4ptr[2]; /* high */
3721 var_to_reg_int(s1, src, REG_ITMP1);
3722 M_INTMOVE(s1, REG_ITMP1);
3724 i386_alu_imm_reg(cd, I386_SUB, l, REG_ITMP1);
3730 i386_alu_imm_reg(cd, I386_CMP, i - 1, REG_ITMP1);
3731 i386_jcc(cd, I386_CC_A, 0);
3733 /* codegen_addreference(m, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
3734 codegen_addreference(m, (basicblock *) tptr[0], cd->mcodeptr);
3736 /* build jump table top down and use address of lowest entry */
3738 /* s4ptr += 3 + i; */
3742 /* dseg_addtarget(m, BlockPtrOfPC(*--s4ptr)); */
3743 dseg_addtarget(m, (basicblock *) tptr[0]);
3747 /* length of dataseg after last dseg_addtarget is used by load */
3749 i386_mov_imm_reg(cd, 0, REG_ITMP2);
3750 dseg_adddata(m, cd->mcodeptr);
3751 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3752 i386_jmp_reg(cd, REG_ITMP1);
3758 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3760 s4 i, l, val, *s4ptr;
3763 tptr = (void **) iptr->target;
3765 s4ptr = iptr->val.a;
3766 l = s4ptr[0]; /* default */
3767 i = s4ptr[1]; /* count */
3769 MCODECHECK((i<<2)+8);
3770 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3776 i386_alu_imm_reg(cd, I386_CMP, val, s1);
3777 i386_jcc(cd, I386_CC_E, 0);
3778 /* codegen_addreference(m, BlockPtrOfPC(s4ptr[1]), cd->mcodeptr); */
3779 codegen_addreference(m, (basicblock *) tptr[0], cd->mcodeptr);
3782 i386_jmp_imm(cd, 0);
3783 /* codegen_addreference(m, BlockPtrOfPC(l), cd->mcodeptr); */
3785 tptr = (void **) iptr->target;
3786 codegen_addreference(m, (basicblock *) tptr[0], cd->mcodeptr);
3793 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3794 /* op1 = return type, val.a = function pointer*/
3798 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3799 /* op1 = return type, val.a = function pointer*/
3803 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3804 /* op1 = return type, val.a = function pointer*/
3808 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3809 /* op1 = arg count, val.a = method pointer */
3811 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3812 /* op1 = arg count, val.a = method pointer */
3814 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3815 /* op1 = arg count, val.a = method pointer */
3817 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3818 /* op1 = arg count, val.a = method pointer */
3825 MCODECHECK((s3 << 1) + 64);
3827 /* copy arguments to registers or stack location */
3829 for (; --s3 >= 0; src = src->prev) {
3830 if (src->varkind == ARGVAR) {
3834 if (IS_INT_LNG_TYPE(src->type)) {
3835 if (s3 < r->intreg_argnum) {
3836 panic("No integer argument registers available!");
3839 if (!IS_2_WORD_TYPE(src->type)) {
3840 if (src->flags & INMEMORY) {
3841 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3842 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s3 * 8);
3845 i386_mov_reg_membase(cd, src->regoff, REG_SP, s3 * 8);
3849 if (src->flags & INMEMORY) {
3850 M_LNGMEMMOVE(src->regoff, s3);
3853 panic("copy arguments: longs have to be in memory");
3859 if (s3 < r->fltreg_argnum) {
3860 panic("No float argument registers available!");
3863 var_to_reg_flt(d, src, REG_FTMP1);
3864 if (src->type == TYPE_FLT) {
3865 i386_fstps_membase(cd, REG_SP, s3 * 8);
3868 i386_fstpl_membase(cd, REG_SP, s3 * 8);
3875 switch (iptr->opc) {
3882 i386_mov_imm_reg(cd, a, REG_ITMP1);
3883 i386_call_reg(cd, REG_ITMP1);
3886 case ICMD_INVOKESTATIC:
3887 a = (u4) lm->stubroutine;
3890 i386_mov_imm_reg(cd, a, REG_ITMP2);
3891 i386_call_reg(cd, REG_ITMP2);
3894 case ICMD_INVOKESPECIAL:
3895 a = (u4) lm->stubroutine;
3898 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3899 gen_nullptr_check(REG_ITMP1);
3900 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
3902 i386_mov_imm_reg(cd, a, REG_ITMP2);
3903 i386_call_reg(cd, REG_ITMP2);
3906 case ICMD_INVOKEVIRTUAL:
3909 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3910 gen_nullptr_check(REG_ITMP1);
3911 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
3912 i386_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
3914 i386_call_reg(cd, REG_ITMP1);
3917 case ICMD_INVOKEINTERFACE:
3920 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3921 gen_nullptr_check(REG_ITMP1);
3922 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3923 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * lm->class->index, REG_ITMP2);
3924 i386_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - lm->class->methods), REG_ITMP1);
3926 i386_call_reg(cd, REG_ITMP1);
3930 /* d contains return type */
3932 if (d != TYPE_VOID) {
3933 d = reg_of_var(m, iptr->dst, REG_NULL);
3935 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3936 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3937 if (iptr->dst->flags & INMEMORY) {
3938 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3939 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
3942 panic("RETURN: longs have to be in memory");
3946 if (iptr->dst->flags & INMEMORY) {
3947 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3950 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
3955 /* fld from called function -- has other fpu_st_offset counter */
3957 store_reg_to_var_flt(iptr->dst, d);
3964 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3966 /* op1: 0 == array, 1 == class */
3967 /* val.a: (classinfo*) superclass */
3969 /* superclass is an interface:
3971 * return (sub != NULL) &&
3972 * (sub->vftbl->interfacetablelength > super->index) &&
3973 * (sub->vftbl->interfacetable[-super->index] != NULL);
3975 * superclass is a class:
3977 * return ((sub != NULL) && (0
3978 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3979 * super->vftbl->diffvall));
3983 classinfo *super = (classinfo*) iptr->val.a;
3985 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3986 codegen_threadcritrestart(m, cd->mcodeptr - cd->mcodebase);
3988 var_to_reg_int(s1, src, REG_ITMP1);
3989 d = reg_of_var(m, iptr->dst, REG_ITMP3);
3991 M_INTMOVE(s1, REG_ITMP1);
3994 i386_alu_reg_reg(cd, I386_XOR, d, d);
3995 if (iptr->op1) { /* class/interface */
3996 if (super->flags & ACC_INTERFACE) { /* interface */
3997 i386_test_reg_reg(cd, s1, s1);
3999 /* TODO: clean up this calculation */
4001 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4004 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4007 /* CALCOFFSETBYTES(a, super->index); */
4008 CALCIMMEDIATEBYTES(a, super->index);
4014 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4021 i386_jcc(cd, I386_CC_E, a);
4023 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4024 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4025 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4027 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4029 /* TODO: clean up this calculation */
4032 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4039 i386_jcc(cd, I386_CC_LE, a);
4040 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4042 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP1);
4043 /* i386_setcc_reg(cd, I386_CC_A, d); */
4044 /* i386_jcc(cd, I386_CC_BE, 5); */
4045 i386_jcc(cd, I386_CC_E, 5);
4046 i386_mov_imm_reg(cd, 1, d);
4049 } else { /* class */
4050 i386_test_reg_reg(cd, s1, s1);
4052 /* TODO: clean up this calculation */
4054 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4057 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4059 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4062 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4072 i386_jcc(cd, I386_CC_E, a);
4074 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4075 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4076 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4077 codegen_threadcritstart(m, cd->mcodeptr - cd->mcodebase);
4079 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4080 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4081 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4082 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4083 codegen_threadcritstop(m, cd->mcodeptr - cd->mcodebase);
4085 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4086 i386_alu_reg_reg(cd, I386_XOR, d, d);
4088 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4089 i386_jcc(cd, I386_CC_A, 5);
4090 i386_mov_imm_reg(cd, 1, d);
4094 panic ("internal error: no inlined array instanceof");
4096 store_reg_to_var_int(iptr->dst, d);
4099 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4101 /* op1: 0 == array, 1 == class */
4102 /* val.a: (classinfo*) superclass */
4104 /* superclass is an interface:
4106 * OK if ((sub == NULL) ||
4107 * (sub->vftbl->interfacetablelength > super->index) &&
4108 * (sub->vftbl->interfacetable[-super->index] != NULL));
4110 * superclass is a class:
4112 * OK if ((sub == NULL) || (0
4113 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4114 * super->vftbl->diffvall));
4118 classinfo *super = (classinfo*) iptr->val.a;
4120 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4121 codegen_threadcritrestart(m, cd->mcodeptr - cd->mcodebase);
4123 d = reg_of_var(m, iptr->dst, REG_ITMP3);
4124 var_to_reg_int(s1, src, d);
4125 if (iptr->op1) { /* class/interface */
4126 if (super->flags & ACC_INTERFACE) { /* interface */
4127 i386_test_reg_reg(cd, s1, s1);
4129 /* TODO: clean up this calculation */
4131 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4134 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4137 /* CALCOFFSETBYTES(a, super->index); */
4138 CALCIMMEDIATEBYTES(a, super->index);
4144 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4149 i386_jcc(cd, I386_CC_E, a);
4151 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4152 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4153 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4155 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4156 i386_jcc(cd, I386_CC_LE, 0);
4157 codegen_addxcastrefs(m, cd->mcodeptr);
4158 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
4160 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4161 i386_jcc(cd, I386_CC_E, 0);
4162 codegen_addxcastrefs(m, cd->mcodeptr);
4164 } else { /* class */
4165 i386_test_reg_reg(cd, s1, s1);
4167 /* TODO: clean up this calculation */
4169 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4174 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4176 if (d != REG_ITMP3) {
4178 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4181 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4187 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4194 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4201 i386_jcc(cd, I386_CC_E, a);
4203 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4204 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4205 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4206 codegen_threadcritstart(m, cd->mcodeptr - cd->mcodebase);
4208 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4209 if (d != REG_ITMP3) {
4210 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4211 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4212 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4213 codegen_threadcritstop(m, cd->mcodeptr - cd->mcodebase);
4215 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4218 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
4219 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1);
4220 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4221 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4222 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4223 codegen_threadcritstop(m, cd->mcodeptr - cd->mcodebase);
4227 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4228 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
4229 codegen_addxcastrefs(m, cd->mcodeptr);
4233 panic ("internal error: no inlined array checkcast");
4236 store_reg_to_var_int(iptr->dst, d);
4239 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4241 if (src->flags & INMEMORY) {
4242 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4245 i386_test_reg_reg(cd, src->regoff, src->regoff);
4247 i386_jcc(cd, I386_CC_L, 0);
4248 codegen_addxcheckarefs(m, cd->mcodeptr);
4251 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4253 i386_test_reg_reg(cd, REG_RESULT, REG_RESULT);
4254 i386_jcc(cd, I386_CC_E, 0);
4255 codegen_addxexceptionrefs(m, cd->mcodeptr);
4258 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4259 /* op1 = dimension, val.a = array descriptor */
4261 /* check for negative sizes and copy sizes to stack if necessary */
4263 MCODECHECK((iptr->op1 << 1) + 64);
4265 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4266 if (src->flags & INMEMORY) {
4267 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4270 i386_test_reg_reg(cd, src->regoff, src->regoff);
4272 i386_jcc(cd, I386_CC_L, 0);
4273 codegen_addxcheckarefs(m, cd->mcodeptr);
4276 * copy sizes to new stack location, be cause native function
4277 * builtin_nmultianewarray access them as (int *)
4279 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
4280 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);
4282 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
4284 if (src->varkind != ARGVAR) {
4285 if (src->flags & INMEMORY) {
4286 i386_mov_membase_reg(cd, REG_SP, (src->regoff + INT_ARG_CNT) * 8, REG_ITMP1);
4287 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, (s1 + INT_ARG_CNT) * 8);
4290 i386_mov_reg_membase(cd, src->regoff, REG_SP, (s1 + INT_ARG_CNT) * 8);
4294 i386_alu_imm_reg(cd, I386_SUB, iptr->op1 * 4, REG_SP);
4296 /* a0 = dimension count */
4298 /* save stack pointer */
4299 M_INTMOVE(REG_SP, REG_ITMP1);
4301 i386_alu_imm_reg(cd, I386_SUB, 12, REG_SP);
4302 i386_mov_imm_membase(cd, iptr->op1, REG_SP, 0);
4304 /* a1 = arraydescriptor */
4306 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, 4);
4308 /* a2 = pointer to dimensions = stack pointer */
4310 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 8);
4312 i386_mov_imm_reg(cd, (s4) (builtin_nmultianewarray), REG_ITMP1);
4313 i386_call_reg(cd, REG_ITMP1);
4314 i386_alu_imm_reg(cd, I386_ADD, 12 + iptr->op1 * 4, REG_SP);
4316 s1 = reg_of_var(m, iptr->dst, REG_RESULT);
4317 M_INTMOVE(REG_RESULT, s1);
4318 store_reg_to_var_int(iptr->dst, s1);
4322 error ("Unknown pseudo command: %d", iptr->opc);
4325 } /* for instruction */
4327 /* copy values to interface registers */
4329 src = bptr->outstack;
4330 len = bptr->outdepth;
4334 if ((src->varkind != STACKVAR)) {
4336 if (IS_FLT_DBL_TYPE(s2)) {
4337 var_to_reg_flt(s1, src, REG_FTMP1);
4338 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
4339 M_FLTMOVE(s1, r->interfaces[len][s2].regoff);
4342 panic("double store");
4343 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4347 var_to_reg_int(s1, src, REG_ITMP1);
4348 if (!IS_2_WORD_TYPE(r->interfaces[len][s2].type)) {
4349 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
4350 M_INTMOVE(s1, r->interfaces[len][s2].regoff);
4353 i386_mov_reg_membase(cd, s1, REG_SP, r->interfaces[len][s2].regoff * 8);
4357 if (r->interfaces[len][s2].flags & INMEMORY) {
4358 M_LNGMEMMOVE(s1, r->interfaces[len][s2].regoff);
4361 panic("copy interface registers: longs have to be in memory (end)");
4368 } /* if (bptr -> flags >= BBREACHED) */
4369 } /* for basic block */
4371 codegen_createlinenumbertable(m);
4375 /* generate bound check stubs */
4377 u1 *xcodeptr = NULL;
4380 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
4381 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4383 cd->mcodeptr - cd->mcodebase);
4387 /* move index register into REG_ITMP1 */
4388 i386_mov_reg_reg(cd, bref->reg, REG_ITMP1); /* 2 bytes */
4390 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4391 dseg_adddata(m, cd->mcodeptr);
4392 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3); /* 5 bytes */
4393 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4395 if (xcodeptr != NULL) {
4396 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4399 xcodeptr = cd->mcodeptr;
4401 i386_push_reg(cd, REG_ITMP2_XPC);
4403 PREPARE_NATIVE_STACKINFO;
4405 i386_alu_imm_reg(cd, I386_SUB, 2 * 4, REG_SP);
4406 i386_mov_imm_membase(cd, (s4) string_java_lang_ArrayIndexOutOfBoundsException, REG_SP, 0 * 4);
4407 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 1 * 4);
4408 i386_mov_imm_reg(cd, (s4) new_exception_int, REG_ITMP1);
4409 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4410 i386_alu_imm_reg(cd, I386_ADD, 2 * 4, REG_SP);
4412 REMOVE_NATIVE_STACKINFO;
4414 i386_pop_reg(cd, REG_ITMP2_XPC);
4416 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4417 i386_jmp_reg(cd, REG_ITMP3);
4421 /* generate negative array size check stubs */
4425 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
4426 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4427 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4429 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4433 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4435 cd->mcodeptr - cd->mcodebase);
4439 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4440 dseg_adddata(m, cd->mcodeptr);
4441 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4442 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4444 if (xcodeptr != NULL) {
4445 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4448 xcodeptr = cd->mcodeptr;
4450 i386_push_reg(cd, REG_ITMP2_XPC);
4452 PREPARE_NATIVE_STACKINFO;
4454 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4455 i386_mov_imm_membase(cd, (s4) string_java_lang_NegativeArraySizeException, REG_SP, 0 * 4);
4456 i386_mov_imm_reg(cd, (s4) new_exception, REG_ITMP1);
4457 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4458 i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4461 REMOVE_NATIVE_STACKINFO;
4463 i386_pop_reg(cd, REG_ITMP2_XPC);
4465 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4466 i386_jmp_reg(cd, REG_ITMP3);
4470 /* generate cast check stubs */
4474 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
4475 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4476 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4478 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4482 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4484 cd->mcodeptr - cd->mcodebase);
4488 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4489 dseg_adddata(m, cd->mcodeptr);
4490 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4491 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4493 if (xcodeptr != NULL) {
4494 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4497 xcodeptr = cd->mcodeptr;
4499 i386_push_reg(cd, REG_ITMP2_XPC);
4502 PREPARE_NATIVE_STACKINFO;
4504 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4505 i386_mov_imm_membase(cd, (s4) string_java_lang_ClassCastException, REG_SP, 0 * 4);
4506 i386_mov_imm_reg(cd, (s4) new_exception, REG_ITMP1);
4507 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4508 i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4511 REMOVE_NATIVE_STACKINFO;
4513 i386_pop_reg(cd, REG_ITMP2_XPC);
4515 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4516 i386_jmp_reg(cd, REG_ITMP3);
4520 /* generate divide by zero check stubs */
4524 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
4525 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4526 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4528 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4532 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4534 cd->mcodeptr - cd->mcodebase);
4538 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4539 dseg_adddata(m, cd->mcodeptr);
4540 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4541 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4543 if (xcodeptr != NULL) {
4544 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4547 xcodeptr = cd->mcodeptr;
4549 i386_push_reg(cd, REG_ITMP2_XPC);
4551 PREPARE_NATIVE_STACKINFO;
4553 i386_alu_imm_reg(cd, I386_SUB, 2 * 4, REG_SP);
4554 i386_mov_imm_membase(cd, (s4) string_java_lang_ArithmeticException, REG_SP, 0 * 4);
4555 i386_mov_imm_membase(cd, (s4) string_java_lang_ArithmeticException_message, REG_SP, 1 * 4);
4556 i386_mov_imm_reg(cd, (s4) new_exception_message, REG_ITMP1);
4557 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4558 i386_alu_imm_reg(cd, I386_ADD, 2 * 4, REG_SP);
4560 REMOVE_NATIVE_STACKINFO;
4562 i386_pop_reg(cd, REG_ITMP2_XPC);
4564 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4565 i386_jmp_reg(cd, REG_ITMP3);
4569 /* generate exception check stubs */
4573 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
4574 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4575 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4577 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4581 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4583 cd->mcodeptr - cd->mcodebase);
4587 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4588 dseg_adddata(m, cd->mcodeptr);
4589 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4590 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4592 if (xcodeptr != NULL) {
4593 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4596 xcodeptr = cd->mcodeptr;
4598 i386_push_reg(cd, REG_ITMP2_XPC);
4600 PREPARE_NATIVE_STACKINFO;
4602 i386_mov_imm_reg(cd, (s4) codegen_general_stubcalled, REG_ITMP1);
4603 i386_call_reg(cd, REG_ITMP1);
4605 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4606 i386_mov_imm_reg(cd, (s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4607 i386_call_reg(cd, REG_ITMP1);
4608 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP3);
4609 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
4610 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1_XPTR);
4612 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP3);
4613 i386_mov_membase_reg(cd, REG_ITMP3, 0, REG_ITMP1_XPTR);
4614 i386_mov_imm_membase(cd, 0, REG_ITMP3, 0);
4616 i386_push_imm(cd, 0);
4617 i386_push_reg(cd, REG_ITMP1_XPTR);
4619 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4620 java stack at this point*/
4621 i386_mov_membase_reg(cd, REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4622 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, class), REG_ITMP1);
4623 i386_push_imm(cd, (u4) utf_fillInStackTrace_desc);
4624 i386_push_imm(cd, (u4) utf_fillInStackTrace_name);
4625 i386_push_reg(cd, REG_ITMP1);
4626 i386_mov_imm_reg(cd, (s4) class_resolvemethod, REG_ITMP3);
4627 i386_call_reg(cd, REG_ITMP3);
4628 /*cleanup parameters of class_resolvemethod*/
4629 i386_alu_imm_reg(cd, I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4630 /*prepare call to asm_calljavafunction2 */
4631 i386_push_imm(cd, 0);
4632 i386_push_imm(cd, TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
4633 i386_push_reg(cd, REG_SP);
4634 i386_push_imm(cd, sizeof(jni_callblock));
4635 i386_push_imm(cd, 1);
4636 i386_push_reg(cd, REG_RESULT);
4638 i386_mov_imm_reg(cd, (s4) asm_calljavafunction2, REG_ITMP3);
4639 i386_call_reg(cd, REG_ITMP3);
4641 /* check exceptionptr + fail (JOWENN)*/
4643 i386_alu_imm_reg(cd, I386_ADD,6*4,REG_SP);
4645 i386_pop_reg(cd, REG_ITMP1_XPTR);
4646 i386_pop_reg(cd, REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4648 REMOVE_NATIVE_STACKINFO;
4650 i386_pop_reg(cd, REG_ITMP2_XPC);
4652 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4653 i386_jmp_reg(cd, REG_ITMP3);
4657 /* generate null pointer check stubs */
4661 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
4662 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4663 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4665 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4669 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4671 cd->mcodeptr - cd->mcodebase);
4675 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4676 dseg_adddata(m, cd->mcodeptr);
4677 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4678 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4680 if (xcodeptr != NULL) {
4681 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4684 xcodeptr = cd->mcodeptr;
4686 i386_push_reg(cd, REG_ITMP2_XPC);
4688 PREPARE_NATIVE_STACKINFO;
4691 /* create native call block*/
4692 i386_alu_imm_reg(cd, I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4695 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1);
4696 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/
4698 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4699 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
4700 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
4701 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
4702 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4703 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */
4704 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4707 /* create exception*/
4708 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4709 i386_mov_imm_membase(cd, (s4) string_java_lang_NullPointerException, REG_SP, 0 * 4);
4710 i386_mov_imm_reg(cd, (s4) new_exception, REG_ITMP1);
4711 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4712 i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4714 REMOVE_NATIVE_STACKINFO;
4717 /* restore native call stack */
4718 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2);
4719 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3);
4720 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0);
4721 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
4724 i386_pop_reg(cd, REG_ITMP2_XPC);
4726 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4727 i386_jmp_reg(cd, REG_ITMP3);
4732 codegen_finish(m, (u4) (cd->mcodeptr - cd->mcodebase));
4736 /* function createcompilerstub *************************************************
4738 creates a stub routine which calls the compiler
4740 *******************************************************************************/
4742 #define COMPSTUBSIZE 12
4744 u1 *createcompilerstub(methodinfo *m)
4746 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
4749 /* setup codegendata structure */
4752 cd = m->codegendata;
4755 /* code for the stub */
4756 i386_mov_imm_reg(cd, (u4) m, REG_ITMP1);/* pass method pointer to compiler*/
4758 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
4759 i386_mov_imm_reg(cd, (u4) asm_call_jit_compiler, REG_ITMP3);
4760 i386_jmp_reg(cd, REG_ITMP3); /* jump to compiler */
4762 /* free codegendata memory */
4765 #if defined(STATISTICS)
4767 count_cstub_len += COMPSTUBSIZE;
4774 /* function removecompilerstub *************************************************
4776 deletes a compilerstub from memory (simply by freeing it)
4778 *******************************************************************************/
4780 void removecompilerstub(u1 *stub)
4782 CFREE(stub, COMPSTUBSIZE);
4786 /* function: createnativestub **************************************************
4788 creates a stub routine which calls a native method
4790 *******************************************************************************/
4792 #define NATIVESTUBSIZE 350
4794 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4795 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4798 void i386_native_stub_debug(void **p) {
4799 printf("Pos on stack: %p\n",p);
4800 printf("Return adress should be: %p\n",*p);
4803 void i386_native_stub_debug2(void **p) {
4804 printf("Pos on stack: %p\n",p);
4805 printf("Return for lookup is: %p\n",*p);
4808 void traverseStackInfo() {
4809 void **p=builtin_asm_get_stackframeinfo();
4813 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4814 m=*((methodinfo**)((*p)+8));
4815 utf_display(m->name);
4823 u1 *createnativestub(functionptr f, methodinfo *m)
4825 u1 *s = CNEW(u1, NATIVESTUBSIZE); /* memory to hold the stub */
4829 int stackframesize = 4+12; /* initial 4 bytes is space for jni env,
4830 + 4 byte thread pointer + 4 byte previous pointer + method info*/
4831 int stackframeoffset = 4;
4836 /* setup codegendata structure */
4839 cd = m->codegendata;
4842 if (m->flags & ACC_STATIC) {
4843 stackframesize += 4;
4844 stackframeoffset += 4;
4848 descriptor2types(m); /* set paramcount and paramtypes */
4851 /* i386_push_reg(cd, REG_SP);
4852 i386_mov_imm_reg(cd, (s4) i386_native_stub_debug, REG_ITMP1);
4853 i386_call_reg(cd, REG_ITMP1);
4854 i386_pop_reg(cd, REG_ITMP1);*/
4857 /* if function is static, check for initialized */
4859 if (m->flags & ACC_STATIC) {
4860 /* if class isn't yet initialized, do it */
4861 if (!m->class->initialized) {
4862 s4 *header = (s4 *) s;
4863 *header = 0;/*extablesize*/
4865 *header = 0;/*line number table start*/
4867 *header = 0;/*line number table size*/
4869 *header = 0;/*fltsave*/
4871 *header = 0;/*intsave*/
4873 *header = 0;/*isleaf*/
4875 *header = 0;/*issync*/
4877 *header = 0;/*framesize*/
4879 *header = (u4) m;/*methodpointer*/
4881 cd->mcodeptr = s = (u1 *) header;
4884 /* call helper function which patches this code */
4885 i386_mov_imm_reg(cd, (u4) m->class, REG_ITMP1);
4886 i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP2);
4887 i386_call_reg(cd, REG_ITMP2);
4892 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4894 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
4895 t = m->paramtypes[p];
4896 if (IS_INT_LNG_TYPE(t)) {
4897 if (IS_2_WORD_TYPE(t)) {
4898 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4899 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
4900 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4901 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4903 } else if (t == TYPE_ADR) {
4904 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4905 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
4906 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4907 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4910 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
4912 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
4913 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
4917 if (!IS_2_WORD_TYPE(t)) {
4918 i386_flds_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4919 i386_fstps_membase(cd, REG_SP, p * 8);
4920 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
4921 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4924 i386_fldl_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4925 i386_fstpl_membase(cd, REG_SP, p * 8);
4930 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
4931 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
4932 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4933 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
4936 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
4938 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
4939 i386_call_reg(cd, REG_ITMP1);
4941 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4945 * mark the whole fpu stack as free for native functions
4946 * (only for saved register count == 0)
4948 i386_ffree_reg(cd, 0);
4949 i386_ffree_reg(cd, 1);
4950 i386_ffree_reg(cd, 2);
4951 i386_ffree_reg(cd, 3);
4952 i386_ffree_reg(cd, 4);
4953 i386_ffree_reg(cd, 5);
4954 i386_ffree_reg(cd, 6);
4955 i386_ffree_reg(cd, 7);
4957 /* calculate stackframe size for native function */
4958 tptr = m->paramtypes;
4959 for (i = 0; i < m->paramcount; i++) {
4964 stackframesize += 4;
4969 stackframesize += 8;
4973 panic("unknown parameter type in native function");
4977 i386_alu_imm_reg(cd, I386_SUB, stackframesize, REG_SP);
4979 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
4980 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
4981 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
4982 i386_call_reg(cd, REG_ITMP1);
4983 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
4984 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2);
4985 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
4986 i386_mov_reg_reg(cd, REG_SP,REG_ITMP2);
4987 i386_alu_imm_reg(cd, I386_ADD,stackframesize-12,REG_ITMP2);
4988 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0);
4991 /* i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
4992 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
4993 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-12);*/
4995 /* CREATE DYNAMIC STACK INFO -- END*/
4998 tptr = m->paramtypes;
4999 for (i = 0; i < m->paramcount; i++) {
5004 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5005 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5006 stackframeoffset += 4;
5011 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5012 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5013 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5014 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, stackframeoffset + 4);
5015 stackframeoffset += 8;
5019 panic("unknown parameter type in native function");
5023 if (m->flags & ACC_STATIC) {
5024 /* put class into second argument */
5025 i386_mov_imm_membase(cd, (s4) m->class, REG_SP, 4);
5028 /* put env into first argument */
5029 i386_mov_imm_membase(cd, (s4) &env, REG_SP, 0);
5031 i386_mov_imm_reg(cd, (s4) f, REG_ITMP1);
5032 i386_call_reg(cd, REG_ITMP1);
5033 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5034 i386_push_reg(cd, REG_RESULT2);
5035 i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
5036 i386_mov_membase_reg(cd, REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
5037 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT2,0);
5038 i386_pop_reg(cd, REG_RESULT2);
5039 /*REMOVE DYNAMIC STACK INFO -END */
5041 i386_alu_imm_reg(cd, I386_ADD, stackframesize, REG_SP);
5045 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5047 i386_mov_imm_membase(cd, (u4) m, REG_SP, 0);
5049 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
5050 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
5052 i386_fstl_membase(cd, REG_SP, 4 + 8);
5053 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5055 i386_mov_imm_reg(cd, (u4) builtin_displaymethodstop, REG_ITMP1);
5056 i386_call_reg(cd, REG_ITMP1);
5058 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
5059 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
5061 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5065 /* we can't use REG_ITMP3 == REG_RESULT2 */
5066 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5067 i386_push_reg(cd, REG_RESULT);
5068 i386_push_reg(cd, REG_RESULT2);
5069 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5070 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP2);
5071 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5072 i386_pop_reg(cd, REG_RESULT2);
5073 i386_pop_reg(cd, REG_RESULT);
5075 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5076 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP2);
5077 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5079 i386_jcc(cd, I386_CC_NE, 1);
5083 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5084 i386_push_reg(cd, REG_ITMP2);
5085 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5086 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5087 i386_pop_reg(cd, REG_ITMP1_XPTR);
5089 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1_XPTR);
5090 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5091 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5093 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP2_XPC);
5094 i386_alu_imm_reg(cd, I386_SUB, 2, REG_ITMP2_XPC);
5096 i386_mov_imm_reg(cd, (s4) asm_handle_nat_exception, REG_ITMP3);
5097 i386_jmp_reg(cd, REG_ITMP3);
5100 codegen_insertmethod(s, cd->mcodeptr);
5104 dolog_plain("native stubentry: %p, stubsize: %x (for %d params) --", (s4)s,(s4) (cd->mcodeptr - s), m->paramcount);
5105 utf_display(m->name);
5109 /* free codegendata memory */
5112 #if defined(STATISTICS)
5114 count_nstub_len += NATIVESTUBSIZE;
5121 /* function: removenativestub **************************************************
5123 removes a previously created native-stub from memory
5125 *******************************************************************************/
5127 void removenativestub(u1 *stub)
5129 CFREE(stub, NATIVESTUBSIZE);
5134 * These are local overrides for various environment variables in Emacs.
5135 * Please do not remove this and leave it at the end of the file, where
5136 * Emacs will automagically detect them.
5137 * ---------------------------------------------------------------------
5140 * indent-tabs-mode: t