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 2291 2005-04-12 21:59:24Z twisti $
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.cls);
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:
636 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
637 /* EAX: NO ECX: NO EDX: NO */
640 case ICMD_NOP: /* ... ==> ... */
641 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
642 /* EAX: NO ECX: NO EDX: NO */
645 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
646 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
647 /* EAX: NO ECX: NO EDX: NO */
648 if (src->flags & INMEMORY) {
649 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
652 i386_test_reg_reg(cd, src->regoff, src->regoff);
654 i386_jcc(cd, I386_CC_E, 0);
655 codegen_addxnullrefs(cd, cd->mcodeptr);
658 /* constant operations ************************************************/
660 case ICMD_ICONST: /* ... ==> ..., constant */
661 /* op1 = 0, val.i = constant */
663 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
664 /* EAX: NO ECX: NO EDX: NO */
665 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
666 if (iptr->dst->flags & INMEMORY) {
667 i386_mov_imm_membase(cd, iptr->val.i, REG_SP, iptr->dst->regoff * 8);
670 if (iptr->val.i == 0) {
671 i386_alu_reg_reg(cd, I386_XOR, d, d);
674 i386_mov_imm_reg(cd, iptr->val.i, d);
679 case ICMD_LCONST: /* ... ==> ..., constant */
680 /* op1 = 0, val.l = constant */
682 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
683 /* EAX: NO ECX: NO EDX: NO */
684 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
685 if (iptr->dst->flags & INMEMORY) {
686 i386_mov_imm_membase(cd, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
687 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
690 panic("LCONST: longs have to be in memory");
694 case ICMD_FCONST: /* ... ==> ..., constant */
695 /* op1 = 0, val.f = constant */
696 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
697 /* EAX: YES ECX: NO EDX: NO */
699 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
700 if (iptr->val.f == 0.0) {
705 if (iptr->val.i == 0x80000000) {
709 } else if (iptr->val.f == 1.0) {
713 } else if (iptr->val.f == 2.0) {
720 a = dseg_addfloat(cd, iptr->val.f);
721 i386_mov_imm_reg(cd, 0, REG_ITMP1);
722 dseg_adddata(cd, cd->mcodeptr);
723 i386_flds_membase(cd, REG_ITMP1, a);
726 store_reg_to_var_flt(iptr->dst, d);
729 case ICMD_DCONST: /* ... ==> ..., constant */
730 /* op1 = 0, val.d = constant */
731 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
732 /* EAX: YES ECX: NO EDX: NO */
734 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
735 if (iptr->val.d == 0.0) {
740 if (iptr->val.l == 0x8000000000000000LL) {
744 } else if (iptr->val.d == 1.0) {
748 } else if (iptr->val.d == 2.0) {
755 a = dseg_adddouble(cd, iptr->val.d);
756 i386_mov_imm_reg(cd, 0, REG_ITMP1);
757 dseg_adddata(cd, cd->mcodeptr);
758 i386_fldl_membase(cd, REG_ITMP1, a);
761 store_reg_to_var_flt(iptr->dst, d);
764 case ICMD_ACONST: /* ... ==> ..., constant */
765 /* op1 = 0, val.a = constant */
766 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
767 /* EAX: YES ECX: NO EDX: NO */
769 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
770 if (iptr->dst->flags & INMEMORY) {
771 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
774 if ((s4) iptr->val.a == 0) {
775 i386_alu_reg_reg(cd, I386_XOR, d, d);
778 i386_mov_imm_reg(cd, (s4) iptr->val.a, d);
784 /* load/store operations **********************************************/
786 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
787 case ICMD_ALOAD: /* op1 = local variable */
788 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
789 /* EAX: YES ECX: NO EDX: NO */
791 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
792 if ((iptr->dst->varkind == LOCALVAR) &&
793 (iptr->dst->varnum == iptr->op1)) {
796 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
797 if (iptr->dst->flags & INMEMORY) {
798 if (var->flags & INMEMORY) {
799 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, REG_ITMP1);
800 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
803 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
807 if (var->flags & INMEMORY) {
808 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, iptr->dst->regoff);
811 M_INTMOVE(var->regoff, iptr->dst->regoff);
816 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
817 /* op1 = local variable */
818 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
819 /* EAX: NO ECX: NO EDX: NO */
821 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
822 if ((iptr->dst->varkind == LOCALVAR) &&
823 (iptr->dst->varnum == iptr->op1)) {
826 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
827 if (iptr->dst->flags & INMEMORY) {
828 if (var->flags & INMEMORY) {
829 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
832 panic("LLOAD: longs have to be in memory");
836 panic("LLOAD: longs have to be in memory");
840 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
841 /* op1 = local variable */
842 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
843 /* EAX: NO ECX: NO EDX: NO */
845 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
846 if ((iptr->dst->varkind == LOCALVAR) &&
847 (iptr->dst->varnum == iptr->op1)) {
850 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
851 if (var->flags & INMEMORY) {
852 i386_flds_membase(cd, REG_SP, var->regoff * 8);
855 i386_fld_reg(cd, var->regoff + fpu_st_offset);
858 store_reg_to_var_flt(iptr->dst, d);
861 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
862 /* op1 = local variable */
863 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
864 /* EAX: NO ECX: NO EDX: NO */
866 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
867 if ((iptr->dst->varkind == LOCALVAR) &&
868 (iptr->dst->varnum == iptr->op1)) {
871 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
872 if (var->flags & INMEMORY) {
873 i386_fldl_membase(cd, REG_SP, var->regoff * 8);
876 i386_fld_reg(cd, var->regoff + fpu_st_offset);
879 store_reg_to_var_flt(iptr->dst, d);
882 case ICMD_ISTORE: /* ..., value ==> ... */
883 case ICMD_ASTORE: /* op1 = local variable */
884 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
885 /* EAX: YES ECX: NO EDX: NO */
887 if ((src->varkind == LOCALVAR) &&
888 (src->varnum == iptr->op1)) {
891 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
892 if (var->flags & INMEMORY) {
893 if (src->flags & INMEMORY) {
894 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
895 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
898 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 8);
902 var_to_reg_int(s1, src, var->regoff);
903 M_INTMOVE(s1, var->regoff);
907 case ICMD_LSTORE: /* ..., value ==> ... */
908 /* op1 = local variable */
909 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
910 /* EAX: NO ECX: NO EDX: NO */
912 if ((src->varkind == LOCALVAR) &&
913 (src->varnum == iptr->op1)) {
916 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
917 if (var->flags & INMEMORY) {
918 if (src->flags & INMEMORY) {
919 M_LNGMEMMOVE(src->regoff, var->regoff);
922 panic("LSTORE: longs have to be in memory");
926 panic("LSTORE: longs have to be in memory");
930 case ICMD_FSTORE: /* ..., value ==> ... */
931 /* op1 = local variable */
932 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
933 /* EAX: NO ECX: NO EDX: NO */
935 if ((src->varkind == LOCALVAR) &&
936 (src->varnum == iptr->op1)) {
939 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
940 if (var->flags & INMEMORY) {
941 var_to_reg_flt(s1, src, REG_FTMP1);
942 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
945 var_to_reg_flt(s1, src, var->regoff);
946 /* M_FLTMOVE(s1, var->regoff); */
947 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
952 case ICMD_DSTORE: /* ..., value ==> ... */
953 /* op1 = local variable */
954 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
955 /* EAX: NO ECX: NO EDX: NO */
957 if ((src->varkind == LOCALVAR) &&
958 (src->varnum == iptr->op1)) {
961 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
962 if (var->flags & INMEMORY) {
963 var_to_reg_flt(s1, src, REG_FTMP1);
964 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
967 var_to_reg_flt(s1, src, var->regoff);
968 /* M_FLTMOVE(s1, var->regoff); */
969 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
975 /* pop/dup/swap operations ********************************************/
977 /* attention: double and longs are only one entry in CACAO ICMDs */
979 case ICMD_POP: /* ..., value ==> ... */
980 case ICMD_POP2: /* ..., value, value ==> ... */
981 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
982 /* EAX: NO ECX: NO EDX: NO */
985 case ICMD_DUP: /* ..., a ==> ..., a, a */
986 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
987 /* EAX: YES ECX: NO EDX: NO */
988 M_COPY(src, iptr->dst);
991 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
992 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
993 /* EAX: YES ECX: NO EDX: NO */
995 M_COPY(src, iptr->dst);
996 M_COPY(src->prev, iptr->dst->prev);
999 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
1000 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1001 /* EAX: YES ECX: NO EDX: NO */
1003 M_COPY(src, iptr->dst);
1004 M_COPY(src->prev, iptr->dst->prev);
1005 M_COPY(iptr->dst, iptr->dst->prev->prev);
1008 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
1010 M_COPY(src, iptr->dst);
1011 M_COPY(src->prev, iptr->dst->prev);
1012 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1013 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
1016 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
1017 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1018 /* EAX: YES ECX: NO EDX: NO */
1020 M_COPY(src, iptr->dst);
1021 M_COPY(src->prev, iptr->dst->prev);
1022 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1023 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
1024 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev);
1027 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
1028 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1029 /* EAX: YES ECX: NO EDX: NO */
1031 M_COPY(src, iptr->dst);
1032 M_COPY(src->prev, iptr->dst->prev);
1033 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1034 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
1035 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
1036 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
1039 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1040 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1041 /* EAX: YES ECX: NO EDX: NO */
1043 M_COPY(src, iptr->dst->prev);
1044 M_COPY(src->prev, iptr->dst);
1048 /* integer operations *************************************************/
1050 case ICMD_INEG: /* ..., value ==> ..., - value */
1051 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1052 /* EAX: YES ECX: NO EDX: NO */
1054 d = reg_of_var(rd, iptr->dst, REG_NULL);
1055 if (iptr->dst->flags & INMEMORY) {
1056 if (src->flags & INMEMORY) {
1057 if (src->regoff == iptr->dst->regoff) {
1058 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1061 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1062 i386_neg_reg(cd, REG_ITMP1);
1063 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1067 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1068 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1072 if (src->flags & INMEMORY) {
1073 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1074 i386_neg_reg(cd, iptr->dst->regoff);
1077 M_INTMOVE(src->regoff, iptr->dst->regoff);
1078 i386_neg_reg(cd, iptr->dst->regoff);
1083 case ICMD_LNEG: /* ..., value ==> ..., - value */
1084 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1085 /* EAX: YES ECX: NO EDX: NO */
1087 d = reg_of_var(rd, iptr->dst, REG_NULL);
1088 if (iptr->dst->flags & INMEMORY) {
1089 if (src->flags & INMEMORY) {
1090 if (src->regoff == iptr->dst->regoff) {
1091 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1092 i386_alu_imm_membase(cd, I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1093 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8 + 4);
1096 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1097 i386_neg_reg(cd, REG_ITMP1);
1098 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1099 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1100 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP1);
1101 i386_neg_reg(cd, REG_ITMP1);
1102 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1108 case ICMD_I2L: /* ..., value ==> ..., value */
1109 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1110 /* EAX: YES ECX: NO EDX: YES */
1112 d = reg_of_var(rd, iptr->dst, REG_NULL);
1113 if (iptr->dst->flags & INMEMORY) {
1114 if (src->flags & INMEMORY) {
1115 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, EAX);
1117 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1118 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1121 M_INTMOVE(src->regoff, EAX);
1123 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1124 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1129 case ICMD_L2I: /* ..., value ==> ..., value */
1130 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1131 /* EAX: YES ECX: NO EDX: NO */
1133 d = reg_of_var(rd, iptr->dst, REG_NULL);
1134 if (iptr->dst->flags & INMEMORY) {
1135 if (src->flags & INMEMORY) {
1136 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1137 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1141 if (src->flags & INMEMORY) {
1142 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1147 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1148 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1149 /* EAX: YES ECX: NO EDX: NO */
1151 d = reg_of_var(rd, iptr->dst, REG_NULL);
1152 if (iptr->dst->flags & INMEMORY) {
1153 if (src->flags & INMEMORY) {
1154 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1155 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1156 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1157 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1160 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1161 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1162 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1166 if (src->flags & INMEMORY) {
1167 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1168 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1169 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1172 M_INTMOVE(src->regoff, iptr->dst->regoff);
1173 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1174 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1179 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1180 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1181 /* EAX: YES ECX: NO EDX: NO */
1183 d = reg_of_var(rd, iptr->dst, REG_NULL);
1184 if (iptr->dst->flags & INMEMORY) {
1185 if (src->flags & INMEMORY) {
1186 if (src->regoff == iptr->dst->regoff) {
1187 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1190 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1191 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, REG_ITMP1);
1192 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1196 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1197 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1201 if (src->flags & INMEMORY) {
1202 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1203 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1206 M_INTMOVE(src->regoff, iptr->dst->regoff);
1207 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1212 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1213 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1214 /* EAX: YES ECX: NO EDX: NO */
1216 d = reg_of_var(rd, iptr->dst, REG_NULL);
1217 if (iptr->dst->flags & INMEMORY) {
1218 if (src->flags & INMEMORY) {
1219 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1220 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1221 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1222 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1225 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1226 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1227 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1231 if (src->flags & INMEMORY) {
1232 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1233 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1234 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1237 M_INTMOVE(src->regoff, iptr->dst->regoff);
1238 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1239 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1245 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1246 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1247 /* EAX: S|YES ECX: NO EDX: NO */
1249 d = reg_of_var(rd, iptr->dst, REG_NULL);
1250 i386_emit_ialu(cd, I386_ADD, src, iptr);
1253 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1254 /* val.i = constant */
1255 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1256 /* EAX: NO ECX: NO EDX: NO */
1258 d = reg_of_var(rd, iptr->dst, REG_NULL);
1259 i386_emit_ialuconst(cd, I386_ADD, src, iptr);
1262 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1263 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1264 /* EAX: S|YES ECX: NO EDX: NO */
1266 d = reg_of_var(rd, iptr->dst, REG_NULL);
1267 if (iptr->dst->flags & INMEMORY) {
1268 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1269 if (src->regoff == iptr->dst->regoff) {
1270 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1271 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1272 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1273 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1275 } else if (src->prev->regoff == iptr->dst->regoff) {
1276 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1277 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1278 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1279 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1282 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1283 i386_alu_membase_reg(cd, I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1284 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1285 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1286 i386_alu_membase_reg(cd, I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1287 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1294 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1295 /* val.l = constant */
1296 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1297 /* EAX: NO ECX: NO EDX: NO */
1298 /* else path can never happen? longs stay in memory! */
1300 d = reg_of_var(rd, iptr->dst, REG_NULL);
1301 if (iptr->dst->flags & INMEMORY) {
1302 if (src->flags & INMEMORY) {
1303 if (src->regoff == iptr->dst->regoff) {
1304 i386_alu_imm_membase(cd, I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1305 i386_alu_imm_membase(cd, I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1308 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1309 i386_alu_imm_reg(cd, I386_ADD, iptr->val.l, REG_ITMP1);
1310 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1311 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1312 i386_alu_imm_reg(cd, I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1313 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1319 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1320 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1321 /* EAX: S|YES ECX: NO EDX: NO */
1323 d = reg_of_var(rd, iptr->dst, REG_NULL);
1324 if (iptr->dst->flags & INMEMORY) {
1325 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1326 if (src->prev->regoff == iptr->dst->regoff) {
1327 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1328 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1331 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1332 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1333 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1336 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1337 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1338 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1339 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1341 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1342 if (src->prev->regoff == iptr->dst->regoff) {
1343 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1346 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1347 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1348 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1352 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1353 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1357 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1358 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1359 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1361 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1362 M_INTMOVE(src->prev->regoff, d);
1363 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1365 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1366 /* workaround for reg alloc */
1367 if (src->regoff == iptr->dst->regoff) {
1368 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1369 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1370 M_INTMOVE(REG_ITMP1, d);
1373 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1374 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1378 /* workaround for reg alloc */
1379 if (src->regoff == iptr->dst->regoff) {
1380 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1381 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1382 M_INTMOVE(REG_ITMP1, d);
1385 M_INTMOVE(src->prev->regoff, d);
1386 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1392 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1393 /* val.i = constant */
1394 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1395 /* EAX: NO ECX: NO EDX: NO */
1397 d = reg_of_var(rd, iptr->dst, REG_NULL);
1398 i386_emit_ialuconst(cd, I386_SUB, src, iptr);
1401 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1402 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1403 /* EAX: S|YES ECX: NO EDX: NO */
1405 d = reg_of_var(rd, iptr->dst, REG_NULL);
1406 if (iptr->dst->flags & INMEMORY) {
1407 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1408 if (src->prev->regoff == iptr->dst->regoff) {
1409 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1410 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1411 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1412 i386_alu_reg_membase(cd, I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1415 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1416 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1417 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1418 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1419 i386_alu_membase_reg(cd, I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1420 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1426 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1427 /* val.l = constant */
1428 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1429 /* EAX: NO ECX: NO EDX: NO */
1430 /* else path can never happen? longs stay in memory! */
1432 d = reg_of_var(rd, iptr->dst, REG_NULL);
1433 if (iptr->dst->flags & INMEMORY) {
1434 if (src->flags & INMEMORY) {
1435 if (src->regoff == iptr->dst->regoff) {
1436 i386_alu_imm_membase(cd, I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1437 i386_alu_imm_membase(cd, I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1440 /* TODO: could be size optimized with lea -- see gcc output */
1441 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1442 i386_alu_imm_reg(cd, I386_SUB, iptr->val.l, REG_ITMP1);
1443 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1444 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1445 i386_alu_imm_reg(cd, I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1446 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1452 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1453 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1454 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1456 d = reg_of_var(rd, iptr->dst, REG_NULL);
1457 if (iptr->dst->flags & INMEMORY) {
1458 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1459 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1460 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1461 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1463 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1464 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1465 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1466 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1468 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1469 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1470 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1471 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1474 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1475 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1476 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1480 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1481 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1482 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1484 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1485 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1486 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1488 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1489 M_INTMOVE(src->regoff, iptr->dst->regoff);
1490 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1493 if (src->regoff == iptr->dst->regoff) {
1494 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1497 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1498 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1504 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1505 /* val.i = constant */
1506 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1507 /* EAX: YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1509 d = reg_of_var(rd, iptr->dst, REG_NULL);
1510 if (iptr->dst->flags & INMEMORY) {
1511 if (src->flags & INMEMORY) {
1512 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1513 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1516 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1517 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1521 if (src->flags & INMEMORY) {
1522 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1525 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1530 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1531 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1532 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1534 d = reg_of_var(rd, iptr->dst, REG_NULL);
1535 if (iptr->dst->flags & INMEMORY) {
1536 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1537 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX); /* mem -> EAX */
1538 /* optimize move EAX -> REG_ITMP3 is slower??? */
1539 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1540 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1542 /* TODO: optimize move EAX -> REG_ITMP3 */
1543 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); /* mem -> ITMP3 */
1544 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1545 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1547 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP2); /* mem -> ITMP3 */
1548 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1550 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1551 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1552 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1557 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1558 /* val.l = constant */
1559 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1560 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1562 d = reg_of_var(rd, iptr->dst, REG_NULL);
1563 if (iptr->dst->flags & INMEMORY) {
1564 if (src->flags & INMEMORY) {
1565 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1566 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1567 /* TODO: optimize move EAX -> REG_ITMP3 */
1568 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1569 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1571 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1572 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1573 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1575 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1576 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1577 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1582 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1583 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1584 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX*/ /* Really uses EDX? */
1586 d = reg_of_var(rd, iptr->dst, REG_NULL);
1587 var_to_reg_int(s1, src, REG_ITMP2);
1589 if (src->prev->flags & INMEMORY) {
1590 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1593 M_INTMOVE(src->prev->regoff, EAX);
1596 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1597 i386_jcc(cd, I386_CC_NE, 3 + 6);
1598 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1599 i386_jcc(cd, I386_CC_E, 1 + 2);
1602 i386_idiv_reg(cd, s1);
1604 if (iptr->dst->flags & INMEMORY) {
1605 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1608 M_INTMOVE(EAX, iptr->dst->regoff);
1612 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1613 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1614 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EDX*/
1617 d = reg_of_var(rd, iptr->dst, REG_NULL);
1618 var_to_reg_int(s1, src, REG_ITMP2);
1620 if (src->prev->flags & INMEMORY) {
1621 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1624 M_INTMOVE(src->prev->regoff, EAX);
1627 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1628 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1629 i386_alu_reg_reg(cd, I386_XOR, EDX, EDX);
1630 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1631 i386_jcc(cd, I386_CC_E, 1 + 2);
1634 i386_idiv_reg(cd, s1);
1636 if (iptr->dst->flags & INMEMORY) {
1637 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8);
1640 M_INTMOVE(EDX, iptr->dst->regoff);
1644 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1645 /* val.i = constant */
1646 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1647 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1649 /* TODO: optimize for `/ 2' */
1650 var_to_reg_int(s1, src, REG_ITMP1);
1651 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1654 i386_test_reg_reg(cd, d, d);
1656 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1657 i386_jcc(cd, I386_CC_NS, a);
1658 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, d);
1660 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1661 store_reg_to_var_int(iptr->dst, d);
1664 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1665 /* val.i = constant */
1666 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1667 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1669 d = reg_of_var(rd, iptr->dst, REG_NULL);
1670 if (iptr->dst->flags & INMEMORY) {
1671 if (src->flags & INMEMORY) {
1673 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1675 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1676 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1678 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1679 i386_jcc(cd, I386_CC_NS, a);
1680 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1681 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1682 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1683 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1685 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1686 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1691 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1692 /* val.i = constant */
1693 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1694 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1696 var_to_reg_int(s1, src, REG_ITMP1);
1697 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1699 M_INTMOVE(s1, REG_ITMP1);
1706 CALCIMMEDIATEBYTES(a, iptr->val.i);
1709 /* TODO: optimize */
1711 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1712 i386_test_reg_reg(cd, s1, s1);
1713 i386_jcc(cd, I386_CC_GE, a);
1714 i386_mov_reg_reg(cd, s1, d);
1715 i386_neg_reg(cd, d);
1716 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1717 i386_neg_reg(cd, d);
1719 /* M_INTMOVE(s1, EAX); */
1720 /* i386_cltd(cd); */
1721 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1722 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1723 /* i386_alu_reg_reg(cd, I386_AND, iptr->val.i, EAX); */
1724 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1725 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1726 /* M_INTMOVE(EAX, d); */
1728 /* i386_alu_reg_reg(cd, I386_XOR, d, d); */
1729 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1730 /* i386_shrd_reg_reg(cd, s1, d); */
1731 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1733 store_reg_to_var_int(iptr->dst, d);
1736 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1737 /* val.l = constant */
1738 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1739 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1741 d = reg_of_var(rd, iptr->dst, REG_NULL);
1742 if (iptr->dst->flags & INMEMORY) {
1743 if (src->flags & INMEMORY) {
1744 /* Intel algorithm -- does not work, because constant is wrong */
1745 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1); */
1746 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1748 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1749 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1750 /* i386_jcc(cd, I386_CC_NS, offset); */
1751 /* i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1752 /* i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP3); */
1754 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1755 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1756 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1758 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1760 /* i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1); */
1761 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1762 /* i386_alu_reg_reg(cd, I386_SBB, REG_ITMP3, REG_ITMP2); */
1764 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1765 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1767 /* Alpha algorithm */
1769 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1771 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1777 /* TODO: hmm, don't know if this is always correct */
1779 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1781 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1787 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1788 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1790 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1791 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1792 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1793 i386_jcc(cd, I386_CC_GE, a);
1795 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1796 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1798 i386_neg_reg(cd, REG_ITMP1);
1799 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1800 i386_neg_reg(cd, REG_ITMP2);
1802 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1803 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1805 i386_neg_reg(cd, REG_ITMP1);
1806 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1807 i386_neg_reg(cd, REG_ITMP2);
1809 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1810 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1815 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1816 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1817 /* EAX: YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
1819 d = reg_of_var(rd, iptr->dst, REG_NULL);
1820 i386_emit_ishift(cd, I386_SHL, src, iptr);
1823 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1824 /* val.i = constant */
1825 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1826 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1828 d = reg_of_var(rd, iptr->dst, REG_NULL);
1829 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1832 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1833 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1834 /* EAX: YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
1836 d = reg_of_var(rd, iptr->dst, REG_NULL);
1837 i386_emit_ishift(cd, I386_SAR, src, iptr);
1840 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1841 /* val.i = constant */
1842 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1843 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1845 d = reg_of_var(rd, iptr->dst, REG_NULL);
1846 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1849 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1850 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1851 /* EAX: YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
1853 d = reg_of_var(rd, iptr->dst, REG_NULL);
1854 i386_emit_ishift(cd, I386_SHR, src, iptr);
1857 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1858 /* val.i = constant */
1859 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1860 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1862 d = reg_of_var(rd, iptr->dst, REG_NULL);
1863 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1866 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1867 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1868 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
1870 d = reg_of_var(rd, iptr->dst, REG_NULL);
1871 if (iptr->dst->flags & INMEMORY ){
1872 if (src->prev->flags & INMEMORY) {
1873 /* if (src->prev->regoff == iptr->dst->regoff) { */
1874 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1876 /* if (src->flags & INMEMORY) { */
1877 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1879 /* M_INTMOVE(src->regoff, ECX); */
1882 /* i386_test_imm_reg(cd, 32, ECX); */
1883 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1884 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1885 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1); */
1887 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1888 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1891 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1892 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1894 if (src->flags & INMEMORY) {
1895 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1897 M_INTMOVE(src->regoff, ECX);
1900 i386_test_imm_reg(cd, 32, ECX);
1901 i386_jcc(cd, I386_CC_E, 2 + 2);
1902 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1903 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1905 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1906 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1907 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1908 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1914 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1915 /* val.i = constant */
1916 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1917 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1919 d = reg_of_var(rd, iptr->dst, REG_NULL);
1920 if (iptr->dst->flags & INMEMORY ) {
1921 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1922 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1924 if (iptr->val.i & 0x20) {
1925 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1926 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1927 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1930 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1931 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1934 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1935 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1939 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1940 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1941 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
1943 d = reg_of_var(rd, iptr->dst, REG_NULL);
1944 if (iptr->dst->flags & INMEMORY ){
1945 if (src->prev->flags & INMEMORY) {
1946 /* if (src->prev->regoff == iptr->dst->regoff) { */
1947 /* TODO: optimize */
1948 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1949 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1951 /* if (src->flags & INMEMORY) { */
1952 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1954 /* M_INTMOVE(src->regoff, ECX); */
1957 /* i386_test_imm_reg(cd, 32, ECX); */
1958 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1959 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1960 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1962 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1963 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1964 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1965 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1968 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1969 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1971 if (src->flags & INMEMORY) {
1972 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1974 M_INTMOVE(src->regoff, ECX);
1977 i386_test_imm_reg(cd, 32, ECX);
1978 i386_jcc(cd, I386_CC_E, 2 + 3);
1979 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1980 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1982 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1983 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1984 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1985 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1991 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1992 /* val.i = constant */
1993 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
1994 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1996 d = reg_of_var(rd, iptr->dst, REG_NULL);
1997 if (iptr->dst->flags & INMEMORY ) {
1998 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1999 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2001 if (iptr->val.i & 0x20) {
2002 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2003 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
2004 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2007 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2008 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
2011 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2012 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2016 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
2017 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2018 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
2020 d = reg_of_var(rd, iptr->dst, REG_NULL);
2021 if (iptr->dst->flags & INMEMORY ){
2022 if (src->prev->flags & INMEMORY) {
2023 /* if (src->prev->regoff == iptr->dst->regoff) { */
2024 /* TODO: optimize */
2025 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
2026 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
2028 /* if (src->flags & INMEMORY) { */
2029 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
2031 /* M_INTMOVE(src->regoff, ECX); */
2034 /* i386_test_imm_reg(cd, 32, ECX); */
2035 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
2036 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2037 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2); */
2039 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2040 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
2041 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
2042 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
2045 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
2046 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
2048 if (src->flags & INMEMORY) {
2049 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
2051 M_INTMOVE(src->regoff, ECX);
2054 i386_test_imm_reg(cd, 32, ECX);
2055 i386_jcc(cd, I386_CC_E, 2 + 2);
2056 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2057 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP3, REG_ITMP3);
2059 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2060 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
2061 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2062 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2068 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
2069 /* val.l = constant */
2070 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2071 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
2073 d = reg_of_var(rd, iptr->dst, REG_NULL);
2074 if (iptr->dst->flags & INMEMORY ) {
2075 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
2076 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2078 if (iptr->val.i & 0x20) {
2079 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2080 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
2081 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2084 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2085 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
2088 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2089 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2093 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2094 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2095 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2097 d = reg_of_var(rd, iptr->dst, REG_NULL);
2098 i386_emit_ialu(cd, I386_AND, src, iptr);
2101 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
2102 /* val.i = constant */
2103 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2104 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2106 d = reg_of_var(rd, iptr->dst, REG_NULL);
2107 i386_emit_ialuconst(cd, I386_AND, src, iptr);
2110 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2111 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2112 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2114 d = reg_of_var(rd, iptr->dst, REG_NULL);
2115 i386_emit_lalu(cd, I386_AND, src, iptr);
2118 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
2119 /* val.l = constant */
2120 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2121 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2123 d = reg_of_var(rd, iptr->dst, REG_NULL);
2124 i386_emit_laluconst(cd, I386_AND, src, iptr);
2127 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2128 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2129 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2131 d = reg_of_var(rd, iptr->dst, REG_NULL);
2132 i386_emit_ialu(cd, I386_OR, src, iptr);
2135 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2136 /* val.i = constant */
2137 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2138 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2140 d = reg_of_var(rd, iptr->dst, REG_NULL);
2141 i386_emit_ialuconst(cd, I386_OR, src, iptr);
2144 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2145 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2146 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2148 d = reg_of_var(rd, iptr->dst, REG_NULL);
2149 i386_emit_lalu(cd, I386_OR, src, iptr);
2152 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2153 /* val.l = constant */
2154 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2155 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2157 d = reg_of_var(rd, iptr->dst, REG_NULL);
2158 i386_emit_laluconst(cd, I386_OR, src, iptr);
2161 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2162 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2163 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2165 d = reg_of_var(rd, iptr->dst, REG_NULL);
2166 i386_emit_ialu(cd, I386_XOR, src, iptr);
2169 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2170 /* val.i = constant */
2171 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2172 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2174 d = reg_of_var(rd, iptr->dst, REG_NULL);
2175 i386_emit_ialuconst(cd, I386_XOR, src, iptr);
2178 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2179 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2180 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2182 d = reg_of_var(rd, iptr->dst, REG_NULL);
2183 i386_emit_lalu(cd, I386_XOR, src, iptr);
2186 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2187 /* val.l = constant */
2188 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2189 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2191 d = reg_of_var(rd, iptr->dst, REG_NULL);
2192 i386_emit_laluconst(cd, I386_XOR, src, iptr);
2195 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2196 /* op1 = variable, val.i = constant */
2197 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2198 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2200 var = &(rd->locals[iptr->op1][TYPE_INT]);
2201 if (var->flags & INMEMORY) {
2202 i386_alu_imm_membase(cd, I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2205 /* `inc reg' is slower on p4's (regarding to ia32 */
2206 /* optimization reference manual and benchmarks) and as fast */
2208 i386_alu_imm_reg(cd, I386_ADD, iptr->val.i, var->regoff);
2213 /* floating operations ************************************************/
2215 #define ROUND_TO_SINGLE \
2216 i386_fstps_membase(cd, REG_SP, -8); \
2217 i386_flds_membase(cd, REG_SP, -8);
2219 #define ROUND_TO_DOUBLE \
2220 i386_fstpl_membase(cd, REG_SP, -8); \
2221 i386_fldl_membase(cd, REG_SP, -8);
2223 #define FPU_SET_24BIT_MODE \
2224 if (!fpu_in_24bit_mode) { \
2225 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2226 fpu_in_24bit_mode = 1; \
2229 #define FPU_SET_53BIT_MODE \
2230 if (fpu_in_24bit_mode) { \
2231 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2232 fpu_in_24bit_mode = 0; \
2235 #define ROUND_TO_SINGLE
2236 #define ROUND_TO_DOUBLE
2237 #define FPU_SET_24BIT_MODE
2238 #define FPU_SET_53BIT_MODE
2240 case ICMD_FNEG: /* ..., value ==> ..., - value */
2241 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2242 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2245 var_to_reg_flt(s1, src, REG_FTMP1);
2246 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2248 store_reg_to_var_flt(iptr->dst, d);
2251 case ICMD_DNEG: /* ..., value ==> ..., - value */
2252 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2253 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2256 var_to_reg_flt(s1, src, REG_FTMP1);
2257 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2259 store_reg_to_var_flt(iptr->dst, d);
2262 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2263 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2264 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2267 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2268 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2269 var_to_reg_flt(s2, src, REG_FTMP2);
2272 store_reg_to_var_flt(iptr->dst, d);
2275 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2276 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2277 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2280 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2281 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2282 var_to_reg_flt(s2, src, REG_FTMP2);
2285 store_reg_to_var_flt(iptr->dst, d);
2288 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2289 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2290 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2293 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2294 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2295 var_to_reg_flt(s2, src, REG_FTMP2);
2298 store_reg_to_var_flt(iptr->dst, d);
2301 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2302 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2303 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2306 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2307 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2308 var_to_reg_flt(s2, src, REG_FTMP2);
2311 store_reg_to_var_flt(iptr->dst, d);
2314 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2315 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2316 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2319 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2320 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2321 var_to_reg_flt(s2, src, REG_FTMP2);
2325 store_reg_to_var_flt(iptr->dst, d);
2328 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2329 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2330 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2333 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2334 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2336 /* i386_fldt_mem(cd, subnormal_bias1); */
2337 /* i386_fmulp(cd); */
2339 var_to_reg_flt(s2, src, REG_FTMP2);
2344 /* i386_fldt_mem(cd, subnormal_bias2); */
2345 /* i386_fmulp(cd); */
2347 store_reg_to_var_flt(iptr->dst, d);
2350 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2351 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2352 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2355 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2356 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2357 var_to_reg_flt(s2, src, REG_FTMP2);
2361 store_reg_to_var_flt(iptr->dst, d);
2364 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2365 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2366 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2369 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2370 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2372 /* i386_fldt_mem(cd, subnormal_bias1); */
2373 /* i386_fmulp(cd); */
2375 var_to_reg_flt(s2, src, REG_FTMP2);
2380 /* i386_fldt_mem(cd, subnormal_bias2); */
2381 /* i386_fmulp(cd); */
2383 store_reg_to_var_flt(iptr->dst, d);
2386 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2387 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2388 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2391 /* exchanged to skip fxch */
2392 var_to_reg_flt(s2, src, REG_FTMP2);
2393 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2394 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2395 /* i386_fxch(cd); */
2400 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2401 store_reg_to_var_flt(iptr->dst, d);
2402 i386_ffree_reg(cd, 0);
2407 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2408 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2409 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2412 /* exchanged to skip fxch */
2413 var_to_reg_flt(s2, src, REG_FTMP2);
2414 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2415 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2416 /* i386_fxch(cd); */
2421 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2422 store_reg_to_var_flt(iptr->dst, d);
2423 i386_ffree_reg(cd, 0);
2428 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2429 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2430 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2431 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2433 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2434 if (src->flags & INMEMORY) {
2435 i386_fildl_membase(cd, REG_SP, src->regoff * 8);
2439 a = dseg_adds4(cd, 0);
2440 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2441 dseg_adddata(cd, cd->mcodeptr);
2442 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, a);
2443 i386_fildl_membase(cd, REG_ITMP1, a);
2446 store_reg_to_var_flt(iptr->dst, d);
2449 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2450 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2451 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2452 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2454 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2455 if (src->flags & INMEMORY) {
2456 i386_fildll_membase(cd, REG_SP, src->regoff * 8);
2460 panic("L2F: longs have to be in memory");
2462 store_reg_to_var_flt(iptr->dst, d);
2465 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2466 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2467 /* EAX: YES ECX: NO EDX: NO OUTPUT: EAX*/
2469 var_to_reg_flt(s1, src, REG_FTMP1);
2470 d = reg_of_var(rd, iptr->dst, REG_NULL);
2472 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2473 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2474 dseg_adddata(cd, cd->mcodeptr);
2475 i386_fldcw_membase(cd, REG_ITMP1, a);
2477 if (iptr->dst->flags & INMEMORY) {
2478 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2481 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2482 i386_fldcw_membase(cd, REG_ITMP1, a);
2484 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2487 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2489 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2492 a = dseg_adds4(cd, 0);
2493 i386_fistpl_membase(cd, REG_ITMP1, a);
2495 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2497 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2498 i386_fldcw_membase(cd, REG_ITMP1, a);
2500 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2503 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2504 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2507 i386_jcc(cd, I386_CC_NE, a);
2509 /* XXX: change this when we use registers */
2510 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2511 i386_mov_imm_reg(cd, (s4) asm_builtin_f2i, REG_ITMP1);
2512 i386_call_reg(cd, REG_ITMP1);
2514 if (iptr->dst->flags & INMEMORY) {
2515 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2518 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2522 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2523 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2524 /* EAX: YES ECX: NO EDX: NO OUTPUT: EAX*/
2526 var_to_reg_flt(s1, src, REG_FTMP1);
2527 d = reg_of_var(rd, iptr->dst, REG_NULL);
2529 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2530 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2531 dseg_adddata(cd, cd->mcodeptr);
2532 i386_fldcw_membase(cd, REG_ITMP1, a);
2534 if (iptr->dst->flags & INMEMORY) {
2535 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2538 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2539 i386_fldcw_membase(cd, REG_ITMP1, a);
2541 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2544 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2546 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2549 a = dseg_adds4(cd, 0);
2550 i386_fistpl_membase(cd, REG_ITMP1, a);
2552 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2554 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2555 i386_fldcw_membase(cd, REG_ITMP1, a);
2557 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2560 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2561 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2564 i386_jcc(cd, I386_CC_NE, a);
2566 /* XXX: change this when we use registers */
2567 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2568 i386_mov_imm_reg(cd, (s4) asm_builtin_d2i, REG_ITMP1);
2569 i386_call_reg(cd, REG_ITMP1);
2571 if (iptr->dst->flags & INMEMORY) {
2572 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2574 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2578 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2579 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2580 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2582 var_to_reg_flt(s1, src, REG_FTMP1);
2583 d = reg_of_var(rd, iptr->dst, REG_NULL);
2585 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2586 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2587 dseg_adddata(cd, cd->mcodeptr);
2588 i386_fldcw_membase(cd, REG_ITMP1, a);
2590 if (iptr->dst->flags & INMEMORY) {
2591 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2594 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2595 i386_fldcw_membase(cd, REG_ITMP1, a);
2597 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2600 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2602 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2605 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2607 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2609 i386_jcc(cd, I386_CC_NE, a);
2611 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2614 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2616 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2618 i386_jcc(cd, I386_CC_NE, a);
2620 /* XXX: change this when we use registers */
2621 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2622 i386_mov_imm_reg(cd, (s4) asm_builtin_f2l, REG_ITMP1);
2623 i386_call_reg(cd, REG_ITMP1);
2624 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2625 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2628 panic("F2L: longs have to be in memory");
2632 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2633 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2634 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2636 var_to_reg_flt(s1, src, REG_FTMP1);
2637 d = reg_of_var(rd, iptr->dst, REG_NULL);
2639 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2640 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2641 dseg_adddata(cd, cd->mcodeptr);
2642 i386_fldcw_membase(cd, REG_ITMP1, a);
2644 if (iptr->dst->flags & INMEMORY) {
2645 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2648 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2649 i386_fldcw_membase(cd, REG_ITMP1, a);
2651 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2654 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2656 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2659 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2661 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2663 i386_jcc(cd, I386_CC_NE, a);
2665 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2668 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2670 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2672 i386_jcc(cd, I386_CC_NE, a);
2674 /* XXX: change this when we use registers */
2675 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2676 i386_mov_imm_reg(cd, (s4) asm_builtin_d2l, REG_ITMP1);
2677 i386_call_reg(cd, REG_ITMP1);
2678 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2679 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2682 panic("D2L: longs have to be in memory");
2686 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2687 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2688 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2690 var_to_reg_flt(s1, src, REG_FTMP1);
2691 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2693 store_reg_to_var_flt(iptr->dst, d);
2696 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2697 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2698 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2700 var_to_reg_flt(s1, src, REG_FTMP1);
2701 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2703 store_reg_to_var_flt(iptr->dst, d);
2706 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2708 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2709 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2711 /* exchanged to skip fxch */
2712 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2713 var_to_reg_flt(s1, src, REG_FTMP2);
2714 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2715 /* i386_fxch(cd); */
2719 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2720 i386_jcc(cd, I386_CC_E, 6);
2721 i386_alu_imm_reg(cd, I386_AND, 0x000000ff, EAX);
2723 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2724 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2725 i386_jcc(cd, I386_CC_B, 3 + 5);
2726 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2727 i386_jmp_imm(cd, 3);
2728 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2729 store_reg_to_var_int(iptr->dst, d);
2732 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2734 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2735 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2737 /* exchanged to skip fxch */
2738 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2739 var_to_reg_flt(s1, src, REG_FTMP2);
2740 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2741 /* i386_fxch(cd); */
2745 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2746 i386_jcc(cd, I386_CC_E, 3);
2747 i386_movb_imm_reg(cd, 1, I386_AH);
2749 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2750 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2751 i386_jcc(cd, I386_CC_B, 3 + 5);
2752 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2753 i386_jmp_imm(cd, 3);
2754 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2755 store_reg_to_var_int(iptr->dst, d);
2759 /* memory operations **************************************************/
2761 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2762 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2763 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2765 var_to_reg_int(s1, src, REG_ITMP1);
2766 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2767 gen_nullptr_check(s1);
2768 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2769 store_reg_to_var_int(iptr->dst, d);
2772 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2773 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2774 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2776 var_to_reg_int(s1, src->prev, REG_ITMP1);
2777 var_to_reg_int(s2, src, REG_ITMP2);
2778 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2779 if (iptr->op1 == 0) {
2780 gen_nullptr_check(s1);
2783 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2784 store_reg_to_var_int(iptr->dst, d);
2787 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2788 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2789 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2791 var_to_reg_int(s1, src->prev, REG_ITMP1);
2792 var_to_reg_int(s2, src, REG_ITMP2);
2793 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2794 if (iptr->op1 == 0) {
2795 gen_nullptr_check(s1);
2799 if (iptr->dst->flags & INMEMORY) {
2800 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2801 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2802 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2803 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2807 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2808 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2809 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2811 var_to_reg_int(s1, src->prev, REG_ITMP1);
2812 var_to_reg_int(s2, src, REG_ITMP2);
2813 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2814 if (iptr->op1 == 0) {
2815 gen_nullptr_check(s1);
2818 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2819 store_reg_to_var_int(iptr->dst, d);
2822 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2823 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2824 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2826 var_to_reg_int(s1, src->prev, REG_ITMP1);
2827 var_to_reg_int(s2, src, REG_ITMP2);
2828 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2829 if (iptr->op1 == 0) {
2830 gen_nullptr_check(s1);
2833 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2835 store_reg_to_var_flt(iptr->dst, d);
2838 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2839 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2840 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2842 var_to_reg_int(s1, src->prev, REG_ITMP1);
2843 var_to_reg_int(s2, src, REG_ITMP2);
2844 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2845 if (iptr->op1 == 0) {
2846 gen_nullptr_check(s1);
2849 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2851 store_reg_to_var_flt(iptr->dst, d);
2854 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2855 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2856 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2858 var_to_reg_int(s1, src->prev, REG_ITMP1);
2859 var_to_reg_int(s2, src, REG_ITMP2);
2860 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2861 if (iptr->op1 == 0) {
2862 gen_nullptr_check(s1);
2865 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2866 store_reg_to_var_int(iptr->dst, d);
2869 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2870 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2871 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2873 var_to_reg_int(s1, src->prev, REG_ITMP1);
2874 var_to_reg_int(s2, src, REG_ITMP2);
2875 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2876 if (iptr->op1 == 0) {
2877 gen_nullptr_check(s1);
2880 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2881 store_reg_to_var_int(iptr->dst, d);
2884 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2885 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2886 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2888 var_to_reg_int(s1, src->prev, REG_ITMP1);
2889 var_to_reg_int(s2, src, REG_ITMP2);
2890 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2891 if (iptr->op1 == 0) {
2892 gen_nullptr_check(s1);
2895 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2896 store_reg_to_var_int(iptr->dst, d);
2900 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2901 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2902 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2904 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2905 var_to_reg_int(s2, src->prev, REG_ITMP2);
2906 if (iptr->op1 == 0) {
2907 gen_nullptr_check(s1);
2910 var_to_reg_int(s3, src, REG_ITMP3);
2911 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2914 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2915 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2916 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2918 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2919 var_to_reg_int(s2, src->prev, REG_ITMP2);
2920 if (iptr->op1 == 0) {
2921 gen_nullptr_check(s1);
2925 if (src->flags & INMEMORY) {
2926 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
2927 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2928 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2929 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2933 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2934 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2935 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2937 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2938 var_to_reg_int(s2, src->prev, REG_ITMP2);
2939 if (iptr->op1 == 0) {
2940 gen_nullptr_check(s1);
2943 var_to_reg_int(s3, src, REG_ITMP3);
2944 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2947 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2948 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2949 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2951 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2952 var_to_reg_int(s2, src->prev, REG_ITMP2);
2953 if (iptr->op1 == 0) {
2954 gen_nullptr_check(s1);
2957 var_to_reg_flt(s3, src, REG_FTMP1);
2958 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2962 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2963 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2964 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2966 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2967 var_to_reg_int(s2, src->prev, REG_ITMP2);
2968 if (iptr->op1 == 0) {
2969 gen_nullptr_check(s1);
2972 var_to_reg_flt(s3, src, REG_FTMP1);
2973 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2977 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2978 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2979 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2981 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2982 var_to_reg_int(s2, src->prev, REG_ITMP2);
2983 if (iptr->op1 == 0) {
2984 gen_nullptr_check(s1);
2987 var_to_reg_int(s3, src, REG_ITMP3);
2988 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2991 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2992 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
2993 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2995 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2996 var_to_reg_int(s2, src->prev, REG_ITMP2);
2997 if (iptr->op1 == 0) {
2998 gen_nullptr_check(s1);
3001 var_to_reg_int(s3, src, REG_ITMP3);
3002 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3005 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
3006 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3007 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3009 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3010 var_to_reg_int(s2, src->prev, REG_ITMP2);
3011 if (iptr->op1 == 0) {
3012 gen_nullptr_check(s1);
3015 var_to_reg_int(s3, src, REG_ITMP3);
3016 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
3017 M_INTMOVE(s3, REG_ITMP3);
3020 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3023 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
3024 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3025 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3027 var_to_reg_int(s1, src->prev, REG_ITMP1);
3028 var_to_reg_int(s2, src, REG_ITMP2);
3029 if (iptr->op1 == 0) {
3030 gen_nullptr_check(s1);
3033 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
3036 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
3037 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3038 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3040 var_to_reg_int(s1, src->prev, REG_ITMP1);
3041 var_to_reg_int(s2, src, REG_ITMP2);
3042 if (iptr->op1 == 0) {
3043 gen_nullptr_check(s1);
3047 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
3048 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
3051 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
3052 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3053 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3055 var_to_reg_int(s1, src->prev, REG_ITMP1);
3056 var_to_reg_int(s2, src, REG_ITMP2);
3057 if (iptr->op1 == 0) {
3058 gen_nullptr_check(s1);
3061 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3064 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
3065 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3066 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3068 var_to_reg_int(s1, src->prev, REG_ITMP1);
3069 var_to_reg_int(s2, src, REG_ITMP2);
3070 if (iptr->op1 == 0) {
3071 gen_nullptr_check(s1);
3074 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3077 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
3078 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3079 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3081 var_to_reg_int(s1, src->prev, REG_ITMP1);
3082 var_to_reg_int(s2, src, REG_ITMP2);
3083 if (iptr->op1 == 0) {
3084 gen_nullptr_check(s1);
3087 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
3090 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
3091 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3092 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3094 var_to_reg_int(s1, src->prev, REG_ITMP1);
3095 var_to_reg_int(s2, src, REG_ITMP2);
3096 if (iptr->op1 == 0) {
3097 gen_nullptr_check(s1);
3100 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3104 case ICMD_PUTSTATIC: /* ..., value ==> ... */
3105 /* op1 = type, val.a = field address */
3106 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3107 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3109 /* If the static fields' class is not yet initialized, we do it */
3110 /* now. The call code is generated later. */
3111 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
3112 codegen_addpatchref(cd, cd->mcodeptr, asm_check_clinit, ((fieldinfo *) iptr->val.a)->class);
3114 /* This is just for debugging purposes. Is very difficult to */
3115 /* read patched code. Here we patch the following 5 nop's */
3116 /* so that the real code keeps untouched. */
3117 if (showdisassemble) {
3126 a = (ptrint) &(((fieldinfo *) iptr->val.a)->value);
3127 switch (iptr->op1) {
3130 var_to_reg_int(s2, src, REG_ITMP1);
3131 i386_mov_reg_mem(cd, s2, a);
3134 if (src->flags & INMEMORY) {
3135 /* Using both REG_ITMP1 and REG_ITMP2 is faster than only */
3136 /* using REG_ITMP1 alternating. */
3138 i386_mov_membase_reg(cd, REG_SP, s2 * 8, REG_ITMP1);
3139 i386_mov_membase_reg(cd, REG_SP, s2 * 8 + 4, REG_ITMP2);
3140 i386_mov_reg_mem(cd, REG_ITMP1, a);
3141 i386_mov_reg_mem(cd, REG_ITMP2, a + 4);
3143 panic("PUTSTATIC: longs have to be in memory");
3147 var_to_reg_flt(s2, src, REG_FTMP1);
3148 i386_fstps_mem(cd, a);
3152 var_to_reg_flt(s2, src, REG_FTMP1);
3153 i386_fstpl_mem(cd, a);
3159 case ICMD_PUTSTATICCONST: /* ... ==> ... */
3160 /* val = value (in current instruction) */
3161 /* op1 = type, val.a = field address (in */
3162 /* following NOP) */
3163 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3164 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3166 /* If the static fields' class is not yet initialized, we do it */
3167 /* now. The call code is generated later. */
3168 if (!((fieldinfo *) iptr[1].val.a)->class->initialized) {
3169 codegen_addpatchref(cd, cd->mcodeptr, asm_check_clinit, ((fieldinfo *) iptr[1].val.a)->class);
3171 /* This is just for debugging purposes. Is very difficult to */
3172 /* read patched code. Here we patch the following 5 nop's */
3173 /* so that the real code keeps untouched. */
3174 if (showdisassemble) {
3183 a = (ptrint) &(((fieldinfo *) iptr[1].val.a)->value);
3184 switch (iptr[1].op1) {
3187 i386_mov_imm_mem(cd, iptr->val.i, a);
3190 i386_mov_imm_mem(cd, (ptrint) iptr->val.a, a);
3194 i386_mov_imm_mem(cd, iptr->val.l, a);
3195 i386_mov_imm_mem(cd, iptr->val.l >> 32, a + 4);
3200 case ICMD_GETSTATIC: /* ... ==> ..., value */
3201 /* op1 = type, val.a = field address */
3202 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3203 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX*/
3205 /* If the static fields' class is not yet initialized, we do it */
3206 /* now. The call code is generated later. */
3207 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
3208 codegen_addpatchref(cd, cd->mcodeptr, asm_check_clinit, ((fieldinfo *) iptr->val.a)->class);
3210 /* This is just for debugging purposes. Is very difficult to */
3211 /* read patched code. Here we patch the following 5 nop's */
3212 /* so that the real code keeps untouched. */
3213 if (showdisassemble) {
3222 a = (ptrint) &(((fieldinfo *) iptr->val.a)->value);
3223 switch (iptr->op1) {
3226 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
3227 i386_mov_mem_reg(cd, a, d);
3228 store_reg_to_var_int(iptr->dst, d);
3231 d = reg_of_var(rd, iptr->dst, REG_NULL);
3232 if (iptr->dst->flags & INMEMORY) {
3233 /* Using both REG_ITMP1 and REG_ITMP2 is faster than only */
3234 /* using REG_ITMP1 alternating. */
3235 i386_mov_mem_reg(cd, a, REG_ITMP1);
3236 i386_mov_mem_reg(cd, a + 4, REG_ITMP2);
3237 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
3238 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
3240 panic("GETSTATIC: longs have to be in memory");
3244 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3245 i386_flds_mem(cd, a);
3247 store_reg_to_var_flt(iptr->dst, d);
3250 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3251 i386_fldl_mem(cd, a);
3253 store_reg_to_var_flt(iptr->dst, d);
3258 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
3259 /* op1 = type, val.a = field address */
3260 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3261 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3263 a = ((fieldinfo *) (iptr->val.a))->offset;
3264 var_to_reg_int(s1, src->prev, REG_ITMP1);
3265 gen_nullptr_check(s1);
3266 switch (iptr->op1) {
3269 var_to_reg_int(s2, src, REG_ITMP2);
3270 i386_mov_reg_membase(cd, s2, s1, a);
3273 if (src->flags & INMEMORY) {
3274 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);
3275 i386_mov_reg_membase(cd, REG_ITMP2, s1, a);
3276 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3277 i386_mov_reg_membase(cd, REG_ITMP2, s1, a + 4);
3279 panic("PUTFIELD: longs have to be in memory");
3283 var_to_reg_flt(s2, src, REG_FTMP1);
3284 i386_fstps_membase(cd, s1, a);
3288 var_to_reg_flt(s2, src, REG_FTMP1);
3289 i386_fstpl_membase(cd, s1, a);
3295 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
3296 /* val = value (in current instruction) */
3297 /* op1 = type, val.a = field address (in */
3298 /* following NOP) */
3299 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3300 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
3302 a = ((fieldinfo *) (iptr[1].val.a))->offset;
3303 var_to_reg_int(s1, src, REG_ITMP1);
3304 gen_nullptr_check(s1);
3305 switch (iptr[1].op1) {
3308 i386_mov_imm_membase(cd, iptr->val.i, s1, a);
3311 i386_mov_imm_membase(cd, (ptrint) iptr->val.a, s1, a);
3315 i386_mov_imm_membase(cd, iptr->val.l, s1, a);
3316 i386_mov_imm_membase(cd, iptr->val.l >> 32, s1, a + 4);
3321 case ICMD_GETFIELD: /* .., objectref. ==> ..., value */
3322 /* op1 = type, val.i = field offset */
3323 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3324 /* EAX: YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3326 a = ((fieldinfo *) (iptr->val.a))->offset;
3327 var_to_reg_int(s1, src, REG_ITMP1);
3328 gen_nullptr_check(s1);
3329 switch (iptr->op1) {
3332 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3333 i386_mov_membase_reg(cd, s1, a, d);
3334 store_reg_to_var_int(iptr->dst, d);
3337 d = reg_of_var(rd, iptr->dst, REG_NULL);
3338 i386_mov_membase_reg(cd, s1, a, REG_ITMP2);
3339 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
3340 i386_mov_membase_reg(cd, s1, a + 4, REG_ITMP2);
3341 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
3344 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3345 i386_flds_membase(cd, s1, a);
3347 store_reg_to_var_flt(iptr->dst, d);
3350 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3351 i386_fldl_membase(cd, s1, a);
3353 store_reg_to_var_flt(iptr->dst, d);
3359 /* branch operations **************************************************/
3361 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3362 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3363 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3365 var_to_reg_int(s1, src, REG_ITMP1);
3366 M_INTMOVE(s1, REG_ITMP1_XPTR);
3368 i386_call_imm(cd, 0); /* passing exception pointer */
3369 i386_pop_reg(cd, REG_ITMP2_XPC);
3371 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
3372 i386_jmp_reg(cd, REG_ITMP3);
3376 case ICMD_GOTO: /* ... ==> ... */
3377 /* op1 = target JavaVM pc */
3378 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3379 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3381 i386_jmp_imm(cd, 0);
3382 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3386 case ICMD_JSR: /* ... ==> ... */
3387 /* op1 = target JavaVM pc */
3388 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3389 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3391 i386_call_imm(cd, 0);
3392 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3395 case ICMD_RET: /* ... ==> ... */
3396 /* op1 = local variable */
3397 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3398 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3400 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3401 var_to_reg_int(s1, var, REG_ITMP1);
3402 i386_jmp_reg(cd, s1);
3405 case ICMD_IFNULL: /* ..., value ==> ... */
3406 /* op1 = target JavaVM pc */
3407 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3408 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3410 if (src->flags & INMEMORY) {
3411 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3414 i386_test_reg_reg(cd, src->regoff, src->regoff);
3416 i386_jcc(cd, I386_CC_E, 0);
3417 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3420 case ICMD_IFNONNULL: /* ..., value ==> ... */
3421 /* op1 = target JavaVM pc */
3422 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3423 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3425 if (src->flags & INMEMORY) {
3426 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3429 i386_test_reg_reg(cd, src->regoff, src->regoff);
3431 i386_jcc(cd, I386_CC_NE, 0);
3432 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3435 case ICMD_IFEQ: /* ..., value ==> ... */
3436 /* op1 = target JavaVM pc, val.i = constant */
3437 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3438 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3440 if (src->flags & INMEMORY) {
3441 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3444 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3446 i386_jcc(cd, I386_CC_E, 0);
3447 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3450 case ICMD_IFLT: /* ..., value ==> ... */
3451 /* op1 = target JavaVM pc, val.i = constant */
3452 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3453 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3455 if (src->flags & INMEMORY) {
3456 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3459 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3461 i386_jcc(cd, I386_CC_L, 0);
3462 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3465 case ICMD_IFLE: /* ..., value ==> ... */
3466 /* op1 = target JavaVM pc, val.i = constant */
3467 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3468 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3470 if (src->flags & INMEMORY) {
3471 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3474 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3476 i386_jcc(cd, I386_CC_LE, 0);
3477 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3480 case ICMD_IFNE: /* ..., value ==> ... */
3481 /* op1 = target JavaVM pc, val.i = constant */
3482 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3483 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3485 if (src->flags & INMEMORY) {
3486 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3489 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3491 i386_jcc(cd, I386_CC_NE, 0);
3492 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3495 case ICMD_IFGT: /* ..., value ==> ... */
3496 /* op1 = target JavaVM pc, val.i = constant */
3497 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3498 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3500 if (src->flags & INMEMORY) {
3501 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3504 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3506 i386_jcc(cd, I386_CC_G, 0);
3507 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3510 case ICMD_IFGE: /* ..., value ==> ... */
3511 /* op1 = target JavaVM pc, val.i = constant */
3512 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3513 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3515 if (src->flags & INMEMORY) {
3516 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3519 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3521 i386_jcc(cd, I386_CC_GE, 0);
3522 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3525 case ICMD_IF_LEQ: /* ..., value ==> ... */
3526 /* op1 = target JavaVM pc, val.l = constant */
3527 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3528 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3530 if (src->flags & INMEMORY) {
3531 if (iptr->val.l == 0) {
3532 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3533 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3536 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3537 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3538 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3539 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l, REG_ITMP1);
3540 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3543 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3544 i386_jcc(cd, I386_CC_E, 0);
3545 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3548 case ICMD_IF_LLT: /* ..., value ==> ... */
3549 /* op1 = target JavaVM pc, val.l = constant */
3550 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3551 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3553 if (src->flags & INMEMORY) {
3554 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3555 i386_jcc(cd, I386_CC_L, 0);
3556 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3559 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3560 CALCIMMEDIATEBYTES(a, iptr->val.l);
3562 i386_jcc(cd, I386_CC_G, a);
3564 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3565 i386_jcc(cd, I386_CC_B, 0);
3566 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3570 case ICMD_IF_LLE: /* ..., value ==> ... */
3571 /* op1 = target JavaVM pc, val.l = constant */
3572 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3573 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3575 if (src->flags & INMEMORY) {
3576 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3577 i386_jcc(cd, I386_CC_L, 0);
3578 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3581 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3582 CALCIMMEDIATEBYTES(a, iptr->val.l);
3584 i386_jcc(cd, I386_CC_G, a);
3586 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3587 i386_jcc(cd, I386_CC_BE, 0);
3588 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3592 case ICMD_IF_LNE: /* ..., value ==> ... */
3593 /* op1 = target JavaVM pc, val.l = constant */
3594 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3595 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3597 if (src->flags & INMEMORY) {
3598 if (iptr->val.l == 0) {
3599 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3600 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3603 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3604 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3605 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3606 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3607 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3610 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3611 i386_jcc(cd, I386_CC_NE, 0);
3612 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3615 case ICMD_IF_LGT: /* ..., value ==> ... */
3616 /* op1 = target JavaVM pc, val.l = constant */
3617 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3618 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3620 if (src->flags & INMEMORY) {
3621 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3622 i386_jcc(cd, I386_CC_G, 0);
3623 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3626 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3627 CALCIMMEDIATEBYTES(a, iptr->val.l);
3629 i386_jcc(cd, I386_CC_L, a);
3631 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3632 i386_jcc(cd, I386_CC_A, 0);
3633 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3637 case ICMD_IF_LGE: /* ..., value ==> ... */
3638 /* op1 = target JavaVM pc, val.l = constant */
3639 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3640 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3642 if (src->flags & INMEMORY) {
3643 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3644 i386_jcc(cd, I386_CC_G, 0);
3645 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3648 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3649 CALCIMMEDIATEBYTES(a, iptr->val.l);
3651 i386_jcc(cd, I386_CC_L, a);
3653 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3654 i386_jcc(cd, I386_CC_AE, 0);
3655 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3659 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3660 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3661 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3662 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3664 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3665 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3666 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3668 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3669 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3671 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3672 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3675 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3677 i386_jcc(cd, I386_CC_E, 0);
3678 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3681 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3682 /* op1 = target JavaVM pc */
3683 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3684 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3686 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3687 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3688 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3689 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3690 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3691 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3692 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3694 i386_jcc(cd, I386_CC_E, 0);
3695 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3698 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3699 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3700 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3701 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3703 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3704 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3705 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3707 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3708 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3710 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3711 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3714 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3716 i386_jcc(cd, I386_CC_NE, 0);
3717 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3720 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3721 /* op1 = target JavaVM pc */
3722 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3723 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3725 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3726 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3727 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3728 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3729 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3730 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3731 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3733 i386_jcc(cd, I386_CC_NE, 0);
3734 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3737 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3738 /* op1 = target JavaVM pc */
3739 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3740 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3742 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3743 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3744 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3746 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3747 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3749 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3750 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3753 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3755 i386_jcc(cd, I386_CC_L, 0);
3756 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3759 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3760 /* op1 = target JavaVM pc */
3761 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3762 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3764 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3765 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3766 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3767 i386_jcc(cd, I386_CC_L, 0);
3768 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3771 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3772 CALCOFFSETBYTES(a, REG_SP, src->regoff*8);
3774 i386_jcc(cd, I386_CC_G, a);
3776 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3777 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3778 i386_jcc(cd, I386_CC_B, 0);
3779 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3783 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3784 /* op1 = target JavaVM pc */
3785 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3786 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3788 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3789 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3790 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3792 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3793 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3795 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3796 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3799 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3801 i386_jcc(cd, I386_CC_G, 0);
3802 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3805 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3806 /* op1 = target JavaVM pc */
3807 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3808 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3810 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3811 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3812 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3813 i386_jcc(cd, I386_CC_G, 0);
3814 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3817 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3818 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3820 i386_jcc(cd, I386_CC_L, a);
3822 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3823 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3824 i386_jcc(cd, I386_CC_A, 0);
3825 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3829 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3830 /* op1 = target JavaVM pc */
3831 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3832 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3834 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3835 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3836 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3838 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3839 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3841 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3842 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3845 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3847 i386_jcc(cd, I386_CC_LE, 0);
3848 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3851 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3852 /* op1 = target JavaVM pc */
3853 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3854 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3856 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3857 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3858 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3859 i386_jcc(cd, I386_CC_L, 0);
3860 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3863 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3864 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3866 i386_jcc(cd, I386_CC_G, a);
3868 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3869 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3870 i386_jcc(cd, I386_CC_BE, 0);
3871 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3875 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3876 /* op1 = target JavaVM pc */
3877 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3878 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3880 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3881 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3882 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3884 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3885 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3887 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3888 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3891 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3893 i386_jcc(cd, I386_CC_GE, 0);
3894 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3897 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3898 /* op1 = target JavaVM pc */
3899 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3900 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3902 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3903 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3904 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3905 i386_jcc(cd, I386_CC_G, 0);
3906 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3909 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3910 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3912 i386_jcc(cd, I386_CC_L, a);
3914 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3915 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3916 i386_jcc(cd, I386_CC_AE, 0);
3917 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3921 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3923 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3924 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3925 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3928 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3929 /* val.i = constant */
3930 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3931 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3933 d = reg_of_var(rd, iptr->dst, REG_NULL);
3934 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
3937 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3938 /* val.i = constant */
3939 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3940 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3942 d = reg_of_var(rd, iptr->dst, REG_NULL);
3943 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
3946 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3947 /* val.i = constant */
3948 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3949 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3951 d = reg_of_var(rd, iptr->dst, REG_NULL);
3952 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
3955 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3956 /* val.i = constant */
3957 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3958 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3960 d = reg_of_var(rd, iptr->dst, REG_NULL);
3961 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
3964 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3965 /* val.i = constant */
3966 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3967 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3969 d = reg_of_var(rd, iptr->dst, REG_NULL);
3970 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
3973 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3974 /* val.i = constant */
3975 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3976 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3978 d = reg_of_var(rd, iptr->dst, REG_NULL);
3979 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
3983 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3985 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3986 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3988 var_to_reg_int(s1, src, REG_RESULT);
3989 M_INTMOVE(s1, REG_RESULT);
3991 goto nowperformreturn;
3993 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3994 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
3995 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3997 if (src->flags & INMEMORY) {
3998 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_RESULT);
3999 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_RESULT2);
4002 panic("LRETURN: longs have to be in memory");
4005 goto nowperformreturn;
4007 case ICMD_FRETURN: /* ..., retvalue ==> ... */
4008 case ICMD_DRETURN: /* ..., retvalue ==> ... */
4009 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4010 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4012 var_to_reg_flt(s1, src, REG_FRESULT);
4013 /* this may be an early return -- keep the offset correct for the
4017 goto nowperformreturn;
4019 case ICMD_RETURN: /* ... ==> ... */
4020 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4021 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4027 p = parentargs_base;
4029 /* call trace function */
4031 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
4033 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
4035 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
4036 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
4038 i386_fstl_membase(cd, REG_SP, 4 + 8);
4039 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
4041 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
4042 i386_call_reg(cd, REG_ITMP1);
4044 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
4045 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
4047 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
4050 #if defined(USE_THREADS)
4051 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
4052 i386_mov_membase_reg(cd, REG_SP, 8 * rd->maxmemuse, REG_ITMP2);
4054 /* we need to save the proper return value */
4055 switch (iptr->opc) {
4058 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
4062 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
4063 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, rd->maxmemuse * 8 + 4);
4067 i386_fsts_membase(cd, REG_SP, rd->maxmemuse * 8);
4071 i386_fstl_membase(cd, REG_SP, rd->maxmemuse * 8);
4075 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
4076 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, 0);
4077 i386_mov_imm_reg(cd, (s4) builtin_monitorexit, REG_ITMP1);
4078 i386_call_reg(cd, REG_ITMP1);
4079 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
4081 /* and now restore the proper return value */
4082 switch (iptr->opc) {
4085 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
4089 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
4090 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8 + 4, REG_RESULT2);
4094 i386_flds_membase(cd, REG_SP, rd->maxmemuse * 8);
4098 i386_fldl_membase(cd, REG_SP, rd->maxmemuse * 8);
4104 /* restore saved registers */
4105 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
4107 i386_mov_membase_reg(cd, REG_SP, p * 8, rd->savintregs[i]);
4109 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
4111 i386_fldl_membase(cd, REG_SP, p * 8);
4113 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
4114 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
4116 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
4121 /* deallocate stack */
4122 if (parentargs_base) {
4123 i386_alu_imm_reg(cd, I386_ADD, parentargs_base * 8, REG_SP);
4132 case ICMD_TABLESWITCH: /* ..., index ==> ... */
4133 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4134 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4139 tptr = (void **) iptr->target;
4141 s4ptr = iptr->val.a;
4142 l = s4ptr[1]; /* low */
4143 i = s4ptr[2]; /* high */
4145 var_to_reg_int(s1, src, REG_ITMP1);
4146 M_INTMOVE(s1, REG_ITMP1);
4148 i386_alu_imm_reg(cd, I386_SUB, l, REG_ITMP1);
4154 i386_alu_imm_reg(cd, I386_CMP, i - 1, REG_ITMP1);
4155 i386_jcc(cd, I386_CC_A, 0);
4157 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
4158 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4160 /* build jump table top down and use address of lowest entry */
4162 /* s4ptr += 3 + i; */
4166 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
4167 dseg_addtarget(cd, (basicblock *) tptr[0]);
4171 /* length of dataseg after last dseg_addtarget is used by load */
4173 i386_mov_imm_reg(cd, 0, REG_ITMP2);
4174 dseg_adddata(cd, cd->mcodeptr);
4175 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
4176 i386_jmp_reg(cd, REG_ITMP1);
4182 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
4183 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4184 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4186 s4 i, l, val, *s4ptr;
4189 tptr = (void **) iptr->target;
4191 s4ptr = iptr->val.a;
4192 l = s4ptr[0]; /* default */
4193 i = s4ptr[1]; /* count */
4195 MCODECHECK((i<<2)+8);
4196 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
4202 i386_alu_imm_reg(cd, I386_CMP, val, s1);
4203 i386_jcc(cd, I386_CC_E, 0);
4204 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), cd->mcodeptr); */
4205 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4208 i386_jmp_imm(cd, 0);
4209 /* codegen_addreference(cd, BlockPtrOfPC(l), cd->mcodeptr); */
4211 tptr = (void **) iptr->target;
4212 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4219 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
4220 /* op1 = return type, val.a = function pointer*/
4221 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4222 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4226 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
4227 /* op1 = return type, val.a = function pointer*/
4228 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4229 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4233 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
4234 /* op1 = return type, val.a = function pointer*/
4235 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4236 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4240 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
4241 /* op1 = arg count, val.a = method pointer */
4242 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4243 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4245 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
4246 /* op1 = arg count, val.a = method pointer */
4247 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4248 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4250 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
4251 /* op1 = arg count, val.a = method pointer */
4252 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4253 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4255 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
4256 /* op1 = arg count, val.a = method pointer */
4257 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4258 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4265 MCODECHECK((s3 << 1) + 64);
4267 /* copy arguments to registers or stack location */
4269 for (; --s3 >= 0; src = src->prev) {
4270 if (src->varkind == ARGVAR) {
4274 if (IS_INT_LNG_TYPE(src->type)) {
4275 if (s3 < rd->intreg_argnum) {
4276 panic("No integer argument registers available!");
4279 if (!IS_2_WORD_TYPE(src->type)) {
4280 if (src->flags & INMEMORY) {
4281 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
4282 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s3 * 8);
4285 i386_mov_reg_membase(cd, src->regoff, REG_SP, s3 * 8);
4289 if (src->flags & INMEMORY) {
4290 M_LNGMEMMOVE(src->regoff, s3);
4293 panic("copy arguments: longs have to be in memory");
4299 if (s3 < rd->fltreg_argnum) {
4300 panic("No float argument registers available!");
4303 var_to_reg_flt(d, src, REG_FTMP1);
4304 if (src->type == TYPE_FLT) {
4305 i386_fstps_membase(cd, REG_SP, s3 * 8);
4308 i386_fstpl_membase(cd, REG_SP, s3 * 8);
4315 switch (iptr->opc) {
4322 i386_mov_imm_reg(cd, a, REG_ITMP1);
4323 i386_call_reg(cd, REG_ITMP1);
4326 case ICMD_INVOKESTATIC:
4327 a = (ptrint) lm->stubroutine;
4330 i386_mov_imm_reg(cd, a, REG_ITMP2);
4331 i386_call_reg(cd, REG_ITMP2);
4334 case ICMD_INVOKESPECIAL:
4335 /* methodinfo* is not resolved, call the assembler function */
4338 unresolved_method *um = iptr->target;
4340 codegen_addpatchref(cd, cd->mcodeptr,
4341 asm_patcher_invokestatic_special, um);
4344 d = um->methodref->parseddesc.md->returntype.type;
4347 a = (ptrint) lm->stubroutine;
4348 d = lm->parseddesc->returntype.type;
4351 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
4352 gen_nullptr_check(REG_ITMP1);
4353 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
4355 i386_mov_imm_reg(cd, a, REG_ITMP2);
4356 i386_call_reg(cd, REG_ITMP2);
4359 case ICMD_INVOKEVIRTUAL:
4362 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
4363 gen_nullptr_check(REG_ITMP1);
4364 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
4365 i386_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
4367 i386_call_reg(cd, REG_ITMP1);
4370 case ICMD_INVOKEINTERFACE:
4373 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
4374 gen_nullptr_check(REG_ITMP1);
4375 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4376 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * lm->class->index, REG_ITMP2);
4377 i386_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - lm->class->methods), REG_ITMP1);
4379 i386_call_reg(cd, REG_ITMP1);
4383 /* d contains return type */
4385 if (d != TYPE_VOID) {
4386 d = reg_of_var(rd, iptr->dst, REG_NULL);
4388 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
4389 if (IS_2_WORD_TYPE(iptr->dst->type)) {
4390 if (iptr->dst->flags & INMEMORY) {
4391 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
4392 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
4395 panic("RETURN: longs have to be in memory");
4399 if (iptr->dst->flags & INMEMORY) {
4400 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
4403 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
4408 /* fld from called function -- has other fpu_st_offset counter */
4410 store_reg_to_var_flt(iptr->dst, d);
4417 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
4419 /* op1: 0 == array, 1 == class */
4420 /* val.a: (classinfo*) superclass */
4421 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4422 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4424 /* superclass is an interface:
4426 * return (sub != NULL) &&
4427 * (sub->vftbl->interfacetablelength > super->index) &&
4428 * (sub->vftbl->interfacetable[-super->index] != NULL);
4430 * superclass is a class:
4432 * return ((sub != NULL) && (0
4433 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4434 * super->vftbl->diffvall));
4438 classinfo *super = (classinfo*) iptr->val.a;
4440 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4441 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4443 var_to_reg_int(s1, src, REG_ITMP1);
4444 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4446 M_INTMOVE(s1, REG_ITMP1);
4449 i386_alu_reg_reg(cd, I386_XOR, d, d);
4450 if (iptr->op1) { /* class/interface */
4451 if (super->flags & ACC_INTERFACE) { /* interface */
4452 i386_test_reg_reg(cd, s1, s1);
4454 /* TODO: clean up this calculation */
4456 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4459 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4462 /* CALCOFFSETBYTES(a, super->index); */
4463 CALCIMMEDIATEBYTES(a, super->index);
4469 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4476 i386_jcc(cd, I386_CC_E, a);
4478 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4479 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4480 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4482 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4484 /* TODO: clean up this calculation */
4487 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4494 i386_jcc(cd, I386_CC_LE, a);
4495 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4497 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP1);
4498 /* i386_setcc_reg(cd, I386_CC_A, d); */
4499 /* i386_jcc(cd, I386_CC_BE, 5); */
4500 i386_jcc(cd, I386_CC_E, 5);
4501 i386_mov_imm_reg(cd, 1, d);
4504 } else { /* class */
4505 i386_test_reg_reg(cd, s1, s1);
4507 /* TODO: clean up this calculation */
4509 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4512 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4514 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4517 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4527 i386_jcc(cd, I386_CC_E, a);
4529 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4530 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4531 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4532 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4534 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4535 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4536 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4537 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4538 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4540 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4541 i386_alu_reg_reg(cd, I386_XOR, d, d);
4543 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4544 i386_jcc(cd, I386_CC_A, 5);
4545 i386_mov_imm_reg(cd, 1, d);
4549 panic ("internal error: no inlined array instanceof");
4551 store_reg_to_var_int(iptr->dst, d);
4554 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4555 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4556 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4558 /* op1: 0 == array, 1 == class */
4559 /* val.a: (classinfo*) superclass */
4561 /* superclass is an interface:
4563 * OK if ((sub == NULL) ||
4564 * (sub->vftbl->interfacetablelength > super->index) &&
4565 * (sub->vftbl->interfacetable[-super->index] != NULL));
4567 * superclass is a class:
4569 * OK if ((sub == NULL) || (0
4570 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4571 * super->vftbl->diffval));
4575 classinfo *super = (classinfo *) iptr->val.a;
4577 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4578 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4580 var_to_reg_int(s1, src, REG_ITMP1);
4581 if (iptr->op1) { /* class/interface */
4582 if (super->flags & ACC_INTERFACE) { /* interface */
4583 i386_test_reg_reg(cd, s1, s1);
4585 /* TODO: clean up this calculation */
4587 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4590 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
4593 CALCIMMEDIATEBYTES(a, super->index);
4599 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4604 i386_jcc(cd, I386_CC_E, a);
4606 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
4607 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength), REG_ITMP3);
4608 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP3);
4609 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4610 i386_jcc(cd, I386_CC_LE, 0);
4611 codegen_addxcastrefs(cd, cd->mcodeptr);
4612 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP3);
4613 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4614 i386_jcc(cd, I386_CC_E, 0);
4615 codegen_addxcastrefs(cd, cd->mcodeptr);
4617 } else { /* class */
4618 i386_test_reg_reg(cd, s1, s1);
4620 /* TODO: clean up this calculation */
4622 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4627 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4629 if (s1 != REG_ITMP1) {
4631 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
4634 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
4640 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
4646 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
4652 i386_jcc(cd, I386_CC_E, a);
4654 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
4655 i386_mov_imm_reg(cd, (ptrint) super->vftbl, REG_ITMP3);
4656 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4657 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4659 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
4660 if (s1 != REG_ITMP1) {
4661 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1);
4662 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3);
4663 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4664 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4666 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP1, REG_ITMP2);
4669 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP3);
4670 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP2);
4671 i386_mov_imm_reg(cd, (ptrint) super->vftbl, REG_ITMP3);
4672 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3);
4673 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4674 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4678 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP3, REG_ITMP2);
4679 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
4680 codegen_addxcastrefs(cd, cd->mcodeptr);
4684 panic ("internal error: no inlined array checkcast");
4686 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4688 store_reg_to_var_int(iptr->dst, d);
4691 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4692 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4693 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
4695 if (src->flags & INMEMORY) {
4696 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4699 i386_test_reg_reg(cd, src->regoff, src->regoff);
4701 i386_jcc(cd, I386_CC_L, 0);
4702 codegen_addxcheckarefs(cd, cd->mcodeptr);
4705 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4706 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4707 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
4709 i386_test_reg_reg(cd, REG_RESULT, REG_RESULT);
4710 i386_jcc(cd, I386_CC_E, 0);
4711 codegen_addxexceptionrefs(cd, cd->mcodeptr);
4714 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4715 /* op1 = dimension, val.a = array descriptor */
4716 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
4717 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4719 /* check for negative sizes and copy sizes to stack if necessary */
4721 MCODECHECK((iptr->op1 << 1) + 64);
4723 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4724 if (src->flags & INMEMORY) {
4725 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4728 i386_test_reg_reg(cd, src->regoff, src->regoff);
4730 i386_jcc(cd, I386_CC_L, 0);
4731 codegen_addxcheckarefs(cd, cd->mcodeptr);
4734 * copy sizes to new stack location, because native function
4735 * builtin_nmultianewarray access them as (int *)
4737 /*i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);*/
4738 /*i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);*/
4740 /* copy SAVEDVAR sizes to stack */
4742 if (src->varkind != ARGVAR) {
4743 if (src->flags & INMEMORY) {
4744 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
4745 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s1 * 8);
4748 i386_mov_reg_membase(cd, src->regoff, REG_SP, s1 * 8);
4753 /* now copy the (long *) sizes to (int *), skip the first one */
4755 for (s1 = 1; s1 < iptr->op1; s1++) {
4756 i386_mov_membase_reg(cd, REG_SP, s1 * 8, REG_ITMP1);
4757 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s1 * 4);
4760 /* save stack pointer */
4761 M_INTMOVE(REG_SP, REG_ITMP1);
4763 i386_alu_imm_reg(cd, I386_SUB, 3 * 4, REG_SP);
4765 /* a0 = dimension count */
4767 i386_mov_imm_membase(cd, iptr->op1, REG_SP, 0);
4769 /* a1 = arraydescriptor */
4771 i386_mov_imm_membase(cd, (u4) iptr->val.a, REG_SP, 4);
4773 /* a2 = pointer to dimensions = stack pointer */
4775 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 8);
4777 i386_mov_imm_reg(cd, (u4) (builtin_nmultianewarray), REG_ITMP1);
4778 i386_call_reg(cd, REG_ITMP1);
4779 i386_alu_imm_reg(cd, I386_ADD, 3 * 4, REG_SP);
4781 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
4782 M_INTMOVE(REG_RESULT, s1);
4783 store_reg_to_var_int(iptr->dst, s1);
4787 throw_cacao_exception_exit(string_java_lang_InternalError,
4788 "Unknown ICMD %d", iptr->opc);
4791 } /* for instruction */
4793 /* copy values to interface registers */
4795 src = bptr->outstack;
4796 len = bptr->outdepth;
4803 if ((src->varkind != STACKVAR)) {
4805 if (IS_FLT_DBL_TYPE(s2)) {
4806 var_to_reg_flt(s1, src, REG_FTMP1);
4807 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4808 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
4811 panic("double store");
4812 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4816 var_to_reg_int(s1, src, REG_ITMP1);
4817 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
4818 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4819 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
4822 i386_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
4826 if (rd->interfaces[len][s2].flags & INMEMORY) {
4827 M_LNGMEMMOVE(s1, rd->interfaces[len][s2].regoff);
4830 panic("copy interface registers: longs have to be in memory (end)");
4837 } /* if (bptr -> flags >= BBREACHED) */
4838 } /* for basic block */
4840 codegen_createlinenumbertable(cd);
4844 /* generate bound check stubs */
4846 u1 *xcodeptr = NULL;
4849 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
4850 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4852 cd->mcodeptr - cd->mcodebase);
4856 /* move index register into REG_ITMP1 */
4857 i386_mov_reg_reg(cd, bref->reg, REG_ITMP1); /* 2 bytes */
4859 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4860 dseg_adddata(cd, cd->mcodeptr);
4861 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3); /* 5 bytes */
4862 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4864 if (xcodeptr != NULL) {
4865 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4868 xcodeptr = cd->mcodeptr;
4870 i386_push_reg(cd, REG_ITMP2_XPC);
4872 /*PREPARE_NATIVE_STACKINFO;*/
4873 i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
4874 i386_push_imm(cd,0);
4875 i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
4876 i386_call_reg(cd,REG_ITMP3);
4878 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4879 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 4);
4880 i386_mov_imm_reg(cd, (u4) new_arrayindexoutofboundsexception, REG_ITMP1);
4881 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4882 i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4884 /*REMOVE_NATIVE_STACKINFO;*/
4885 i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
4886 i386_call_reg(cd,REG_ITMP3);
4888 i386_pop_reg(cd, REG_ITMP2_XPC);
4890 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4891 i386_jmp_reg(cd, REG_ITMP3);
4895 /* generate negative array size check stubs */
4899 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
4900 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4901 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4903 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4907 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4909 cd->mcodeptr - cd->mcodebase);
4913 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4914 dseg_adddata(cd, cd->mcodeptr);
4915 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4916 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4918 if (xcodeptr != NULL) {
4919 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4922 xcodeptr = cd->mcodeptr;
4924 i386_push_reg(cd, REG_ITMP2_XPC);
4926 /*PREPARE_NATIVE_STACKINFO;*/
4927 i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
4928 i386_push_imm(cd,0);
4929 i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
4930 i386_call_reg(cd,REG_ITMP3);
4934 i386_mov_imm_reg(cd, (u4) new_negativearraysizeexception, REG_ITMP1);
4935 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4936 /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4939 /*REMOVE_NATIVE_STACKINFO;*/
4940 i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
4941 i386_call_reg(cd,REG_ITMP3);
4944 i386_pop_reg(cd, REG_ITMP2_XPC);
4946 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4947 i386_jmp_reg(cd, REG_ITMP3);
4951 /* generate cast check stubs */
4955 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
4956 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4957 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4959 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4963 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4965 cd->mcodeptr - cd->mcodebase);
4969 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4970 dseg_adddata(cd, cd->mcodeptr);
4971 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4972 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4974 if (xcodeptr != NULL) {
4975 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4978 xcodeptr = cd->mcodeptr;
4980 i386_push_reg(cd, REG_ITMP2_XPC);
4982 /*PREPARE_NATIVE_STACKINFO;*/
4983 i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
4984 i386_push_imm(cd,0);
4985 i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
4986 i386_call_reg(cd,REG_ITMP3);
4989 i386_mov_imm_reg(cd, (u4) new_classcastexception, REG_ITMP1);
4990 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4991 /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4994 /*REMOVE_NATIVE_STACKINFO;*/
4995 i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
4996 i386_call_reg(cd,REG_ITMP3);
4999 i386_pop_reg(cd, REG_ITMP2_XPC);
5001 i386_mov_imm_reg(cd, (u4) asm_handle_exception, REG_ITMP3);
5002 i386_jmp_reg(cd, REG_ITMP3);
5006 /* generate divide by zero check stubs */
5010 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
5011 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
5012 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5014 xcodeptr - cd->mcodebase - (5 + 5 + 2));
5018 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5020 cd->mcodeptr - cd->mcodebase);
5024 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
5025 dseg_adddata(cd, cd->mcodeptr);
5026 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
5027 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
5029 if (xcodeptr != NULL) {
5030 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
5033 xcodeptr = cd->mcodeptr;
5035 i386_push_reg(cd, REG_ITMP2_XPC);
5037 /*PREPARE_NATIVE_STACKINFO;*/
5038 i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
5039 i386_push_imm(cd,0);
5040 i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
5041 i386_call_reg(cd,REG_ITMP3);
5045 i386_mov_imm_reg(cd, (u4) new_arithmeticexception, REG_ITMP1);
5046 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
5048 /*REMOVE_NATIVE_STACKINFO;*/
5049 i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
5050 i386_call_reg(cd,REG_ITMP3);
5053 i386_pop_reg(cd, REG_ITMP2_XPC);
5055 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
5056 i386_jmp_reg(cd, REG_ITMP3);
5060 /* generate exception check stubs */
5064 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
5065 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
5066 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5068 xcodeptr - cd->mcodebase - (5 + 5 + 2));
5072 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5074 cd->mcodeptr - cd->mcodebase);
5078 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
5079 dseg_adddata(cd, cd->mcodeptr);
5080 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
5081 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
5083 if (xcodeptr != NULL) {
5084 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
5087 xcodeptr = cd->mcodeptr;
5089 i386_push_reg(cd, REG_ITMP2_XPC);
5091 /*PREPARE_NATIVE_STACKINFO;*/
5092 i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
5093 i386_push_imm(cd,0);
5094 i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
5095 i386_call_reg(cd,REG_ITMP3);
5097 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5098 i386_mov_imm_reg(cd, (s4) &builtin_get_exceptionptrptr, REG_ITMP1);
5099 i386_call_reg(cd, REG_ITMP1);
5100 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP3);
5101 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5102 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1_XPTR);
5104 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP3);
5105 i386_mov_membase_reg(cd, REG_ITMP3, 0, REG_ITMP1_XPTR);
5106 i386_mov_imm_membase(cd, 0, REG_ITMP3, 0);
5108 i386_push_imm(cd, 0);
5109 i386_push_reg(cd, REG_ITMP1_XPTR);
5111 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
5112 java stack at this point*/
5113 i386_mov_membase_reg(cd, REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
5114 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, class), REG_ITMP1);
5115 i386_push_imm(cd, (u4) utf_void__java_lang_Throwable);
5116 i386_push_imm(cd, (u4) utf_fillInStackTrace);
5117 i386_push_reg(cd, REG_ITMP1);
5118 i386_mov_imm_reg(cd, (s4) class_resolvemethod, REG_ITMP3);
5119 i386_call_reg(cd, REG_ITMP3);
5120 /*cleanup parameters of class_resolvemethod*/
5121 i386_alu_imm_reg(cd, I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
5122 /*prepare call to asm_calljavafunction2 */
5123 i386_push_imm(cd, 0);
5124 i386_push_imm(cd, TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
5125 i386_push_reg(cd, REG_SP);
5126 i386_push_imm(cd, sizeof(jni_callblock));
5127 i386_push_imm(cd, 1);
5128 i386_push_reg(cd, REG_RESULT);
5130 i386_mov_imm_reg(cd, (s4) asm_calljavafunction2, REG_ITMP3);
5131 i386_call_reg(cd, REG_ITMP3);
5133 /* check exceptionptr + fail (JOWENN)*/
5135 i386_alu_imm_reg(cd, I386_ADD,6*4,REG_SP);
5137 i386_pop_reg(cd, REG_ITMP1_XPTR);
5138 i386_pop_reg(cd, REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
5140 /*REMOVE_NATIVE_STACKINFO;*/
5141 i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
5142 i386_call_reg(cd,REG_ITMP3);
5145 i386_pop_reg(cd, REG_ITMP2_XPC);
5147 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
5148 i386_jmp_reg(cd, REG_ITMP3);
5152 /* generate null pointer check stubs */
5156 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
5157 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
5158 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5160 xcodeptr - cd->mcodebase - (5 + 5 + 2));
5164 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5166 cd->mcodeptr - cd->mcodebase);
5170 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
5171 dseg_adddata(cd, cd->mcodeptr);
5172 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
5173 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
5175 if (xcodeptr != NULL) {
5176 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
5179 xcodeptr = cd->mcodeptr;
5181 i386_push_reg(cd, REG_ITMP2_XPC);
5183 /*PREPARE_NATIVE_STACKINFO;*/
5184 i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
5185 i386_push_imm(cd,0);
5186 i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
5187 i386_call_reg(cd,REG_ITMP3);
5192 /* create native call block*/
5193 i386_alu_imm_reg(cd, I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
5196 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1);
5197 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/
5199 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
5200 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
5201 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
5202 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
5203 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
5204 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */
5205 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
5208 i386_mov_imm_reg(cd, (u4) new_nullpointerexception, REG_ITMP1);
5209 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
5211 /*REMOVE_NATIVE_STACKINFO;*/
5212 i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
5213 i386_call_reg(cd,REG_ITMP3);
5217 /* restore native call stack */
5218 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2);
5219 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3);
5220 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0);
5221 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
5224 i386_pop_reg(cd, REG_ITMP2_XPC);
5226 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
5227 i386_jmp_reg(cd, REG_ITMP3);
5231 /* generate put/getstatic stub call code */
5239 tmpcd = DNEW(codegendata);
5241 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5242 /* check code segment size */
5245 /* Get machine code which is patched back in later. A */
5246 /* `call rel32' is 5 bytes long. */
5247 xcodeptr = cd->mcodebase + pref->branchpos;
5249 mcode = *((u4 *) (xcodeptr + 1));
5251 /* patch in `call rel32' to call the following code */
5252 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5253 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5255 /* Save current stack pointer into a temporary register. */
5256 i386_mov_reg_reg(cd, REG_SP, REG_ITMP1);
5258 /* Push machine code bytes to patch onto the stack. */
5259 i386_push_imm(cd, (u4) xmcode);
5260 i386_push_imm(cd, (u4) mcode);
5262 i386_push_imm(cd, (u4) pref->ref);
5264 /* Push previously saved stack pointer onto stack. */
5265 i386_push_reg(cd, REG_ITMP1);
5267 i386_mov_imm_reg(cd, (u4) pref->asmwrapper, REG_ITMP1);
5268 i386_jmp_reg(cd, REG_ITMP1);
5273 codegen_finish(m, cd, (u4) (cd->mcodeptr - cd->mcodebase));
5277 /* function createcompilerstub *************************************************
5279 creates a stub routine which calls the compiler
5281 *******************************************************************************/
5283 #define COMPSTUBSIZE 12
5285 u1 *createcompilerstub(methodinfo *m)
5287 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
5291 /* mark start of dump memory area */
5293 dumpsize = dump_size();
5295 cd = DNEW(codegendata);
5298 /* code for the stub */
5299 i386_mov_imm_reg(cd, (u4) m, REG_ITMP1);/* pass method pointer to compiler*/
5301 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
5302 i386_mov_imm_reg(cd, (u4) asm_call_jit_compiler, REG_ITMP3);
5303 i386_jmp_reg(cd, REG_ITMP3); /* jump to compiler */
5305 #if defined(STATISTICS)
5307 count_cstub_len += COMPSTUBSIZE;
5310 /* release dump area */
5312 dump_release(dumpsize);
5318 /* function removecompilerstub *************************************************
5320 deletes a compilerstub from memory (simply by freeing it)
5322 *******************************************************************************/
5324 void removecompilerstub(u1 *stub)
5326 CFREE(stub, COMPSTUBSIZE);
5330 /* function: createnativestub **************************************************
5332 creates a stub routine which calls a native method
5334 *******************************************************************************/
5336 #define NATIVESTUB_SIZE 450 /* keep this size high enough! */
5337 #define NATIVESTUB_OFFSET 0
5338 #define NATIVESTUB_DATA_SIZE 9 * 4
5340 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5341 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
5345 void i386_native_stub_debug(void **p) {
5346 printf("Pos on stack: %p\n",p);
5347 printf("Return adress should be: %p\n",*p);
5350 void i386_native_stub_debug2(void **p) {
5351 printf("Pos on stack: %p\n",p);
5352 printf("Return for lookup is: %p\n",*p);
5355 void traverseStackInfo() {
5356 void **p=builtin_asm_get_stackframeinfo();
5360 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
5361 m=*((methodinfo**)((*p)+8));
5362 utf_display(m->name);
5369 u1 *createnativestub(functionptr f, methodinfo *m)
5371 u1 *s; /* pointer to stub memory */
5376 t_inlining_globals *id;
5381 s4 stackframeoffset;
5382 bool require_clinit_call;
5384 s4 *callAddrPatchPos;
5386 s4 *jmpInstrPatchPos;
5388 /* initial 4 bytes is space for jni env, + 4 byte thread pointer + 4 byte */
5389 /* previous pointer + method info + 4 offset native */
5390 stackframesize = 4 + 16;
5391 stackframeoffset = 4;
5393 /* mark start of dump memory area */
5395 dumpsize = dump_size();
5397 /* allocate required dump memory */
5399 cd = DNEW(codegendata);
5400 rd = DNEW(registerdata);
5401 id = DNEW(t_inlining_globals);
5403 /* setup registers before using it */
5405 inlining_setup(m, id);
5406 reg_setup(m, rd, id);
5408 method_descriptor2types(m); /* set paramcount and paramtypes */
5410 require_clinit_call = (m->flags & ACC_STATIC) && !m->class->initialized;
5412 stubsize = NATIVESTUB_SIZE; /* calculate nativestub size */
5414 if (require_clinit_call)
5415 stubsize += NATIVESTUB_DATA_SIZE;
5417 /* if ((m->flags & ACC_STATIC) && !m->class->initialized) */
5418 /* stubsize += NATIVESTUB_STATIC_SIZE; */
5420 s = CNEW(u1, stubsize); /* memory to hold the stub */
5422 if (require_clinit_call) {
5423 /* build a dummy data segment *****************************************/
5425 cs = (u4 *) (s + NATIVESTUB_DATA_SIZE);
5427 *(cs - 9) = 0; /* extable size */
5428 *(cs - 8) = 0; /* line number table start */
5429 *(cs - 7) = 0; /* line number table size */
5430 *(cs - 6) = 0; /* fltsave */
5431 *(cs - 5) = 0; /* intsave */
5432 *(cs - 4) = 0; /* isleaf */
5433 *(cs - 3) = 0; /* issync */
5434 *(cs - 2) = 0; /* frame size */
5435 *(cs - 1) = (u4) m; /* method pointer */
5441 /* set some required varibles which are normally set by codegen_setup */
5442 cd->mcodebase = (u1 *) cs;
5443 cd->mcodeptr = (u1 *) cs;
5444 cd->patchrefs = NULL;
5446 /* if function is static, check for initialized */
5448 if (m->flags & ACC_STATIC) {
5449 stackframesize += 4;
5450 stackframeoffset += 4;
5452 /* if class isn't yet initialized, do it */
5453 if (!m->class->initialized)
5454 codegen_addpatchref(cd, cd->mcodeptr, asm_check_clinit, m->class);
5460 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
5462 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
5463 t = m->paramtypes[p];
5464 if (IS_INT_LNG_TYPE(t)) {
5465 if (IS_2_WORD_TYPE(t)) {
5466 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
5467 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
5468 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5469 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5471 } else if (t == TYPE_ADR) {
5472 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
5473 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
5474 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5475 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5478 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
5480 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
5481 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
5485 if (!IS_2_WORD_TYPE(t)) {
5486 i386_flds_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
5487 i386_fstps_membase(cd, REG_SP, p * 8);
5488 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
5489 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5492 i386_fldl_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
5493 i386_fstpl_membase(cd, REG_SP, p * 8);
5498 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
5499 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
5500 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5501 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
5504 i386_mov_imm_membase(cd, (u4) m, REG_SP, TRACE_ARGS_NUM * 8);
5506 i386_mov_imm_reg(cd, (u4) builtin_trace_args, REG_ITMP1);
5507 i386_call_reg(cd, REG_ITMP1);
5509 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
5512 /* Mark the whole fpu stack as free for native functions (only for saved */
5513 /* register count == 0). */
5514 i386_ffree_reg(cd, 0);
5515 i386_ffree_reg(cd, 1);
5516 i386_ffree_reg(cd, 2);
5517 i386_ffree_reg(cd, 3);
5518 i386_ffree_reg(cd, 4);
5519 i386_ffree_reg(cd, 5);
5520 i386_ffree_reg(cd, 6);
5521 i386_ffree_reg(cd, 7);
5523 /* calculate stackframe size for native function */
5524 tptr = m->paramtypes;
5525 for (i = 0; i < m->paramcount; i++) {
5526 stackframesize += IS_2_WORD_TYPE(*tptr++) ? 8 : 4;
5529 i386_alu_imm_reg(cd, I386_SUB, stackframesize, REG_SP);
5531 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
5532 i386_mov_imm_membase(cd,0,REG_SP,stackframesize-4);
5533 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
5534 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
5535 i386_call_reg(cd, REG_ITMP1);
5536 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-12); /*save thread specific pointer*/
5537 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2);
5538 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-16); /*save previous value of memory adress pointed to by thread specific pointer*/
5539 i386_mov_reg_reg(cd, REG_SP,REG_ITMP2);
5540 i386_alu_imm_reg(cd, I386_ADD,stackframesize-16,REG_ITMP2);
5541 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0);
5544 /* i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
5545 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
5546 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-12);*/
5548 /* CREATE DYNAMIC STACK INFO -- END*/
5550 /* RESOLVE NATIVE METHOD -- BEGIN*/
5551 #if !defined(STATIC_CLASSPATH)
5553 /*log_text("Dynamic classpath: preparing for delayed native function resolving");*/
5554 i386_jmp_imm(cd, 0);
5555 jmpInstrPos = cd->mcodeptr - 4;
5557 /* patch position */
5558 i386_mov_imm_reg(cd, (s4) jmpInstrPos, REG_ITMP1);
5559 i386_push_reg(cd, REG_ITMP1);
5562 i386_mov_imm_reg(cd, 0, REG_ITMP1);
5563 jmpInstrPatchPos = (s4 *) (cd->mcodeptr - 4);
5564 i386_push_reg(cd, REG_ITMP1);
5566 /* position of call address to patch */
5567 i386_mov_imm_reg(cd, 0, REG_ITMP1);
5568 callAddrPatchPos = (s4 *) (cd->mcodeptr - 4);
5569 i386_push_reg(cd, REG_ITMP1);
5571 /* method info structure */
5572 i386_mov_imm_reg(cd, (s4) m, REG_ITMP1);
5573 i386_push_reg(cd, REG_ITMP1);
5575 /* call resolve functions */
5576 i386_mov_imm_reg(cd, (s4) codegen_resolve_native, REG_ITMP1);
5577 i386_call_reg(cd, REG_ITMP1);
5580 i386_alu_imm_reg(cd, I386_ADD, 4 * 4, REG_SP);
5582 /* fix jmp offset replacement */
5583 *jmpInstrPatchPos = cd->mcodeptr - jmpInstrPos - 4;
5584 } /*else log_text("Dynamic classpath: immediate native function resolution possible");*/
5586 /* RESOLVE NATIVE METHOD -- END*/
5588 /* copy arguments into new stackframe */
5590 tptr = m->paramtypes;
5591 for (i = 0; i < m->paramcount; i++) {
5592 if (IS_2_WORD_TYPE(*tptr++)) {
5593 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5594 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5595 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5596 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, stackframeoffset + 4);
5597 stackframeoffset += 8;
5600 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5601 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5602 stackframeoffset += 4;
5606 /* if function is static, put class into second argument */
5608 if (m->flags & ACC_STATIC) {
5609 i386_mov_imm_membase(cd, (u4) m->class, REG_SP, 4);
5612 /* put env into first argument */
5614 i386_mov_imm_membase(cd, (u4) &env, REG_SP, 0);
5616 /* call the native function */
5618 i386_mov_imm_reg(cd, (u4) f, REG_ITMP1);
5619 #if !defined(STATIC_CLASSPATH)
5621 *callAddrPatchPos = (u4) cd->mcodeptr - 4;
5623 i386_call_reg(cd, REG_ITMP1);
5625 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5626 i386_push_reg(cd, REG_RESULT2);
5627 i386_mov_membase_reg(cd, REG_SP,stackframesize-12,REG_ITMP2); /*old value*/
5628 i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_RESULT2); /*pointer*/
5629 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT2,0);
5630 i386_pop_reg(cd, REG_RESULT2);
5631 /*REMOVE DYNAMIC STACK INFO -END */
5633 i386_alu_imm_reg(cd, I386_ADD, stackframesize, REG_SP);
5637 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5639 i386_mov_imm_membase(cd, (u4) m, REG_SP, 0);
5641 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
5642 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
5644 i386_fstl_membase(cd, REG_SP, 4 + 8);
5645 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5647 i386_mov_imm_reg(cd, (u4) builtin_displaymethodstop, REG_ITMP1);
5648 i386_call_reg(cd, REG_ITMP1);
5650 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
5651 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
5653 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5656 /* we can't use REG_ITMP3 == REG_RESULT2 */
5657 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5658 i386_push_reg(cd, REG_RESULT);
5659 i386_push_reg(cd, REG_RESULT2);
5660 i386_call_mem(cd, (u4) &callgetexceptionptrptr);
5661 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP2);
5662 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5663 i386_pop_reg(cd, REG_RESULT2);
5664 i386_pop_reg(cd, REG_RESULT);
5666 i386_mov_imm_reg(cd, (u4) &_exceptionptr, REG_ITMP2);
5667 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP2);
5668 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5670 i386_jcc(cd, I386_CC_NE, 1);
5674 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5675 i386_push_reg(cd, REG_ITMP2);
5676 i386_call_mem(cd, (u4) &callgetexceptionptrptr);
5677 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5678 i386_pop_reg(cd, REG_ITMP1_XPTR);
5680 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1_XPTR);
5681 i386_mov_imm_reg(cd, (u4) &_exceptionptr, REG_ITMP2);
5682 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5684 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP2_XPC);
5685 i386_alu_imm_reg(cd, I386_SUB, 2, REG_ITMP2_XPC);
5687 i386_mov_imm_reg(cd, (u4) asm_handle_nat_exception, REG_ITMP3);
5688 i386_jmp_reg(cd, REG_ITMP3);
5690 /* patch in a clinit call if required *************************************/
5692 if (require_clinit_call) {
5699 tmpcd = DNEW(codegendata);
5701 /* there can only be one clinit ref entry */
5702 pref = cd->patchrefs;
5705 /* Get machine code which is patched back in later. A */
5706 /* `call rel32' is 5 bytes long. */
5707 xcodeptr = cd->mcodebase + pref->branchpos;
5709 mcode = *((u4 *) (xcodeptr + 1));
5711 /* patch in `call rel32' to call the following code */
5712 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5713 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5715 /* Save current stack pointer into a temporary register. */
5716 i386_mov_reg_reg(cd, REG_SP, REG_ITMP1);
5718 /* Push machine code bytes to patch onto the stack. */
5719 i386_push_imm(cd, (u4) xmcode);
5720 i386_push_imm(cd, (u4) mcode);
5722 i386_push_imm(cd, (u4) pref->ref);
5724 /* Push previously saved stack pointer onto stack. */
5725 i386_push_reg(cd, REG_ITMP1);
5727 i386_mov_imm_reg(cd, (u4) pref->asmwrapper, REG_ITMP1);
5728 i386_jmp_reg(cd, REG_ITMP1);
5731 /* insert the native stub into the method table */
5733 codegen_insertmethod((functionptr) cs, (functionptr) cd->mcodeptr);
5736 /* Check if the stub size is big enough to hold the whole stub generated. */
5737 /* If not, this can lead into unpredictable crashes, because of heap */
5739 if ((s4) (cd->mcodeptr - s) > stubsize) {
5740 throw_cacao_exception_exit(string_java_lang_InternalError,
5741 "Native stub size %d is to small for current stub size %d",
5742 stubsize, (s4) (cd->mcodeptr - s));
5745 #if defined(STATISTICS)
5747 count_nstub_len += stubsize;
5750 /* release dump area */
5752 dump_release(dumpsize);
5758 /* function: removenativestub **************************************************
5760 removes a previously created native-stub from memory
5762 *******************************************************************************/
5764 void removenativestub(u1 *stub)
5766 CFREE(stub, NATIVESTUB_SIZE);
5771 * These are local overrides for various environment variables in Emacs.
5772 * Please do not remove this and leave it at the end of the file, where
5773 * Emacs will automagically detect them.
5774 * ---------------------------------------------------------------------
5777 * indent-tabs-mode: t