1 /* src/vm/jit/i386/codegen.c - machine code generator for i386
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
30 Changes: Joseph Wenninger
32 $Id: codegen.c 2184 2005-04-01 21:19:05Z edwin $
42 #include <machine/signal.h>
46 #include "cacao/cacao.h"
47 #include "native/jni.h"
48 #include "native/native.h"
49 #include "vm/builtin.h"
50 #include "vm/exceptions.h"
51 #include "vm/global.h"
52 #include "vm/loader.h"
53 #include "vm/tables.h"
55 #include "vm/jit/asmpart.h"
56 #include "vm/jit/jit.h"
57 #include "vm/jit/parse.h"
58 #include "vm/jit/reg.h"
59 #include "vm/jit/i386/codegen.h"
60 #include "vm/jit/i386/emitfuncs.h"
61 #include "vm/jit/i386/types.h"
62 #include "vm/jit/i386/asmoffsets.h"
65 /* register descripton - array ************************************************/
67 /* #define REG_RES 0 reserved register for OS or code generator */
68 /* #define REG_RET 1 return value register */
69 /* #define REG_EXC 2 exception value register (only old jit) */
70 /* #define REG_SAV 3 (callee) saved register */
71 /* #define REG_TMP 4 scratch temporary register (caller saved) */
72 /* #define REG_ARG 5 argument register (caller saved) */
74 /* #define REG_END -1 last entry in tables */
76 static int nregdescint[] = {
77 REG_RET, REG_RES, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV,
82 static int nregdescfloat[] = {
83 /* rounding problems with callee saved registers */
84 /* REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_RES, REG_RES, */
85 /* REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, */
86 REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
91 /*******************************************************************************
93 include independent code generation stuff -- include after register
94 descriptions to avoid extern definitions
96 *******************************************************************************/
98 #include "vm/jit/codegen.inc"
99 #include "vm/jit/reg.inc"
101 #include "vm/jit/lsra.inc"
104 void codegen_stubcalled() {
105 log_text("Stub has been called");
109 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
110 void thread_restartcriticalsection(ucontext_t *uc)
114 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.mc_eip)) != NULL)
115 uc->uc_mcontext.mc_eip = (u4) critical;
117 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL)
118 uc->uc_mcontext.gregs[REG_EIP] = (u4) critical;
126 /* NullPointerException signal handler for hardware null pointer check */
128 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
132 ucontext_t *_uc = (ucontext_t *) _p;
134 mcontext_t *sigctx = (mcontext_t *) &_uc->uc_mcontext;
136 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
138 struct sigaction act;
140 /* Reset signal handler - necessary for SysV, does no harm for BSD */
142 act.sa_sigaction = catch_NullPointerException;
143 act.sa_flags = SA_SIGINFO;
144 sigaction(sig, &act, NULL); /* reinstall handler */
147 sigaddset(&nsig, sig);
148 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
151 sigctx->mc_ecx = sigctx->mc_eip; /* REG_ITMP2_XPC*/
152 sigctx->mc_eax = (u4) string_java_lang_NullPointerException;
153 sigctx->mc_eip = (u4) asm_throw_and_handle_exception;
155 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
156 sigctx->eax = (u4) string_java_lang_NullPointerException;
157 sigctx->eip = (u4) asm_throw_and_handle_exception;
164 /* ArithmeticException signal handler for hardware divide by zero check */
166 void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p)
171 ucontext_t *_uc = (ucontext_t *) _p;
172 mcontext_t *sigctx = (mcontext_t *) &_uc->uc_mcontext;
174 struct ucontext *_uc = (struct ucontext *) _p;
175 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
178 struct sigaction act;
180 /* Reset signal handler - necessary for SysV, does no harm for BSD */
182 act.sa_sigaction = catch_ArithmeticException;
183 act.sa_flags = SA_SIGINFO;
184 sigaction(sig, &act, NULL); /* reinstall handler */
187 sigaddset(&nsig, sig);
188 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
191 sigctx->mc_ecx = sigctx->mc_eip; /* REG_ITMP2_XPC */
192 sigctx->mc_eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
194 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
195 sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
201 void init_exceptions(void)
203 struct sigaction act;
205 /* install signal handlers we need to convert to exceptions */
206 sigemptyset(&act.sa_mask);
209 act.sa_sigaction = catch_NullPointerException;
210 act.sa_flags = SA_SIGINFO;
213 sigaction(SIGSEGV, &act, NULL);
217 sigaction(SIGBUS, &act, NULL);
222 act.sa_sigaction = catch_ArithmeticException;
223 act.sa_flags = SA_SIGINFO;
224 sigaction(SIGFPE, &act, NULL);
229 /* function codegen ************************************************************
231 generates machine code
233 *******************************************************************************/
235 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
237 s4 len, s1, s2, s3, d;
245 s4 fpu_st_offset = 0;
251 s4 savedregs_num = 0;
253 /* space to save used callee saved registers */
255 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
256 savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
258 parentargs_base = rd->maxmemuse + savedregs_num;
261 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
263 if (checksync && (m->flags & ACC_SYNCHRONIZED))
268 /* create method header */
270 (void) dseg_addaddress(cd, m); /* MethodPointer */
271 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
273 #if defined(USE_THREADS)
275 /* IsSync contains the offset relative to the stack pointer for the
276 argument of monitor_exit used in the exception handler. Since the
277 offset could be zero and give a wrong meaning of the flag it is
281 if (checksync && (m->flags & ACC_SYNCHRONIZED))
282 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8); /* IsSync */
287 (void) dseg_adds4(cd, 0); /* IsSync */
289 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
290 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
291 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
293 /* adds a reference for the length of the line number counter. We don't
294 know the size yet, since we evaluate the information during code
295 generation, to save one additional iteration over the whole
296 instructions. During code optimization the position could have changed
297 to the information gotten from the class file */
298 (void) dseg_addlinenumbertablesize(cd);
300 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
302 /* create exception table */
304 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
305 dseg_addtarget(cd, ex->start);
306 dseg_addtarget(cd, ex->end);
307 dseg_addtarget(cd, ex->handler);
308 (void) dseg_addaddress(cd, ex->catchtype);
312 /* initialize mcode variables */
314 cd->mcodeptr = cd->mcodebase;
315 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
316 MCODECHECK(128 + m->paramcount);
318 /* create stack frame (if necessary) */
320 if (parentargs_base) {
321 i386_alu_imm_reg(cd, I386_SUB, parentargs_base * 8, REG_SP);
324 /* save return address and used callee saved registers */
327 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
328 p--; i386_mov_reg_membase(cd, rd->savintregs[i], REG_SP, p * 8);
330 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
331 p--; i386_fld_reg(cd, rd->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 8);
334 /* save monitorenter argument */
336 #if defined(USE_THREADS)
337 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
338 s4 func_enter = (m->flags & ACC_STATIC) ?
339 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
341 if (m->flags & ACC_STATIC) {
342 i386_mov_imm_reg(cd, (s4) m->class, REG_ITMP1);
343 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
346 i386_mov_membase_reg(cd, REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
347 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
350 /* call monitorenter function */
352 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
353 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
354 i386_mov_imm_reg(cd, func_enter, REG_ITMP1);
355 i386_call_reg(cd, REG_ITMP1);
356 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
360 /* copy argument registers to stack and call trace function with pointer
361 to arguments on stack.
365 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
367 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
368 t = m->paramtypes[p];
370 if (IS_INT_LNG_TYPE(t)) {
371 if (IS_2_WORD_TYPE(t)) {
372 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
373 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
374 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
375 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
377 /* } else if (t == TYPE_ADR) { */
379 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
380 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
381 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
382 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
385 /* i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
387 /* i386_mov_reg_membase(cd, EAX, REG_SP, p * 8); */
388 /* i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4); */
392 if (!IS_2_WORD_TYPE(t)) {
393 i386_flds_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
394 i386_fstps_membase(cd, REG_SP, p * 8);
395 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
396 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
399 i386_fldl_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
400 i386_fstpl_membase(cd, REG_SP, p * 8);
405 /* fill up the remaining arguments */
406 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
407 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
408 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
409 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
412 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
413 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
414 i386_call_reg(cd, REG_ITMP1);
416 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
419 /* take arguments out of register or stack frame */
421 for (p = 0, l = 0; p < m->paramcount; p++) {
422 t = m->paramtypes[p];
423 var = &(rd->locals[l][t]);
425 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
429 if (IS_INT_LNG_TYPE(t)) { /* integer args */
430 if (p < rd->intreg_argnum) { /* register arguments */
431 panic("integer register argument");
432 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
433 /* M_INTMOVE (argintregs[p], r); */
435 } else { /* reg arg -> spilled */
436 /* M_LST (argintregs[p], REG_SP, 8 * r); */
438 } else { /* stack arguments */
439 pa = p - rd->intreg_argnum;
440 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
441 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, var->regoff); /* + 4 for return address */
442 } else { /* stack arg -> spilled */
443 if (!IS_2_WORD_TYPE(t)) {
444 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
445 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
448 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
449 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
450 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1); /* + 4 for return address */
451 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8 + 4);
456 } else { /* floating args */
457 if (p < rd->fltreg_argnum) { /* register arguments */
458 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
459 panic("There are no float argument registers!");
461 } else { /* reg arg -> spilled */
462 panic("There are no float argument registers!");
465 } else { /* stack arguments */
466 pa = p - rd->fltreg_argnum;
467 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
469 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
471 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
475 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
477 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
481 } else { /* stack-arg -> spilled */
482 /* i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
483 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r * 8); */
485 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
486 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
489 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
490 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
499 /* end of header generation */
501 /* walk through all basic blocks */
502 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
504 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
506 if (bptr->flags >= BBREACHED) {
508 /* branch resolving */
511 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
512 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
517 /* copy interface registers to their destination */
525 while (src != NULL) {
527 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
528 if (!IS_2_WORD_TYPE(src->type)) {
529 if (bptr->type == BBTYPE_SBR) {
530 /* d = reg_of_var(m, src, REG_ITMP1); */
531 if (!(src->flags & INMEMORY))
536 store_reg_to_var_int(src, d);
537 } else if (bptr->type == BBTYPE_EXH) {
538 /* d = reg_of_var(m, src, REG_ITMP1); */
539 if (!(src->flags & INMEMORY))
543 M_INTMOVE(REG_ITMP1, d);
544 store_reg_to_var_int(src, d);
548 panic("copy interface registers(EXH, SBR): longs have to me in memory (begin 1)");
555 while (src != NULL) {
557 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
558 if (!IS_2_WORD_TYPE(src->type)) {
559 if (bptr->type == BBTYPE_SBR) {
560 d = reg_of_var(rd, src, REG_ITMP1);
562 store_reg_to_var_int(src, d);
563 } else if (bptr->type == BBTYPE_EXH) {
564 d = reg_of_var(rd, src, REG_ITMP1);
565 M_INTMOVE(REG_ITMP1, d);
566 store_reg_to_var_int(src, d);
570 panic("copy interface registers: longs have to me in memory (begin 1)");
574 d = reg_of_var(rd, src, REG_ITMP1);
575 if ((src->varkind != STACKVAR)) {
577 if (IS_FLT_DBL_TYPE(s2)) {
578 s1 = rd->interfaces[len][s2].regoff;
579 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
583 if (s2 == TYPE_FLT) {
584 i386_flds_membase(cd, REG_SP, s1 * 8);
587 i386_fldl_membase(cd, REG_SP, s1 * 8);
590 store_reg_to_var_flt(src, d);
593 s1 = rd->interfaces[len][s2].regoff;
594 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
595 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
599 i386_mov_membase_reg(cd, REG_SP, s1 * 8, d);
601 store_reg_to_var_int(src, d);
604 if (rd->interfaces[len][s2].flags & INMEMORY) {
605 M_LNGMEMMOVE(s1, src->regoff);
608 panic("copy interface registers: longs have to be in memory (begin 2)");
620 /* walk through all instructions */
625 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
626 if (iptr->line != currentline) {
627 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
628 currentline = iptr->line;
631 MCODECHECK(64); /* an instruction usually needs < 64 words */
634 case ICMD_INLINE_START:
635 case ICMD_INLINE_END:
638 case ICMD_NOP: /* ... ==> ... */
641 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
642 if (src->flags & INMEMORY) {
643 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
646 i386_test_reg_reg(cd, src->regoff, src->regoff);
648 i386_jcc(cd, I386_CC_E, 0);
649 codegen_addxnullrefs(cd, cd->mcodeptr);
652 /* constant operations ************************************************/
654 case ICMD_ICONST: /* ... ==> ..., constant */
655 /* op1 = 0, val.i = constant */
657 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
658 if (iptr->dst->flags & INMEMORY) {
659 i386_mov_imm_membase(cd, iptr->val.i, REG_SP, iptr->dst->regoff * 8);
662 if (iptr->val.i == 0) {
663 i386_alu_reg_reg(cd, I386_XOR, d, d);
666 i386_mov_imm_reg(cd, iptr->val.i, d);
671 case ICMD_LCONST: /* ... ==> ..., constant */
672 /* op1 = 0, val.l = constant */
674 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
675 if (iptr->dst->flags & INMEMORY) {
676 i386_mov_imm_membase(cd, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
677 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
680 panic("LCONST: longs have to be in memory");
684 case ICMD_FCONST: /* ... ==> ..., constant */
685 /* op1 = 0, val.f = constant */
687 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
688 if (iptr->val.f == 0.0) {
693 if (iptr->val.i == 0x80000000) {
697 } else if (iptr->val.f == 1.0) {
701 } else if (iptr->val.f == 2.0) {
708 a = dseg_addfloat(cd, iptr->val.f);
709 i386_mov_imm_reg(cd, 0, REG_ITMP1);
710 dseg_adddata(cd, cd->mcodeptr);
711 i386_flds_membase(cd, REG_ITMP1, a);
714 store_reg_to_var_flt(iptr->dst, d);
717 case ICMD_DCONST: /* ... ==> ..., constant */
718 /* op1 = 0, val.d = constant */
720 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
721 if (iptr->val.d == 0.0) {
726 if (iptr->val.l == 0x8000000000000000LL) {
730 } else if (iptr->val.d == 1.0) {
734 } else if (iptr->val.d == 2.0) {
741 a = dseg_adddouble(cd, iptr->val.d);
742 i386_mov_imm_reg(cd, 0, REG_ITMP1);
743 dseg_adddata(cd, cd->mcodeptr);
744 i386_fldl_membase(cd, REG_ITMP1, a);
747 store_reg_to_var_flt(iptr->dst, d);
750 case ICMD_ACONST: /* ... ==> ..., constant */
751 /* op1 = 0, val.a = constant */
753 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
754 if (iptr->dst->flags & INMEMORY) {
755 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
758 if ((s4) iptr->val.a == 0) {
759 i386_alu_reg_reg(cd, I386_XOR, d, d);
762 i386_mov_imm_reg(cd, (s4) iptr->val.a, d);
768 /* load/store operations **********************************************/
770 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
771 case ICMD_ALOAD: /* op1 = local variable */
773 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
774 if ((iptr->dst->varkind == LOCALVAR) &&
775 (iptr->dst->varnum == iptr->op1)) {
778 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
779 if (iptr->dst->flags & INMEMORY) {
780 if (var->flags & INMEMORY) {
781 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, REG_ITMP1);
782 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
785 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
789 if (var->flags & INMEMORY) {
790 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, iptr->dst->regoff);
793 M_INTMOVE(var->regoff, iptr->dst->regoff);
798 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
799 /* op1 = local variable */
801 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
802 if ((iptr->dst->varkind == LOCALVAR) &&
803 (iptr->dst->varnum == iptr->op1)) {
806 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
807 if (iptr->dst->flags & INMEMORY) {
808 if (var->flags & INMEMORY) {
809 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
812 panic("LLOAD: longs have to be in memory");
816 panic("LLOAD: longs have to be in memory");
820 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
821 /* op1 = local variable */
823 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
824 if ((iptr->dst->varkind == LOCALVAR) &&
825 (iptr->dst->varnum == iptr->op1)) {
828 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
829 if (var->flags & INMEMORY) {
830 i386_flds_membase(cd, REG_SP, var->regoff * 8);
833 i386_fld_reg(cd, var->regoff + fpu_st_offset);
836 store_reg_to_var_flt(iptr->dst, d);
839 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
840 /* op1 = local variable */
842 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
843 if ((iptr->dst->varkind == LOCALVAR) &&
844 (iptr->dst->varnum == iptr->op1)) {
847 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
848 if (var->flags & INMEMORY) {
849 i386_fldl_membase(cd, REG_SP, var->regoff * 8);
852 i386_fld_reg(cd, var->regoff + fpu_st_offset);
855 store_reg_to_var_flt(iptr->dst, d);
858 case ICMD_ISTORE: /* ..., value ==> ... */
859 case ICMD_ASTORE: /* op1 = local variable */
861 if ((src->varkind == LOCALVAR) &&
862 (src->varnum == iptr->op1)) {
865 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
866 if (var->flags & INMEMORY) {
867 if (src->flags & INMEMORY) {
868 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
869 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
872 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 8);
876 var_to_reg_int(s1, src, var->regoff);
877 M_INTMOVE(s1, var->regoff);
881 case ICMD_LSTORE: /* ..., value ==> ... */
882 /* op1 = local variable */
884 if ((src->varkind == LOCALVAR) &&
885 (src->varnum == iptr->op1)) {
888 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
889 if (var->flags & INMEMORY) {
890 if (src->flags & INMEMORY) {
891 M_LNGMEMMOVE(src->regoff, var->regoff);
894 panic("LSTORE: longs have to be in memory");
898 panic("LSTORE: longs have to be in memory");
902 case ICMD_FSTORE: /* ..., value ==> ... */
903 /* op1 = local variable */
905 if ((src->varkind == LOCALVAR) &&
906 (src->varnum == iptr->op1)) {
909 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
910 if (var->flags & INMEMORY) {
911 var_to_reg_flt(s1, src, REG_FTMP1);
912 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
915 var_to_reg_flt(s1, src, var->regoff);
916 /* M_FLTMOVE(s1, var->regoff); */
917 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
922 case ICMD_DSTORE: /* ..., value ==> ... */
923 /* op1 = local variable */
925 if ((src->varkind == LOCALVAR) &&
926 (src->varnum == iptr->op1)) {
929 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
930 if (var->flags & INMEMORY) {
931 var_to_reg_flt(s1, src, REG_FTMP1);
932 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
935 var_to_reg_flt(s1, src, var->regoff);
936 /* M_FLTMOVE(s1, var->regoff); */
937 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
943 /* pop/dup/swap operations ********************************************/
945 /* attention: double and longs are only one entry in CACAO ICMDs */
947 case ICMD_POP: /* ..., value ==> ... */
948 case ICMD_POP2: /* ..., value, value ==> ... */
951 case ICMD_DUP: /* ..., a ==> ..., a, a */
952 M_COPY(src, iptr->dst);
955 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
957 M_COPY(src, iptr->dst);
958 M_COPY(src->prev, iptr->dst->prev);
961 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
963 M_COPY(src, iptr->dst);
964 M_COPY(src->prev, iptr->dst->prev);
965 M_COPY(iptr->dst, iptr->dst->prev->prev);
968 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
970 M_COPY(src, iptr->dst);
971 M_COPY(src->prev, iptr->dst->prev);
972 M_COPY(src->prev->prev, iptr->dst->prev->prev);
973 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
976 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
978 M_COPY(src, iptr->dst);
979 M_COPY(src->prev, iptr->dst->prev);
980 M_COPY(src->prev->prev, iptr->dst->prev->prev);
981 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
982 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev);
985 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
987 M_COPY(src, iptr->dst);
988 M_COPY(src->prev, iptr->dst->prev);
989 M_COPY(src->prev->prev, iptr->dst->prev->prev);
990 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
991 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
992 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
995 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
997 M_COPY(src, iptr->dst->prev);
998 M_COPY(src->prev, iptr->dst);
1002 /* integer operations *************************************************/
1004 case ICMD_INEG: /* ..., value ==> ..., - value */
1006 d = reg_of_var(rd, iptr->dst, REG_NULL);
1007 if (iptr->dst->flags & INMEMORY) {
1008 if (src->flags & INMEMORY) {
1009 if (src->regoff == iptr->dst->regoff) {
1010 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1013 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1014 i386_neg_reg(cd, REG_ITMP1);
1015 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1019 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1020 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1024 if (src->flags & INMEMORY) {
1025 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1026 i386_neg_reg(cd, iptr->dst->regoff);
1029 M_INTMOVE(src->regoff, iptr->dst->regoff);
1030 i386_neg_reg(cd, iptr->dst->regoff);
1035 case ICMD_LNEG: /* ..., value ==> ..., - value */
1037 d = reg_of_var(rd, iptr->dst, REG_NULL);
1038 if (iptr->dst->flags & INMEMORY) {
1039 if (src->flags & INMEMORY) {
1040 if (src->regoff == iptr->dst->regoff) {
1041 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1042 i386_alu_imm_membase(cd, I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1043 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8 + 4);
1046 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1047 i386_neg_reg(cd, REG_ITMP1);
1048 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1049 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1050 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP1);
1051 i386_neg_reg(cd, REG_ITMP1);
1052 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1058 case ICMD_I2L: /* ..., value ==> ..., value */
1060 d = reg_of_var(rd, iptr->dst, REG_NULL);
1061 if (iptr->dst->flags & INMEMORY) {
1062 if (src->flags & INMEMORY) {
1063 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, EAX);
1065 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1066 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1069 M_INTMOVE(src->regoff, EAX);
1071 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1072 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1077 case ICMD_L2I: /* ..., value ==> ..., value */
1079 d = reg_of_var(rd, iptr->dst, REG_NULL);
1080 if (iptr->dst->flags & INMEMORY) {
1081 if (src->flags & INMEMORY) {
1082 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1083 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1087 if (src->flags & INMEMORY) {
1088 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1093 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1095 d = reg_of_var(rd, iptr->dst, REG_NULL);
1096 if (iptr->dst->flags & INMEMORY) {
1097 if (src->flags & INMEMORY) {
1098 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1099 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1100 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1101 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1104 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1105 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1106 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1110 if (src->flags & INMEMORY) {
1111 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1112 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1113 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1116 M_INTMOVE(src->regoff, iptr->dst->regoff);
1117 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1118 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1123 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1125 d = reg_of_var(rd, iptr->dst, REG_NULL);
1126 if (iptr->dst->flags & INMEMORY) {
1127 if (src->flags & INMEMORY) {
1128 if (src->regoff == iptr->dst->regoff) {
1129 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1132 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1133 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, REG_ITMP1);
1134 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1138 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1139 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, 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_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1148 M_INTMOVE(src->regoff, iptr->dst->regoff);
1149 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1154 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1156 d = reg_of_var(rd, iptr->dst, REG_NULL);
1157 if (iptr->dst->flags & INMEMORY) {
1158 if (src->flags & INMEMORY) {
1159 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1160 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1161 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1162 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1165 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1166 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1167 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1171 if (src->flags & INMEMORY) {
1172 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1173 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1174 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1177 M_INTMOVE(src->regoff, iptr->dst->regoff);
1178 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1179 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1185 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1187 d = reg_of_var(rd, iptr->dst, REG_NULL);
1188 i386_emit_ialu(cd, I386_ADD, src, iptr);
1191 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1192 /* val.i = constant */
1194 d = reg_of_var(rd, iptr->dst, REG_NULL);
1195 i386_emit_ialuconst(cd, I386_ADD, src, iptr);
1198 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1200 d = reg_of_var(rd, iptr->dst, REG_NULL);
1201 if (iptr->dst->flags & INMEMORY) {
1202 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1203 if (src->regoff == iptr->dst->regoff) {
1204 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1205 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1206 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1207 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1209 } else if (src->prev->regoff == iptr->dst->regoff) {
1210 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1211 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1212 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1213 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1216 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1217 i386_alu_membase_reg(cd, I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1218 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1219 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1220 i386_alu_membase_reg(cd, I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1221 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1228 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1229 /* val.l = constant */
1231 d = reg_of_var(rd, iptr->dst, REG_NULL);
1232 if (iptr->dst->flags & INMEMORY) {
1233 if (src->flags & INMEMORY) {
1234 if (src->regoff == iptr->dst->regoff) {
1235 i386_alu_imm_membase(cd, I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1236 i386_alu_imm_membase(cd, I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1239 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1240 i386_alu_imm_reg(cd, I386_ADD, iptr->val.l, REG_ITMP1);
1241 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1242 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1243 i386_alu_imm_reg(cd, I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1244 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1250 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1252 d = reg_of_var(rd, iptr->dst, REG_NULL);
1253 if (iptr->dst->flags & INMEMORY) {
1254 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1255 if (src->prev->regoff == iptr->dst->regoff) {
1256 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1257 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1260 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1261 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1262 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1265 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1266 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1267 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1268 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1270 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1271 if (src->prev->regoff == iptr->dst->regoff) {
1272 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1275 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1276 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1277 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1281 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1282 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1286 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1287 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1288 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1290 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1291 M_INTMOVE(src->prev->regoff, d);
1292 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1294 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1295 /* workaround for reg alloc */
1296 if (src->regoff == iptr->dst->regoff) {
1297 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1298 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1299 M_INTMOVE(REG_ITMP1, d);
1302 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1303 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1307 /* workaround for reg alloc */
1308 if (src->regoff == iptr->dst->regoff) {
1309 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1310 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1311 M_INTMOVE(REG_ITMP1, d);
1314 M_INTMOVE(src->prev->regoff, d);
1315 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1321 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1322 /* val.i = constant */
1324 d = reg_of_var(rd, iptr->dst, REG_NULL);
1325 i386_emit_ialuconst(cd, I386_SUB, src, iptr);
1328 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1330 d = reg_of_var(rd, iptr->dst, REG_NULL);
1331 if (iptr->dst->flags & INMEMORY) {
1332 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1333 if (src->prev->regoff == iptr->dst->regoff) {
1334 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1335 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1336 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1337 i386_alu_reg_membase(cd, I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1340 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1341 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1342 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1343 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1344 i386_alu_membase_reg(cd, I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1345 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1351 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1352 /* val.l = constant */
1354 d = reg_of_var(rd, iptr->dst, REG_NULL);
1355 if (iptr->dst->flags & INMEMORY) {
1356 if (src->flags & INMEMORY) {
1357 if (src->regoff == iptr->dst->regoff) {
1358 i386_alu_imm_membase(cd, I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1359 i386_alu_imm_membase(cd, I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1362 /* TODO: could be size optimized with lea -- see gcc output */
1363 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1364 i386_alu_imm_reg(cd, I386_SUB, iptr->val.l, REG_ITMP1);
1365 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1366 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1367 i386_alu_imm_reg(cd, I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1368 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1374 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1376 d = reg_of_var(rd, iptr->dst, REG_NULL);
1377 if (iptr->dst->flags & INMEMORY) {
1378 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1379 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1380 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1381 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1383 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1384 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1385 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1386 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1388 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1389 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1390 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1391 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1394 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1395 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1396 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1400 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1401 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1402 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1404 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1405 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1406 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1408 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1409 M_INTMOVE(src->regoff, iptr->dst->regoff);
1410 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1413 if (src->regoff == iptr->dst->regoff) {
1414 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1417 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1418 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1424 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1425 /* val.i = constant */
1427 d = reg_of_var(rd, iptr->dst, REG_NULL);
1428 if (iptr->dst->flags & INMEMORY) {
1429 if (src->flags & INMEMORY) {
1430 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1431 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1434 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1435 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1439 if (src->flags & INMEMORY) {
1440 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1443 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1448 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1450 d = reg_of_var(rd, iptr->dst, REG_NULL);
1451 if (iptr->dst->flags & INMEMORY) {
1452 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1453 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX); /* mem -> EAX */
1454 /* optimize move EAX -> REG_ITMP3 is slower??? */
1455 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1456 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1458 /* TODO: optimize move EAX -> REG_ITMP3 */
1459 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); /* mem -> ITMP3 */
1460 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1461 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1463 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP2); /* mem -> ITMP3 */
1464 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1466 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1467 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1468 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1473 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1474 /* val.l = constant */
1476 d = reg_of_var(rd, iptr->dst, REG_NULL);
1477 if (iptr->dst->flags & INMEMORY) {
1478 if (src->flags & INMEMORY) {
1479 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1480 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1481 /* TODO: optimize move EAX -> REG_ITMP3 */
1482 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1483 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1485 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1486 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1487 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1489 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1490 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1491 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1496 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1498 d = reg_of_var(rd, iptr->dst, REG_NULL);
1499 var_to_reg_int(s1, src, REG_ITMP2);
1501 if (src->prev->flags & INMEMORY) {
1502 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1505 M_INTMOVE(src->prev->regoff, EAX);
1508 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1509 i386_jcc(cd, I386_CC_NE, 3 + 6);
1510 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1511 i386_jcc(cd, I386_CC_E, 1 + 2);
1514 i386_idiv_reg(cd, s1);
1516 if (iptr->dst->flags & INMEMORY) {
1517 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1520 M_INTMOVE(EAX, iptr->dst->regoff);
1524 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1526 d = reg_of_var(rd, iptr->dst, REG_NULL);
1527 var_to_reg_int(s1, src, REG_ITMP2);
1529 if (src->prev->flags & INMEMORY) {
1530 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1533 M_INTMOVE(src->prev->regoff, EAX);
1536 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1537 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1538 i386_alu_reg_reg(cd, I386_XOR, EDX, EDX);
1539 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1540 i386_jcc(cd, I386_CC_E, 1 + 2);
1543 i386_idiv_reg(cd, s1);
1545 if (iptr->dst->flags & INMEMORY) {
1546 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8);
1549 M_INTMOVE(EDX, iptr->dst->regoff);
1553 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1554 /* val.i = constant */
1556 /* TODO: optimize for `/ 2' */
1557 var_to_reg_int(s1, src, REG_ITMP1);
1558 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1561 i386_test_reg_reg(cd, d, d);
1563 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1564 i386_jcc(cd, I386_CC_NS, a);
1565 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, d);
1567 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1568 store_reg_to_var_int(iptr->dst, d);
1571 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1572 /* val.i = constant */
1574 d = reg_of_var(rd, iptr->dst, REG_NULL);
1575 if (iptr->dst->flags & INMEMORY) {
1576 if (src->flags & INMEMORY) {
1578 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1580 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1581 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1583 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1584 i386_jcc(cd, I386_CC_NS, a);
1585 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1586 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1587 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1588 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1590 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1591 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1596 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1597 /* val.i = constant */
1599 var_to_reg_int(s1, src, REG_ITMP1);
1600 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1602 M_INTMOVE(s1, REG_ITMP1);
1609 CALCIMMEDIATEBYTES(a, iptr->val.i);
1612 /* TODO: optimize */
1614 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1615 i386_test_reg_reg(cd, s1, s1);
1616 i386_jcc(cd, I386_CC_GE, a);
1617 i386_mov_reg_reg(cd, s1, d);
1618 i386_neg_reg(cd, d);
1619 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1620 i386_neg_reg(cd, d);
1622 /* M_INTMOVE(s1, EAX); */
1623 /* i386_cltd(cd); */
1624 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1625 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1626 /* i386_alu_reg_reg(cd, I386_AND, iptr->val.i, EAX); */
1627 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1628 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1629 /* M_INTMOVE(EAX, d); */
1631 /* i386_alu_reg_reg(cd, I386_XOR, d, d); */
1632 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1633 /* i386_shrd_reg_reg(cd, s1, d); */
1634 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1636 store_reg_to_var_int(iptr->dst, d);
1639 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1640 /* val.l = constant */
1642 d = reg_of_var(rd, iptr->dst, REG_NULL);
1643 if (iptr->dst->flags & INMEMORY) {
1644 if (src->flags & INMEMORY) {
1645 /* Intel algorithm -- does not work, because constant is wrong */
1646 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1); */
1647 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1649 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1650 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1651 /* i386_jcc(cd, I386_CC_NS, offset); */
1652 /* i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1653 /* i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP3); */
1655 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1656 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1657 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1659 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1661 /* i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1); */
1662 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1663 /* i386_alu_reg_reg(cd, I386_SBB, REG_ITMP3, REG_ITMP2); */
1665 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1666 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1668 /* Alpha algorithm */
1670 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1672 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1678 /* TODO: hmm, don't know if this is always correct */
1680 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1682 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1688 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1689 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1691 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1692 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1693 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1694 i386_jcc(cd, I386_CC_GE, a);
1696 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1697 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1699 i386_neg_reg(cd, REG_ITMP1);
1700 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1701 i386_neg_reg(cd, REG_ITMP2);
1703 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1704 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1706 i386_neg_reg(cd, REG_ITMP1);
1707 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1708 i386_neg_reg(cd, REG_ITMP2);
1710 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1711 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1716 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1718 d = reg_of_var(rd, iptr->dst, REG_NULL);
1719 i386_emit_ishift(cd, I386_SHL, src, iptr);
1722 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1723 /* val.i = constant */
1725 d = reg_of_var(rd, iptr->dst, REG_NULL);
1726 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1729 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1731 d = reg_of_var(rd, iptr->dst, REG_NULL);
1732 i386_emit_ishift(cd, I386_SAR, src, iptr);
1735 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1736 /* val.i = constant */
1738 d = reg_of_var(rd, iptr->dst, REG_NULL);
1739 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1742 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1744 d = reg_of_var(rd, iptr->dst, REG_NULL);
1745 i386_emit_ishift(cd, I386_SHR, src, iptr);
1748 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1749 /* val.i = constant */
1751 d = reg_of_var(rd, iptr->dst, REG_NULL);
1752 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1755 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1757 d = reg_of_var(rd, iptr->dst, REG_NULL);
1758 if (iptr->dst->flags & INMEMORY ){
1759 if (src->prev->flags & INMEMORY) {
1760 /* if (src->prev->regoff == iptr->dst->regoff) { */
1761 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1763 /* if (src->flags & INMEMORY) { */
1764 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1766 /* M_INTMOVE(src->regoff, ECX); */
1769 /* i386_test_imm_reg(cd, 32, ECX); */
1770 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1771 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1772 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1); */
1774 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1775 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1778 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1779 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1781 if (src->flags & INMEMORY) {
1782 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1784 M_INTMOVE(src->regoff, ECX);
1787 i386_test_imm_reg(cd, 32, ECX);
1788 i386_jcc(cd, I386_CC_E, 2 + 2);
1789 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1790 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1792 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1793 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1794 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1795 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1801 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1802 /* val.i = constant */
1804 d = reg_of_var(rd, iptr->dst, REG_NULL);
1805 if (iptr->dst->flags & INMEMORY ) {
1806 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1807 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1809 if (iptr->val.i & 0x20) {
1810 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1811 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1812 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1815 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1816 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1819 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1820 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1824 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1826 d = reg_of_var(rd, iptr->dst, REG_NULL);
1827 if (iptr->dst->flags & INMEMORY ){
1828 if (src->prev->flags & INMEMORY) {
1829 /* if (src->prev->regoff == iptr->dst->regoff) { */
1830 /* TODO: optimize */
1831 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1832 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1834 /* if (src->flags & INMEMORY) { */
1835 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1837 /* M_INTMOVE(src->regoff, ECX); */
1840 /* i386_test_imm_reg(cd, 32, ECX); */
1841 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1842 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1843 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1845 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1846 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1847 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1848 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1851 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1852 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1854 if (src->flags & INMEMORY) {
1855 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1857 M_INTMOVE(src->regoff, ECX);
1860 i386_test_imm_reg(cd, 32, ECX);
1861 i386_jcc(cd, I386_CC_E, 2 + 3);
1862 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1863 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1865 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1866 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1867 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1868 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1874 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1875 /* val.i = constant */
1877 d = reg_of_var(rd, iptr->dst, REG_NULL);
1878 if (iptr->dst->flags & INMEMORY ) {
1879 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1880 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1882 if (iptr->val.i & 0x20) {
1883 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1884 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
1885 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1888 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1889 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1892 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1893 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1897 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1899 d = reg_of_var(rd, iptr->dst, REG_NULL);
1900 if (iptr->dst->flags & INMEMORY ){
1901 if (src->prev->flags & INMEMORY) {
1902 /* if (src->prev->regoff == iptr->dst->regoff) { */
1903 /* TODO: optimize */
1904 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1905 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1907 /* if (src->flags & INMEMORY) { */
1908 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1910 /* M_INTMOVE(src->regoff, ECX); */
1913 /* i386_test_imm_reg(cd, 32, ECX); */
1914 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1915 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1916 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2); */
1918 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1919 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
1920 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1921 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1924 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1925 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1927 if (src->flags & INMEMORY) {
1928 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1930 M_INTMOVE(src->regoff, ECX);
1933 i386_test_imm_reg(cd, 32, ECX);
1934 i386_jcc(cd, I386_CC_E, 2 + 2);
1935 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1936 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP3, REG_ITMP3);
1938 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1939 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
1940 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1941 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1947 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1948 /* val.l = constant */
1950 d = reg_of_var(rd, iptr->dst, REG_NULL);
1951 if (iptr->dst->flags & INMEMORY ) {
1952 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1953 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1955 if (iptr->val.i & 0x20) {
1956 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1957 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
1958 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1961 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1962 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
1965 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1966 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1970 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1972 d = reg_of_var(rd, iptr->dst, REG_NULL);
1973 i386_emit_ialu(cd, I386_AND, src, iptr);
1976 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1977 /* val.i = constant */
1979 d = reg_of_var(rd, iptr->dst, REG_NULL);
1980 i386_emit_ialuconst(cd, I386_AND, src, iptr);
1983 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1985 d = reg_of_var(rd, iptr->dst, REG_NULL);
1986 i386_emit_lalu(cd, I386_AND, src, iptr);
1989 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1990 /* val.l = constant */
1992 d = reg_of_var(rd, iptr->dst, REG_NULL);
1993 i386_emit_laluconst(cd, I386_AND, src, iptr);
1996 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1998 d = reg_of_var(rd, iptr->dst, REG_NULL);
1999 i386_emit_ialu(cd, I386_OR, src, iptr);
2002 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2003 /* val.i = constant */
2005 d = reg_of_var(rd, iptr->dst, REG_NULL);
2006 i386_emit_ialuconst(cd, I386_OR, src, iptr);
2009 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2011 d = reg_of_var(rd, iptr->dst, REG_NULL);
2012 i386_emit_lalu(cd, I386_OR, src, iptr);
2015 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2016 /* val.l = constant */
2018 d = reg_of_var(rd, iptr->dst, REG_NULL);
2019 i386_emit_laluconst(cd, I386_OR, src, iptr);
2022 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2024 d = reg_of_var(rd, iptr->dst, REG_NULL);
2025 i386_emit_ialu(cd, I386_XOR, src, iptr);
2028 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2029 /* val.i = constant */
2031 d = reg_of_var(rd, iptr->dst, REG_NULL);
2032 i386_emit_ialuconst(cd, I386_XOR, src, iptr);
2035 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2037 d = reg_of_var(rd, iptr->dst, REG_NULL);
2038 i386_emit_lalu(cd, I386_XOR, src, iptr);
2041 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2042 /* val.l = constant */
2044 d = reg_of_var(rd, iptr->dst, REG_NULL);
2045 i386_emit_laluconst(cd, I386_XOR, src, iptr);
2048 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2049 /* op1 = variable, val.i = constant */
2051 var = &(rd->locals[iptr->op1][TYPE_INT]);
2052 if (var->flags & INMEMORY) {
2053 i386_alu_imm_membase(cd, I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2056 /* `inc reg' is slower on p4's (regarding to ia32 */
2057 /* optimization reference manual and benchmarks) and as fast */
2059 i386_alu_imm_reg(cd, I386_ADD, iptr->val.i, var->regoff);
2064 /* floating operations ************************************************/
2066 #define ROUND_TO_SINGLE \
2067 i386_fstps_membase(cd, REG_SP, -8); \
2068 i386_flds_membase(cd, REG_SP, -8);
2070 #define ROUND_TO_DOUBLE \
2071 i386_fstpl_membase(cd, REG_SP, -8); \
2072 i386_fldl_membase(cd, REG_SP, -8);
2074 #define FPU_SET_24BIT_MODE \
2075 if (!fpu_in_24bit_mode) { \
2076 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2077 fpu_in_24bit_mode = 1; \
2080 #define FPU_SET_53BIT_MODE \
2081 if (fpu_in_24bit_mode) { \
2082 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2083 fpu_in_24bit_mode = 0; \
2086 #define ROUND_TO_SINGLE
2087 #define ROUND_TO_DOUBLE
2088 #define FPU_SET_24BIT_MODE
2089 #define FPU_SET_53BIT_MODE
2091 case ICMD_FNEG: /* ..., value ==> ..., - value */
2094 var_to_reg_flt(s1, src, REG_FTMP1);
2095 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2097 store_reg_to_var_flt(iptr->dst, d);
2100 case ICMD_DNEG: /* ..., value ==> ..., - value */
2103 var_to_reg_flt(s1, src, REG_FTMP1);
2104 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2106 store_reg_to_var_flt(iptr->dst, d);
2109 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2112 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2113 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2114 var_to_reg_flt(s2, src, REG_FTMP2);
2117 store_reg_to_var_flt(iptr->dst, d);
2120 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2123 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2124 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2125 var_to_reg_flt(s2, src, REG_FTMP2);
2128 store_reg_to_var_flt(iptr->dst, d);
2131 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2134 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2135 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2136 var_to_reg_flt(s2, src, REG_FTMP2);
2139 store_reg_to_var_flt(iptr->dst, d);
2142 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2145 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2146 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2147 var_to_reg_flt(s2, src, REG_FTMP2);
2150 store_reg_to_var_flt(iptr->dst, d);
2153 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2156 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2157 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2158 var_to_reg_flt(s2, src, REG_FTMP2);
2162 store_reg_to_var_flt(iptr->dst, d);
2165 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2168 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2169 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2171 /* i386_fldt_mem(cd, subnormal_bias1); */
2172 /* i386_fmulp(cd); */
2174 var_to_reg_flt(s2, src, REG_FTMP2);
2179 /* i386_fldt_mem(cd, subnormal_bias2); */
2180 /* i386_fmulp(cd); */
2182 store_reg_to_var_flt(iptr->dst, d);
2185 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2188 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2189 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2190 var_to_reg_flt(s2, src, REG_FTMP2);
2194 store_reg_to_var_flt(iptr->dst, d);
2197 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2200 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2201 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2203 /* i386_fldt_mem(cd, subnormal_bias1); */
2204 /* i386_fmulp(cd); */
2206 var_to_reg_flt(s2, src, REG_FTMP2);
2211 /* i386_fldt_mem(cd, subnormal_bias2); */
2212 /* i386_fmulp(cd); */
2214 store_reg_to_var_flt(iptr->dst, d);
2217 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2220 /* exchanged to skip fxch */
2221 var_to_reg_flt(s2, src, REG_FTMP2);
2222 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2223 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2224 /* i386_fxch(cd); */
2229 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2230 store_reg_to_var_flt(iptr->dst, d);
2231 i386_ffree_reg(cd, 0);
2236 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2239 /* exchanged to skip fxch */
2240 var_to_reg_flt(s2, src, REG_FTMP2);
2241 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2242 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2243 /* i386_fxch(cd); */
2248 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2249 store_reg_to_var_flt(iptr->dst, d);
2250 i386_ffree_reg(cd, 0);
2255 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2256 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2258 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2259 if (src->flags & INMEMORY) {
2260 i386_fildl_membase(cd, REG_SP, src->regoff * 8);
2264 a = dseg_adds4(cd, 0);
2265 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2266 dseg_adddata(cd, cd->mcodeptr);
2267 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, a);
2268 i386_fildl_membase(cd, REG_ITMP1, a);
2271 store_reg_to_var_flt(iptr->dst, d);
2274 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2275 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2277 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2278 if (src->flags & INMEMORY) {
2279 i386_fildll_membase(cd, REG_SP, src->regoff * 8);
2283 panic("L2F: longs have to be in memory");
2285 store_reg_to_var_flt(iptr->dst, d);
2288 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2290 var_to_reg_flt(s1, src, REG_FTMP1);
2291 d = reg_of_var(rd, iptr->dst, REG_NULL);
2293 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2294 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2295 dseg_adddata(cd, cd->mcodeptr);
2296 i386_fldcw_membase(cd, REG_ITMP1, a);
2298 if (iptr->dst->flags & INMEMORY) {
2299 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2302 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2303 i386_fldcw_membase(cd, REG_ITMP1, a);
2305 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2308 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2310 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2313 a = dseg_adds4(cd, 0);
2314 i386_fistpl_membase(cd, REG_ITMP1, a);
2316 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2318 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2319 i386_fldcw_membase(cd, REG_ITMP1, a);
2321 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2324 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2325 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2328 i386_jcc(cd, I386_CC_NE, a);
2330 /* XXX: change this when we use registers */
2331 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2332 i386_mov_imm_reg(cd, (s4) asm_builtin_f2i, REG_ITMP1);
2333 i386_call_reg(cd, REG_ITMP1);
2335 if (iptr->dst->flags & INMEMORY) {
2336 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2339 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2343 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2345 var_to_reg_flt(s1, src, REG_FTMP1);
2346 d = reg_of_var(rd, iptr->dst, REG_NULL);
2348 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2349 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2350 dseg_adddata(cd, cd->mcodeptr);
2351 i386_fldcw_membase(cd, REG_ITMP1, a);
2353 if (iptr->dst->flags & INMEMORY) {
2354 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2357 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2358 i386_fldcw_membase(cd, REG_ITMP1, a);
2360 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2363 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2365 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2368 a = dseg_adds4(cd, 0);
2369 i386_fistpl_membase(cd, REG_ITMP1, a);
2371 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2373 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2374 i386_fldcw_membase(cd, REG_ITMP1, a);
2376 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2379 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2380 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2383 i386_jcc(cd, I386_CC_NE, a);
2385 /* XXX: change this when we use registers */
2386 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2387 i386_mov_imm_reg(cd, (s4) asm_builtin_d2i, REG_ITMP1);
2388 i386_call_reg(cd, REG_ITMP1);
2390 if (iptr->dst->flags & INMEMORY) {
2391 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2393 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2397 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2399 var_to_reg_flt(s1, src, REG_FTMP1);
2400 d = reg_of_var(rd, iptr->dst, REG_NULL);
2402 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2403 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2404 dseg_adddata(cd, cd->mcodeptr);
2405 i386_fldcw_membase(cd, REG_ITMP1, a);
2407 if (iptr->dst->flags & INMEMORY) {
2408 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2411 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2412 i386_fldcw_membase(cd, REG_ITMP1, a);
2414 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2417 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2419 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2422 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2424 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2426 i386_jcc(cd, I386_CC_NE, a);
2428 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2431 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2433 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2435 i386_jcc(cd, I386_CC_NE, a);
2437 /* XXX: change this when we use registers */
2438 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2439 i386_mov_imm_reg(cd, (s4) asm_builtin_f2l, REG_ITMP1);
2440 i386_call_reg(cd, REG_ITMP1);
2441 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2442 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2445 panic("F2L: longs have to be in memory");
2449 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2451 var_to_reg_flt(s1, src, REG_FTMP1);
2452 d = reg_of_var(rd, iptr->dst, REG_NULL);
2454 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2455 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2456 dseg_adddata(cd, cd->mcodeptr);
2457 i386_fldcw_membase(cd, REG_ITMP1, a);
2459 if (iptr->dst->flags & INMEMORY) {
2460 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2463 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2464 i386_fldcw_membase(cd, REG_ITMP1, a);
2466 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2469 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2471 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2474 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2476 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2478 i386_jcc(cd, I386_CC_NE, a);
2480 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2483 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2485 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2487 i386_jcc(cd, I386_CC_NE, a);
2489 /* XXX: change this when we use registers */
2490 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2491 i386_mov_imm_reg(cd, (s4) asm_builtin_d2l, REG_ITMP1);
2492 i386_call_reg(cd, REG_ITMP1);
2493 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2494 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2497 panic("D2L: longs have to be in memory");
2501 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2503 var_to_reg_flt(s1, src, REG_FTMP1);
2504 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2506 store_reg_to_var_flt(iptr->dst, d);
2509 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2511 var_to_reg_flt(s1, src, REG_FTMP1);
2512 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2514 store_reg_to_var_flt(iptr->dst, d);
2517 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2520 /* exchanged to skip fxch */
2521 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2522 var_to_reg_flt(s1, src, REG_FTMP2);
2523 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2524 /* i386_fxch(cd); */
2528 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2529 i386_jcc(cd, I386_CC_E, 6);
2530 i386_alu_imm_reg(cd, I386_AND, 0x000000ff, EAX);
2532 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2533 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2534 i386_jcc(cd, I386_CC_B, 3 + 5);
2535 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2536 i386_jmp_imm(cd, 3);
2537 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2538 store_reg_to_var_int(iptr->dst, d);
2541 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2544 /* exchanged to skip fxch */
2545 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2546 var_to_reg_flt(s1, src, REG_FTMP2);
2547 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2548 /* i386_fxch(cd); */
2552 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2553 i386_jcc(cd, I386_CC_E, 3);
2554 i386_movb_imm_reg(cd, 1, I386_AH);
2556 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2557 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2558 i386_jcc(cd, I386_CC_B, 3 + 5);
2559 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2560 i386_jmp_imm(cd, 3);
2561 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2562 store_reg_to_var_int(iptr->dst, d);
2566 /* memory operations **************************************************/
2568 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2570 var_to_reg_int(s1, src, REG_ITMP1);
2571 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2572 gen_nullptr_check(s1);
2573 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2574 store_reg_to_var_int(iptr->dst, d);
2577 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2579 var_to_reg_int(s1, src->prev, REG_ITMP1);
2580 var_to_reg_int(s2, src, REG_ITMP2);
2581 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2582 if (iptr->op1 == 0) {
2583 gen_nullptr_check(s1);
2586 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2587 store_reg_to_var_int(iptr->dst, d);
2590 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2592 var_to_reg_int(s1, src->prev, REG_ITMP1);
2593 var_to_reg_int(s2, src, REG_ITMP2);
2594 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2595 if (iptr->op1 == 0) {
2596 gen_nullptr_check(s1);
2600 if (iptr->dst->flags & INMEMORY) {
2601 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2602 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2603 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2604 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2608 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2610 var_to_reg_int(s1, src->prev, REG_ITMP1);
2611 var_to_reg_int(s2, src, REG_ITMP2);
2612 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2613 if (iptr->op1 == 0) {
2614 gen_nullptr_check(s1);
2617 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2618 store_reg_to_var_int(iptr->dst, d);
2621 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2623 var_to_reg_int(s1, src->prev, REG_ITMP1);
2624 var_to_reg_int(s2, src, REG_ITMP2);
2625 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2626 if (iptr->op1 == 0) {
2627 gen_nullptr_check(s1);
2630 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2632 store_reg_to_var_flt(iptr->dst, d);
2635 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2637 var_to_reg_int(s1, src->prev, REG_ITMP1);
2638 var_to_reg_int(s2, src, REG_ITMP2);
2639 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2640 if (iptr->op1 == 0) {
2641 gen_nullptr_check(s1);
2644 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2646 store_reg_to_var_flt(iptr->dst, d);
2649 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2651 var_to_reg_int(s1, src->prev, REG_ITMP1);
2652 var_to_reg_int(s2, src, REG_ITMP2);
2653 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2654 if (iptr->op1 == 0) {
2655 gen_nullptr_check(s1);
2658 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2659 store_reg_to_var_int(iptr->dst, d);
2662 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2664 var_to_reg_int(s1, src->prev, REG_ITMP1);
2665 var_to_reg_int(s2, src, REG_ITMP2);
2666 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2667 if (iptr->op1 == 0) {
2668 gen_nullptr_check(s1);
2671 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2672 store_reg_to_var_int(iptr->dst, d);
2675 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2677 var_to_reg_int(s1, src->prev, REG_ITMP1);
2678 var_to_reg_int(s2, src, REG_ITMP2);
2679 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2680 if (iptr->op1 == 0) {
2681 gen_nullptr_check(s1);
2684 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2685 store_reg_to_var_int(iptr->dst, d);
2689 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2691 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2692 var_to_reg_int(s2, src->prev, REG_ITMP2);
2693 if (iptr->op1 == 0) {
2694 gen_nullptr_check(s1);
2697 var_to_reg_int(s3, src, REG_ITMP3);
2698 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2701 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2703 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2704 var_to_reg_int(s2, src->prev, REG_ITMP2);
2705 if (iptr->op1 == 0) {
2706 gen_nullptr_check(s1);
2710 if (src->flags & INMEMORY) {
2711 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
2712 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2713 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2714 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2718 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2720 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2721 var_to_reg_int(s2, src->prev, REG_ITMP2);
2722 if (iptr->op1 == 0) {
2723 gen_nullptr_check(s1);
2726 var_to_reg_int(s3, src, REG_ITMP3);
2727 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2730 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2732 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2733 var_to_reg_int(s2, src->prev, REG_ITMP2);
2734 if (iptr->op1 == 0) {
2735 gen_nullptr_check(s1);
2738 var_to_reg_flt(s3, src, REG_FTMP1);
2739 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2743 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2745 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2746 var_to_reg_int(s2, src->prev, REG_ITMP2);
2747 if (iptr->op1 == 0) {
2748 gen_nullptr_check(s1);
2751 var_to_reg_flt(s3, src, REG_FTMP1);
2752 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2756 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2758 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2759 var_to_reg_int(s2, src->prev, REG_ITMP2);
2760 if (iptr->op1 == 0) {
2761 gen_nullptr_check(s1);
2764 var_to_reg_int(s3, src, REG_ITMP3);
2765 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2768 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2770 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2771 var_to_reg_int(s2, src->prev, REG_ITMP2);
2772 if (iptr->op1 == 0) {
2773 gen_nullptr_check(s1);
2776 var_to_reg_int(s3, src, REG_ITMP3);
2777 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2780 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2782 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2783 var_to_reg_int(s2, src->prev, REG_ITMP2);
2784 if (iptr->op1 == 0) {
2785 gen_nullptr_check(s1);
2788 var_to_reg_int(s3, src, REG_ITMP3);
2789 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2790 M_INTMOVE(s3, REG_ITMP3);
2793 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2796 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2798 var_to_reg_int(s1, src->prev, REG_ITMP1);
2799 var_to_reg_int(s2, src, REG_ITMP2);
2800 if (iptr->op1 == 0) {
2801 gen_nullptr_check(s1);
2804 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2807 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2809 var_to_reg_int(s1, src->prev, REG_ITMP1);
2810 var_to_reg_int(s2, src, REG_ITMP2);
2811 if (iptr->op1 == 0) {
2812 gen_nullptr_check(s1);
2816 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2817 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2820 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2822 var_to_reg_int(s1, src->prev, REG_ITMP1);
2823 var_to_reg_int(s2, src, REG_ITMP2);
2824 if (iptr->op1 == 0) {
2825 gen_nullptr_check(s1);
2828 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2831 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2833 var_to_reg_int(s1, src->prev, REG_ITMP1);
2834 var_to_reg_int(s2, src, REG_ITMP2);
2835 if (iptr->op1 == 0) {
2836 gen_nullptr_check(s1);
2839 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2842 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2844 var_to_reg_int(s1, src->prev, REG_ITMP1);
2845 var_to_reg_int(s2, src, REG_ITMP2);
2846 if (iptr->op1 == 0) {
2847 gen_nullptr_check(s1);
2850 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2853 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2855 var_to_reg_int(s1, src->prev, REG_ITMP1);
2856 var_to_reg_int(s2, src, REG_ITMP2);
2857 if (iptr->op1 == 0) {
2858 gen_nullptr_check(s1);
2861 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2865 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2866 /* op1 = type, val.a = field address */
2868 /* If the static fields' class is not yet initialized, we do it */
2869 /* now. The call code is generated later. */
2870 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2871 codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
2873 /* This is just for debugging purposes. Is very difficult to */
2874 /* read patched code. Here we patch the following 5 nop's */
2875 /* so that the real code keeps untouched. */
2876 if (showdisassemble) {
2885 a = (ptrint) &(((fieldinfo *) iptr->val.a)->value);
2886 switch (iptr->op1) {
2889 var_to_reg_int(s2, src, REG_ITMP1);
2890 i386_mov_reg_mem(cd, s2, a);
2893 if (src->flags & INMEMORY) {
2894 /* Using both REG_ITMP1 and REG_ITMP2 is faster than only */
2895 /* using REG_ITMP1 alternating. */
2897 i386_mov_membase_reg(cd, REG_SP, s2 * 8, REG_ITMP1);
2898 i386_mov_membase_reg(cd, REG_SP, s2 * 8 + 4, REG_ITMP2);
2899 i386_mov_reg_mem(cd, REG_ITMP1, a);
2900 i386_mov_reg_mem(cd, REG_ITMP2, a + 4);
2902 panic("PUTSTATIC: longs have to be in memory");
2906 var_to_reg_flt(s2, src, REG_FTMP1);
2907 i386_fstps_mem(cd, a);
2911 var_to_reg_flt(s2, src, REG_FTMP1);
2912 i386_fstpl_mem(cd, a);
2918 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2919 /* val = value (in current instruction) */
2920 /* op1 = type, val.a = field address (in */
2921 /* following NOP) */
2923 /* If the static fields' class is not yet initialized, we do it */
2924 /* now. The call code is generated later. */
2925 if (!((fieldinfo *) iptr[1].val.a)->class->initialized) {
2926 codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr[1].val.a)->class);
2928 /* This is just for debugging purposes. Is very difficult to */
2929 /* read patched code. Here we patch the following 5 nop's */
2930 /* so that the real code keeps untouched. */
2931 if (showdisassemble) {
2940 a = (ptrint) &(((fieldinfo *) iptr[1].val.a)->value);
2941 switch (iptr[1].op1) {
2944 i386_mov_imm_mem(cd, iptr->val.i, a);
2947 i386_mov_imm_mem(cd, (ptrint) iptr->val.a, a);
2951 i386_mov_imm_mem(cd, iptr->val.l, a);
2952 i386_mov_imm_mem(cd, iptr->val.l >> 32, a + 4);
2957 case ICMD_GETSTATIC: /* ... ==> ..., value */
2958 /* op1 = type, val.a = field address */
2960 /* If the static fields' class is not yet initialized, we do it */
2961 /* now. The call code is generated later. */
2962 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2963 codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
2965 /* This is just for debugging purposes. Is very difficult to */
2966 /* read patched code. Here we patch the following 5 nop's */
2967 /* so that the real code keeps untouched. */
2968 if (showdisassemble) {
2977 a = (ptrint) &(((fieldinfo *) iptr->val.a)->value);
2978 switch (iptr->op1) {
2981 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2982 i386_mov_mem_reg(cd, a, d);
2983 store_reg_to_var_int(iptr->dst, d);
2986 d = reg_of_var(rd, iptr->dst, REG_NULL);
2987 if (iptr->dst->flags & INMEMORY) {
2988 /* Using both REG_ITMP1 and REG_ITMP2 is faster than only */
2989 /* using REG_ITMP1 alternating. */
2990 i386_mov_mem_reg(cd, a, REG_ITMP1);
2991 i386_mov_mem_reg(cd, a + 4, REG_ITMP2);
2992 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2993 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2995 panic("GETSTATIC: longs have to be in memory");
2999 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3000 i386_flds_mem(cd, a);
3002 store_reg_to_var_flt(iptr->dst, d);
3005 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3006 i386_fldl_mem(cd, a);
3008 store_reg_to_var_flt(iptr->dst, d);
3013 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
3014 /* op1 = type, val.a = field address */
3016 a = ((fieldinfo *) (iptr->val.a))->offset;
3017 var_to_reg_int(s1, src->prev, REG_ITMP1);
3018 gen_nullptr_check(s1);
3019 switch (iptr->op1) {
3022 var_to_reg_int(s2, src, REG_ITMP2);
3023 i386_mov_reg_membase(cd, s2, s1, a);
3026 if (src->flags & INMEMORY) {
3027 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);
3028 i386_mov_reg_membase(cd, REG_ITMP2, s1, a);
3029 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3030 i386_mov_reg_membase(cd, REG_ITMP2, s1, a + 4);
3032 panic("PUTFIELD: longs have to be in memory");
3036 var_to_reg_flt(s2, src, REG_FTMP1);
3037 i386_fstps_membase(cd, s1, a);
3041 var_to_reg_flt(s2, src, REG_FTMP1);
3042 i386_fstpl_membase(cd, s1, a);
3048 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
3049 /* val = value (in current instruction) */
3050 /* op1 = type, val.a = field address (in */
3051 /* following NOP) */
3053 a = ((fieldinfo *) (iptr[1].val.a))->offset;
3054 var_to_reg_int(s1, src, REG_ITMP1);
3055 gen_nullptr_check(s1);
3056 switch (iptr[1].op1) {
3059 i386_mov_imm_membase(cd, iptr->val.i, s1, a);
3062 i386_mov_imm_membase(cd, (ptrint) iptr->val.a, s1, a);
3066 i386_mov_imm_membase(cd, iptr->val.l, s1, a);
3067 i386_mov_imm_membase(cd, iptr->val.l >> 32, s1, a + 4);
3072 case ICMD_GETFIELD: /* ... ==> ..., value */
3073 /* op1 = type, val.i = field offset */
3075 a = ((fieldinfo *) (iptr->val.a))->offset;
3076 var_to_reg_int(s1, src, REG_ITMP1);
3077 gen_nullptr_check(s1);
3078 switch (iptr->op1) {
3081 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3082 i386_mov_membase_reg(cd, s1, a, d);
3083 store_reg_to_var_int(iptr->dst, d);
3086 d = reg_of_var(rd, iptr->dst, REG_NULL);
3087 i386_mov_membase_reg(cd, s1, a, REG_ITMP2);
3088 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
3089 i386_mov_membase_reg(cd, s1, a + 4, REG_ITMP2);
3090 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
3093 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3094 i386_flds_membase(cd, s1, a);
3096 store_reg_to_var_flt(iptr->dst, d);
3099 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3100 i386_fldl_membase(cd, s1, a);
3102 store_reg_to_var_flt(iptr->dst, d);
3108 /* branch operations **************************************************/
3110 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3112 var_to_reg_int(s1, src, REG_ITMP1);
3113 M_INTMOVE(s1, REG_ITMP1_XPTR);
3115 i386_call_imm(cd, 0); /* passing exception pointer */
3116 i386_pop_reg(cd, REG_ITMP2_XPC);
3118 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
3119 i386_jmp_reg(cd, REG_ITMP3);
3123 case ICMD_GOTO: /* ... ==> ... */
3124 /* op1 = target JavaVM pc */
3126 i386_jmp_imm(cd, 0);
3127 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3131 case ICMD_JSR: /* ... ==> ... */
3132 /* op1 = target JavaVM pc */
3134 i386_call_imm(cd, 0);
3135 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3138 case ICMD_RET: /* ... ==> ... */
3139 /* op1 = local variable */
3141 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3142 var_to_reg_int(s1, var, REG_ITMP1);
3143 i386_jmp_reg(cd, s1);
3146 case ICMD_IFNULL: /* ..., value ==> ... */
3147 /* op1 = target JavaVM pc */
3149 if (src->flags & INMEMORY) {
3150 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3153 i386_test_reg_reg(cd, src->regoff, src->regoff);
3155 i386_jcc(cd, I386_CC_E, 0);
3156 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3159 case ICMD_IFNONNULL: /* ..., value ==> ... */
3160 /* op1 = target JavaVM pc */
3162 if (src->flags & INMEMORY) {
3163 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3166 i386_test_reg_reg(cd, src->regoff, src->regoff);
3168 i386_jcc(cd, I386_CC_NE, 0);
3169 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3172 case ICMD_IFEQ: /* ..., value ==> ... */
3173 /* op1 = target JavaVM pc, val.i = constant */
3175 if (src->flags & INMEMORY) {
3176 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3179 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3181 i386_jcc(cd, I386_CC_E, 0);
3182 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3185 case ICMD_IFLT: /* ..., value ==> ... */
3186 /* op1 = target JavaVM pc, val.i = constant */
3188 if (src->flags & INMEMORY) {
3189 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3192 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3194 i386_jcc(cd, I386_CC_L, 0);
3195 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3198 case ICMD_IFLE: /* ..., value ==> ... */
3199 /* op1 = target JavaVM pc, val.i = constant */
3201 if (src->flags & INMEMORY) {
3202 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3205 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3207 i386_jcc(cd, I386_CC_LE, 0);
3208 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3211 case ICMD_IFNE: /* ..., value ==> ... */
3212 /* op1 = target JavaVM pc, val.i = constant */
3214 if (src->flags & INMEMORY) {
3215 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3218 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3220 i386_jcc(cd, I386_CC_NE, 0);
3221 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3224 case ICMD_IFGT: /* ..., value ==> ... */
3225 /* op1 = target JavaVM pc, val.i = constant */
3227 if (src->flags & INMEMORY) {
3228 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3231 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3233 i386_jcc(cd, I386_CC_G, 0);
3234 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3237 case ICMD_IFGE: /* ..., value ==> ... */
3238 /* op1 = target JavaVM pc, val.i = constant */
3240 if (src->flags & INMEMORY) {
3241 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3244 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3246 i386_jcc(cd, I386_CC_GE, 0);
3247 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3250 case ICMD_IF_LEQ: /* ..., value ==> ... */
3251 /* op1 = target JavaVM pc, val.l = constant */
3253 if (src->flags & INMEMORY) {
3254 if (iptr->val.l == 0) {
3255 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3256 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3259 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3260 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3261 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3262 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l, REG_ITMP1);
3263 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3266 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3267 i386_jcc(cd, I386_CC_E, 0);
3268 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3271 case ICMD_IF_LLT: /* ..., value ==> ... */
3272 /* op1 = target JavaVM pc, val.l = constant */
3274 if (src->flags & INMEMORY) {
3275 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3276 i386_jcc(cd, I386_CC_L, 0);
3277 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3280 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3281 CALCIMMEDIATEBYTES(a, iptr->val.l);
3283 i386_jcc(cd, I386_CC_G, a);
3285 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3286 i386_jcc(cd, I386_CC_B, 0);
3287 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3291 case ICMD_IF_LLE: /* ..., value ==> ... */
3292 /* op1 = target JavaVM pc, val.l = constant */
3294 if (src->flags & INMEMORY) {
3295 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3296 i386_jcc(cd, I386_CC_L, 0);
3297 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3300 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3301 CALCIMMEDIATEBYTES(a, iptr->val.l);
3303 i386_jcc(cd, I386_CC_G, a);
3305 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3306 i386_jcc(cd, I386_CC_BE, 0);
3307 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3311 case ICMD_IF_LNE: /* ..., value ==> ... */
3312 /* op1 = target JavaVM pc, val.l = constant */
3314 if (src->flags & INMEMORY) {
3315 if (iptr->val.l == 0) {
3316 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3317 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3320 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3321 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3322 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3323 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3324 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3327 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3328 i386_jcc(cd, I386_CC_NE, 0);
3329 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3332 case ICMD_IF_LGT: /* ..., value ==> ... */
3333 /* op1 = target JavaVM pc, val.l = constant */
3335 if (src->flags & INMEMORY) {
3336 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3337 i386_jcc(cd, I386_CC_G, 0);
3338 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3341 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3342 CALCIMMEDIATEBYTES(a, iptr->val.l);
3344 i386_jcc(cd, I386_CC_L, a);
3346 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3347 i386_jcc(cd, I386_CC_A, 0);
3348 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3352 case ICMD_IF_LGE: /* ..., value ==> ... */
3353 /* op1 = target JavaVM pc, val.l = constant */
3355 if (src->flags & INMEMORY) {
3356 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3357 i386_jcc(cd, I386_CC_G, 0);
3358 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3361 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3362 CALCIMMEDIATEBYTES(a, iptr->val.l);
3364 i386_jcc(cd, I386_CC_L, a);
3366 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3367 i386_jcc(cd, I386_CC_AE, 0);
3368 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3372 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3373 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3375 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3376 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3377 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3379 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3380 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3382 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3383 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3386 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3388 i386_jcc(cd, I386_CC_E, 0);
3389 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3392 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3393 /* op1 = target JavaVM pc */
3395 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3396 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3397 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3398 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3399 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3400 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3401 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3403 i386_jcc(cd, I386_CC_E, 0);
3404 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3407 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3408 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3410 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3411 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3412 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3414 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3415 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3417 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3418 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3421 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3423 i386_jcc(cd, I386_CC_NE, 0);
3424 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3427 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3428 /* op1 = target JavaVM pc */
3430 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3431 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3432 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3433 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3434 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3435 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3436 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3438 i386_jcc(cd, I386_CC_NE, 0);
3439 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3442 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3443 /* op1 = target JavaVM pc */
3445 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3446 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3447 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3449 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3450 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3452 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3453 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3456 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3458 i386_jcc(cd, I386_CC_L, 0);
3459 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3462 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3463 /* op1 = target JavaVM pc */
3465 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3466 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3467 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3468 i386_jcc(cd, I386_CC_L, 0);
3469 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3472 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3473 CALCOFFSETBYTES(a, REG_SP, src->regoff*8);
3475 i386_jcc(cd, I386_CC_G, a);
3477 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3478 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3479 i386_jcc(cd, I386_CC_B, 0);
3480 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3484 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3485 /* op1 = target JavaVM pc */
3487 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3488 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3489 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3491 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3492 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3494 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3495 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3498 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3500 i386_jcc(cd, I386_CC_G, 0);
3501 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3504 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3505 /* op1 = target JavaVM pc */
3507 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3508 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3509 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3510 i386_jcc(cd, I386_CC_G, 0);
3511 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3514 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3515 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3517 i386_jcc(cd, I386_CC_L, a);
3519 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3520 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3521 i386_jcc(cd, I386_CC_A, 0);
3522 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3526 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3527 /* op1 = target JavaVM pc */
3529 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3530 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3531 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3533 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3534 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3536 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3537 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3540 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3542 i386_jcc(cd, I386_CC_LE, 0);
3543 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3546 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3547 /* op1 = target JavaVM pc */
3549 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3550 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3551 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3552 i386_jcc(cd, I386_CC_L, 0);
3553 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3556 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3557 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3559 i386_jcc(cd, I386_CC_G, a);
3561 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3562 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3563 i386_jcc(cd, I386_CC_BE, 0);
3564 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3568 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3569 /* op1 = target JavaVM pc */
3571 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3572 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3573 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3575 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3576 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3578 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3579 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3582 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3584 i386_jcc(cd, I386_CC_GE, 0);
3585 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3588 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3589 /* op1 = target JavaVM pc */
3591 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3592 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3593 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3594 i386_jcc(cd, I386_CC_G, 0);
3595 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3598 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3599 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3601 i386_jcc(cd, I386_CC_L, a);
3603 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3604 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3605 i386_jcc(cd, I386_CC_AE, 0);
3606 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3610 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3612 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3615 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3616 /* val.i = constant */
3618 d = reg_of_var(rd, iptr->dst, REG_NULL);
3619 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
3622 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3623 /* val.i = constant */
3625 d = reg_of_var(rd, iptr->dst, REG_NULL);
3626 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
3629 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3630 /* val.i = constant */
3632 d = reg_of_var(rd, iptr->dst, REG_NULL);
3633 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
3636 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3637 /* val.i = constant */
3639 d = reg_of_var(rd, iptr->dst, REG_NULL);
3640 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
3643 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3644 /* val.i = constant */
3646 d = reg_of_var(rd, iptr->dst, REG_NULL);
3647 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
3650 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3651 /* val.i = constant */
3653 d = reg_of_var(rd, iptr->dst, REG_NULL);
3654 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
3658 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3661 var_to_reg_int(s1, src, REG_RESULT);
3662 M_INTMOVE(s1, REG_RESULT);
3664 goto nowperformreturn;
3666 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3668 if (src->flags & INMEMORY) {
3669 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_RESULT);
3670 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3673 panic("LRETURN: longs have to be in memory");
3676 goto nowperformreturn;
3678 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3679 case ICMD_DRETURN: /* ..., retvalue ==> ... */
3681 var_to_reg_flt(s1, src, REG_FRESULT);
3682 /* this may be an early return -- keep the offset correct for the
3686 goto nowperformreturn;
3688 case ICMD_RETURN: /* ... ==> ... */
3694 p = parentargs_base;
3696 /* call trace function */
3698 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3700 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3702 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3703 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3705 i386_fstl_membase(cd, REG_SP, 4 + 8);
3706 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3708 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3709 i386_call_reg(cd, REG_ITMP1);
3711 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3712 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3714 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3717 #if defined(USE_THREADS)
3718 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3719 i386_mov_membase_reg(cd, REG_SP, 8 * rd->maxmemuse, REG_ITMP2);
3721 /* we need to save the proper return value */
3722 switch (iptr->opc) {
3725 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
3729 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
3730 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, rd->maxmemuse * 8 + 4);
3734 i386_fsts_membase(cd, REG_SP, rd->maxmemuse * 8);
3738 i386_fstl_membase(cd, REG_SP, rd->maxmemuse * 8);
3742 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
3743 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, 0);
3744 i386_mov_imm_reg(cd, (s4) builtin_monitorexit, REG_ITMP1);
3745 i386_call_reg(cd, REG_ITMP1);
3746 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
3748 /* and now restore the proper return value */
3749 switch (iptr->opc) {
3752 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
3756 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
3757 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8 + 4, REG_RESULT2);
3761 i386_flds_membase(cd, REG_SP, rd->maxmemuse * 8);
3765 i386_fldl_membase(cd, REG_SP, rd->maxmemuse * 8);
3771 /* restore saved registers */
3772 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
3774 i386_mov_membase_reg(cd, REG_SP, p * 8, rd->savintregs[i]);
3776 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
3778 i386_fldl_membase(cd, REG_SP, p * 8);
3780 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3781 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
3783 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
3788 /* deallocate stack */
3789 if (parentargs_base) {
3790 i386_alu_imm_reg(cd, I386_ADD, parentargs_base * 8, REG_SP);
3799 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3804 tptr = (void **) iptr->target;
3806 s4ptr = iptr->val.a;
3807 l = s4ptr[1]; /* low */
3808 i = s4ptr[2]; /* high */
3810 var_to_reg_int(s1, src, REG_ITMP1);
3811 M_INTMOVE(s1, REG_ITMP1);
3813 i386_alu_imm_reg(cd, I386_SUB, l, REG_ITMP1);
3819 i386_alu_imm_reg(cd, I386_CMP, i - 1, REG_ITMP1);
3820 i386_jcc(cd, I386_CC_A, 0);
3822 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
3823 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3825 /* build jump table top down and use address of lowest entry */
3827 /* s4ptr += 3 + i; */
3831 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
3832 dseg_addtarget(cd, (basicblock *) tptr[0]);
3836 /* length of dataseg after last dseg_addtarget is used by load */
3838 i386_mov_imm_reg(cd, 0, REG_ITMP2);
3839 dseg_adddata(cd, cd->mcodeptr);
3840 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3841 i386_jmp_reg(cd, REG_ITMP1);
3847 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3849 s4 i, l, val, *s4ptr;
3852 tptr = (void **) iptr->target;
3854 s4ptr = iptr->val.a;
3855 l = s4ptr[0]; /* default */
3856 i = s4ptr[1]; /* count */
3858 MCODECHECK((i<<2)+8);
3859 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3865 i386_alu_imm_reg(cd, I386_CMP, val, s1);
3866 i386_jcc(cd, I386_CC_E, 0);
3867 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), cd->mcodeptr); */
3868 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3871 i386_jmp_imm(cd, 0);
3872 /* codegen_addreference(cd, BlockPtrOfPC(l), cd->mcodeptr); */
3874 tptr = (void **) iptr->target;
3875 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3882 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3883 /* op1 = return type, val.a = function pointer*/
3887 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3888 /* op1 = return type, val.a = function pointer*/
3892 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3893 /* op1 = return type, val.a = function pointer*/
3897 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3898 /* op1 = arg count, val.a = method pointer */
3900 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3901 /* op1 = arg count, val.a = method pointer */
3903 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3904 /* op1 = arg count, val.a = method pointer */
3906 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3907 /* op1 = arg count, val.a = method pointer */
3914 MCODECHECK((s3 << 1) + 64);
3916 /* copy arguments to registers or stack location */
3918 for (; --s3 >= 0; src = src->prev) {
3919 if (src->varkind == ARGVAR) {
3923 if (IS_INT_LNG_TYPE(src->type)) {
3924 if (s3 < rd->intreg_argnum) {
3925 panic("No integer argument registers available!");
3928 if (!IS_2_WORD_TYPE(src->type)) {
3929 if (src->flags & INMEMORY) {
3930 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3931 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s3 * 8);
3934 i386_mov_reg_membase(cd, src->regoff, REG_SP, s3 * 8);
3938 if (src->flags & INMEMORY) {
3939 M_LNGMEMMOVE(src->regoff, s3);
3942 panic("copy arguments: longs have to be in memory");
3948 if (s3 < rd->fltreg_argnum) {
3949 panic("No float argument registers available!");
3952 var_to_reg_flt(d, src, REG_FTMP1);
3953 if (src->type == TYPE_FLT) {
3954 i386_fstps_membase(cd, REG_SP, s3 * 8);
3957 i386_fstpl_membase(cd, REG_SP, s3 * 8);
3964 switch (iptr->opc) {
3971 i386_mov_imm_reg(cd, a, REG_ITMP1);
3972 i386_call_reg(cd, REG_ITMP1);
3975 case ICMD_INVOKESTATIC:
3976 a = (u4) lm->stubroutine;
3979 i386_mov_imm_reg(cd, a, REG_ITMP2);
3980 i386_call_reg(cd, REG_ITMP2);
3983 case ICMD_INVOKESPECIAL:
3984 a = (u4) lm->stubroutine;
3987 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3988 gen_nullptr_check(REG_ITMP1);
3989 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
3991 i386_mov_imm_reg(cd, a, REG_ITMP2);
3992 i386_call_reg(cd, REG_ITMP2);
3995 case ICMD_INVOKEVIRTUAL:
3998 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3999 gen_nullptr_check(REG_ITMP1);
4000 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
4001 i386_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
4003 i386_call_reg(cd, REG_ITMP1);
4006 case ICMD_INVOKEINTERFACE:
4009 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
4010 gen_nullptr_check(REG_ITMP1);
4011 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4012 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * lm->class->index, REG_ITMP2);
4013 i386_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - lm->class->methods), REG_ITMP1);
4015 i386_call_reg(cd, REG_ITMP1);
4019 /* d contains return type */
4021 if (d != TYPE_VOID) {
4022 d = reg_of_var(rd, iptr->dst, REG_NULL);
4024 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
4025 if (IS_2_WORD_TYPE(iptr->dst->type)) {
4026 if (iptr->dst->flags & INMEMORY) {
4027 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
4028 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
4031 panic("RETURN: longs have to be in memory");
4035 if (iptr->dst->flags & INMEMORY) {
4036 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
4039 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
4044 /* fld from called function -- has other fpu_st_offset counter */
4046 store_reg_to_var_flt(iptr->dst, d);
4053 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
4055 /* op1: 0 == array, 1 == class */
4056 /* val.a: (classinfo*) superclass */
4058 /* superclass is an interface:
4060 * return (sub != NULL) &&
4061 * (sub->vftbl->interfacetablelength > super->index) &&
4062 * (sub->vftbl->interfacetable[-super->index] != NULL);
4064 * superclass is a class:
4066 * return ((sub != NULL) && (0
4067 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4068 * super->vftbl->diffvall));
4072 classinfo *super = (classinfo*) iptr->val.a;
4074 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4075 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4077 var_to_reg_int(s1, src, REG_ITMP1);
4078 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4080 M_INTMOVE(s1, REG_ITMP1);
4083 i386_alu_reg_reg(cd, I386_XOR, d, d);
4084 if (iptr->op1) { /* class/interface */
4085 if (super->flags & ACC_INTERFACE) { /* interface */
4086 i386_test_reg_reg(cd, s1, s1);
4088 /* TODO: clean up this calculation */
4090 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4093 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4096 /* CALCOFFSETBYTES(a, super->index); */
4097 CALCIMMEDIATEBYTES(a, super->index);
4103 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4110 i386_jcc(cd, I386_CC_E, a);
4112 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4113 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4114 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4116 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4118 /* TODO: clean up this calculation */
4121 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4128 i386_jcc(cd, I386_CC_LE, a);
4129 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4131 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP1);
4132 /* i386_setcc_reg(cd, I386_CC_A, d); */
4133 /* i386_jcc(cd, I386_CC_BE, 5); */
4134 i386_jcc(cd, I386_CC_E, 5);
4135 i386_mov_imm_reg(cd, 1, d);
4138 } else { /* class */
4139 i386_test_reg_reg(cd, s1, s1);
4141 /* TODO: clean up this calculation */
4143 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4146 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4148 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4151 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4161 i386_jcc(cd, I386_CC_E, a);
4163 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4164 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4165 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4166 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4168 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4169 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4170 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4171 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4172 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4174 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4175 i386_alu_reg_reg(cd, I386_XOR, d, d);
4177 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4178 i386_jcc(cd, I386_CC_A, 5);
4179 i386_mov_imm_reg(cd, 1, d);
4183 panic ("internal error: no inlined array instanceof");
4185 store_reg_to_var_int(iptr->dst, d);
4188 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4190 /* op1: 0 == array, 1 == class */
4191 /* val.a: (classinfo*) superclass */
4193 /* superclass is an interface:
4195 * OK if ((sub == NULL) ||
4196 * (sub->vftbl->interfacetablelength > super->index) &&
4197 * (sub->vftbl->interfacetable[-super->index] != NULL));
4199 * superclass is a class:
4201 * OK if ((sub == NULL) || (0
4202 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4203 * super->vftbl->diffval));
4207 classinfo *super = (classinfo *) iptr->val.a;
4209 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4210 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4212 var_to_reg_int(s1, src, REG_ITMP1);
4213 if (iptr->op1) { /* class/interface */
4214 if (super->flags & ACC_INTERFACE) { /* interface */
4215 i386_test_reg_reg(cd, s1, s1);
4217 /* TODO: clean up this calculation */
4219 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4222 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
4225 CALCIMMEDIATEBYTES(a, super->index);
4231 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4236 i386_jcc(cd, I386_CC_E, a);
4238 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
4239 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength), REG_ITMP3);
4240 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP3);
4241 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4242 i386_jcc(cd, I386_CC_LE, 0);
4243 codegen_addxcastrefs(cd, cd->mcodeptr);
4244 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP3);
4245 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4246 i386_jcc(cd, I386_CC_E, 0);
4247 codegen_addxcastrefs(cd, cd->mcodeptr);
4249 } else { /* class */
4250 i386_test_reg_reg(cd, s1, s1);
4252 /* TODO: clean up this calculation */
4254 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4259 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4261 if (s1 != REG_ITMP1) {
4263 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
4266 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
4272 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
4278 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
4284 i386_jcc(cd, I386_CC_E, a);
4286 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
4287 i386_mov_imm_reg(cd, (ptrint) super->vftbl, REG_ITMP3);
4288 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4289 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4291 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
4292 if (s1 != REG_ITMP1) {
4293 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1);
4294 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3);
4295 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4296 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4298 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP1, REG_ITMP2);
4301 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP3);
4302 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP2);
4303 i386_mov_imm_reg(cd, (ptrint) super->vftbl, REG_ITMP3);
4304 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3);
4305 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4306 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4310 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP3, REG_ITMP2);
4311 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
4312 codegen_addxcastrefs(cd, cd->mcodeptr);
4316 panic ("internal error: no inlined array checkcast");
4318 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4320 store_reg_to_var_int(iptr->dst, d);
4323 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4325 if (src->flags & INMEMORY) {
4326 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4329 i386_test_reg_reg(cd, src->regoff, src->regoff);
4331 i386_jcc(cd, I386_CC_L, 0);
4332 codegen_addxcheckarefs(cd, cd->mcodeptr);
4335 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4337 i386_test_reg_reg(cd, REG_RESULT, REG_RESULT);
4338 i386_jcc(cd, I386_CC_E, 0);
4339 codegen_addxexceptionrefs(cd, cd->mcodeptr);
4342 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4343 /* op1 = dimension, val.a = array descriptor */
4345 /* check for negative sizes and copy sizes to stack if necessary */
4347 MCODECHECK((iptr->op1 << 1) + 64);
4349 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4350 if (src->flags & INMEMORY) {
4351 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4354 i386_test_reg_reg(cd, src->regoff, src->regoff);
4356 i386_jcc(cd, I386_CC_L, 0);
4357 codegen_addxcheckarefs(cd, cd->mcodeptr);
4360 * copy sizes to new stack location, because native function
4361 * builtin_nmultianewarray access them as (int *)
4363 /*i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);*/
4364 /*i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);*/
4366 /* copy SAVEDVAR sizes to stack */
4368 if (src->varkind != ARGVAR) {
4369 if (src->flags & INMEMORY) {
4370 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
4371 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s1 * 8);
4374 i386_mov_reg_membase(cd, src->regoff, REG_SP, s1 * 8);
4379 /* now copy the (long *) sizes to (int *), skip the first one */
4381 for (s1 = 1; s1 < iptr->op1; s1++) {
4382 i386_mov_membase_reg(cd, REG_SP, s1 * 8, REG_ITMP1);
4383 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s1 * 4);
4386 /* save stack pointer */
4387 M_INTMOVE(REG_SP, REG_ITMP1);
4389 i386_alu_imm_reg(cd, I386_SUB, 3 * 4, REG_SP);
4391 /* a0 = dimension count */
4393 i386_mov_imm_membase(cd, iptr->op1, REG_SP, 0);
4395 /* a1 = arraydescriptor */
4397 i386_mov_imm_membase(cd, (u4) iptr->val.a, REG_SP, 4);
4399 /* a2 = pointer to dimensions = stack pointer */
4401 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 8);
4403 i386_mov_imm_reg(cd, (u4) (builtin_nmultianewarray), REG_ITMP1);
4404 i386_call_reg(cd, REG_ITMP1);
4405 i386_alu_imm_reg(cd, I386_ADD, 3 * 4, REG_SP);
4407 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
4408 M_INTMOVE(REG_RESULT, s1);
4409 store_reg_to_var_int(iptr->dst, s1);
4413 throw_cacao_exception_exit(string_java_lang_InternalError,
4414 "Unknown ICMD %d", iptr->opc);
4417 } /* for instruction */
4419 /* copy values to interface registers */
4421 src = bptr->outstack;
4422 len = bptr->outdepth;
4429 if ((src->varkind != STACKVAR)) {
4431 if (IS_FLT_DBL_TYPE(s2)) {
4432 var_to_reg_flt(s1, src, REG_FTMP1);
4433 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4434 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
4437 panic("double store");
4438 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4442 var_to_reg_int(s1, src, REG_ITMP1);
4443 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
4444 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4445 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
4448 i386_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
4452 if (rd->interfaces[len][s2].flags & INMEMORY) {
4453 M_LNGMEMMOVE(s1, rd->interfaces[len][s2].regoff);
4456 panic("copy interface registers: longs have to be in memory (end)");
4463 } /* if (bptr -> flags >= BBREACHED) */
4464 } /* for basic block */
4466 codegen_createlinenumbertable(cd);
4470 /* generate bound check stubs */
4472 u1 *xcodeptr = NULL;
4475 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
4476 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4478 cd->mcodeptr - cd->mcodebase);
4482 /* move index register into REG_ITMP1 */
4483 i386_mov_reg_reg(cd, bref->reg, REG_ITMP1); /* 2 bytes */
4485 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4486 dseg_adddata(cd, cd->mcodeptr);
4487 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3); /* 5 bytes */
4488 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4490 if (xcodeptr != NULL) {
4491 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4494 xcodeptr = cd->mcodeptr;
4496 i386_push_reg(cd, REG_ITMP2_XPC);
4498 /*PREPARE_NATIVE_STACKINFO;*/
4499 i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
4500 i386_push_imm(cd,0);
4501 i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
4502 i386_call_reg(cd,REG_ITMP3);
4504 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4505 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 4);
4506 i386_mov_imm_reg(cd, (u4) new_arrayindexoutofboundsexception, 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);
4510 /*REMOVE_NATIVE_STACKINFO;*/
4511 i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
4512 i386_call_reg(cd,REG_ITMP3);
4514 i386_pop_reg(cd, REG_ITMP2_XPC);
4516 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4517 i386_jmp_reg(cd, REG_ITMP3);
4521 /* generate negative array size check stubs */
4525 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
4526 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4527 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4529 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4533 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4535 cd->mcodeptr - cd->mcodebase);
4539 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4540 dseg_adddata(cd, cd->mcodeptr);
4541 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4542 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4544 if (xcodeptr != NULL) {
4545 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4548 xcodeptr = cd->mcodeptr;
4550 i386_push_reg(cd, REG_ITMP2_XPC);
4552 /*PREPARE_NATIVE_STACKINFO;*/
4553 i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
4554 i386_push_imm(cd,0);
4555 i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
4556 i386_call_reg(cd,REG_ITMP3);
4560 i386_mov_imm_reg(cd, (u4) new_negativearraysizeexception, REG_ITMP1);
4561 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4562 /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4565 /*REMOVE_NATIVE_STACKINFO;*/
4566 i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
4567 i386_call_reg(cd,REG_ITMP3);
4570 i386_pop_reg(cd, REG_ITMP2_XPC);
4572 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4573 i386_jmp_reg(cd, REG_ITMP3);
4577 /* generate cast check stubs */
4581 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
4582 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4583 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4585 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4589 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4591 cd->mcodeptr - cd->mcodebase);
4595 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4596 dseg_adddata(cd, cd->mcodeptr);
4597 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4598 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4600 if (xcodeptr != NULL) {
4601 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4604 xcodeptr = cd->mcodeptr;
4606 i386_push_reg(cd, REG_ITMP2_XPC);
4608 /*PREPARE_NATIVE_STACKINFO;*/
4609 i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
4610 i386_push_imm(cd,0);
4611 i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
4612 i386_call_reg(cd,REG_ITMP3);
4615 i386_mov_imm_reg(cd, (u4) new_classcastexception, REG_ITMP1);
4616 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4617 /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4620 /*REMOVE_NATIVE_STACKINFO;*/
4621 i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
4622 i386_call_reg(cd,REG_ITMP3);
4625 i386_pop_reg(cd, REG_ITMP2_XPC);
4627 i386_mov_imm_reg(cd, (u4) asm_handle_exception, REG_ITMP3);
4628 i386_jmp_reg(cd, REG_ITMP3);
4632 /* generate divide by zero check stubs */
4636 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
4637 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4638 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4640 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4644 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4646 cd->mcodeptr - cd->mcodebase);
4650 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4651 dseg_adddata(cd, cd->mcodeptr);
4652 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4653 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4655 if (xcodeptr != NULL) {
4656 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4659 xcodeptr = cd->mcodeptr;
4661 i386_push_reg(cd, REG_ITMP2_XPC);
4663 /*PREPARE_NATIVE_STACKINFO;*/
4664 i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
4665 i386_push_imm(cd,0);
4666 i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
4667 i386_call_reg(cd,REG_ITMP3);
4671 i386_mov_imm_reg(cd, (u4) new_arithmeticexception, REG_ITMP1);
4672 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4674 /*REMOVE_NATIVE_STACKINFO;*/
4675 i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
4676 i386_call_reg(cd,REG_ITMP3);
4679 i386_pop_reg(cd, REG_ITMP2_XPC);
4681 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4682 i386_jmp_reg(cd, REG_ITMP3);
4686 /* generate exception check stubs */
4690 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
4691 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4692 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4694 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4698 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4700 cd->mcodeptr - cd->mcodebase);
4704 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4705 dseg_adddata(cd, cd->mcodeptr);
4706 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4707 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4709 if (xcodeptr != NULL) {
4710 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4713 xcodeptr = cd->mcodeptr;
4715 i386_push_reg(cd, REG_ITMP2_XPC);
4717 /*PREPARE_NATIVE_STACKINFO;*/
4718 i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
4719 i386_push_imm(cd,0);
4720 i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
4721 i386_call_reg(cd,REG_ITMP3);
4723 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4724 i386_mov_imm_reg(cd, (s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4725 i386_call_reg(cd, REG_ITMP1);
4726 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP3);
4727 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
4728 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1_XPTR);
4730 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP3);
4731 i386_mov_membase_reg(cd, REG_ITMP3, 0, REG_ITMP1_XPTR);
4732 i386_mov_imm_membase(cd, 0, REG_ITMP3, 0);
4734 i386_push_imm(cd, 0);
4735 i386_push_reg(cd, REG_ITMP1_XPTR);
4737 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4738 java stack at this point*/
4739 i386_mov_membase_reg(cd, REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4740 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, class), REG_ITMP1);
4741 i386_push_imm(cd, (u4) utf_void__java_lang_Throwable);
4742 i386_push_imm(cd, (u4) utf_fillInStackTrace);
4743 i386_push_reg(cd, REG_ITMP1);
4744 i386_mov_imm_reg(cd, (s4) class_resolvemethod, REG_ITMP3);
4745 i386_call_reg(cd, REG_ITMP3);
4746 /*cleanup parameters of class_resolvemethod*/
4747 i386_alu_imm_reg(cd, I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4748 /*prepare call to asm_calljavafunction2 */
4749 i386_push_imm(cd, 0);
4750 i386_push_imm(cd, TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
4751 i386_push_reg(cd, REG_SP);
4752 i386_push_imm(cd, sizeof(jni_callblock));
4753 i386_push_imm(cd, 1);
4754 i386_push_reg(cd, REG_RESULT);
4756 i386_mov_imm_reg(cd, (s4) asm_calljavafunction2, REG_ITMP3);
4757 i386_call_reg(cd, REG_ITMP3);
4759 /* check exceptionptr + fail (JOWENN)*/
4761 i386_alu_imm_reg(cd, I386_ADD,6*4,REG_SP);
4763 i386_pop_reg(cd, REG_ITMP1_XPTR);
4764 i386_pop_reg(cd, REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4766 /*REMOVE_NATIVE_STACKINFO;*/
4767 i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
4768 i386_call_reg(cd,REG_ITMP3);
4771 i386_pop_reg(cd, REG_ITMP2_XPC);
4773 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4774 i386_jmp_reg(cd, REG_ITMP3);
4778 /* generate null pointer check stubs */
4782 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
4783 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4784 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4786 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4790 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4792 cd->mcodeptr - cd->mcodebase);
4796 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4797 dseg_adddata(cd, cd->mcodeptr);
4798 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4799 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4801 if (xcodeptr != NULL) {
4802 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4805 xcodeptr = cd->mcodeptr;
4807 i386_push_reg(cd, REG_ITMP2_XPC);
4809 /*PREPARE_NATIVE_STACKINFO;*/
4810 i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
4811 i386_push_imm(cd,0);
4812 i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
4813 i386_call_reg(cd,REG_ITMP3);
4818 /* create native call block*/
4819 i386_alu_imm_reg(cd, I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4822 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1);
4823 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/
4825 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4826 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
4827 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
4828 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
4829 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4830 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */
4831 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4834 i386_mov_imm_reg(cd, (u4) new_nullpointerexception, REG_ITMP1);
4835 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4837 /*REMOVE_NATIVE_STACKINFO;*/
4838 i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
4839 i386_call_reg(cd,REG_ITMP3);
4843 /* restore native call stack */
4844 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2);
4845 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3);
4846 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0);
4847 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
4850 i386_pop_reg(cd, REG_ITMP2_XPC);
4852 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4853 i386_jmp_reg(cd, REG_ITMP3);
4857 /* generate put/getstatic stub call code */
4865 tmpcd = DNEW(codegendata);
4867 for (cref = cd->clinitrefs; cref != NULL; cref = cref->next) {
4868 /* Get machine code which is patched back in later. A */
4869 /* `call rel32' is 5 bytes long. */
4870 xcodeptr = cd->mcodebase + cref->branchpos;
4872 mcode = *((u4 *) (xcodeptr + 1));
4876 /* patch in `call rel32' to call the following code */
4877 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
4878 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
4880 /* Save current stack pointer into a temporary register. */
4881 i386_mov_reg_reg(cd, REG_SP, REG_ITMP1);
4883 /* Push machine code bytes to patch onto the stack. */
4884 i386_push_imm(cd, (u4) xmcode);
4885 i386_push_imm(cd, (u4) mcode);
4887 i386_push_imm(cd, (u4) cref->class);
4889 /* Push previously saved stack pointer onto stack. */
4890 i386_push_reg(cd, REG_ITMP1);
4892 i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP1);
4893 i386_jmp_reg(cd, REG_ITMP1);
4898 codegen_finish(m, cd, (u4) (cd->mcodeptr - cd->mcodebase));
4902 /* function createcompilerstub *************************************************
4904 creates a stub routine which calls the compiler
4906 *******************************************************************************/
4908 #define COMPSTUBSIZE 12
4910 u1 *createcompilerstub(methodinfo *m)
4912 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
4916 /* mark start of dump memory area */
4918 dumpsize = dump_size();
4920 cd = DNEW(codegendata);
4923 /* code for the stub */
4924 i386_mov_imm_reg(cd, (u4) m, REG_ITMP1);/* pass method pointer to compiler*/
4926 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
4927 i386_mov_imm_reg(cd, (u4) asm_call_jit_compiler, REG_ITMP3);
4928 i386_jmp_reg(cd, REG_ITMP3); /* jump to compiler */
4930 #if defined(STATISTICS)
4932 count_cstub_len += COMPSTUBSIZE;
4935 /* release dump area */
4937 dump_release(dumpsize);
4943 /* function removecompilerstub *************************************************
4945 deletes a compilerstub from memory (simply by freeing it)
4947 *******************************************************************************/
4949 void removecompilerstub(u1 *stub)
4951 CFREE(stub, COMPSTUBSIZE);
4955 /* function: createnativestub **************************************************
4957 creates a stub routine which calls a native method
4959 *******************************************************************************/
4961 #define NATIVESTUB_SIZE 450 /* keep this size high enough! */
4962 #define NATIVESTUB_OFFSET 0
4963 #define NATIVESTUB_DATA_SIZE 9 * 4
4965 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4966 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4970 void i386_native_stub_debug(void **p) {
4971 printf("Pos on stack: %p\n",p);
4972 printf("Return adress should be: %p\n",*p);
4975 void i386_native_stub_debug2(void **p) {
4976 printf("Pos on stack: %p\n",p);
4977 printf("Return for lookup is: %p\n",*p);
4980 void traverseStackInfo() {
4981 void **p=builtin_asm_get_stackframeinfo();
4985 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4986 m=*((methodinfo**)((*p)+8));
4987 utf_display(m->name);
4994 u1 *createnativestub(functionptr f, methodinfo *m)
4996 u1 *s; /* pointer to stub memory */
5001 t_inlining_globals *id;
5006 s4 stackframeoffset;
5007 bool require_clinit_call;
5009 s4 *callAddrPatchPos;
5011 s4 *jmpInstrPatchPos;
5013 /* initial 4 bytes is space for jni env, + 4 byte thread pointer + 4 byte */
5014 /* previous pointer + method info + 4 offset native */
5015 stackframesize = 4 + 16;
5016 stackframeoffset = 4;
5018 /* mark start of dump memory area */
5020 dumpsize = dump_size();
5022 /* allocate required dump memory */
5024 cd = DNEW(codegendata);
5025 rd = DNEW(registerdata);
5026 id = DNEW(t_inlining_globals);
5028 /* setup registers before using it */
5030 inlining_setup(m, id);
5031 reg_setup(m, rd, id);
5033 method_descriptor2types(m); /* set paramcount and paramtypes */
5035 require_clinit_call = (m->flags & ACC_STATIC) && !m->class->initialized;
5037 stubsize = NATIVESTUB_SIZE; /* calculate nativestub size */
5039 if (require_clinit_call)
5040 stubsize += NATIVESTUB_DATA_SIZE;
5042 /* if ((m->flags & ACC_STATIC) && !m->class->initialized) */
5043 /* stubsize += NATIVESTUB_STATIC_SIZE; */
5045 s = CNEW(u1, stubsize); /* memory to hold the stub */
5047 if (require_clinit_call) {
5048 /* build a dummy data segment *****************************************/
5050 cs = (u4 *) (s + NATIVESTUB_DATA_SIZE);
5052 *(cs - 9) = 0; /* extable size */
5053 *(cs - 8) = 0; /* line number table start */
5054 *(cs - 7) = 0; /* line number table size */
5055 *(cs - 6) = 0; /* fltsave */
5056 *(cs - 5) = 0; /* intsave */
5057 *(cs - 4) = 0; /* isleaf */
5058 *(cs - 3) = 0; /* issync */
5059 *(cs - 2) = 0; /* frame size */
5060 *(cs - 1) = (u4) m; /* method pointer */
5066 /* set some required varibles which are normally set by codegen_setup */
5067 cd->mcodebase = (u1 *) cs;
5068 cd->mcodeptr = (u1 *) cs;
5069 cd->clinitrefs = NULL;
5071 /* if function is static, check for initialized */
5073 if (m->flags & ACC_STATIC) {
5074 stackframesize += 4;
5075 stackframeoffset += 4;
5077 /* if class isn't yet initialized, do it */
5078 if (!m->class->initialized)
5079 codegen_addclinitref(cd, cd->mcodeptr, m->class);
5085 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
5087 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
5088 t = m->paramtypes[p];
5089 if (IS_INT_LNG_TYPE(t)) {
5090 if (IS_2_WORD_TYPE(t)) {
5091 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
5092 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
5093 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5094 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5096 } else if (t == TYPE_ADR) {
5097 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
5098 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
5099 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5100 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5103 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
5105 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
5106 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
5110 if (!IS_2_WORD_TYPE(t)) {
5111 i386_flds_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
5112 i386_fstps_membase(cd, REG_SP, p * 8);
5113 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
5114 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5117 i386_fldl_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
5118 i386_fstpl_membase(cd, REG_SP, p * 8);
5123 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
5124 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
5125 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5126 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
5129 i386_mov_imm_membase(cd, (u4) m, REG_SP, TRACE_ARGS_NUM * 8);
5131 i386_mov_imm_reg(cd, (u4) builtin_trace_args, REG_ITMP1);
5132 i386_call_reg(cd, REG_ITMP1);
5134 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
5137 /* Mark the whole fpu stack as free for native functions (only for saved */
5138 /* register count == 0). */
5139 i386_ffree_reg(cd, 0);
5140 i386_ffree_reg(cd, 1);
5141 i386_ffree_reg(cd, 2);
5142 i386_ffree_reg(cd, 3);
5143 i386_ffree_reg(cd, 4);
5144 i386_ffree_reg(cd, 5);
5145 i386_ffree_reg(cd, 6);
5146 i386_ffree_reg(cd, 7);
5148 /* calculate stackframe size for native function */
5149 tptr = m->paramtypes;
5150 for (i = 0; i < m->paramcount; i++) {
5151 stackframesize += IS_2_WORD_TYPE(*tptr++) ? 8 : 4;
5154 i386_alu_imm_reg(cd, I386_SUB, stackframesize, REG_SP);
5156 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
5157 i386_mov_imm_membase(cd,0,REG_SP,stackframesize-4);
5158 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
5159 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
5160 i386_call_reg(cd, REG_ITMP1);
5161 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-12); /*save thread specific pointer*/
5162 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2);
5163 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-16); /*save previous value of memory adress pointed to by thread specific pointer*/
5164 i386_mov_reg_reg(cd, REG_SP,REG_ITMP2);
5165 i386_alu_imm_reg(cd, I386_ADD,stackframesize-16,REG_ITMP2);
5166 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0);
5169 /* i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
5170 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
5171 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-12);*/
5173 /* CREATE DYNAMIC STACK INFO -- END*/
5175 /* RESOLVE NATIVE METHOD -- BEGIN*/
5176 #if !defined(STATIC_CLASSPATH)
5178 /*log_text("Dynamic classpath: preparing for delayed native function resolving");*/
5179 i386_jmp_imm(cd, 0);
5180 jmpInstrPos = cd->mcodeptr - 4;
5182 /* patch position */
5183 i386_mov_imm_reg(cd, (s4) jmpInstrPos, REG_ITMP1);
5184 i386_push_reg(cd, REG_ITMP1);
5187 i386_mov_imm_reg(cd, 0, REG_ITMP1);
5188 jmpInstrPatchPos = (s4 *) (cd->mcodeptr - 4);
5189 i386_push_reg(cd, REG_ITMP1);
5191 /* position of call address to patch */
5192 i386_mov_imm_reg(cd, 0, REG_ITMP1);
5193 callAddrPatchPos = (s4 *) (cd->mcodeptr - 4);
5194 i386_push_reg(cd, REG_ITMP1);
5196 /* method info structure */
5197 i386_mov_imm_reg(cd, (s4) m, REG_ITMP1);
5198 i386_push_reg(cd, REG_ITMP1);
5200 /* call resolve functions */
5201 i386_mov_imm_reg(cd, (s4) codegen_resolve_native, REG_ITMP1);
5202 i386_call_reg(cd, REG_ITMP1);
5205 i386_alu_imm_reg(cd, I386_ADD, 4 * 4, REG_SP);
5207 /* fix jmp offset replacement */
5208 *jmpInstrPatchPos = cd->mcodeptr - jmpInstrPos - 4;
5209 } /*else log_text("Dynamic classpath: immediate native function resolution possible");*/
5211 /* RESOLVE NATIVE METHOD -- END*/
5213 /* copy arguments into new stackframe */
5215 tptr = m->paramtypes;
5216 for (i = 0; i < m->paramcount; i++) {
5217 if (IS_2_WORD_TYPE(*tptr++)) {
5218 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5219 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5220 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5221 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, stackframeoffset + 4);
5222 stackframeoffset += 8;
5225 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5226 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5227 stackframeoffset += 4;
5231 /* if function is static, put class into second argument */
5233 if (m->flags & ACC_STATIC) {
5234 i386_mov_imm_membase(cd, (u4) m->class, REG_SP, 4);
5237 /* put env into first argument */
5239 i386_mov_imm_membase(cd, (u4) &env, REG_SP, 0);
5241 /* call the native function */
5243 i386_mov_imm_reg(cd, (u4) f, REG_ITMP1);
5244 #if !defined(STATIC_CLASSPATH)
5246 *callAddrPatchPos = (u4) cd->mcodeptr - 4;
5248 i386_call_reg(cd, REG_ITMP1);
5250 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5251 i386_push_reg(cd, REG_RESULT2);
5252 i386_mov_membase_reg(cd, REG_SP,stackframesize-12,REG_ITMP2); /*old value*/
5253 i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_RESULT2); /*pointer*/
5254 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT2,0);
5255 i386_pop_reg(cd, REG_RESULT2);
5256 /*REMOVE DYNAMIC STACK INFO -END */
5258 i386_alu_imm_reg(cd, I386_ADD, stackframesize, REG_SP);
5262 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5264 i386_mov_imm_membase(cd, (u4) m, REG_SP, 0);
5266 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
5267 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
5269 i386_fstl_membase(cd, REG_SP, 4 + 8);
5270 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5272 i386_mov_imm_reg(cd, (u4) builtin_displaymethodstop, REG_ITMP1);
5273 i386_call_reg(cd, REG_ITMP1);
5275 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
5276 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
5278 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5281 /* we can't use REG_ITMP3 == REG_RESULT2 */
5282 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5283 i386_push_reg(cd, REG_RESULT);
5284 i386_push_reg(cd, REG_RESULT2);
5285 i386_call_mem(cd, (u4) &callgetexceptionptrptr);
5286 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP2);
5287 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5288 i386_pop_reg(cd, REG_RESULT2);
5289 i386_pop_reg(cd, REG_RESULT);
5291 i386_mov_imm_reg(cd, (u4) &_exceptionptr, REG_ITMP2);
5292 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP2);
5293 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5295 i386_jcc(cd, I386_CC_NE, 1);
5299 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5300 i386_push_reg(cd, REG_ITMP2);
5301 i386_call_mem(cd, (u4) &callgetexceptionptrptr);
5302 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5303 i386_pop_reg(cd, REG_ITMP1_XPTR);
5305 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1_XPTR);
5306 i386_mov_imm_reg(cd, (u4) &_exceptionptr, REG_ITMP2);
5307 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5309 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP2_XPC);
5310 i386_alu_imm_reg(cd, I386_SUB, 2, REG_ITMP2_XPC);
5312 i386_mov_imm_reg(cd, (u4) asm_handle_nat_exception, REG_ITMP3);
5313 i386_jmp_reg(cd, REG_ITMP3);
5315 /* patch in a clinit call if required *************************************/
5317 if (require_clinit_call) {
5324 tmpcd = DNEW(codegendata);
5326 /* there can only be one clinit ref entry */
5327 cref = cd->clinitrefs;
5330 /* Get machine code which is patched back in later. A */
5331 /* `call rel32' is 5 bytes long. */
5332 xcodeptr = cd->mcodebase + cref->branchpos;
5334 mcode = *((u4 *) (xcodeptr + 1));
5336 /* patch in `call rel32' to call the following code */
5337 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5338 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5340 /* Save current stack pointer into a temporary register. */
5341 i386_mov_reg_reg(cd, REG_SP, REG_ITMP1);
5343 /* Push machine code bytes to patch onto the stack. */
5344 i386_push_imm(cd, (u4) xmcode);
5345 i386_push_imm(cd, (u4) mcode);
5347 i386_push_imm(cd, (u4) cref->class);
5349 /* Push previously saved stack pointer onto stack. */
5350 i386_push_reg(cd, REG_ITMP1);
5352 i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP1);
5353 i386_jmp_reg(cd, REG_ITMP1);
5356 /* insert the native stub into the method table */
5358 codegen_insertmethod((functionptr) cs, (functionptr) cd->mcodeptr);
5361 /* Check if the stub size is big enough to hold the whole stub generated. */
5362 /* If not, this can lead into unpredictable crashes, because of heap */
5364 if ((s4) (cd->mcodeptr - s) > stubsize) {
5365 throw_cacao_exception_exit(string_java_lang_InternalError,
5366 "Native stub size %d is to small for current stub size %d",
5367 stubsize, (s4) (cd->mcodeptr - s));
5370 #if defined(STATISTICS)
5372 count_nstub_len += stubsize;
5375 /* release dump area */
5377 dump_release(dumpsize);
5383 /* function: removenativestub **************************************************
5385 removes a previously created native-stub from memory
5387 *******************************************************************************/
5389 void removenativestub(u1 *stub)
5391 CFREE(stub, NATIVESTUB_SIZE);
5396 * These are local overrides for various environment variables in Emacs.
5397 * Please do not remove this and leave it at the end of the file, where
5398 * Emacs will automagically detect them.
5399 * ---------------------------------------------------------------------
5402 * indent-tabs-mode: t