1 /* src/vm/jit/i386/codegen.c - machine code generator for i386
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Andreas Krall
30 Changes: Joseph Wenninger
34 $Id: codegen.c 4734 2006-04-05 09:57:55Z edwin $
46 #include "vm/jit/i386/md-abi.h"
48 #include "vm/jit/i386/codegen.h"
49 #include "vm/jit/i386/emitfuncs.h"
51 #include "mm/memory.h"
52 #include "native/jni.h"
53 #include "native/native.h"
54 #include "vm/builtin.h"
55 #include "vm/exceptions.h"
56 #include "vm/global.h"
57 #include "vm/loader.h"
58 #include "vm/options.h"
59 #include "vm/stringlocal.h"
62 #include "vm/jit/asmpart.h"
63 #include "vm/jit/codegen-common.h"
64 #include "vm/jit/dseg.h"
65 #include "vm/jit/jit.h"
66 #include "vm/jit/parse.h"
67 #include "vm/jit/patcher.h"
68 #include "vm/jit/reg.h"
69 #include "vm/jit/replace.h"
71 #if defined(ENABLE_LSRA)
72 # ifdef LSRA_USES_REG_RES
73 # include "vm/jit/i386/icmd_uses_reg_res.inc"
75 # include "vm/jit/allocator/lsra.h"
79 /* codegen *********************************************************************
81 Generates machine code.
83 *******************************************************************************/
85 bool codegen(jitdata *jd)
90 s4 len, s1, s2, s3, d, off, disp;
98 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
99 builtintable_entry *bte;
101 s4 fpu_st_offset = 0;
102 rplpoint *replacementpoint;
104 /* get required compiler data */
110 /* prevent compiler warnings */
120 s4 savedregs_num = 0;
123 /* space to save used callee saved registers */
125 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
127 /* float register are saved on 2 4-byte stackslots */
128 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
130 stackframesize = rd->memuse + savedregs_num;
133 #if defined(USE_THREADS)
134 /* space to save argument of monitor_enter */
136 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
137 /* reserve 2 slots for long/double return values for monitorexit */
139 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
146 /* create method header */
148 /* Keep stack of non-leaf functions 16-byte aligned. */
150 if (!m->isleafmethod)
151 stackframesize |= 0x3;
153 (void) dseg_addaddress(cd, m); /* MethodPointer */
154 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
156 #if defined(USE_THREADS)
157 /* IsSync contains the offset relative to the stack pointer for the
158 argument of monitor_exit used in the exception handler. Since the
159 offset could be zero and give a wrong meaning of the flag it is
163 if (checksync && (m->flags & ACC_SYNCHRONIZED))
164 (void) dseg_adds4(cd, (rd->memuse + 1) * 4); /* IsSync */
167 (void) dseg_adds4(cd, 0); /* IsSync */
169 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
170 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
171 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
173 /* adds a reference for the length of the line number counter. We don't
174 know the size yet, since we evaluate the information during code
175 generation, to save one additional iteration over the whole
176 instructions. During code optimization the position could have changed
177 to the information gotten from the class file */
178 (void) dseg_addlinenumbertablesize(cd);
180 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
182 /* create exception table */
184 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
185 dseg_addtarget(cd, ex->start);
186 dseg_addtarget(cd, ex->end);
187 dseg_addtarget(cd, ex->handler);
188 (void) dseg_addaddress(cd, ex->catchtype.cls);
191 /* initialize mcode variables */
193 cd->mcodeptr = cd->mcodebase;
194 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
196 /* initialize the last patcher pointer */
198 cd->lastmcodeptr = cd->mcodeptr;
200 /* generate method profiling code */
203 /* count frequency */
205 M_MOV_IMM(m, REG_ITMP1);
206 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(methodinfo, frequency));
209 /* create stack frame (if necessary) */
212 M_ASUB_IMM(stackframesize * 4, REG_SP);
214 /* save return address and used callee saved registers */
217 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
218 p--; M_AST(rd->savintregs[i], REG_SP, p * 4);
220 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
221 p-=2; i386_fld_reg(cd, rd->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 4);
224 /* take arguments out of register or stack frame */
229 for (p = 0, l = 0; p < md->paramcount; p++) {
230 t = md->paramtypes[p].type;
231 var = &(rd->locals[l][t]);
233 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
237 s1 = md->params[p].regoff;
238 if (IS_INT_LNG_TYPE(t)) { /* integer args */
239 if (!md->params[p].inmemory) { /* register arguments */
240 log_text("integer register argument");
242 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
243 /* rd->argintregs[md->params[p].regoff -> var->regoff */
244 } else { /* reg arg -> spilled */
245 /* rd->argintregs[md->params[p].regoff -> var->regoff * 4 */
247 } else { /* stack arguments */
248 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
249 i386_mov_membase_reg( /* + 4 for return address */
250 cd, REG_SP, (stackframesize + s1) * 4 + 4, var->regoff);
251 /* + 4 for return address */
252 } else { /* stack arg -> spilled */
253 if (!IS_2_WORD_TYPE(t)) {
255 i386_mov_membase_reg( /* + 4 for return address */
256 cd, REG_SP, (stackframesize + s1) * 4 + 4,
258 i386_mov_reg_membase(
259 cd, REG_ITMP1, REG_SP, var->regoff * 4);
261 /* reuse Stackslotand avoid copying */
262 var->regoff = stackframesize + s1 + 1;
267 i386_mov_membase_reg( /* + 4 for return address */
268 cd, REG_SP, (stackframesize + s1) * 4 + 4,
270 i386_mov_reg_membase(
271 cd, REG_ITMP1, REG_SP, var->regoff * 4);
272 i386_mov_membase_reg( /* + 4 for return address */
273 cd, REG_SP, (stackframesize + s1) * 4 + 4 + 4,
275 i386_mov_reg_membase(
276 cd, REG_ITMP1, REG_SP, var->regoff * 4 + 4);
278 /* reuse Stackslotand avoid copying */
279 var->regoff = stackframesize + s1 + 1;
285 } else { /* floating args */
286 if (!md->params[p].inmemory) { /* register arguments */
287 log_text("There are no float argument registers!");
289 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
290 /* rd->argfltregs[md->params[p].regoff -> var->regoff */
291 } else { /* reg arg -> spilled */
292 /* rd->argfltregs[md->params[p].regoff -> var->regoff * 4 */
295 } else { /* stack arguments */
296 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
299 cd, REG_SP, (stackframesize + s1) * 4 + 4);
301 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
306 cd, REG_SP, (stackframesize + s1) * 4 + 4);
308 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
312 } else { /* stack-arg -> spilled */
314 i386_mov_membase_reg(
315 cd, REG_SP, (stackframesize + s1) * 4 + 4, REG_ITMP1);
316 i386_mov_reg_membase(
317 cd, REG_ITMP1, REG_SP, var->regoff * 4);
320 cd, REG_SP, (stackframesize + s1) * 4 + 4);
321 i386_fstps_membase(cd, REG_SP, var->regoff * 4);
324 cd, REG_SP, (stackframesize + s1) * 4 + 4);
325 i386_fstpl_membase(cd, REG_SP, var->regoff * 4);
328 /* reuse Stackslotand avoid copying */
329 var->regoff = stackframesize + s1 + 1;
336 /* call monitorenter function */
338 #if defined(USE_THREADS)
339 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
342 if (m->flags & ACC_STATIC) {
343 M_MOV_IMM(m->class, REG_ITMP1);
344 M_AST(REG_ITMP1, REG_SP, s1 * 4);
345 M_AST(REG_ITMP1, REG_SP, 0 * 4);
346 M_MOV_IMM(BUILTIN_staticmonitorenter, REG_ITMP1);
350 M_ALD(REG_ITMP1, REG_SP, stackframesize * 4 + 4);
353 codegen_add_nullpointerexception_ref(cd, cd->mcodeptr);
354 M_AST(REG_ITMP1, REG_SP, s1 * 4);
355 M_AST(REG_ITMP1, REG_SP, 0 * 4);
356 M_MOV_IMM(BUILTIN_monitorenter, REG_ITMP1);
362 /* copy argument registers to stack and call trace function with pointer
363 to arguments on stack.
367 if (opt_verbosecall) {
369 s1 = INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4 + 4 + stackframesize * 4;
371 M_ISUB_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
373 /* save temporary registers for leaf methods */
375 for (p = 0; p < INT_TMP_CNT; p++)
376 M_IST(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
378 for (p = 0, l = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
379 t = md->paramtypes[p].type;
381 if (IS_INT_LNG_TYPE(t)) {
382 if (IS_2_WORD_TYPE(t)) {
383 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
384 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
385 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off + 4, REG_ITMP1);
386 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
388 } else if (t == TYPE_ADR) {
390 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
391 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
392 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
393 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
396 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, EAX);
398 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
399 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
403 if (!IS_2_WORD_TYPE(t)) {
404 i386_flds_membase(cd, REG_SP, s1 + stack_off);
405 i386_fstps_membase(cd, REG_SP, p * 8);
406 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
407 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
410 i386_fldl_membase(cd, REG_SP, s1 + stack_off);
411 i386_fstpl_membase(cd, REG_SP, p * 8);
414 stack_off += (IS_2_WORD_TYPE(t)) ? 8 : 4;
417 /* fill up the remaining arguments */
418 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
419 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
420 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
421 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
424 i386_mov_imm_membase(cd, (ptrint) m, REG_SP, TRACE_ARGS_NUM * 8);
425 i386_mov_imm_reg(cd, (ptrint) builtin_trace_args, REG_ITMP1);
426 i386_call_reg(cd, REG_ITMP1);
428 /* restore temporary registers for leaf methods */
430 for (p = 0; p < INT_TMP_CNT; p++)
431 M_ILD(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
433 M_IADD_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
435 #endif /* !defined(NDEBUG) */
439 /* end of header generation */
441 replacementpoint = jd->code->rplpoints;
443 /* walk through all basic blocks */
444 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
446 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
448 if (bptr->flags >= BBREACHED) {
450 /* branch resolving */
453 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
454 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
459 /* handle replacement points */
461 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
462 replacementpoint->pc = (u1*)bptr->mpc; /* will be resolved later */
466 assert(cd->lastmcodeptr <= cd->mcodeptr);
467 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
470 /* copy interface registers to their destination */
476 /* generate basic block profiling code */
479 /* count frequency */
481 M_MOV_IMM(m->bbfrequency, REG_ITMP1);
482 M_IADD_IMM_MEMBASE(1, REG_ITMP1, bptr->debug_nr * 4);
486 #if defined(ENABLE_LSRA)
488 while (src != NULL) {
490 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
491 if (!IS_2_WORD_TYPE(src->type)) {
492 if (bptr->type == BBTYPE_SBR) {
493 /* d = reg_of_var(m, src, REG_ITMP1); */
494 if (!(src->flags & INMEMORY))
500 store_reg_to_var_int(src, d);
502 } else if (bptr->type == BBTYPE_EXH) {
503 /* d = reg_of_var(m, src, REG_ITMP1); */
504 if (!(src->flags & INMEMORY))
508 M_INTMOVE(REG_ITMP1, d);
509 store_reg_to_var_int(src, d);
513 log_text("copy interface registers(EXH, SBR): longs have to be in memory (begin 1)");
522 while (src != NULL) {
524 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
525 if (!IS_2_WORD_TYPE(src->type)) {
526 if (bptr->type == BBTYPE_SBR) {
527 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
529 store_reg_to_var_int(src, d);
530 } else if (bptr->type == BBTYPE_EXH) {
531 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
532 M_INTMOVE(REG_ITMP1, d);
533 store_reg_to_var_int(src, d);
537 log_text("copy interface registers: longs have to be in memory (begin 1)");
542 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
543 if ((src->varkind != STACKVAR)) {
545 if (IS_FLT_DBL_TYPE(s2)) {
546 s1 = rd->interfaces[len][s2].regoff;
547 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
551 if (s2 == TYPE_FLT) {
552 i386_flds_membase(cd, REG_SP, s1 * 4);
555 i386_fldl_membase(cd, REG_SP, s1 * 4);
558 store_reg_to_var_flt(src, d);
561 s1 = rd->interfaces[len][s2].regoff;
562 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
563 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
567 i386_mov_membase_reg(cd, REG_SP, s1 * 4, d);
569 store_reg_to_var_int(src, d);
572 if (rd->interfaces[len][s2].flags & INMEMORY) {
573 M_LNGMEMMOVE(s1, src->regoff);
576 log_text("copy interface registers: longs have to be in memory (begin 2)");
585 #if defined(ENABLE_LSRA)
589 /* walk through all instructions */
594 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
595 if (iptr->line != currentline) {
596 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
597 currentline = iptr->line;
600 MCODECHECK(1024); /* 1kB should be enough */
603 case ICMD_INLINE_START:
605 insinfo_inline *insinfo = (insinfo_inline *) iptr->target;
606 #if defined(USE_THREADS)
607 if (insinfo->synchronize) {
608 /* add monitor enter code */
609 if (insinfo->method->flags & ACC_STATIC) {
610 M_MOV_IMM(insinfo->method->class, REG_ITMP1);
611 M_AST(REG_ITMP1, REG_SP, 0 * 4);
612 M_MOV_IMM(BUILTIN_staticmonitorenter, REG_ITMP1);
616 /* nullpointer check must have been performed before */
617 /* (XXX not done, yet) */
618 var = &(rd->locals[insinfo->synclocal][TYPE_ADR]);
619 if (var->flags & INMEMORY) {
620 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP1);
621 M_AST(REG_ITMP1, REG_SP, 0 * 4);
624 M_AST(var->regoff, REG_SP, 0 * 4);
626 M_MOV_IMM(BUILTIN_monitorenter, REG_ITMP1);
631 dseg_addlinenumber_inline_start(cd, iptr, cd->mcodeptr);
635 case ICMD_INLINE_END:
637 insinfo_inline *insinfo = (insinfo_inline *) iptr->target;
639 dseg_addlinenumber_inline_end(cd, iptr);
640 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
642 #if defined(USE_THREADS)
643 if (insinfo->synchronize) {
644 /* add monitor exit code */
645 if (insinfo->method->flags & ACC_STATIC) {
646 M_MOV_IMM(insinfo->method->class, REG_ITMP1);
647 M_AST(REG_ITMP1, REG_SP, 0 * 4);
648 M_MOV_IMM(BUILTIN_monitorexit, REG_ITMP1);
652 var = &(rd->locals[insinfo->synclocal][TYPE_ADR]);
653 if (var->flags & INMEMORY) {
654 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP1);
655 M_AST(REG_ITMP1, REG_SP, 0 * 4);
658 M_AST(var->regoff, REG_SP, 0 * 4);
660 M_MOV_IMM(BUILTIN_monitorexit, REG_ITMP1);
668 case ICMD_NOP: /* ... ==> ... */
669 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
670 /* EAX: NO ECX: NO EDX: NO */
673 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
674 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
675 /* EAX: NO ECX: NO EDX: NO */
677 if (src->flags & INMEMORY)
678 M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 4);
682 codegen_add_nullpointerexception_ref(cd, cd->mcodeptr);
685 /* constant operations ************************************************/
687 case ICMD_ICONST: /* ... ==> ..., constant */
688 /* op1 = 0, val.i = constant */
690 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
691 /* EAX: NO ECX: NO EDX: NO */
693 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
694 if (iptr->dst->flags & INMEMORY) {
695 M_IST_IMM(iptr->val.i, REG_SP, iptr->dst->regoff * 4);
698 if (iptr->val.i == 0) {
702 M_MOV_IMM(iptr->val.i, d);
707 case ICMD_LCONST: /* ... ==> ..., constant */
708 /* op1 = 0, val.l = constant */
710 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
711 /* EAX: NO ECX: NO EDX: NO */
713 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
714 if (iptr->dst->flags & INMEMORY) {
715 M_IST_IMM(iptr->val.l, REG_SP, iptr->dst->regoff * 4);
716 M_IST_IMM(iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
719 log_text("LCONST: longs have to be in memory");
724 case ICMD_FCONST: /* ... ==> ..., constant */
725 /* op1 = 0, val.f = constant */
727 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
728 /* EAX: YES ECX: NO EDX: NO */
730 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
731 if (iptr->val.f == 0.0) {
736 if (iptr->val.i == 0x80000000) {
740 } else if (iptr->val.f == 1.0) {
744 } else if (iptr->val.f == 2.0) {
751 disp = dseg_addfloat(cd, iptr->val.f);
752 i386_mov_imm_reg(cd, 0, REG_ITMP1);
753 dseg_adddata(cd, cd->mcodeptr);
754 i386_flds_membase(cd, REG_ITMP1, disp);
757 store_reg_to_var_flt(iptr->dst, d);
760 case ICMD_DCONST: /* ... ==> ..., constant */
761 /* op1 = 0, val.d = constant */
763 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
764 /* EAX: YES ECX: NO EDX: NO */
766 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
767 if (iptr->val.d == 0.0) {
772 if (iptr->val.l == 0x8000000000000000LL) {
776 } else if (iptr->val.d == 1.0) {
780 } else if (iptr->val.d == 2.0) {
787 disp = dseg_adddouble(cd, iptr->val.d);
788 i386_mov_imm_reg(cd, 0, REG_ITMP1);
789 dseg_adddata(cd, cd->mcodeptr);
790 i386_fldl_membase(cd, REG_ITMP1, disp);
793 store_reg_to_var_flt(iptr->dst, d);
796 case ICMD_ACONST: /* ... ==> ..., constant */
797 /* op1 = 0, val.a = constant */
799 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
800 /* EAX: YES ECX: NO EDX: NO */
802 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
804 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
805 codegen_addpatchref(cd, cd->mcodeptr,
807 (unresolved_class *) iptr->target, 0);
809 if (opt_showdisassemble) {
810 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
813 M_MOV_IMM(iptr->val.a, d);
814 store_reg_to_var_int(iptr->dst, d);
817 if (iptr->dst->flags & INMEMORY) {
818 M_AST_IMM((ptrint) iptr->val.a, REG_SP, iptr->dst->regoff * 4);
821 if ((ptrint) iptr->val.a == 0) {
824 M_MOV_IMM(iptr->val.a, d);
831 /* load/store operations **********************************************/
833 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
834 case ICMD_ALOAD: /* op1 = local variable */
835 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
836 /* EAX: YES ECX: NO EDX: NO */
838 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
839 if ((iptr->dst->varkind == LOCALVAR) &&
840 (iptr->dst->varnum == iptr->op1)) {
843 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
844 if (iptr->dst->flags & INMEMORY) {
845 if (var->flags & INMEMORY) {
846 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP1);
847 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
850 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 4);
854 if (var->flags & INMEMORY) {
855 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, iptr->dst->regoff);
858 M_INTMOVE(var->regoff, iptr->dst->regoff);
863 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
864 /* op1 = local variable */
865 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
866 /* EAX: NO ECX: NO EDX: NO */
868 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
869 if ((iptr->dst->varkind == LOCALVAR) &&
870 (iptr->dst->varnum == iptr->op1)) {
873 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
874 if (iptr->dst->flags & INMEMORY) {
875 if (var->flags & INMEMORY) {
876 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
879 log_text("LLOAD: longs have to be in memory");
884 log_text("LLOAD: longs have to be in memory");
889 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
890 /* op1 = local variable */
891 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
892 /* EAX: NO ECX: NO EDX: NO */
894 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
895 if ((iptr->dst->varkind == LOCALVAR) &&
896 (iptr->dst->varnum == iptr->op1)) {
899 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
900 if (var->flags & INMEMORY) {
901 i386_flds_membase(cd, REG_SP, var->regoff * 4);
904 i386_fld_reg(cd, var->regoff + fpu_st_offset);
907 store_reg_to_var_flt(iptr->dst, d);
910 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
911 /* op1 = local variable */
912 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
913 /* EAX: NO ECX: NO EDX: NO */
915 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
916 if ((iptr->dst->varkind == LOCALVAR) &&
917 (iptr->dst->varnum == iptr->op1)) {
920 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
921 if (var->flags & INMEMORY) {
922 i386_fldl_membase(cd, REG_SP, var->regoff * 4);
925 i386_fld_reg(cd, var->regoff + fpu_st_offset);
928 store_reg_to_var_flt(iptr->dst, d);
931 case ICMD_ISTORE: /* ..., value ==> ... */
932 case ICMD_ASTORE: /* op1 = local variable */
933 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
934 /* EAX: YES ECX: NO EDX: NO */
936 if ((src->varkind == LOCALVAR) &&
937 (src->varnum == iptr->op1)) {
940 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
941 if (var->flags & INMEMORY) {
942 if (src->flags & INMEMORY) {
943 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
944 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 4);
947 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 4);
951 var_to_reg_int(s1, src, var->regoff);
952 M_INTMOVE(s1, var->regoff);
956 case ICMD_LSTORE: /* ..., value ==> ... */
957 /* op1 = local variable */
958 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
959 /* EAX: NO ECX: NO EDX: NO */
961 if ((src->varkind == LOCALVAR) &&
962 (src->varnum == iptr->op1)) {
965 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
966 if (var->flags & INMEMORY) {
967 if (src->flags & INMEMORY) {
968 M_LNGMEMMOVE(src->regoff, var->regoff);
971 log_text("LSTORE: longs have to be in memory");
976 log_text("LSTORE: longs have to be in memory");
981 case ICMD_FSTORE: /* ..., value ==> ... */
982 /* op1 = local variable */
983 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
984 /* EAX: NO ECX: NO EDX: NO */
986 if ((src->varkind == LOCALVAR) &&
987 (src->varnum == iptr->op1)) {
990 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
991 if (var->flags & INMEMORY) {
992 var_to_reg_flt(s1, src, REG_FTMP1);
993 i386_fstps_membase(cd, REG_SP, var->regoff * 4);
996 var_to_reg_flt(s1, src, var->regoff);
997 /* M_FLTMOVE(s1, var->regoff); */
998 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
1003 case ICMD_DSTORE: /* ..., value ==> ... */
1004 /* op1 = local variable */
1005 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1006 /* EAX: NO ECX: NO EDX: NO */
1008 if ((src->varkind == LOCALVAR) &&
1009 (src->varnum == iptr->op1)) {
1012 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
1013 if (var->flags & INMEMORY) {
1014 var_to_reg_flt(s1, src, REG_FTMP1);
1015 i386_fstpl_membase(cd, REG_SP, var->regoff * 4);
1018 var_to_reg_flt(s1, src, var->regoff);
1019 /* M_FLTMOVE(s1, var->regoff); */
1020 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
1026 /* pop/dup/swap operations ********************************************/
1028 /* attention: double and longs are only one entry in CACAO ICMDs */
1030 case ICMD_POP: /* ..., value ==> ... */
1031 case ICMD_POP2: /* ..., value, value ==> ... */
1032 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1033 /* EAX: NO ECX: NO EDX: NO */
1036 case ICMD_DUP: /* ..., a ==> ..., a, a */
1037 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1038 /* EAX: YES ECX: NO EDX: NO */
1039 M_COPY(src, iptr->dst);
1042 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
1043 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1044 /* EAX: YES ECX: NO EDX: NO */
1046 M_COPY(src, iptr->dst);
1047 M_COPY(src->prev, iptr->dst->prev);
1050 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
1051 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1052 /* EAX: YES ECX: NO EDX: NO */
1054 M_COPY(src, iptr->dst);
1055 M_COPY(src->prev, iptr->dst->prev);
1056 M_COPY(iptr->dst, iptr->dst->prev->prev);
1059 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
1061 M_COPY(src, iptr->dst);
1062 M_COPY(src->prev, iptr->dst->prev);
1063 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1064 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
1067 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
1068 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1069 /* EAX: YES ECX: NO EDX: NO */
1071 M_COPY(src, iptr->dst);
1072 M_COPY(src->prev, iptr->dst->prev);
1073 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1074 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
1075 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
1078 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
1079 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1080 /* EAX: YES ECX: NO EDX: NO */
1082 M_COPY(src, iptr->dst);
1083 M_COPY(src->prev, iptr->dst->prev);
1084 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1085 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
1086 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
1087 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
1090 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1091 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1092 /* EAX: YES ECX: NO EDX: NO */
1094 M_COPY(src, iptr->dst->prev);
1095 M_COPY(src->prev, iptr->dst);
1099 /* integer operations *************************************************/
1101 case ICMD_INEG: /* ..., value ==> ..., - value */
1102 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1103 /* EAX: YES ECX: NO EDX: NO */
1105 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1106 if (iptr->dst->flags & INMEMORY) {
1107 if (src->flags & INMEMORY) {
1108 if (src->regoff == iptr->dst->regoff) {
1109 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1112 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1113 i386_neg_reg(cd, REG_ITMP1);
1114 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1118 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1119 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1123 if (src->flags & INMEMORY) {
1124 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1125 i386_neg_reg(cd, iptr->dst->regoff);
1128 M_INTMOVE(src->regoff, iptr->dst->regoff);
1129 i386_neg_reg(cd, iptr->dst->regoff);
1134 case ICMD_LNEG: /* ..., value ==> ..., - value */
1135 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1136 /* EAX: YES ECX: NO EDX: NO */
1138 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1139 if (iptr->dst->flags & INMEMORY) {
1140 if (src->flags & INMEMORY) {
1141 if (src->regoff == iptr->dst->regoff) {
1142 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1143 i386_alu_imm_membase(cd, ALU_ADC, 0, REG_SP, iptr->dst->regoff * 4 + 4);
1144 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4 + 4);
1147 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1148 i386_neg_reg(cd, REG_ITMP1);
1149 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1150 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1151 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP1);
1152 i386_neg_reg(cd, REG_ITMP1);
1153 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1159 case ICMD_I2L: /* ..., value ==> ..., value */
1160 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1161 /* EAX: YES ECX: NO EDX: YES */
1163 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1164 if (iptr->dst->flags & INMEMORY) {
1165 if (src->flags & INMEMORY) {
1166 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, EAX);
1168 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1169 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1172 M_INTMOVE(src->regoff, EAX);
1174 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1175 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1180 case ICMD_L2I: /* ..., value ==> ..., value */
1181 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1182 /* EAX: YES ECX: NO EDX: NO */
1184 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1185 if (iptr->dst->flags & INMEMORY) {
1186 if (src->flags & INMEMORY) {
1187 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1188 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1192 if (src->flags & INMEMORY) {
1193 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1198 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1199 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1200 /* EAX: YES ECX: NO EDX: NO */
1202 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1203 if (iptr->dst->flags & INMEMORY) {
1204 if (src->flags & INMEMORY) {
1205 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1206 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1207 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1208 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1211 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1212 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 4);
1213 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 4);
1217 if (src->flags & INMEMORY) {
1218 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1219 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1220 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1223 M_INTMOVE(src->regoff, iptr->dst->regoff);
1224 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1225 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1230 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1231 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1232 /* EAX: YES ECX: NO EDX: NO */
1234 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1235 if (iptr->dst->flags & INMEMORY) {
1236 if (src->flags & INMEMORY) {
1237 if (src->regoff == iptr->dst->regoff) {
1238 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1241 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1242 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, REG_ITMP1);
1243 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1247 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1248 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1252 if (src->flags & INMEMORY) {
1253 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1254 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1257 M_INTMOVE(src->regoff, iptr->dst->regoff);
1258 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1263 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1264 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1265 /* EAX: YES ECX: NO EDX: NO */
1267 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1268 if (iptr->dst->flags & INMEMORY) {
1269 if (src->flags & INMEMORY) {
1270 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1271 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1272 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1273 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1276 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1277 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 4);
1278 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 4);
1282 if (src->flags & INMEMORY) {
1283 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1284 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1285 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1288 M_INTMOVE(src->regoff, iptr->dst->regoff);
1289 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1290 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1296 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1297 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1298 /* EAX: S|YES ECX: NO EDX: NO */
1300 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1301 i386_emit_ialu(cd, ALU_ADD, src, iptr);
1304 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1305 /* val.i = constant */
1306 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1307 /* EAX: NO ECX: NO EDX: NO */
1309 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1310 i386_emit_ialuconst(cd, ALU_ADD, src, iptr);
1313 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1314 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1315 /* EAX: S|YES ECX: NO EDX: NO */
1317 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1318 if (iptr->dst->flags & INMEMORY) {
1319 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1320 if (src->regoff == iptr->dst->regoff) {
1321 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1322 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1323 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1324 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1326 } else if (src->prev->regoff == iptr->dst->regoff) {
1327 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1328 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1329 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1330 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1333 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1334 i386_alu_membase_reg(cd, ALU_ADD, REG_SP, src->regoff * 4, REG_ITMP1);
1335 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1336 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1337 i386_alu_membase_reg(cd, ALU_ADC, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1338 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1345 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1346 /* val.l = constant */
1347 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1348 /* EAX: NO ECX: NO EDX: NO */
1349 /* else path can never happen? longs stay in memory! */
1351 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1352 if (iptr->dst->flags & INMEMORY) {
1353 if (src->flags & INMEMORY) {
1354 if (src->regoff == iptr->dst->regoff) {
1355 i386_alu_imm_membase(cd, ALU_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1356 i386_alu_imm_membase(cd, ALU_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1359 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1360 i386_alu_imm_reg(cd, ALU_ADD, iptr->val.l, REG_ITMP1);
1361 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1362 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1363 i386_alu_imm_reg(cd, ALU_ADC, iptr->val.l >> 32, REG_ITMP1);
1364 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1370 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1371 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1372 /* EAX: S|YES ECX: NO EDX: NO */
1374 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1375 if (iptr->dst->flags & INMEMORY) {
1376 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1377 if (src->prev->regoff == iptr->dst->regoff) {
1378 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1379 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1382 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1383 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1384 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1387 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1388 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1389 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1390 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1392 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1393 if (src->prev->regoff == iptr->dst->regoff) {
1394 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1397 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1398 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1399 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1403 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 4);
1404 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1408 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1409 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1410 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1412 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1413 M_INTMOVE(src->prev->regoff, d);
1414 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1416 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1417 /* workaround for reg alloc */
1418 if (src->regoff == iptr->dst->regoff) {
1419 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1420 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1421 M_INTMOVE(REG_ITMP1, d);
1424 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1425 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1429 /* workaround for reg alloc */
1430 if (src->regoff == iptr->dst->regoff) {
1431 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1432 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1433 M_INTMOVE(REG_ITMP1, d);
1436 M_INTMOVE(src->prev->regoff, d);
1437 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1443 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1444 /* val.i = constant */
1445 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1446 /* EAX: NO ECX: NO EDX: NO */
1448 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1449 i386_emit_ialuconst(cd, ALU_SUB, src, iptr);
1452 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1453 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1454 /* EAX: S|YES ECX: NO EDX: NO */
1456 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1457 if (iptr->dst->flags & INMEMORY) {
1458 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1459 if (src->prev->regoff == iptr->dst->regoff) {
1460 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1461 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1462 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1463 i386_alu_reg_membase(cd, ALU_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1466 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1467 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1468 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1469 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1470 i386_alu_membase_reg(cd, ALU_SBB, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1471 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1477 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1478 /* val.l = constant */
1479 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1480 /* EAX: NO ECX: NO EDX: NO */
1481 /* else path can never happen? longs stay in memory! */
1483 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1484 if (iptr->dst->flags & INMEMORY) {
1485 if (src->flags & INMEMORY) {
1486 if (src->regoff == iptr->dst->regoff) {
1487 i386_alu_imm_membase(cd, ALU_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1488 i386_alu_imm_membase(cd, ALU_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1491 /* TODO: could be size optimized with lea -- see gcc output */
1492 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1493 i386_alu_imm_reg(cd, ALU_SUB, iptr->val.l, REG_ITMP1);
1494 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1495 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1496 i386_alu_imm_reg(cd, ALU_SBB, iptr->val.l >> 32, REG_ITMP1);
1497 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1503 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1504 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1505 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1507 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1508 if (iptr->dst->flags & INMEMORY) {
1509 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1510 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1511 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1512 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1514 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1515 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1516 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1517 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1519 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1520 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1521 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1522 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1525 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1526 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1527 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1531 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1532 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1533 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1535 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1536 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1537 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1539 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1540 M_INTMOVE(src->regoff, iptr->dst->regoff);
1541 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1544 if (src->regoff == iptr->dst->regoff) {
1545 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1548 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1549 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1555 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1556 /* val.i = constant */
1557 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1558 /* EAX: YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1560 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1561 if (iptr->dst->flags & INMEMORY) {
1562 if (src->flags & INMEMORY) {
1563 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, REG_ITMP1);
1564 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1567 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1568 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1572 if (src->flags & INMEMORY) {
1573 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, iptr->dst->regoff);
1576 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1581 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1582 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1583 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1585 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1586 if (iptr->dst->flags & INMEMORY) {
1587 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1588 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX); /* mem -> EAX */
1589 /* optimize move EAX -> REG_ITMP3 is slower??? */
1590 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1591 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1593 /* TODO: optimize move EAX -> REG_ITMP3 */
1594 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); /* mem -> ITMP3 */
1595 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1596 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1598 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP2); /* mem -> ITMP3 */
1599 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1601 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1602 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1603 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1608 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1609 /* val.l = constant */
1610 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1611 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1613 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1614 if (iptr->dst->flags & INMEMORY) {
1615 if (src->flags & INMEMORY) {
1616 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1617 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1618 /* TODO: optimize move EAX -> REG_ITMP3 */
1619 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1620 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1622 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1623 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1624 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1626 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1627 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1628 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1633 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1634 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1635 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX */
1637 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1638 var_to_reg_int(s1, src, REG_ITMP2);
1640 if (src->prev->flags & INMEMORY) {
1641 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1644 M_INTMOVE(src->prev->regoff, EAX);
1647 /* check as described in jvm spec */
1649 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1650 i386_jcc(cd, I386_CC_NE, 3 + 6);
1651 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1652 i386_jcc(cd, I386_CC_E, 1 + 2);
1655 i386_idiv_reg(cd, s1);
1657 if (iptr->dst->flags & INMEMORY) {
1658 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1661 M_INTMOVE(EAX, iptr->dst->regoff);
1665 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1666 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1667 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EDX */
1670 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1671 var_to_reg_int(s1, src, REG_ITMP2);
1673 if (src->prev->flags & INMEMORY) {
1674 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1677 M_INTMOVE(src->prev->regoff, EAX);
1680 /* check as described in jvm spec */
1682 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1683 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1684 i386_alu_reg_reg(cd, ALU_XOR, EDX, EDX);
1685 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1686 i386_jcc(cd, I386_CC_E, 1 + 2);
1689 i386_idiv_reg(cd, s1);
1691 if (iptr->dst->flags & INMEMORY) {
1692 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4);
1695 M_INTMOVE(EDX, iptr->dst->regoff);
1699 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1700 /* val.i = constant */
1701 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1702 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL */
1704 /* TODO: optimize for `/ 2' */
1705 var_to_reg_int(s1, src, REG_ITMP1);
1706 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1709 i386_test_reg_reg(cd, d, d);
1711 CALCIMMEDIATEBYTES(disp, (1 << iptr->val.i) - 1);
1712 i386_jcc(cd, I386_CC_NS, disp);
1713 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, d);
1715 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1716 store_reg_to_var_int(iptr->dst, d);
1719 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1720 /* val.i = constant */
1721 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1722 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1724 var_to_reg_int(s1, src, REG_ITMP1);
1725 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1727 M_INTMOVE(s1, REG_ITMP1);
1734 CALCIMMEDIATEBYTES(disp, iptr->val.i);
1737 /* TODO: optimize */
1739 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1740 i386_test_reg_reg(cd, s1, s1);
1741 i386_jcc(cd, I386_CC_GE, disp);
1742 i386_mov_reg_reg(cd, s1, d);
1743 i386_neg_reg(cd, d);
1744 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1745 i386_neg_reg(cd, d);
1747 /* M_INTMOVE(s1, EAX); */
1748 /* i386_cltd(cd); */
1749 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1750 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1751 /* i386_alu_reg_reg(cd, ALU_AND, iptr->val.i, EAX); */
1752 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1753 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1754 /* M_INTMOVE(EAX, d); */
1756 /* i386_alu_reg_reg(cd, ALU_XOR, d, d); */
1757 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1758 /* i386_shrd_reg_reg(cd, s1, d); */
1759 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1761 store_reg_to_var_int(iptr->dst, d);
1764 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1765 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1767 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1768 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4);
1769 M_OR_MEMBASE(REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1772 codegen_add_arithmeticexception_ref(cd, cd->mcodeptr);
1777 M_ILD(REG_ITMP1, REG_SP, src->prev->regoff * 4);
1778 M_ILD(REG_ITMP2, REG_SP, src->prev->regoff * 4 + 4);
1779 M_IST(REG_ITMP1, REG_SP, 0 * 4);
1780 M_IST(REG_ITMP2, REG_SP, 0 * 4 + 4);
1782 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
1783 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4 + 4);
1784 M_IST(REG_ITMP1, REG_SP, 2 * 4);
1785 M_IST(REG_ITMP2, REG_SP, 2 * 4 + 4);
1787 M_MOV_IMM(bte->fp, REG_ITMP3);
1790 M_IST(REG_RESULT, REG_SP, iptr->dst->regoff * 4);
1791 M_IST(REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
1794 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1795 /* val.i = constant */
1796 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1797 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1799 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1800 if (iptr->dst->flags & INMEMORY) {
1801 if (src->flags & INMEMORY) {
1803 CALCIMMEDIATEBYTES(disp, (1 << iptr->val.i) - 1);
1805 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1806 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1808 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1809 i386_jcc(cd, I386_CC_NS, disp);
1810 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1811 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1812 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1813 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1815 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1816 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1821 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1822 /* val.l = constant */
1823 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1824 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1826 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1827 if (iptr->dst->flags & INMEMORY) {
1828 if (src->flags & INMEMORY) {
1829 /* Intel algorithm -- does not work, because constant is wrong */
1830 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1); */
1831 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3); */
1833 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1834 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1835 /* i386_jcc(cd, I386_CC_NS, offset); */
1836 /* i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1837 /* i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP3); */
1839 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1840 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1841 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1843 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1845 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1); */
1846 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); */
1847 /* i386_alu_reg_reg(cd, ALU_SBB, REG_ITMP3, REG_ITMP2); */
1849 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1850 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1852 /* Alpha algorithm */
1854 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1856 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4 + 4);
1862 /* TODO: hmm, don't know if this is always correct */
1864 CALCIMMEDIATEBYTES(disp, iptr->val.l & 0x00000000ffffffff);
1866 CALCIMMEDIATEBYTES(disp, iptr->val.l >> 32);
1872 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1873 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1875 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1876 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1877 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4 + 4);
1878 i386_jcc(cd, I386_CC_GE, disp);
1880 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1881 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1883 i386_neg_reg(cd, REG_ITMP1);
1884 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1885 i386_neg_reg(cd, REG_ITMP2);
1887 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1888 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1890 i386_neg_reg(cd, REG_ITMP1);
1891 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1892 i386_neg_reg(cd, REG_ITMP2);
1894 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1895 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1900 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1901 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1902 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1904 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1905 i386_emit_ishift(cd, I386_SHL, src, iptr);
1908 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1909 /* val.i = constant */
1910 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1911 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1913 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1914 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1917 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1918 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1919 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1921 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1922 i386_emit_ishift(cd, I386_SAR, src, iptr);
1925 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1926 /* val.i = constant */
1927 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1928 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1930 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1931 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1934 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1935 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1936 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1938 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1939 i386_emit_ishift(cd, I386_SHR, src, iptr);
1942 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1943 /* val.i = constant */
1944 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1945 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1947 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1948 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1951 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1952 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1953 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
1955 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1956 if (iptr->dst->flags & INMEMORY ){
1957 if (src->prev->flags & INMEMORY) {
1958 /* if (src->prev->regoff == iptr->dst->regoff) { */
1959 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1961 /* if (src->flags & INMEMORY) { */
1962 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1964 /* M_INTMOVE(src->regoff, ECX); */
1967 /* i386_test_imm_reg(cd, 32, ECX); */
1968 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1969 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1970 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1); */
1972 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 4 + 4); */
1973 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 4); */
1976 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1977 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1979 if (src->flags & INMEMORY) {
1980 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1982 M_INTMOVE(src->regoff, ECX);
1985 i386_test_imm_reg(cd, 32, ECX);
1986 i386_jcc(cd, I386_CC_E, 2 + 2);
1987 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1988 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1990 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1991 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1992 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1993 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
1999 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
2000 /* val.i = constant */
2001 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2002 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
2004 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2005 if (iptr->dst->flags & INMEMORY ) {
2006 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
2007 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
2009 if (iptr->val.i & 0x20) {
2010 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
2011 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
2012 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
2015 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
2016 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
2019 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2020 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
2024 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
2025 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2026 /* EAX: S|YES ECX: YES S|EDX: YES OUTPUT: REG_NULL*/
2028 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2029 if (iptr->dst->flags & INMEMORY ){
2030 if (src->prev->flags & INMEMORY) {
2031 /* if (src->prev->regoff == iptr->dst->regoff) { */
2032 /* TODO: optimize */
2033 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
2034 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
2036 /* if (src->flags & INMEMORY) { */
2037 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
2039 /* M_INTMOVE(src->regoff, ECX); */
2042 /* i386_test_imm_reg(cd, 32, ECX); */
2043 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
2044 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2045 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
2047 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2048 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
2049 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
2050 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
2053 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
2054 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
2056 if (src->flags & INMEMORY) {
2057 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
2059 M_INTMOVE(src->regoff, ECX);
2062 i386_test_imm_reg(cd, 32, ECX);
2063 i386_jcc(cd, I386_CC_E, 2 + 3);
2064 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2065 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
2067 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2068 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
2069 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2070 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2076 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
2077 /* val.i = constant */
2078 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2079 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
2081 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2082 if (iptr->dst->flags & INMEMORY ) {
2083 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
2084 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
2086 if (iptr->val.i & 0x20) {
2087 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2088 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
2089 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2092 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2093 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
2096 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2097 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
2101 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
2102 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2103 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
2105 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2106 if (iptr->dst->flags & INMEMORY ){
2107 if (src->prev->flags & INMEMORY) {
2108 /* if (src->prev->regoff == iptr->dst->regoff) { */
2109 /* TODO: optimize */
2110 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
2111 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
2113 /* if (src->flags & INMEMORY) { */
2114 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
2116 /* M_INTMOVE(src->regoff, ECX); */
2119 /* i386_test_imm_reg(cd, 32, ECX); */
2120 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
2121 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2122 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2); */
2124 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2125 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
2126 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
2127 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
2130 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
2131 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
2133 if (src->flags & INMEMORY) {
2134 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
2136 M_INTMOVE(src->regoff, ECX);
2139 i386_test_imm_reg(cd, 32, ECX);
2140 i386_jcc(cd, I386_CC_E, 2 + 2);
2141 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2142 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP3, REG_ITMP3);
2144 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2145 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
2146 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2147 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2153 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
2154 /* val.l = constant */
2155 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2156 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
2158 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2159 if (iptr->dst->flags & INMEMORY ) {
2160 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
2161 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
2163 if (iptr->val.i & 0x20) {
2164 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2165 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
2166 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2169 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2170 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
2173 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2174 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
2178 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2179 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2180 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2182 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2183 i386_emit_ialu(cd, ALU_AND, src, iptr);
2186 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
2187 /* val.i = constant */
2188 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2189 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2191 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2192 i386_emit_ialuconst(cd, ALU_AND, src, iptr);
2195 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2196 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2197 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2199 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2200 i386_emit_lalu(cd, ALU_AND, src, iptr);
2203 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
2204 /* val.l = constant */
2205 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2206 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2208 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2209 i386_emit_laluconst(cd, ALU_AND, src, iptr);
2212 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2213 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2214 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2216 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2217 i386_emit_ialu(cd, ALU_OR, src, iptr);
2220 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2221 /* val.i = constant */
2222 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2223 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2225 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2226 i386_emit_ialuconst(cd, ALU_OR, src, iptr);
2229 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2230 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2231 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2233 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2234 i386_emit_lalu(cd, ALU_OR, src, iptr);
2237 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2238 /* val.l = constant */
2239 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2240 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2242 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2243 i386_emit_laluconst(cd, ALU_OR, src, iptr);
2246 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2247 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2248 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2250 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2251 i386_emit_ialu(cd, ALU_XOR, src, iptr);
2254 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2255 /* val.i = constant */
2256 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2257 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2259 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2260 i386_emit_ialuconst(cd, ALU_XOR, src, iptr);
2263 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2264 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2265 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2267 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2268 i386_emit_lalu(cd, ALU_XOR, src, iptr);
2271 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2272 /* val.l = constant */
2273 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2274 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2276 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2277 i386_emit_laluconst(cd, ALU_XOR, src, iptr);
2280 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2281 /* op1 = variable, val.i = constant */
2282 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2283 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL */
2285 var = &(rd->locals[iptr->op1][TYPE_INT]);
2286 if (var->flags & INMEMORY)
2287 M_IADD_IMM_MEMBASE(iptr->val.i, REG_SP, var->regoff * 4);
2289 /* `inc reg' is slower on p4's (regarding to ia32
2290 optimization reference manual and benchmarks) and
2291 as fast on athlon's. */
2292 M_IADD_IMM(iptr->val.i, var->regoff);
2297 /* floating operations ************************************************/
2299 #define ROUND_TO_SINGLE \
2300 i386_fstps_membase(cd, REG_SP, -8); \
2301 i386_flds_membase(cd, REG_SP, -8);
2303 #define ROUND_TO_DOUBLE \
2304 i386_fstpl_membase(cd, REG_SP, -8); \
2305 i386_fldl_membase(cd, REG_SP, -8);
2307 #define FPU_SET_24BIT_MODE \
2308 if (!fpu_in_24bit_mode) { \
2309 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2310 fpu_in_24bit_mode = 1; \
2313 #define FPU_SET_53BIT_MODE \
2314 if (fpu_in_24bit_mode) { \
2315 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2316 fpu_in_24bit_mode = 0; \
2319 #define ROUND_TO_SINGLE
2320 #define ROUND_TO_DOUBLE
2321 #define FPU_SET_24BIT_MODE
2322 #define FPU_SET_53BIT_MODE
2324 case ICMD_FNEG: /* ..., value ==> ..., - value */
2325 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2326 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2329 var_to_reg_flt(s1, src, REG_FTMP1);
2330 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2332 store_reg_to_var_flt(iptr->dst, d);
2335 case ICMD_DNEG: /* ..., value ==> ..., - value */
2336 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2337 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2340 var_to_reg_flt(s1, src, REG_FTMP1);
2341 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2343 store_reg_to_var_flt(iptr->dst, d);
2346 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2347 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2348 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2351 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2352 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2353 var_to_reg_flt(s2, src, REG_FTMP2);
2356 store_reg_to_var_flt(iptr->dst, d);
2359 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2360 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2361 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2364 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2365 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2366 var_to_reg_flt(s2, src, REG_FTMP2);
2369 store_reg_to_var_flt(iptr->dst, d);
2372 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2373 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2374 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2377 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2378 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2379 var_to_reg_flt(s2, src, REG_FTMP2);
2382 store_reg_to_var_flt(iptr->dst, d);
2385 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2386 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2387 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2390 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2391 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2392 var_to_reg_flt(s2, src, REG_FTMP2);
2395 store_reg_to_var_flt(iptr->dst, d);
2398 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2399 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2400 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2403 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2404 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2405 var_to_reg_flt(s2, src, REG_FTMP2);
2409 store_reg_to_var_flt(iptr->dst, d);
2412 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2413 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2414 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2417 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2418 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2420 /* i386_fldt_mem(cd, subnormal_bias1); */
2421 /* i386_fmulp(cd); */
2423 var_to_reg_flt(s2, src, REG_FTMP2);
2428 /* i386_fldt_mem(cd, subnormal_bias2); */
2429 /* i386_fmulp(cd); */
2431 store_reg_to_var_flt(iptr->dst, d);
2434 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2435 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2436 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2439 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2440 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2441 var_to_reg_flt(s2, src, REG_FTMP2);
2445 store_reg_to_var_flt(iptr->dst, d);
2448 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2449 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2450 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2453 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2454 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2456 /* i386_fldt_mem(cd, subnormal_bias1); */
2457 /* i386_fmulp(cd); */
2459 var_to_reg_flt(s2, src, REG_FTMP2);
2464 /* i386_fldt_mem(cd, subnormal_bias2); */
2465 /* i386_fmulp(cd); */
2467 store_reg_to_var_flt(iptr->dst, d);
2470 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2471 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2472 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2475 /* exchanged to skip fxch */
2476 var_to_reg_flt(s2, src, REG_FTMP2);
2477 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2478 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2479 /* i386_fxch(cd); */
2484 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2485 store_reg_to_var_flt(iptr->dst, d);
2486 i386_ffree_reg(cd, 0);
2491 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2492 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2493 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2496 /* exchanged to skip fxch */
2497 var_to_reg_flt(s2, src, REG_FTMP2);
2498 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2499 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2500 /* i386_fxch(cd); */
2505 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2506 store_reg_to_var_flt(iptr->dst, d);
2507 i386_ffree_reg(cd, 0);
2512 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2513 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2514 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2515 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2517 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2518 if (src->flags & INMEMORY) {
2519 i386_fildl_membase(cd, REG_SP, src->regoff * 4);
2523 disp = dseg_adds4(cd, 0);
2524 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2525 dseg_adddata(cd, cd->mcodeptr);
2526 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, disp);
2527 i386_fildl_membase(cd, REG_ITMP1, disp);
2530 store_reg_to_var_flt(iptr->dst, d);
2533 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2534 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2535 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2536 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2538 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2539 if (src->flags & INMEMORY) {
2540 i386_fildll_membase(cd, REG_SP, src->regoff * 4);
2544 log_text("L2F: longs have to be in memory");
2547 store_reg_to_var_flt(iptr->dst, d);
2550 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2551 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2552 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2554 var_to_reg_flt(s1, src, REG_FTMP1);
2555 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2557 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2558 dseg_adddata(cd, cd->mcodeptr);
2560 /* Round to zero, 53-bit mode, exception masked */
2561 disp = dseg_adds4(cd, 0x0e7f);
2562 i386_fldcw_membase(cd, REG_ITMP1, disp);
2564 if (iptr->dst->flags & INMEMORY) {
2565 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2568 /* Round to nearest, 53-bit mode, exceptions masked */
2569 disp = dseg_adds4(cd, 0x027f);
2570 i386_fldcw_membase(cd, REG_ITMP1, disp);
2572 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2575 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2577 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2580 disp = dseg_adds4(cd, 0);
2581 i386_fistpl_membase(cd, REG_ITMP1, disp);
2583 i386_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2585 /* Round to nearest, 53-bit mode, exceptions masked */
2586 disp = dseg_adds4(cd, 0x027f);
2587 i386_fldcw_membase(cd, REG_ITMP1, disp);
2589 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2592 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2593 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2596 i386_jcc(cd, I386_CC_NE, disp);
2598 /* XXX: change this when we use registers */
2599 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2600 i386_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP1);
2601 i386_call_reg(cd, REG_ITMP1);
2603 if (iptr->dst->flags & INMEMORY) {
2604 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2607 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2611 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2612 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2613 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2615 var_to_reg_flt(s1, src, REG_FTMP1);
2616 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2618 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2619 dseg_adddata(cd, cd->mcodeptr);
2621 /* Round to zero, 53-bit mode, exception masked */
2622 disp = dseg_adds4(cd, 0x0e7f);
2623 i386_fldcw_membase(cd, REG_ITMP1, disp);
2625 if (iptr->dst->flags & INMEMORY) {
2626 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2629 /* Round to nearest, 53-bit mode, exceptions masked */
2630 disp = dseg_adds4(cd, 0x027f);
2631 i386_fldcw_membase(cd, REG_ITMP1, disp);
2633 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2636 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2638 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2641 disp = dseg_adds4(cd, 0);
2642 i386_fistpl_membase(cd, REG_ITMP1, disp);
2644 i386_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2646 /* Round to nearest, 53-bit mode, exceptions masked */
2647 disp = dseg_adds4(cd, 0x027f);
2648 i386_fldcw_membase(cd, REG_ITMP1, disp);
2650 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2653 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2654 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2657 i386_jcc(cd, I386_CC_NE, disp);
2659 /* XXX: change this when we use registers */
2660 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2661 i386_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP1);
2662 i386_call_reg(cd, REG_ITMP1);
2664 if (iptr->dst->flags & INMEMORY) {
2665 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2667 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2671 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2672 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2673 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2675 var_to_reg_flt(s1, src, REG_FTMP1);
2676 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2678 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2679 dseg_adddata(cd, cd->mcodeptr);
2681 /* Round to zero, 53-bit mode, exception masked */
2682 disp = dseg_adds4(cd, 0x0e7f);
2683 i386_fldcw_membase(cd, REG_ITMP1, disp);
2685 if (iptr->dst->flags & INMEMORY) {
2686 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2689 /* Round to nearest, 53-bit mode, exceptions masked */
2690 disp = dseg_adds4(cd, 0x027f);
2691 i386_fldcw_membase(cd, REG_ITMP1, disp);
2693 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2696 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2698 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2701 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2703 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2705 i386_jcc(cd, I386_CC_NE, disp);
2707 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2710 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2712 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2714 i386_jcc(cd, I386_CC_NE, disp);
2716 /* XXX: change this when we use registers */
2717 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2718 i386_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP1);
2719 i386_call_reg(cd, REG_ITMP1);
2720 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2721 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2724 log_text("F2L: longs have to be in memory");
2729 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2730 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2731 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2733 var_to_reg_flt(s1, src, REG_FTMP1);
2734 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2736 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2737 dseg_adddata(cd, cd->mcodeptr);
2739 /* Round to zero, 53-bit mode, exception masked */
2740 disp = dseg_adds4(cd, 0x0e7f);
2741 i386_fldcw_membase(cd, REG_ITMP1, disp);
2743 if (iptr->dst->flags & INMEMORY) {
2744 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2747 /* Round to nearest, 53-bit mode, exceptions masked */
2748 disp = dseg_adds4(cd, 0x027f);
2749 i386_fldcw_membase(cd, REG_ITMP1, disp);
2751 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2754 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2756 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2759 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2761 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2763 i386_jcc(cd, I386_CC_NE, disp);
2765 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2768 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2770 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2772 i386_jcc(cd, I386_CC_NE, disp);
2774 /* XXX: change this when we use registers */
2775 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2776 i386_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP1);
2777 i386_call_reg(cd, REG_ITMP1);
2778 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2779 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2782 log_text("D2L: longs have to be in memory");
2787 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2788 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2789 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2791 var_to_reg_flt(s1, src, REG_FTMP1);
2792 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2794 store_reg_to_var_flt(iptr->dst, d);
2797 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2798 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2799 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2801 var_to_reg_flt(s1, src, REG_FTMP1);
2802 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2804 store_reg_to_var_flt(iptr->dst, d);
2807 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2809 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2810 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2812 /* exchanged to skip fxch */
2813 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2814 var_to_reg_flt(s1, src, REG_FTMP2);
2815 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2816 /* i386_fxch(cd); */
2820 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2821 i386_jcc(cd, I386_CC_E, 6);
2822 i386_alu_imm_reg(cd, ALU_AND, 0x000000ff, EAX);
2824 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2825 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2826 i386_jcc(cd, I386_CC_B, 3 + 5);
2827 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2828 i386_jmp_imm(cd, 3);
2829 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2830 store_reg_to_var_int(iptr->dst, d);
2833 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2835 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2836 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2838 /* exchanged to skip fxch */
2839 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2840 var_to_reg_flt(s1, src, REG_FTMP2);
2841 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2842 /* i386_fxch(cd); */
2846 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2847 i386_jcc(cd, I386_CC_E, 3);
2848 i386_movb_imm_reg(cd, 1, REG_AH);
2850 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2851 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2852 i386_jcc(cd, I386_CC_B, 3 + 5);
2853 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2854 i386_jmp_imm(cd, 3);
2855 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2856 store_reg_to_var_int(iptr->dst, d);
2860 /* memory operations **************************************************/
2862 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2863 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2864 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2866 var_to_reg_int(s1, src, REG_ITMP1);
2867 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2868 gen_nullptr_check(s1);
2869 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2870 store_reg_to_var_int(iptr->dst, d);
2873 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2874 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2875 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2877 var_to_reg_int(s1, src->prev, REG_ITMP1);
2878 var_to_reg_int(s2, src, REG_ITMP2);
2879 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2880 if (iptr->op1 == 0) {
2881 gen_nullptr_check(s1);
2884 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2885 store_reg_to_var_int(iptr->dst, d);
2888 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2889 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2890 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2892 var_to_reg_int(s1, src->prev, REG_ITMP1);
2893 var_to_reg_int(s2, src, REG_ITMP2);
2894 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2895 if (iptr->op1 == 0) {
2896 gen_nullptr_check(s1);
2900 if (iptr->dst->flags & INMEMORY) {
2901 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2902 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4);
2903 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2904 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2908 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2909 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2910 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2912 var_to_reg_int(s1, src->prev, REG_ITMP1);
2913 var_to_reg_int(s2, src, REG_ITMP2);
2914 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2915 if (iptr->op1 == 0) {
2916 gen_nullptr_check(s1);
2919 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2920 store_reg_to_var_int(iptr->dst, d);
2923 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2924 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2925 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2927 var_to_reg_int(s1, src->prev, REG_ITMP1);
2928 var_to_reg_int(s2, src, REG_ITMP2);
2929 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2930 if (iptr->op1 == 0) {
2931 gen_nullptr_check(s1);
2934 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2936 store_reg_to_var_flt(iptr->dst, d);
2939 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2940 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2941 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2943 var_to_reg_int(s1, src->prev, REG_ITMP1);
2944 var_to_reg_int(s2, src, REG_ITMP2);
2945 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2946 if (iptr->op1 == 0) {
2947 gen_nullptr_check(s1);
2950 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2952 store_reg_to_var_flt(iptr->dst, d);
2955 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2956 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2957 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2959 var_to_reg_int(s1, src->prev, REG_ITMP1);
2960 var_to_reg_int(s2, src, REG_ITMP2);
2961 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2962 if (iptr->op1 == 0) {
2963 gen_nullptr_check(s1);
2966 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2967 store_reg_to_var_int(iptr->dst, d);
2970 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2971 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2972 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2974 var_to_reg_int(s1, src->prev, REG_ITMP1);
2975 var_to_reg_int(s2, src, REG_ITMP2);
2976 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2977 if (iptr->op1 == 0) {
2978 gen_nullptr_check(s1);
2981 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2982 store_reg_to_var_int(iptr->dst, d);
2985 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2986 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2987 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2989 var_to_reg_int(s1, src->prev, REG_ITMP1);
2990 var_to_reg_int(s2, src, REG_ITMP2);
2991 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2992 if (iptr->op1 == 0) {
2993 gen_nullptr_check(s1);
2996 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2997 store_reg_to_var_int(iptr->dst, d);
3001 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
3002 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3003 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
3005 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3006 var_to_reg_int(s2, src->prev, REG_ITMP2);
3007 if (iptr->op1 == 0) {
3008 gen_nullptr_check(s1);
3012 if (src->flags & INMEMORY) {
3013 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP3);
3014 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
3015 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
3016 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
3020 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
3021 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3022 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3024 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3025 var_to_reg_int(s2, src->prev, REG_ITMP2);
3026 if (iptr->op1 == 0) {
3027 gen_nullptr_check(s1);
3030 var_to_reg_int(s3, src, REG_ITMP3);
3031 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
3034 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
3035 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3036 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3038 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3039 var_to_reg_int(s2, src->prev, REG_ITMP2);
3040 if (iptr->op1 == 0) {
3041 gen_nullptr_check(s1);
3044 var_to_reg_flt(s3, src, REG_FTMP1);
3045 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
3049 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
3050 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3051 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3053 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3054 var_to_reg_int(s2, src->prev, REG_ITMP2);
3055 if (iptr->op1 == 0) {
3056 gen_nullptr_check(s1);
3059 var_to_reg_flt(s3, src, REG_FTMP1);
3060 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
3064 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
3065 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3066 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3068 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3069 var_to_reg_int(s2, src->prev, REG_ITMP2);
3070 if (iptr->op1 == 0) {
3071 gen_nullptr_check(s1);
3074 var_to_reg_int(s3, src, REG_ITMP3);
3075 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
3078 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
3079 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3080 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3082 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3083 var_to_reg_int(s2, src->prev, REG_ITMP2);
3084 if (iptr->op1 == 0) {
3085 gen_nullptr_check(s1);
3088 var_to_reg_int(s3, src, REG_ITMP3);
3089 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3092 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
3093 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3094 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3096 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3097 var_to_reg_int(s2, src->prev, REG_ITMP2);
3098 if (iptr->op1 == 0) {
3099 gen_nullptr_check(s1);
3102 var_to_reg_int(s3, src, REG_ITMP3);
3103 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
3104 M_INTMOVE(s3, REG_ITMP3);
3107 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3110 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
3112 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3113 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
3115 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3116 var_to_reg_int(s2, src->prev, REG_ITMP2);
3117 if (iptr->op1 == 0) {
3118 gen_nullptr_check(s1);
3121 var_to_reg_int(s3, src, REG_ITMP3);
3123 M_AST(s1, REG_SP, 0 * 4);
3124 M_AST(s3, REG_SP, 1 * 4);
3125 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
3129 codegen_add_arraystoreexception_ref(cd, cd->mcodeptr);
3131 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3132 var_to_reg_int(s2, src->prev, REG_ITMP2);
3133 var_to_reg_int(s3, src, REG_ITMP3);
3134 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3137 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
3138 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3139 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3141 var_to_reg_int(s1, src->prev, REG_ITMP1);
3142 var_to_reg_int(s2, src, REG_ITMP2);
3143 if (iptr->op1 == 0) {
3144 gen_nullptr_check(s1);
3147 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
3150 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
3151 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3152 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3154 var_to_reg_int(s1, src->prev, REG_ITMP1);
3155 var_to_reg_int(s2, src, REG_ITMP2);
3156 if (iptr->op1 == 0) {
3157 gen_nullptr_check(s1);
3161 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
3162 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
3165 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
3166 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3167 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3169 var_to_reg_int(s1, src->prev, REG_ITMP1);
3170 var_to_reg_int(s2, src, REG_ITMP2);
3171 if (iptr->op1 == 0) {
3172 gen_nullptr_check(s1);
3175 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3178 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
3179 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3180 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3182 var_to_reg_int(s1, src->prev, REG_ITMP1);
3183 var_to_reg_int(s2, src, REG_ITMP2);
3184 if (iptr->op1 == 0) {
3185 gen_nullptr_check(s1);
3188 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3191 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
3192 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3193 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3195 var_to_reg_int(s1, src->prev, REG_ITMP1);
3196 var_to_reg_int(s2, src, REG_ITMP2);
3197 if (iptr->op1 == 0) {
3198 gen_nullptr_check(s1);
3201 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
3204 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
3205 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3206 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3208 var_to_reg_int(s1, src->prev, REG_ITMP1);
3209 var_to_reg_int(s2, src, REG_ITMP2);
3210 if (iptr->op1 == 0) {
3211 gen_nullptr_check(s1);
3214 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3218 case ICMD_GETSTATIC: /* ... ==> ..., value */
3219 /* op1 = type, val.a = field address */
3220 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3221 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX*/
3223 if (iptr->val.a == NULL) {
3224 codegen_addpatchref(cd, cd->mcodeptr,
3225 PATCHER_get_putstatic,
3226 (unresolved_field *) iptr->target, 0);
3228 if (opt_showdisassemble) {
3229 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3235 fieldinfo *fi = iptr->val.a;
3237 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3238 codegen_addpatchref(cd, cd->mcodeptr,
3239 PATCHER_clinit, fi->class, 0);
3241 if (opt_showdisassemble) {
3242 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3246 disp = (ptrint) &(fi->value);
3249 M_MOV_IMM(disp, REG_ITMP1);
3250 switch (iptr->op1) {
3253 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3254 M_ILD(d, REG_ITMP1, 0);
3255 store_reg_to_var_int(iptr->dst, d);
3258 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
3259 if (iptr->dst->flags & INMEMORY) {
3260 /* Using both REG_ITMP2 and REG_ITMP3 is faster
3261 than only using REG_ITMP2 alternating. */
3262 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP2);
3263 i386_mov_membase_reg(cd, REG_ITMP1, 4, REG_ITMP3);
3264 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4);
3265 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
3267 log_text("GETSTATIC: longs have to be in memory");
3272 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
3273 i386_flds_membase(cd, REG_ITMP1, 0);
3275 store_reg_to_var_flt(iptr->dst, d);
3278 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
3279 i386_fldl_membase(cd, REG_ITMP1, 0);
3281 store_reg_to_var_flt(iptr->dst, d);
3286 case ICMD_PUTSTATIC: /* ..., value ==> ... */
3287 /* op1 = type, val.a = field address */
3288 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3289 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3291 if (iptr->val.a == NULL) {
3292 codegen_addpatchref(cd, cd->mcodeptr,
3293 PATCHER_get_putstatic,
3294 (unresolved_field *) iptr->target, 0);
3296 if (opt_showdisassemble) {
3297 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3303 fieldinfo *fi = iptr->val.a;
3305 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3306 codegen_addpatchref(cd, cd->mcodeptr,
3307 PATCHER_clinit, fi->class, 0);
3309 if (opt_showdisassemble) {
3310 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3314 disp = (ptrint) &(fi->value);
3317 M_MOV_IMM(disp, REG_ITMP1);
3318 switch (iptr->op1) {
3321 var_to_reg_int(s2, src, REG_ITMP2);
3322 M_IST(s2, REG_ITMP1, 0);
3325 if (src->flags & INMEMORY) {
3326 /* Using both REG_ITMP2 and REG_ITMP3 is faster
3327 than only using REG_ITMP2 alternating. */
3330 i386_mov_membase_reg(cd, REG_SP, s2 * 4, REG_ITMP2);
3331 i386_mov_membase_reg(cd, REG_SP, s2 * 4 + 4, REG_ITMP3);
3332 i386_mov_reg_membase(cd, REG_ITMP2, REG_ITMP1, 0);
3333 i386_mov_reg_membase(cd, REG_ITMP3, REG_ITMP1, 4);
3335 log_text("PUTSTATIC: longs have to be in memory");
3340 var_to_reg_flt(s2, src, REG_FTMP1);
3341 i386_fstps_membase(cd, REG_ITMP1, 0);
3345 var_to_reg_flt(s2, src, REG_FTMP1);
3346 i386_fstpl_membase(cd, REG_ITMP1, 0);
3352 case ICMD_PUTSTATICCONST: /* ... ==> ... */
3353 /* val = value (in current instruction) */
3354 /* op1 = type, val.a = field address (in */
3355 /* following NOP) */
3356 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3357 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3359 if (iptr[1].val.a == NULL) {
3360 codegen_addpatchref(cd, cd->mcodeptr,
3361 PATCHER_get_putstatic,
3362 (unresolved_field *) iptr[1].target, 0);
3364 if (opt_showdisassemble) {
3365 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3371 fieldinfo *fi = iptr[1].val.a;
3373 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3374 codegen_addpatchref(cd, cd->mcodeptr,
3375 PATCHER_clinit, fi->class, 0);
3377 if (opt_showdisassemble) {
3378 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3382 disp = (ptrint) &(fi->value);
3385 M_MOV_IMM(disp, REG_ITMP1);
3386 switch (iptr[1].op1) {
3390 i386_mov_imm_membase(cd, iptr->val.i, REG_ITMP1, 0);
3394 i386_mov_imm_membase(cd, iptr->val.l, REG_ITMP1, 0);
3395 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_ITMP1, 4);
3400 case ICMD_GETFIELD: /* .., objectref. ==> ..., value */
3401 /* op1 = type, val.i = field offset */
3402 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3403 /* EAX: YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
3405 var_to_reg_int(s1, src, REG_ITMP1);
3406 gen_nullptr_check(s1);
3408 if (iptr->val.a == NULL) {
3409 codegen_addpatchref(cd, cd->mcodeptr,
3411 (unresolved_field *) iptr->target, 0);
3413 if (opt_showdisassemble) {
3414 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3420 disp = ((fieldinfo *) (iptr->val.a))->offset;
3423 switch (iptr->op1) {
3426 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3427 M_ILD32(d, s1, disp);
3428 store_reg_to_var_int(iptr->dst, d);
3431 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
3432 M_LLD32(d, s1, disp);
3433 store_reg_to_var_lng(iptr->dst, d);
3436 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
3437 i386_flds_membase32(cd, s1, disp);
3439 store_reg_to_var_flt(iptr->dst, d);
3442 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
3443 i386_fldl_membase32(cd, s1, disp);
3445 store_reg_to_var_flt(iptr->dst, d);
3450 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
3451 /* op1 = type, val.a = field address */
3452 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3453 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3455 var_to_reg_int(s1, src->prev, REG_ITMP1);
3456 gen_nullptr_check(s1);
3458 /* must be done here because of code patching */
3460 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
3461 if (IS_2_WORD_TYPE(iptr->op1))
3462 var_to_reg_lng(s2, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
3464 var_to_reg_int(s2, src, REG_ITMP2);
3466 var_to_reg_flt(s2, src, REG_FTMP2);
3468 if (iptr->val.a == NULL) {
3469 codegen_addpatchref(cd, cd->mcodeptr,
3471 (unresolved_field *) iptr->target, 0);
3473 if (opt_showdisassemble) {
3474 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3480 disp = ((fieldinfo *) (iptr->val.a))->offset;
3483 switch (iptr->op1) {
3486 M_IST32(s2, s1, disp);
3489 M_LST32(s2, s1, disp);
3492 i386_fstps_membase32(cd, s1, disp);
3496 i386_fstpl_membase32(cd, s1, disp);
3502 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
3503 /* val = value (in current instruction) */
3504 /* op1 = type, val.a = field address (in */
3505 /* following NOP) */
3506 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3507 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3509 var_to_reg_int(s1, src, REG_ITMP1);
3510 gen_nullptr_check(s1);
3512 if (iptr[1].val.a == NULL) {
3513 codegen_addpatchref(cd, cd->mcodeptr,
3514 PATCHER_putfieldconst,
3515 (unresolved_field *) iptr[1].target, 0);
3517 if (opt_showdisassemble) {
3518 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3524 disp = ((fieldinfo *) (iptr[1].val.a))->offset;
3527 switch (iptr[1].op1) {
3531 M_IST32_IMM(iptr->val.i, s1, disp);
3535 M_LST32_IMM(iptr->val.l, s1, disp);
3541 /* branch operations **************************************************/
3543 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3544 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3545 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
3547 var_to_reg_int(s1, src, REG_ITMP1);
3548 M_INTMOVE(s1, REG_ITMP1_XPTR);
3550 #ifdef ENABLE_VERIFIER
3552 codegen_addpatchref(cd, cd->mcodeptr,
3553 PATCHER_athrow_areturn,
3554 (unresolved_class *) iptr->val.a, 0);
3556 if (opt_showdisassemble) {
3557 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3560 #endif /* ENABLE_VERIFIER */
3562 M_CALL_IMM(0); /* passing exception pc */
3563 M_POP(REG_ITMP2_XPC);
3565 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
3569 case ICMD_INLINE_GOTO:
3571 M_COPY(src,iptr->dst);
3574 case ICMD_GOTO: /* ... ==> ... */
3575 /* op1 = target JavaVM pc */
3576 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3577 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3580 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3584 case ICMD_JSR: /* ... ==> ... */
3585 /* op1 = target JavaVM pc */
3586 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3587 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3590 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3593 case ICMD_RET: /* ... ==> ... */
3594 /* op1 = local variable */
3595 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3596 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3598 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3599 var_to_reg_int(s1, var, REG_ITMP1);
3600 i386_jmp_reg(cd, s1);
3603 case ICMD_IFNULL: /* ..., value ==> ... */
3604 /* op1 = target JavaVM pc */
3605 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3606 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3608 if (src->flags & INMEMORY) {
3609 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3612 i386_test_reg_reg(cd, src->regoff, src->regoff);
3614 i386_jcc(cd, I386_CC_E, 0);
3615 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3618 case ICMD_IFNONNULL: /* ..., value ==> ... */
3619 /* op1 = target JavaVM pc */
3620 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3621 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3623 if (src->flags & INMEMORY) {
3624 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3627 i386_test_reg_reg(cd, src->regoff, src->regoff);
3629 i386_jcc(cd, I386_CC_NE, 0);
3630 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3633 case ICMD_IFEQ: /* ..., value ==> ... */
3634 /* op1 = target JavaVM pc, val.i = constant */
3635 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3636 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3638 if (src->flags & INMEMORY) {
3639 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3642 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3644 i386_jcc(cd, I386_CC_E, 0);
3645 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3648 case ICMD_IFLT: /* ..., value ==> ... */
3649 /* op1 = target JavaVM pc, val.i = constant */
3650 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3651 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3653 if (src->flags & INMEMORY) {
3654 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3657 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3659 i386_jcc(cd, I386_CC_L, 0);
3660 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3663 case ICMD_IFLE: /* ..., value ==> ... */
3664 /* op1 = target JavaVM pc, val.i = constant */
3665 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3666 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3668 if (src->flags & INMEMORY) {
3669 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3672 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3674 i386_jcc(cd, I386_CC_LE, 0);
3675 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3678 case ICMD_IFNE: /* ..., value ==> ... */
3679 /* op1 = target JavaVM pc, val.i = constant */
3680 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3681 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3683 if (src->flags & INMEMORY) {
3684 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3687 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3689 i386_jcc(cd, I386_CC_NE, 0);
3690 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3693 case ICMD_IFGT: /* ..., value ==> ... */
3694 /* op1 = target JavaVM pc, val.i = constant */
3695 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3696 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3698 if (src->flags & INMEMORY) {
3699 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3702 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3704 i386_jcc(cd, I386_CC_G, 0);
3705 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3708 case ICMD_IFGE: /* ..., value ==> ... */
3709 /* op1 = target JavaVM pc, val.i = constant */
3710 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3711 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3713 if (src->flags & INMEMORY) {
3714 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3717 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3719 i386_jcc(cd, I386_CC_GE, 0);
3720 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3723 case ICMD_IF_LEQ: /* ..., value ==> ... */
3724 /* op1 = target JavaVM pc, val.l = constant */
3725 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3726 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3728 if (src->flags & INMEMORY) {
3729 if (iptr->val.l == 0) {
3730 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3731 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3734 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3735 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l >> 32, REG_ITMP2);
3736 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3737 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l, REG_ITMP1);
3738 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3741 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3742 i386_jcc(cd, I386_CC_E, 0);
3743 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3746 case ICMD_IF_LLT: /* ..., value ==> ... */
3747 /* op1 = target JavaVM pc, val.l = constant */
3748 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3749 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3751 if (src->flags & INMEMORY) {
3752 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3753 i386_jcc(cd, I386_CC_L, 0);
3754 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3757 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3758 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3760 i386_jcc(cd, I386_CC_G, disp);
3762 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3763 i386_jcc(cd, I386_CC_B, 0);
3764 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3768 case ICMD_IF_LLE: /* ..., value ==> ... */
3769 /* op1 = target JavaVM pc, val.l = constant */
3770 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3771 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3773 if (src->flags & INMEMORY) {
3774 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3775 i386_jcc(cd, I386_CC_L, 0);
3776 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3779 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3780 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3782 i386_jcc(cd, I386_CC_G, disp);
3784 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3785 i386_jcc(cd, I386_CC_BE, 0);
3786 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3790 case ICMD_IF_LNE: /* ..., value ==> ... */
3791 /* op1 = target JavaVM pc, val.l = constant */
3792 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3793 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3795 if (src->flags & INMEMORY) {
3796 if (iptr->val.l == 0) {
3797 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3798 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3801 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3802 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3803 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3804 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3805 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3808 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3809 i386_jcc(cd, I386_CC_NE, 0);
3810 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3813 case ICMD_IF_LGT: /* ..., value ==> ... */
3814 /* op1 = target JavaVM pc, val.l = constant */
3815 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3816 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3818 if (src->flags & INMEMORY) {
3819 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3820 i386_jcc(cd, I386_CC_G, 0);
3821 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3824 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3825 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3827 i386_jcc(cd, I386_CC_L, disp);
3829 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3830 i386_jcc(cd, I386_CC_A, 0);
3831 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3835 case ICMD_IF_LGE: /* ..., value ==> ... */
3836 /* op1 = target JavaVM pc, val.l = constant */
3837 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3838 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3840 if (src->flags & INMEMORY) {
3841 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3842 i386_jcc(cd, I386_CC_G, 0);
3843 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3846 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3847 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3849 i386_jcc(cd, I386_CC_L, disp);
3851 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3852 i386_jcc(cd, I386_CC_AE, 0);
3853 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3857 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3858 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3859 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3860 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3862 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3863 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3864 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3866 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3867 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3869 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3870 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3873 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3875 i386_jcc(cd, I386_CC_E, 0);
3876 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3879 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3880 /* op1 = target JavaVM pc */
3881 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3882 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3884 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3885 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3886 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3887 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3888 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3889 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3890 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3892 i386_jcc(cd, I386_CC_E, 0);
3893 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3896 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3897 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3898 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3899 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3901 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3902 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3903 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3905 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3906 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3908 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3909 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3912 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3914 i386_jcc(cd, I386_CC_NE, 0);
3915 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3918 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3919 /* op1 = target JavaVM pc */
3920 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3921 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3923 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3924 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3925 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3926 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3927 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3928 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3929 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3931 i386_jcc(cd, I386_CC_NE, 0);
3932 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3935 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3936 /* op1 = target JavaVM pc */
3937 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3938 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3940 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3941 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3942 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3944 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3945 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3947 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3948 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3951 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3953 i386_jcc(cd, I386_CC_L, 0);
3954 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3957 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3958 /* op1 = target JavaVM pc */
3959 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3960 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3962 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3963 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3964 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3966 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3969 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3970 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3974 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3975 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3976 i386_jcc(cd, I386_CC_B, 0);
3977 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3981 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3982 /* op1 = target JavaVM pc */
3983 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3984 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3986 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3987 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3988 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3990 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3991 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3993 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3994 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3997 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
4000 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4003 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
4004 /* op1 = target JavaVM pc */
4005 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4006 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4008 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
4009 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
4010 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
4012 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4015 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
4016 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
4020 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
4021 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
4022 i386_jcc(cd, I386_CC_A, 0);
4023 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4027 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
4028 /* op1 = target JavaVM pc */
4029 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4030 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4032 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
4033 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
4034 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
4036 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
4037 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
4039 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
4040 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
4043 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
4046 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4049 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
4050 /* op1 = target JavaVM pc */
4051 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4052 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4054 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
4055 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
4056 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
4058 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4061 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
4062 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
4066 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
4067 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
4069 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4073 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
4074 /* op1 = target JavaVM pc */
4075 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4076 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4078 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
4079 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
4080 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
4082 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
4083 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
4085 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
4086 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
4089 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
4092 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4095 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
4096 /* op1 = target JavaVM pc */
4097 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4098 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4100 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
4101 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
4102 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
4104 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4107 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
4108 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
4112 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
4113 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
4115 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4119 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
4121 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
4122 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4123 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4126 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
4127 /* val.i = constant */
4128 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4129 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4131 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4132 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
4135 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
4136 /* val.i = constant */
4137 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4138 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4140 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4141 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
4144 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
4145 /* val.i = constant */
4146 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4147 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4149 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4150 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
4153 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
4154 /* val.i = constant */
4155 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4156 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4158 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4159 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
4162 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
4163 /* val.i = constant */
4164 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4165 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4167 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4168 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
4171 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
4172 /* val.i = constant */
4173 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4174 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4176 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4177 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
4181 case ICMD_IRETURN: /* ..., retvalue ==> ... */
4182 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4183 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4185 var_to_reg_int(s1, src, REG_RESULT);
4186 M_INTMOVE(s1, REG_RESULT);
4187 goto nowperformreturn;
4189 case ICMD_LRETURN: /* ..., retvalue ==> ... */
4190 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4191 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4193 if (src->flags & INMEMORY) {
4194 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_RESULT);
4195 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_RESULT2);
4198 log_text("LRETURN: longs have to be in memory");
4201 goto nowperformreturn;
4203 case ICMD_ARETURN: /* ..., retvalue ==> ... */
4204 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4205 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4207 var_to_reg_int(s1, src, REG_RESULT);
4208 M_INTMOVE(s1, REG_RESULT);
4210 #ifdef ENABLE_VERIFIER
4212 codegen_addpatchref(cd, cd->mcodeptr,
4213 PATCHER_athrow_areturn,
4214 (unresolved_class *) iptr->val.a, 0);
4216 if (opt_showdisassemble) {
4217 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4220 #endif /* ENABLE_VERIFIER */
4221 goto nowperformreturn;
4223 case ICMD_FRETURN: /* ..., retvalue ==> ... */
4225 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4226 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4228 var_to_reg_flt(s1, src, REG_FRESULT);
4229 /* this may be an early return -- keep the offset correct for the
4232 goto nowperformreturn;
4234 case ICMD_RETURN: /* ... ==> ... */
4235 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4236 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4244 #if !defined(NDEBUG)
4245 /* call trace function */
4246 if (opt_verbosecall) {
4247 i386_alu_imm_reg(cd, ALU_SUB, 4 + 8 + 8 + 4, REG_SP);
4249 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
4251 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
4252 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
4254 i386_fstl_membase(cd, REG_SP, 4 + 8);
4255 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
4257 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
4258 i386_call_reg(cd, REG_ITMP1);
4260 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
4261 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
4263 i386_alu_imm_reg(cd, ALU_ADD, 4 + 8 + 8 + 4, REG_SP);
4265 #endif /* !defined(NDEBUG) */
4267 #if defined(USE_THREADS)
4268 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
4269 M_ALD(REG_ITMP2, REG_SP, rd->memuse * 4);
4271 /* we need to save the proper return value */
4272 switch (iptr->opc) {
4275 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4279 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4280 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4284 i386_fstps_membase(cd, REG_SP, rd->memuse * 4);
4288 i386_fstpl_membase(cd, REG_SP, rd->memuse * 4);
4292 M_AST(REG_ITMP2, REG_SP, 0);
4293 M_MOV_IMM(BUILTIN_monitorexit, REG_ITMP1);
4296 /* and now restore the proper return value */
4297 switch (iptr->opc) {
4300 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4304 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4305 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4309 i386_flds_membase(cd, REG_SP, rd->memuse * 4);
4313 i386_fldl_membase(cd, REG_SP, rd->memuse * 4);
4319 /* restore saved registers */
4321 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
4322 p--; M_ALD(rd->savintregs[i], REG_SP, p * 4);
4325 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
4327 i386_fldl_membase(cd, REG_SP, p * 4);
4329 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
4330 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
4332 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
4337 /* deallocate stack */
4340 M_AADD_IMM(stackframesize * 4, REG_SP);
4347 case ICMD_TABLESWITCH: /* ..., index ==> ... */
4348 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4349 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4354 tptr = (void **) iptr->target;
4356 s4ptr = iptr->val.a;
4357 l = s4ptr[1]; /* low */
4358 i = s4ptr[2]; /* high */
4360 var_to_reg_int(s1, src, REG_ITMP1);
4361 M_INTMOVE(s1, REG_ITMP1);
4363 i386_alu_imm_reg(cd, ALU_SUB, l, REG_ITMP1);
4369 i386_alu_imm_reg(cd, ALU_CMP, i - 1, REG_ITMP1);
4370 i386_jcc(cd, I386_CC_A, 0);
4372 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4374 /* build jump table top down and use address of lowest entry */
4379 dseg_addtarget(cd, (basicblock *) tptr[0]);
4383 /* length of dataseg after last dseg_addtarget is used by load */
4385 i386_mov_imm_reg(cd, 0, REG_ITMP2);
4386 dseg_adddata(cd, cd->mcodeptr);
4387 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
4388 i386_jmp_reg(cd, REG_ITMP1);
4393 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
4394 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4395 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4397 s4 i, l, val, *s4ptr;
4400 tptr = (void **) iptr->target;
4402 s4ptr = iptr->val.a;
4403 l = s4ptr[0]; /* default */
4404 i = s4ptr[1]; /* count */
4406 MCODECHECK((i<<2)+8);
4407 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
4413 i386_alu_imm_reg(cd, ALU_CMP, val, s1);
4414 i386_jcc(cd, I386_CC_E, 0);
4415 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4418 i386_jmp_imm(cd, 0);
4420 tptr = (void **) iptr->target;
4421 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4425 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
4426 /* op1 = arg count val.a = builtintable entry */
4427 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4428 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4434 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
4435 /* op1 = arg count, val.a = method pointer */
4437 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
4438 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
4439 case ICMD_INVOKEINTERFACE:
4441 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4442 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
4447 unresolved_method *um = iptr->target;
4448 md = um->methodref->parseddesc.md;
4450 md = lm->parseddesc;
4454 s3 = md->paramcount;
4456 MCODECHECK((s3 << 1) + 64);
4458 /* copy arguments to registers or stack location */
4460 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
4461 if (src->varkind == ARGVAR)
4463 if (IS_INT_LNG_TYPE(src->type)) {
4464 if (!md->params[s3].inmemory) {
4465 log_text("No integer argument registers available!");
4468 if (!IS_2_WORD_TYPE(src->type)) {
4469 if (src->flags & INMEMORY) {
4470 i386_mov_membase_reg(
4471 cd, REG_SP, src->regoff * 4, REG_ITMP1);
4472 i386_mov_reg_membase(
4473 cd, REG_ITMP1, REG_SP,
4474 md->params[s3].regoff * 4);
4476 i386_mov_reg_membase(
4477 cd, src->regoff, REG_SP,
4478 md->params[s3].regoff * 4);
4482 if (src->flags & INMEMORY) {
4484 src->regoff, md->params[s3].regoff);
4486 log_text("copy arguments: longs have to be in memory");
4492 if (!md->params[s3].inmemory) {
4493 log_text("No float argument registers available!");
4496 var_to_reg_flt(d, src, REG_FTMP1);
4497 if (src->type == TYPE_FLT) {
4499 cd, REG_SP, md->params[s3].regoff * 4);
4503 cd, REG_SP, md->params[s3].regoff * 4);
4509 switch (iptr->opc) {
4511 disp = (ptrint) bte->fp;
4512 d = md->returntype.type;
4514 M_MOV_IMM(disp, REG_ITMP1);
4517 /* if op1 == true, we need to check for an exception */
4519 if (iptr->op1 == true) {
4522 codegen_add_fillinstacktrace_ref(cd, cd->mcodeptr);
4526 case ICMD_INVOKESPECIAL:
4527 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
4528 gen_nullptr_check(REG_ITMP1);
4530 /* access memory for hardware nullptr */
4531 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1);
4535 case ICMD_INVOKESTATIC:
4537 unresolved_method *um = iptr->target;
4539 codegen_addpatchref(cd, cd->mcodeptr,
4540 PATCHER_invokestatic_special, um, 0);
4542 if (opt_showdisassemble) {
4543 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4547 d = md->returntype.type;
4550 disp = (ptrint) lm->stubroutine;
4551 d = lm->parseddesc->returntype.type;
4554 M_MOV_IMM(disp, REG_ITMP2);
4558 case ICMD_INVOKEVIRTUAL:
4559 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4560 gen_nullptr_check(REG_ITMP1);
4563 unresolved_method *um = iptr->target;
4565 codegen_addpatchref(cd, cd->mcodeptr,
4566 PATCHER_invokevirtual, um, 0);
4568 if (opt_showdisassemble) {
4569 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4573 d = md->returntype.type;
4576 s1 = OFFSET(vftbl_t, table[0]) +
4577 sizeof(methodptr) * lm->vftblindex;
4578 d = md->returntype.type;
4581 M_ALD(REG_ITMP2, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4582 i386_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP1);
4586 case ICMD_INVOKEINTERFACE:
4587 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4588 gen_nullptr_check(REG_ITMP1);
4591 unresolved_method *um = iptr->target;
4593 codegen_addpatchref(cd, cd->mcodeptr,
4594 PATCHER_invokeinterface, um, 0);
4596 if (opt_showdisassemble) {
4597 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4602 d = md->returntype.type;
4605 s1 = OFFSET(vftbl_t, interfacetable[0]) -
4606 sizeof(methodptr) * lm->class->index;
4608 s2 = sizeof(methodptr) * (lm - lm->class->methods);
4610 d = md->returntype.type;
4613 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4614 i386_mov_membase32_reg(cd, REG_ITMP1, s1, REG_ITMP2);
4615 i386_mov_membase32_reg(cd, REG_ITMP2, s2, REG_ITMP1);
4620 /* d contains return type */
4622 if (d != TYPE_VOID) {
4623 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4625 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
4626 if (IS_2_WORD_TYPE(iptr->dst->type)) {
4627 if (iptr->dst->flags & INMEMORY) {
4628 i386_mov_reg_membase(
4629 cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4630 i386_mov_reg_membase(
4631 cd, REG_RESULT2, REG_SP,
4632 iptr->dst->regoff * 4 + 4);
4634 log_text("RETURN: longs have to be in memory");
4639 if (iptr->dst->flags & INMEMORY) {
4640 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4643 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
4648 /* fld from called function -- has other fpu_st_offset counter */
4650 store_reg_to_var_flt(iptr->dst, d);
4656 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4657 /* op1: 0 == array, 1 == class */
4658 /* val.a: (classinfo*) superclass */
4660 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4661 /* EAX: YES ECX: I|YES EDX: I|YES OUTPUT: REG_NULL */
4663 /* superclass is an interface:
4665 * OK if ((sub == NULL) ||
4666 * (sub->vftbl->interfacetablelength > super->index) &&
4667 * (sub->vftbl->interfacetable[-super->index] != NULL));
4669 * superclass is a class:
4671 * OK if ((sub == NULL) || (0
4672 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4673 * super->vftbl->diffval));
4676 if (iptr->op1 == 1) {
4677 /* object type cast-check */
4680 vftbl_t *supervftbl;
4683 super = (classinfo *) iptr->val.a;
4690 superindex = super->index;
4691 supervftbl = super->vftbl;
4694 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4695 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4697 var_to_reg_int(s1, src, REG_ITMP1);
4699 /* calculate interface checkcast code size */
4701 s2 = 2; /* mov_membase_reg */
4702 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4704 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ +
4705 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4706 2 /* test */ + 6 /* jcc */);
4709 s2 += (opt_showdisassemble ? 5 : 0);
4711 /* calculate class checkcast code size */
4713 s3 = 2; /* mov_membase_reg */
4714 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4716 s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */;
4719 if (s1 != REG_ITMP1) {
4721 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
4724 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
4731 s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ +
4732 5 /* mov_imm_reg */ + 2 /* mov_membase_reg */);
4733 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
4736 s3 += 2 /* cmp */ + 6 /* jcc */;
4739 s3 += (opt_showdisassemble ? 5 : 0);
4741 /* if class is not resolved, check which code to call */
4744 i386_test_reg_reg(cd, s1, s1);
4745 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4747 codegen_addpatchref(cd, cd->mcodeptr,
4748 PATCHER_checkcast_instanceof_flags,
4749 (constant_classref *) iptr->target, 0);
4751 if (opt_showdisassemble) {
4752 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4755 i386_mov_imm_reg(cd, 0, REG_ITMP2); /* super->flags */
4756 i386_alu_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP2);
4757 i386_jcc(cd, I386_CC_Z, s2 + 5);
4760 /* interface checkcast code */
4762 if (!super || (super->flags & ACC_INTERFACE)) {
4764 i386_test_reg_reg(cd, s1, s1);
4765 i386_jcc(cd, I386_CC_Z, s2);
4768 i386_mov_membase_reg(cd, s1,
4769 OFFSET(java_objectheader, vftbl),
4773 codegen_addpatchref(cd, cd->mcodeptr,
4774 PATCHER_checkcast_instanceof_interface,
4775 (constant_classref *) iptr->target, 0);
4777 if (opt_showdisassemble) {
4778 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4782 i386_mov_membase32_reg(cd, REG_ITMP2,
4783 OFFSET(vftbl_t, interfacetablelength),
4785 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4786 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4787 i386_jcc(cd, I386_CC_LE, 0);
4788 codegen_add_classcastexception_ref(cd, cd->mcodeptr);
4789 i386_mov_membase32_reg(cd, REG_ITMP2,
4790 OFFSET(vftbl_t, interfacetable[0]) -
4791 superindex * sizeof(methodptr*),
4793 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4794 i386_jcc(cd, I386_CC_E, 0);
4795 codegen_add_classcastexception_ref(cd, cd->mcodeptr);
4798 i386_jmp_imm(cd, s3);
4801 /* class checkcast code */
4803 if (!super || !(super->flags & ACC_INTERFACE)) {
4805 i386_test_reg_reg(cd, s1, s1);
4806 i386_jcc(cd, I386_CC_Z, s3);
4809 i386_mov_membase_reg(cd, s1,
4810 OFFSET(java_objectheader, vftbl),
4814 codegen_addpatchref(cd, cd->mcodeptr,
4815 PATCHER_checkcast_class,
4816 (constant_classref *) iptr->target, 0);
4818 if (opt_showdisassemble) {
4819 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4823 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4824 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4825 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4827 i386_mov_membase32_reg(cd, REG_ITMP2,
4828 OFFSET(vftbl_t, baseval),
4831 /* if (s1 != REG_ITMP1) { */
4832 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
4833 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
4834 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
4835 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
4837 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
4840 i386_mov_membase32_reg(cd, REG_ITMP3,
4841 OFFSET(vftbl_t, baseval),
4843 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP3, REG_ITMP2);
4844 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4845 i386_mov_membase_reg(cd, REG_ITMP3,
4846 OFFSET(vftbl_t, diffval),
4848 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4849 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4853 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP2);
4854 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
4855 codegen_add_classcastexception_ref(cd, cd->mcodeptr);
4857 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
4860 /* array type cast-check */
4862 var_to_reg_int(s1, src, REG_ITMP1);
4863 M_AST(s1, REG_SP, 0 * 4);
4865 if (iptr->val.a == NULL) {
4866 codegen_addpatchref(cd, cd->mcodeptr,
4867 PATCHER_builtin_arraycheckcast,
4870 if (opt_showdisassemble) {
4871 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4875 M_AST_IMM(iptr->val.a, REG_SP, 1 * 4);
4876 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP3);
4880 codegen_add_classcastexception_ref(cd, cd->mcodeptr);
4882 var_to_reg_int(s1, src, REG_ITMP1);
4883 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
4886 store_reg_to_var_int(iptr->dst, d);
4889 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
4891 /* op1: 0 == array, 1 == class */
4892 /* val.a: (classinfo*) superclass */
4893 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4894 /* EAX: S|D|YES ECX: YES S|D|EDX: S|D|YES OUTPUT: REG_NULL*/
4895 /* ????? Really necessary to block all ????? */
4897 /* superclass is an interface:
4899 * return (sub != NULL) &&
4900 * (sub->vftbl->interfacetablelength > super->index) &&
4901 * (sub->vftbl->interfacetable[-super->index] != NULL);
4903 * superclass is a class:
4905 * return ((sub != NULL) && (0
4906 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4907 * super->vftbl->diffvall));
4912 vftbl_t *supervftbl;
4915 super = (classinfo *) iptr->val.a;
4922 superindex = super->index;
4923 supervftbl = super->vftbl;
4926 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4927 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4930 var_to_reg_int(s1, src, REG_ITMP1);
4931 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
4933 M_INTMOVE(s1, REG_ITMP1);
4937 /* calculate interface instanceof code size */
4939 s2 = 2; /* mov_membase_reg */
4940 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4942 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
4943 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4944 2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4947 s2 += (opt_showdisassemble ? 5 : 0);
4949 /* calculate class instanceof code size */
4951 s3 = 2; /* mov_membase_reg */
4952 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4953 s3 += 5; /* mov_imm_reg */
4955 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
4957 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
4959 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
4961 s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
4962 2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4965 s3 += (opt_showdisassemble ? 5 : 0);
4967 i386_alu_reg_reg(cd, ALU_XOR, d, d);
4969 /* if class is not resolved, check which code to call */
4972 i386_test_reg_reg(cd, s1, s1);
4973 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4975 codegen_addpatchref(cd, cd->mcodeptr,
4976 PATCHER_checkcast_instanceof_flags,
4977 (constant_classref *) iptr->target, 0);
4979 if (opt_showdisassemble) {
4980 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4983 i386_mov_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
4984 i386_alu_imm32_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
4985 i386_jcc(cd, I386_CC_Z, s2 + 5);
4988 /* interface instanceof code */
4990 if (!super || (super->flags & ACC_INTERFACE)) {
4996 i386_mov_membase_reg(cd, s1,
4997 OFFSET(java_objectheader, vftbl),
5001 codegen_addpatchref(cd, cd->mcodeptr,
5002 PATCHER_checkcast_instanceof_interface,
5003 (constant_classref *) iptr->target, 0);
5005 if (opt_showdisassemble) {
5006 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5010 i386_mov_membase32_reg(cd, REG_ITMP1,
5011 OFFSET(vftbl_t, interfacetablelength),
5013 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
5014 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
5016 disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
5017 6 /* jcc */ + 5 /* mov_imm_reg */);
5020 i386_mov_membase32_reg(cd, REG_ITMP1,
5021 OFFSET(vftbl_t, interfacetable[0]) -
5022 superindex * sizeof(methodptr*),
5025 /* i386_setcc_reg(cd, I386_CC_A, d); */
5026 /* i386_jcc(cd, I386_CC_BE, 5); */
5034 /* class instanceof code */
5036 if (!super || !(super->flags & ACC_INTERFACE)) {
5042 i386_mov_membase_reg(cd, s1,
5043 OFFSET(java_objectheader, vftbl),
5047 codegen_addpatchref(cd, cd->mcodeptr,
5048 PATCHER_instanceof_class,
5049 (constant_classref *) iptr->target, 0);
5051 if (opt_showdisassemble) {
5052 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5056 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
5057 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5058 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
5060 i386_mov_membase_reg(cd, REG_ITMP1,
5061 OFFSET(vftbl_t, baseval),
5063 i386_mov_membase_reg(cd, REG_ITMP2,
5064 OFFSET(vftbl_t, diffval),
5066 i386_mov_membase_reg(cd, REG_ITMP2,
5067 OFFSET(vftbl_t, baseval),
5069 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5070 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
5072 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
5073 i386_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
5074 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
5075 i386_jcc(cd, I386_CC_A, 5);
5076 i386_mov_imm_reg(cd, 1, d);
5078 store_reg_to_var_int(iptr->dst, d);
5084 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
5085 /* op1 = dimension, val.a = class */
5086 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
5087 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
5089 /* check for negative sizes and copy sizes to stack if necessary */
5091 MCODECHECK((iptr->op1 << 1) + 64);
5093 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
5094 /* copy SAVEDVAR sizes to stack */
5096 if (src->varkind != ARGVAR) {
5097 if (src->flags & INMEMORY) {
5098 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
5099 M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4);
5102 M_IST(src->regoff, REG_SP, (s1 + 3) * 4);
5107 /* is a patcher function set? */
5109 if (iptr->val.a == NULL) {
5110 codegen_addpatchref(cd, cd->mcodeptr,
5111 PATCHER_builtin_multianewarray,
5112 (constant_classref *) iptr->target, 0);
5114 if (opt_showdisassemble) {
5115 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5121 disp = (ptrint) iptr->val.a;
5124 /* a0 = dimension count */
5126 M_IST_IMM(iptr->op1, REG_SP, 0 * 4);
5128 /* a1 = arraydescriptor */
5130 M_IST_IMM(disp, REG_SP, 1 * 4);
5132 /* a2 = pointer to dimensions = stack pointer */
5134 M_MOV(REG_SP, REG_ITMP1);
5135 M_AADD_IMM(3 * 4, REG_ITMP1);
5136 M_AST(REG_ITMP1, REG_SP, 2 * 4);
5138 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
5141 /* check for exception before result assignment */
5145 codegen_add_fillinstacktrace_ref(cd, cd->mcodeptr);
5147 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
5148 M_INTMOVE(REG_RESULT, s1);
5149 store_reg_to_var_int(iptr->dst, s1);
5154 new_internalerror("Unknown ICMD %d", iptr->opc);
5158 } /* for instruction */
5160 /* copy values to interface registers */
5162 src = bptr->outstack;
5163 len = bptr->outdepth;
5165 #if defined(ENABLE_LSRA)
5170 if ((src->varkind != STACKVAR)) {
5172 if (IS_FLT_DBL_TYPE(s2)) {
5173 var_to_reg_flt(s1, src, REG_FTMP1);
5174 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5175 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
5178 log_text("double store");
5180 /* M_DST(s1, REG_SP, 4 * interfaces[len][s2].regoff); */
5184 var_to_reg_int(s1, src, REG_ITMP1);
5185 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
5186 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5187 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
5190 i386_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5194 if (rd->interfaces[len][s2].flags & INMEMORY) {
5195 M_LNGMEMMOVE(s1, rd->interfaces[len][s2].regoff);
5198 log_text("copy interface registers: longs have to be in memory (end)");
5207 /* At the end of a basic block we may have to append some nops,
5208 because the patcher stub calling code might be longer than the
5209 actual instruction. So codepatching does not change the
5210 following block unintentionally. */
5212 if (cd->mcodeptr < cd->lastmcodeptr) {
5213 while (cd->mcodeptr < cd->lastmcodeptr) {
5218 } /* if (bptr -> flags >= BBREACHED) */
5219 } /* for basic block */
5221 dseg_createlinenumbertable(cd);
5224 /* generate exception and patcher stubs */
5233 savedmcodeptr = NULL;
5235 /* generate exception stubs */
5237 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
5238 gen_resolvebranch(cd->mcodebase + eref->branchpos,
5240 cd->mcodeptr - cd->mcodebase);
5244 /* Check if the exception is an
5245 ArrayIndexOutOfBoundsException. If so, move index register
5248 if (eref->reg != -1)
5249 M_INTMOVE(eref->reg, REG_ITMP1);
5251 /* calcuate exception address */
5253 M_MOV_IMM(0, REG_ITMP2_XPC);
5254 dseg_adddata(cd, cd->mcodeptr);
5255 M_AADD_IMM32(eref->branchpos - 6, REG_ITMP2_XPC);
5257 /* move function to call into REG_ITMP3 */
5259 M_MOV_IMM(eref->function, REG_ITMP3);
5261 if (savedmcodeptr != NULL) {
5262 M_JMP_IMM((savedmcodeptr - cd->mcodeptr) - 5);
5265 savedmcodeptr = cd->mcodeptr;
5267 M_ASUB_IMM(5 * 4, REG_SP);
5269 /* first save REG_ITMP1 so we can use it */
5271 M_AST(REG_ITMP1, REG_SP, 4 * 4); /* for AIOOBE */
5273 M_AST_IMM(0, REG_SP, 0 * 4);
5274 dseg_adddata(cd, cd->mcodeptr);
5275 M_MOV(REG_SP, REG_ITMP1);
5276 M_AADD_IMM(5 * 4, REG_ITMP1);
5277 M_AST(REG_ITMP1, REG_SP, 1 * 4);
5278 M_ALD(REG_ITMP1, REG_SP, (5 + stackframesize) * 4);
5279 M_AST(REG_ITMP1, REG_SP, 2 * 4);
5280 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5284 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5285 M_AADD_IMM(5 * 4, REG_SP);
5287 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
5293 /* generate code patching stub call code */
5295 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5296 /* check code segment size */
5300 /* Get machine code which is patched back in later. A
5301 `call rel32' is 5 bytes long. */
5303 savedmcodeptr = cd->mcodebase + pref->branchpos;
5304 mcode = *((u8 *) savedmcodeptr);
5306 /* patch in `call rel32' to call the following code */
5308 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
5309 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
5311 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
5313 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
5315 /* save REG_ITMP3 */
5319 /* move pointer to java_objectheader onto stack */
5321 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5322 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
5323 off = dseg_addaddress(cd, NULL); /* vftbl */
5325 M_MOV_IMM(0, REG_ITMP3);
5326 dseg_adddata(cd, cd->mcodeptr);
5327 M_AADD_IMM(off, REG_ITMP3);
5333 /* move machine code bytes and classinfo pointer into registers */
5335 M_PUSH_IMM(mcode >> 32);
5337 M_PUSH_IMM(pref->ref);
5338 M_PUSH_IMM(pref->patcher);
5340 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
5345 /* generate replacement-out stubs */
5350 replacementpoint = jd->code->rplpoints;
5352 for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
5353 /* check code segment size */
5357 /* note start of stub code */
5359 replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
5361 /* make machine code for patching */
5363 disp = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
5364 replacementpoint->mcode = 0xe9 | ((u8)disp << 8);
5366 /* push address of `rplpoint` struct */
5368 M_PUSH_IMM(replacementpoint);
5370 /* jump to replacement function */
5372 M_PUSH_IMM(asm_replacement_out);
5377 codegen_finish(jd, (s4) (cd->mcodeptr - cd->mcodebase));
5379 /* everything's ok */
5385 /* createcompilerstub **********************************************************
5387 Creates a stub routine which calls the compiler.
5389 *******************************************************************************/
5391 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
5392 #define COMPILERSTUB_CODESIZE 12
5394 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
5397 u1 *createcompilerstub(methodinfo *m)
5399 u1 *s; /* memory to hold the stub */
5404 s = CNEW(u1, COMPILERSTUB_SIZE);
5406 /* set data pointer and code pointer */
5409 s = s + COMPILERSTUB_DATASIZE;
5411 /* mark start of dump memory area */
5413 dumpsize = dump_size();
5415 cd = DNEW(codegendata);
5418 /* Store the methodinfo* in the same place as in the methodheader
5419 for compiled methods. */
5421 d[0] = (ptrint) asm_call_jit_compiler;
5424 M_MOV_IMM(m, REG_ITMP1);
5426 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
5427 M_MOV_IMM(asm_call_jit_compiler, REG_ITMP3);
5430 #if defined(ENABLE_STATISTICS)
5432 count_cstub_len += COMPILERSTUB_SIZE;
5435 /* release dump area */
5437 dump_release(dumpsize);
5443 /* createnativestub ************************************************************
5445 Creates a stub routine which calls a native method.
5447 *******************************************************************************/
5449 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5450 /* this way we can call the function directly with a memory call */
5452 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
5455 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
5463 s4 i, j; /* count variables */
5467 /* get required compiler data */
5473 /* set some variables */
5476 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
5478 /* calculate stackframe size */
5481 sizeof(stackframeinfo) / SIZEOF_VOID_P +
5482 sizeof(localref_table) / SIZEOF_VOID_P +
5483 1 + /* function pointer */
5484 4 * 4 + /* 4 arguments (start_native_call) */
5487 /* create method header */
5489 (void) dseg_addaddress(cd, m); /* MethodPointer */
5490 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
5491 (void) dseg_adds4(cd, 0); /* IsSync */
5492 (void) dseg_adds4(cd, 0); /* IsLeaf */
5493 (void) dseg_adds4(cd, 0); /* IntSave */
5494 (void) dseg_adds4(cd, 0); /* FltSave */
5495 (void) dseg_addlinenumbertablesize(cd);
5496 (void) dseg_adds4(cd, 0); /* ExTableSize */
5498 /* initialize mcode variables */
5500 cd->mcodeptr = (u1 *) cd->mcodebase;
5501 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
5503 /* generate native method profiling code */
5506 /* count frequency */
5508 M_MOV_IMM(m, REG_ITMP1);
5509 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(methodinfo, frequency));
5512 /* calculate stackframe size for native function */
5514 M_ASUB_IMM(stackframesize * 4, REG_SP);
5516 #if !defined(NDEBUG)
5517 if (opt_verbosecall) {
5520 disp = stackframesize * 4;
5522 M_ASUB_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5524 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
5525 t = md->paramtypes[p].type;
5526 if (IS_INT_LNG_TYPE(t)) {
5527 if (IS_2_WORD_TYPE(t)) {
5528 M_ILD(REG_ITMP1, REG_SP,
5529 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5530 M_ILD(REG_ITMP2, REG_SP,
5531 4 + TRACE_ARGS_NUM * 8 + 4 + disp + 4);
5532 M_IST(REG_ITMP1, REG_SP, p * 8);
5533 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5535 } else if (t == TYPE_ADR) {
5536 M_ALD(REG_ITMP1, REG_SP,
5537 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5539 M_AST(REG_ITMP1, REG_SP, p * 8);
5540 M_AST(REG_ITMP2, REG_SP, p * 8 + 4);
5543 M_ILD(EAX, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5545 M_IST(EAX, REG_SP, p * 8);
5546 M_IST(EDX, REG_SP, p * 8 + 4);
5550 if (!IS_2_WORD_TYPE(t)) {
5551 i386_flds_membase(cd, REG_SP,
5552 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5553 i386_fstps_membase(cd, REG_SP, p * 8);
5554 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
5555 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5558 i386_fldl_membase(cd, REG_SP,
5559 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5560 i386_fstpl_membase(cd, REG_SP, p * 8);
5563 disp += (IS_2_WORD_TYPE(t)) ? 8 : 4;
5567 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
5568 M_IST(REG_ITMP1, REG_SP, p * 8);
5569 M_IST(REG_ITMP1, REG_SP, p * 8 + 4);
5572 M_AST_IMM(m, REG_SP, TRACE_ARGS_NUM * 8);
5574 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
5577 M_AADD_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5579 #endif /* !defined(NDEBUG) */
5581 /* get function address (this must happen before the stackframeinfo) */
5583 #if !defined(WITH_STATIC_CLASSPATH)
5585 codegen_addpatchref(cd, cd->mcodeptr, PATCHER_resolve_native, m, 0);
5587 if (opt_showdisassemble) {
5588 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5593 M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
5595 /* Mark the whole fpu stack as free for native functions (only for saved */
5596 /* register count == 0). */
5598 i386_ffree_reg(cd, 0);
5599 i386_ffree_reg(cd, 1);
5600 i386_ffree_reg(cd, 2);
5601 i386_ffree_reg(cd, 3);
5602 i386_ffree_reg(cd, 4);
5603 i386_ffree_reg(cd, 5);
5604 i386_ffree_reg(cd, 6);
5605 i386_ffree_reg(cd, 7);
5607 /* prepare data structures for native function call */
5609 M_MOV(REG_SP, REG_ITMP1);
5610 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5612 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5613 M_IST_IMM(0, REG_SP, 1 * 4);
5614 dseg_adddata(cd, cd->mcodeptr);
5616 M_MOV(REG_SP, REG_ITMP2);
5617 M_AADD_IMM(stackframesize * 4 + SIZEOF_VOID_P, REG_ITMP2);
5619 M_AST(REG_ITMP2, REG_SP, 2 * 4);
5620 M_ALD(REG_ITMP3, REG_SP, stackframesize * 4);
5621 M_AST(REG_ITMP3, REG_SP, 3 * 4);
5622 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
5625 M_ALD(REG_ITMP3, REG_SP, 4 * 4);
5627 /* copy arguments into new stackframe */
5629 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
5630 t = md->paramtypes[i].type;
5632 if (!md->params[i].inmemory) {
5633 /* no integer argument registers */
5634 } else { /* float/double in memory can be copied like int/longs */
5635 s1 = (md->params[i].regoff + stackframesize + 1) * 4;
5636 s2 = nmd->params[j].regoff * 4;
5638 M_ILD(REG_ITMP1, REG_SP, s1);
5639 M_IST(REG_ITMP1, REG_SP, s2);
5640 if (IS_2_WORD_TYPE(t)) {
5641 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
5642 M_IST(REG_ITMP1, REG_SP, s2 + 4);
5647 /* if function is static, put class into second argument */
5649 if (m->flags & ACC_STATIC)
5650 M_AST_IMM((ptrint) m->class, REG_SP, 1 * 4);
5652 /* put env into first argument */
5654 M_AST_IMM((ptrint) _Jv_env, REG_SP, 0 * 4);
5656 /* call the native function */
5660 /* save return value */
5662 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5663 if (IS_2_WORD_TYPE(md->returntype.type))
5664 M_IST(REG_RESULT2, REG_SP, 2 * 4);
5665 M_IST(REG_RESULT, REG_SP, 1 * 4);
5668 if (IS_2_WORD_TYPE(md->returntype.type))
5669 i386_fstl_membase(cd, REG_SP, 1 * 4);
5671 i386_fsts_membase(cd, REG_SP, 1 * 4);
5674 /* remove data structures for native function call */
5676 M_MOV(REG_SP, REG_ITMP1);
5677 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5679 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5680 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
5683 #if !defined(NDEBUG)
5684 if (opt_verbosecall) {
5685 /* restore return value */
5687 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5688 if (IS_2_WORD_TYPE(md->returntype.type))
5689 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5690 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5693 if (IS_2_WORD_TYPE(md->returntype.type))
5694 i386_fldl_membase(cd, REG_SP, 1 * 4);
5696 i386_flds_membase(cd, REG_SP, 1 * 4);
5699 M_ASUB_IMM(4 + 8 + 8 + 4, REG_SP);
5701 M_AST_IMM((ptrint) m, REG_SP, 0);
5703 M_IST(REG_RESULT, REG_SP, 4);
5704 M_IST(REG_RESULT2, REG_SP, 4 + 4);
5706 i386_fstl_membase(cd, REG_SP, 4 + 8);
5707 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5709 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
5712 M_AADD_IMM(4 + 8 + 8 + 4, REG_SP);
5714 #endif /* !defined(NDEBUG) */
5716 /* check for exception */
5718 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5719 /* i386_call_mem(cd, (ptrint) builtin_get_exceptionptrptr); */
5720 i386_call_mem(cd, (ptrint) &callgetexceptionptrptr);
5722 M_MOV_IMM(&_no_threads_exceptionptr, REG_RESULT);
5724 /* we can't use REG_ITMP3 == REG_RESULT2 */
5725 M_ALD(REG_ITMP2, REG_RESULT, 0);
5727 /* restore return value */
5729 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5730 if (IS_2_WORD_TYPE(md->returntype.type))
5731 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5732 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5735 if (IS_2_WORD_TYPE(md->returntype.type))
5736 i386_fldl_membase(cd, REG_SP, 1 * 4);
5738 i386_flds_membase(cd, REG_SP, 1 * 4);
5741 M_AADD_IMM(stackframesize * 4, REG_SP);
5748 /* handle exception */
5750 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5751 i386_push_reg(cd, REG_ITMP2);
5752 /* i386_call_mem(cd, (ptrint) builtin_get_exceptionptrptr); */
5753 i386_call_mem(cd, (ptrint) &callgetexceptionptrptr);
5754 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5755 i386_pop_reg(cd, REG_ITMP1_XPTR);
5757 M_MOV(REG_ITMP2, REG_ITMP1_XPTR);
5758 M_MOV_IMM(&_no_threads_exceptionptr, REG_ITMP2);
5759 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5761 M_ALD(REG_ITMP2_XPC, REG_SP, 0);
5762 M_ASUB_IMM(2, REG_ITMP2_XPC);
5764 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
5768 /* process patcher calls **************************************************/
5776 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5777 /* Get machine code which is patched back in later. A
5778 `call rel32' is 5 bytes long. */
5780 xcodeptr = cd->mcodebase + pref->branchpos;
5781 mcode = *((u8 *) xcodeptr);
5783 /* patch in `call rel32' to call the following code */
5785 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
5786 cd->mcodeptr = xcodeptr; /* set mcodeptr to patch position */
5788 M_CALL_IMM(tmpmcodeptr - (xcodeptr + PATCHER_CALL_SIZE));
5790 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
5792 /* save REG_ITMP3 */
5796 /* move pointer to java_objectheader onto stack */
5798 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5799 /* create a virtual java_objectheader */
5801 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
5802 disp = dseg_addaddress(cd, NULL); /* vftbl */
5804 M_MOV_IMM(0, REG_ITMP3);
5805 dseg_adddata(cd, cd->mcodeptr);
5806 M_AADD_IMM(disp, REG_ITMP3);
5812 /* move machine code bytes and classinfo pointer onto stack */
5814 M_PUSH_IMM((mcode >> 32));
5816 M_PUSH_IMM(pref->ref);
5817 M_PUSH_IMM(pref->patcher);
5819 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
5824 codegen_finish(jd, (s4) (cd->mcodeptr - cd->mcodebase));
5826 return jd->code->entrypoint;
5831 * These are local overrides for various environment variables in Emacs.
5832 * Please do not remove this and leave it at the end of the file, where
5833 * Emacs will automagically detect them.
5834 * ---------------------------------------------------------------------
5837 * indent-tabs-mode: t
5841 * vim:noexpandtab:sw=4:ts=4: