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
33 $Id: codegen.c 4493 2006-02-12 16:28:35Z twisti $
45 #include "vm/jit/i386/md-abi.h"
47 #include "vm/jit/i386/codegen.h"
48 #include "vm/jit/i386/emitfuncs.h"
50 #include "cacao/cacao.h"
51 #include "native/jni.h"
52 #include "native/native.h"
53 #include "vm/builtin.h"
54 #include "vm/exceptions.h"
55 #include "vm/global.h"
56 #include "vm/loader.h"
57 #include "vm/options.h"
58 #include "vm/stringlocal.h"
60 #include "vm/jit/asmpart.h"
61 #include "vm/jit/codegen-common.h"
62 #include "vm/jit/dseg.h"
63 #include "vm/jit/jit.h"
64 #include "vm/jit/parse.h"
65 #include "vm/jit/patcher.h"
66 #include "vm/jit/reg.h"
68 #if defined(ENABLE_LSRA)
69 # ifdef LSRA_USES_REG_RES
70 # include "vm/jit/i386/icmd_uses_reg_res.inc"
72 # include "vm/jit/allocator/lsra.h"
76 /* codegen *********************************************************************
78 Generates machine code.
80 *******************************************************************************/
82 bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
84 s4 len, s1, s2, s3, d, off, disp;
92 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
93 builtintable_entry *bte;
97 /* prevent compiler warnings */
106 s4 savedregs_num = 0;
109 /* space to save used callee saved registers */
111 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
113 /* float register are saved on 2 4-byte stackslots */
114 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
116 parentargs_base = rd->memuse + savedregs_num;
119 #if defined(USE_THREADS)
120 /* space to save argument of monitor_enter */
122 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
123 /* reserve 2 slots for long/double return values for monitorexit */
125 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
126 parentargs_base += 2;
132 /* create method header */
134 (void) dseg_addaddress(cd, m); /* MethodPointer */
135 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
137 #if defined(USE_THREADS)
138 /* IsSync contains the offset relative to the stack pointer for the
139 argument of monitor_exit used in the exception handler. Since the
140 offset could be zero and give a wrong meaning of the flag it is
144 if (checksync && (m->flags & ACC_SYNCHRONIZED))
145 (void) dseg_adds4(cd, (rd->memuse + 1) * 4); /* IsSync */
148 (void) dseg_adds4(cd, 0); /* IsSync */
150 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
151 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
152 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
154 /* adds a reference for the length of the line number counter. We don't
155 know the size yet, since we evaluate the information during code
156 generation, to save one additional iteration over the whole
157 instructions. During code optimization the position could have changed
158 to the information gotten from the class file */
159 (void) dseg_addlinenumbertablesize(cd);
161 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
163 /* create exception table */
165 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
166 dseg_addtarget(cd, ex->start);
167 dseg_addtarget(cd, ex->end);
168 dseg_addtarget(cd, ex->handler);
169 (void) dseg_addaddress(cd, ex->catchtype.cls);
172 /* initialize mcode variables */
174 cd->mcodeptr = cd->mcodebase;
175 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
177 /* initialize the last patcher pointer */
179 cd->lastmcodeptr = cd->mcodeptr;
181 /* generate method profiling code */
184 /* count frequency */
186 M_MOV_IMM((ptrint) m, REG_ITMP1);
187 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(methodinfo, frequency));
190 /* create stack frame (if necessary) */
193 M_ASUB_IMM(parentargs_base * 4, REG_SP);
195 /* save return address and used callee saved registers */
198 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
199 p--; M_AST(rd->savintregs[i], REG_SP, p * 4);
201 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
202 p-=2; i386_fld_reg(cd, rd->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 4);
205 /* take arguments out of register or stack frame */
210 for (p = 0, l = 0; p < md->paramcount; p++) {
211 t = md->paramtypes[p].type;
212 var = &(rd->locals[l][t]);
214 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
218 s1 = md->params[p].regoff;
219 if (IS_INT_LNG_TYPE(t)) { /* integer args */
220 if (!md->params[p].inmemory) { /* register arguments */
221 log_text("integer register argument");
223 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
224 /* rd->argintregs[md->params[p].regoff -> var->regoff */
225 } else { /* reg arg -> spilled */
226 /* rd->argintregs[md->params[p].regoff -> var->regoff * 4 */
228 } else { /* stack arguments */
229 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
230 i386_mov_membase_reg( /* + 4 for return address */
231 cd, REG_SP, (parentargs_base + s1) * 4 + 4, var->regoff);
232 /* + 4 for return address */
233 } else { /* stack arg -> spilled */
234 if (!IS_2_WORD_TYPE(t)) {
236 i386_mov_membase_reg( /* + 4 for return address */
237 cd, REG_SP, (parentargs_base + s1) * 4 + 4,
239 i386_mov_reg_membase(
240 cd, REG_ITMP1, REG_SP, var->regoff * 4);
242 /* reuse Stackslotand avoid copying */
243 var->regoff = parentargs_base + s1 + 1;
248 i386_mov_membase_reg( /* + 4 for return address */
249 cd, REG_SP, (parentargs_base + s1) * 4 + 4,
251 i386_mov_reg_membase(
252 cd, REG_ITMP1, REG_SP, var->regoff * 4);
253 i386_mov_membase_reg( /* + 4 for return address */
254 cd, REG_SP, (parentargs_base + s1) * 4 + 4 + 4,
256 i386_mov_reg_membase(
257 cd, REG_ITMP1, REG_SP, var->regoff * 4 + 4);
259 /* reuse Stackslotand avoid copying */
260 var->regoff = parentargs_base + s1 + 1;
266 } else { /* floating args */
267 if (!md->params[p].inmemory) { /* register arguments */
268 log_text("There are no float argument registers!");
270 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
271 /* rd->argfltregs[md->params[p].regoff -> var->regoff */
272 } else { /* reg arg -> spilled */
273 /* rd->argfltregs[md->params[p].regoff -> var->regoff * 4 */
276 } else { /* stack arguments */
277 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
280 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
282 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
287 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
289 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
293 } else { /* stack-arg -> spilled */
295 i386_mov_membase_reg(
296 cd, REG_SP, (parentargs_base + s1) * 4 + 4, REG_ITMP1);
297 i386_mov_reg_membase(
298 cd, REG_ITMP1, REG_SP, var->regoff * 4);
301 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
302 i386_fstps_membase(cd, REG_SP, var->regoff * 4);
305 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
306 i386_fstpl_membase(cd, REG_SP, var->regoff * 4);
309 /* reuse Stackslotand avoid copying */
310 var->regoff = parentargs_base + s1 + 1;
317 /* call monitorenter function */
319 #if defined(USE_THREADS)
320 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
323 if (m->flags & ACC_STATIC) {
324 i386_mov_imm_reg(cd, (ptrint) m->class, REG_ITMP1);
325 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s1 * 4);
326 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
327 i386_mov_imm_reg(cd, (ptrint) BUILTIN_staticmonitorenter, REG_ITMP1);
328 i386_call_reg(cd, REG_ITMP1);
331 i386_mov_membase_reg(cd, REG_SP, parentargs_base * 4 + 4, REG_ITMP1);
332 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
333 i386_jcc(cd, I386_CC_Z, 0);
334 codegen_addxnullrefs(cd, cd->mcodeptr);
335 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s1 * 4);
336 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
337 i386_mov_imm_reg(cd, (ptrint) BUILTIN_monitorenter, REG_ITMP1);
338 i386_call_reg(cd, REG_ITMP1);
343 /* copy argument registers to stack and call trace function with pointer
344 to arguments on stack.
349 s1 = INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4 + 4 + parentargs_base * 4;
351 M_ISUB_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
353 /* save temporary registers for leaf methods */
355 for (p = 0; p < INT_TMP_CNT; p++)
356 M_IST(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
358 for (p = 0, l = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
359 t = md->paramtypes[p].type;
361 if (IS_INT_LNG_TYPE(t)) {
362 if (IS_2_WORD_TYPE(t)) {
363 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
364 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
365 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off + 4, REG_ITMP1);
366 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
368 } else if (t == TYPE_ADR) {
370 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
371 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
372 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
373 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
376 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, EAX);
378 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
379 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
383 if (!IS_2_WORD_TYPE(t)) {
384 i386_flds_membase(cd, REG_SP, s1 + stack_off);
385 i386_fstps_membase(cd, REG_SP, p * 8);
386 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
387 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
390 i386_fldl_membase(cd, REG_SP, s1 + stack_off);
391 i386_fstpl_membase(cd, REG_SP, p * 8);
394 stack_off += (IS_2_WORD_TYPE(t)) ? 8 : 4;
397 /* fill up the remaining arguments */
398 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
399 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
400 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
401 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
404 i386_mov_imm_membase(cd, (ptrint) m, REG_SP, TRACE_ARGS_NUM * 8);
405 i386_mov_imm_reg(cd, (ptrint) builtin_trace_args, REG_ITMP1);
406 i386_call_reg(cd, REG_ITMP1);
408 /* restore temporary registers for leaf methods */
410 for (p = 0; p < INT_TMP_CNT; p++)
411 M_ILD(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
413 M_IADD_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
418 /* end of header generation */
420 /* walk through all basic blocks */
421 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
423 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
425 if (bptr->flags >= BBREACHED) {
427 /* branch resolving */
430 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
431 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
436 /* copy interface registers to their destination */
442 /* generate basic block profiling code */
445 /* count frequency */
447 M_MOV_IMM((ptrint) m->bbfrequency, REG_ITMP1);
448 M_IADD_IMM_MEMBASE(1, REG_ITMP1, bptr->debug_nr * 4);
452 #if defined(ENABLE_LSRA)
454 while (src != NULL) {
456 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
457 if (!IS_2_WORD_TYPE(src->type)) {
458 if (bptr->type == BBTYPE_SBR) {
459 /* d = reg_of_var(m, src, REG_ITMP1); */
460 if (!(src->flags & INMEMORY))
466 store_reg_to_var_int(src, d);
468 } else if (bptr->type == BBTYPE_EXH) {
469 /* d = reg_of_var(m, src, REG_ITMP1); */
470 if (!(src->flags & INMEMORY))
474 M_INTMOVE(REG_ITMP1, d);
475 store_reg_to_var_int(src, d);
479 log_text("copy interface registers(EXH, SBR): longs have to be in memory (begin 1)");
488 while (src != NULL) {
490 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
491 if (!IS_2_WORD_TYPE(src->type)) {
492 if (bptr->type == BBTYPE_SBR) {
493 d = reg_of_var(rd, src, REG_ITMP1);
495 store_reg_to_var_int(src, d);
496 } else if (bptr->type == BBTYPE_EXH) {
497 d = reg_of_var(rd, src, REG_ITMP1);
498 M_INTMOVE(REG_ITMP1, d);
499 store_reg_to_var_int(src, d);
503 log_text("copy interface registers: longs have to be in memory (begin 1)");
508 d = reg_of_var(rd, src, REG_ITMP1);
509 if ((src->varkind != STACKVAR)) {
511 if (IS_FLT_DBL_TYPE(s2)) {
512 s1 = rd->interfaces[len][s2].regoff;
513 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
517 if (s2 == TYPE_FLT) {
518 i386_flds_membase(cd, REG_SP, s1 * 4);
521 i386_fldl_membase(cd, REG_SP, s1 * 4);
524 store_reg_to_var_flt(src, d);
527 s1 = rd->interfaces[len][s2].regoff;
528 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
529 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
533 i386_mov_membase_reg(cd, REG_SP, s1 * 4, d);
535 store_reg_to_var_int(src, d);
538 if (rd->interfaces[len][s2].flags & INMEMORY) {
539 M_LNGMEMMOVE(s1, src->regoff);
542 log_text("copy interface registers: longs have to be in memory (begin 2)");
551 #if defined(ENABLE_LSRA)
555 /* walk through all instructions */
560 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
561 if (iptr->line != currentline) {
562 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
563 currentline = iptr->line;
566 MCODECHECK(1024); /* 1kB should be enough */
569 case ICMD_INLINE_START:
570 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
571 /* EAX: NO ECX: NO EDX: NO */
572 dseg_addlinenumber_inline_start(cd, iptr, cd->mcodeptr);
575 case ICMD_INLINE_END:
576 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
577 /* EAX: NO ECX: NO EDX: NO */
578 dseg_addlinenumber_inline_end(cd, iptr);
579 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
582 case ICMD_NOP: /* ... ==> ... */
583 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
584 /* EAX: NO ECX: NO EDX: NO */
587 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
588 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
589 /* EAX: NO ECX: NO EDX: NO */
590 if (src->flags & INMEMORY) {
591 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
594 i386_test_reg_reg(cd, src->regoff, src->regoff);
596 i386_jcc(cd, I386_CC_Z, 0);
597 codegen_addxnullrefs(cd, cd->mcodeptr);
600 /* constant operations ************************************************/
602 case ICMD_ICONST: /* ... ==> ..., constant */
603 /* op1 = 0, val.i = constant */
605 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
606 /* EAX: NO ECX: NO EDX: NO */
608 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
609 if (iptr->dst->flags & INMEMORY) {
610 M_IST_IMM(iptr->val.i, REG_SP, iptr->dst->regoff * 4);
613 if (iptr->val.i == 0) {
617 M_MOV_IMM(iptr->val.i, d);
622 case ICMD_LCONST: /* ... ==> ..., constant */
623 /* op1 = 0, val.l = constant */
625 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
626 /* EAX: NO ECX: NO EDX: NO */
628 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
629 if (iptr->dst->flags & INMEMORY) {
630 M_IST_IMM(iptr->val.l, REG_SP, iptr->dst->regoff * 4);
631 M_IST_IMM(iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
634 log_text("LCONST: longs have to be in memory");
639 case ICMD_FCONST: /* ... ==> ..., constant */
640 /* op1 = 0, val.f = constant */
642 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
643 /* EAX: YES ECX: NO EDX: NO */
645 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
646 if (iptr->val.f == 0.0) {
651 if (iptr->val.i == 0x80000000) {
655 } else if (iptr->val.f == 1.0) {
659 } else if (iptr->val.f == 2.0) {
666 disp = dseg_addfloat(cd, iptr->val.f);
667 i386_mov_imm_reg(cd, 0, REG_ITMP1);
668 dseg_adddata(cd, cd->mcodeptr);
669 i386_flds_membase(cd, REG_ITMP1, disp);
672 store_reg_to_var_flt(iptr->dst, d);
675 case ICMD_DCONST: /* ... ==> ..., constant */
676 /* op1 = 0, val.d = constant */
678 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
679 /* EAX: YES ECX: NO EDX: NO */
681 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
682 if (iptr->val.d == 0.0) {
687 if (iptr->val.l == 0x8000000000000000LL) {
691 } else if (iptr->val.d == 1.0) {
695 } else if (iptr->val.d == 2.0) {
702 disp = dseg_adddouble(cd, iptr->val.d);
703 i386_mov_imm_reg(cd, 0, REG_ITMP1);
704 dseg_adddata(cd, cd->mcodeptr);
705 i386_fldl_membase(cd, REG_ITMP1, disp);
708 store_reg_to_var_flt(iptr->dst, d);
711 case ICMD_ACONST: /* ... ==> ..., constant */
712 /* op1 = 0, val.a = constant */
714 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
715 /* EAX: YES ECX: NO EDX: NO */
717 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
719 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
720 codegen_addpatchref(cd, cd->mcodeptr,
722 (unresolved_class *) iptr->target, 0);
724 if (opt_showdisassemble) {
725 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
728 M_MOV_IMM((ptrint) iptr->val.a, d);
729 store_reg_to_var_int(iptr->dst, d);
732 if (iptr->dst->flags & INMEMORY) {
733 M_AST_IMM((ptrint) iptr->val.a, REG_SP, iptr->dst->regoff * 4);
736 if ((ptrint) iptr->val.a == 0) {
739 M_MOV_IMM((ptrint) iptr->val.a, d);
746 /* load/store operations **********************************************/
748 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
749 case ICMD_ALOAD: /* op1 = local variable */
750 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
751 /* EAX: YES ECX: NO EDX: NO */
753 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
754 if ((iptr->dst->varkind == LOCALVAR) &&
755 (iptr->dst->varnum == iptr->op1)) {
758 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
759 if (iptr->dst->flags & INMEMORY) {
760 if (var->flags & INMEMORY) {
761 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP1);
762 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
765 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 4);
769 if (var->flags & INMEMORY) {
770 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, iptr->dst->regoff);
773 M_INTMOVE(var->regoff, iptr->dst->regoff);
778 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
779 /* op1 = local variable */
780 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
781 /* EAX: NO ECX: NO EDX: NO */
783 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
784 if ((iptr->dst->varkind == LOCALVAR) &&
785 (iptr->dst->varnum == iptr->op1)) {
788 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
789 if (iptr->dst->flags & INMEMORY) {
790 if (var->flags & INMEMORY) {
791 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
794 log_text("LLOAD: longs have to be in memory");
799 log_text("LLOAD: longs have to be in memory");
804 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
805 /* op1 = local variable */
806 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
807 /* EAX: NO ECX: NO EDX: NO */
809 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
810 if ((iptr->dst->varkind == LOCALVAR) &&
811 (iptr->dst->varnum == iptr->op1)) {
814 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
815 if (var->flags & INMEMORY) {
816 i386_flds_membase(cd, REG_SP, var->regoff * 4);
819 i386_fld_reg(cd, var->regoff + fpu_st_offset);
822 store_reg_to_var_flt(iptr->dst, d);
825 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
826 /* op1 = local variable */
827 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
828 /* EAX: NO ECX: NO EDX: NO */
830 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
831 if ((iptr->dst->varkind == LOCALVAR) &&
832 (iptr->dst->varnum == iptr->op1)) {
835 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
836 if (var->flags & INMEMORY) {
837 i386_fldl_membase(cd, REG_SP, var->regoff * 4);
840 i386_fld_reg(cd, var->regoff + fpu_st_offset);
843 store_reg_to_var_flt(iptr->dst, d);
846 case ICMD_ISTORE: /* ..., value ==> ... */
847 case ICMD_ASTORE: /* op1 = local variable */
848 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
849 /* EAX: YES ECX: NO EDX: NO */
851 if ((src->varkind == LOCALVAR) &&
852 (src->varnum == iptr->op1)) {
855 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
856 if (var->flags & INMEMORY) {
857 if (src->flags & INMEMORY) {
858 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
859 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 4);
862 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 4);
866 var_to_reg_int(s1, src, var->regoff);
867 M_INTMOVE(s1, var->regoff);
871 case ICMD_LSTORE: /* ..., value ==> ... */
872 /* op1 = local variable */
873 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
874 /* EAX: NO ECX: NO EDX: NO */
876 if ((src->varkind == LOCALVAR) &&
877 (src->varnum == iptr->op1)) {
880 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
881 if (var->flags & INMEMORY) {
882 if (src->flags & INMEMORY) {
883 M_LNGMEMMOVE(src->regoff, var->regoff);
886 log_text("LSTORE: longs have to be in memory");
891 log_text("LSTORE: longs have to be in memory");
896 case ICMD_FSTORE: /* ..., value ==> ... */
897 /* op1 = local variable */
898 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
899 /* EAX: NO ECX: NO EDX: NO */
901 if ((src->varkind == LOCALVAR) &&
902 (src->varnum == iptr->op1)) {
905 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
906 if (var->flags & INMEMORY) {
907 var_to_reg_flt(s1, src, REG_FTMP1);
908 i386_fstps_membase(cd, REG_SP, var->regoff * 4);
911 var_to_reg_flt(s1, src, var->regoff);
912 /* M_FLTMOVE(s1, var->regoff); */
913 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
918 case ICMD_DSTORE: /* ..., value ==> ... */
919 /* op1 = local variable */
920 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
921 /* EAX: NO ECX: NO EDX: NO */
923 if ((src->varkind == LOCALVAR) &&
924 (src->varnum == iptr->op1)) {
927 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
928 if (var->flags & INMEMORY) {
929 var_to_reg_flt(s1, src, REG_FTMP1);
930 i386_fstpl_membase(cd, REG_SP, var->regoff * 4);
933 var_to_reg_flt(s1, src, var->regoff);
934 /* M_FLTMOVE(s1, var->regoff); */
935 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
941 /* pop/dup/swap operations ********************************************/
943 /* attention: double and longs are only one entry in CACAO ICMDs */
945 case ICMD_POP: /* ..., value ==> ... */
946 case ICMD_POP2: /* ..., value, value ==> ... */
947 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
948 /* EAX: NO ECX: NO EDX: NO */
951 case ICMD_DUP: /* ..., a ==> ..., a, a */
952 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
953 /* EAX: YES ECX: NO EDX: NO */
954 M_COPY(src, iptr->dst);
957 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
958 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
959 /* EAX: YES ECX: NO EDX: NO */
961 M_COPY(src, iptr->dst);
962 M_COPY(src->prev, iptr->dst->prev);
965 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
966 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
967 /* EAX: YES ECX: NO EDX: NO */
969 M_COPY(src, iptr->dst);
970 M_COPY(src->prev, iptr->dst->prev);
971 M_COPY(iptr->dst, iptr->dst->prev->prev);
974 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
976 M_COPY(src, iptr->dst);
977 M_COPY(src->prev, iptr->dst->prev);
978 M_COPY(src->prev->prev, iptr->dst->prev->prev);
979 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
982 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
983 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
984 /* EAX: YES ECX: NO EDX: NO */
986 M_COPY(src, iptr->dst);
987 M_COPY(src->prev, iptr->dst->prev);
988 M_COPY(src->prev->prev, iptr->dst->prev->prev);
989 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
990 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
993 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
994 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
995 /* EAX: YES ECX: NO EDX: NO */
997 M_COPY(src, iptr->dst);
998 M_COPY(src->prev, iptr->dst->prev);
999 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1000 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
1001 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
1002 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
1005 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1006 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1007 /* EAX: YES ECX: NO EDX: NO */
1009 M_COPY(src, iptr->dst->prev);
1010 M_COPY(src->prev, iptr->dst);
1014 /* integer operations *************************************************/
1016 case ICMD_INEG: /* ..., value ==> ..., - value */
1017 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1018 /* EAX: YES ECX: NO EDX: NO */
1020 d = reg_of_var(rd, iptr->dst, REG_NULL);
1021 if (iptr->dst->flags & INMEMORY) {
1022 if (src->flags & INMEMORY) {
1023 if (src->regoff == iptr->dst->regoff) {
1024 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1027 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1028 i386_neg_reg(cd, REG_ITMP1);
1029 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1033 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1034 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1038 if (src->flags & INMEMORY) {
1039 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1040 i386_neg_reg(cd, iptr->dst->regoff);
1043 M_INTMOVE(src->regoff, iptr->dst->regoff);
1044 i386_neg_reg(cd, iptr->dst->regoff);
1049 case ICMD_LNEG: /* ..., value ==> ..., - value */
1050 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1051 /* EAX: YES ECX: NO EDX: NO */
1053 d = reg_of_var(rd, iptr->dst, REG_NULL);
1054 if (iptr->dst->flags & INMEMORY) {
1055 if (src->flags & INMEMORY) {
1056 if (src->regoff == iptr->dst->regoff) {
1057 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1058 i386_alu_imm_membase(cd, ALU_ADC, 0, REG_SP, iptr->dst->regoff * 4 + 4);
1059 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4 + 4);
1062 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1063 i386_neg_reg(cd, REG_ITMP1);
1064 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1065 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1066 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP1);
1067 i386_neg_reg(cd, REG_ITMP1);
1068 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1074 case ICMD_I2L: /* ..., value ==> ..., value */
1075 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1076 /* EAX: YES ECX: NO EDX: YES */
1078 d = reg_of_var(rd, iptr->dst, REG_NULL);
1079 if (iptr->dst->flags & INMEMORY) {
1080 if (src->flags & INMEMORY) {
1081 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, EAX);
1083 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1084 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1087 M_INTMOVE(src->regoff, EAX);
1089 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1090 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1095 case ICMD_L2I: /* ..., value ==> ..., value */
1096 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1097 /* EAX: YES ECX: NO EDX: NO */
1099 d = reg_of_var(rd, iptr->dst, REG_NULL);
1100 if (iptr->dst->flags & INMEMORY) {
1101 if (src->flags & INMEMORY) {
1102 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1103 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1107 if (src->flags & INMEMORY) {
1108 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1113 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1114 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1115 /* EAX: YES ECX: NO EDX: NO */
1117 d = reg_of_var(rd, iptr->dst, REG_NULL);
1118 if (iptr->dst->flags & INMEMORY) {
1119 if (src->flags & INMEMORY) {
1120 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1121 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1122 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1123 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1126 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1127 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 4);
1128 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 4);
1132 if (src->flags & INMEMORY) {
1133 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1134 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1135 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1138 M_INTMOVE(src->regoff, iptr->dst->regoff);
1139 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1140 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1145 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1146 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1147 /* EAX: YES ECX: NO EDX: NO */
1149 d = reg_of_var(rd, iptr->dst, REG_NULL);
1150 if (iptr->dst->flags & INMEMORY) {
1151 if (src->flags & INMEMORY) {
1152 if (src->regoff == iptr->dst->regoff) {
1153 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1156 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1157 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, REG_ITMP1);
1158 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1162 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1163 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1167 if (src->flags & INMEMORY) {
1168 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1169 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1172 M_INTMOVE(src->regoff, iptr->dst->regoff);
1173 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1178 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1179 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1180 /* EAX: YES ECX: NO EDX: NO */
1182 d = reg_of_var(rd, iptr->dst, REG_NULL);
1183 if (iptr->dst->flags & INMEMORY) {
1184 if (src->flags & INMEMORY) {
1185 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1186 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1187 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1188 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1191 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1192 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 4);
1193 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 4);
1197 if (src->flags & INMEMORY) {
1198 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1199 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1200 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1203 M_INTMOVE(src->regoff, iptr->dst->regoff);
1204 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1205 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1211 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1212 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1213 /* EAX: S|YES ECX: NO EDX: NO */
1215 d = reg_of_var(rd, iptr->dst, REG_NULL);
1216 i386_emit_ialu(cd, ALU_ADD, src, iptr);
1219 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1220 /* val.i = constant */
1221 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1222 /* EAX: NO ECX: NO EDX: NO */
1224 d = reg_of_var(rd, iptr->dst, REG_NULL);
1225 i386_emit_ialuconst(cd, ALU_ADD, src, iptr);
1228 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1229 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1230 /* EAX: S|YES ECX: NO EDX: NO */
1232 d = reg_of_var(rd, iptr->dst, REG_NULL);
1233 if (iptr->dst->flags & INMEMORY) {
1234 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1235 if (src->regoff == iptr->dst->regoff) {
1236 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1237 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1238 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1239 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1241 } else if (src->prev->regoff == iptr->dst->regoff) {
1242 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1243 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1244 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1245 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1248 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1249 i386_alu_membase_reg(cd, ALU_ADD, REG_SP, src->regoff * 4, REG_ITMP1);
1250 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1251 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1252 i386_alu_membase_reg(cd, ALU_ADC, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1253 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1260 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1261 /* val.l = constant */
1262 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1263 /* EAX: NO ECX: NO EDX: NO */
1264 /* else path can never happen? longs stay in memory! */
1266 d = reg_of_var(rd, iptr->dst, REG_NULL);
1267 if (iptr->dst->flags & INMEMORY) {
1268 if (src->flags & INMEMORY) {
1269 if (src->regoff == iptr->dst->regoff) {
1270 i386_alu_imm_membase(cd, ALU_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1271 i386_alu_imm_membase(cd, ALU_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1274 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1275 i386_alu_imm_reg(cd, ALU_ADD, iptr->val.l, REG_ITMP1);
1276 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1277 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1278 i386_alu_imm_reg(cd, ALU_ADC, iptr->val.l >> 32, REG_ITMP1);
1279 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1285 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1286 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1287 /* EAX: S|YES ECX: NO EDX: NO */
1289 d = reg_of_var(rd, iptr->dst, REG_NULL);
1290 if (iptr->dst->flags & INMEMORY) {
1291 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1292 if (src->prev->regoff == iptr->dst->regoff) {
1293 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1294 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1297 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1298 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1299 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1302 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1303 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1304 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1305 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1307 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1308 if (src->prev->regoff == iptr->dst->regoff) {
1309 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1312 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1313 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1314 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1318 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 4);
1319 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1323 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1324 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1325 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1327 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1328 M_INTMOVE(src->prev->regoff, d);
1329 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1331 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1332 /* workaround for reg alloc */
1333 if (src->regoff == iptr->dst->regoff) {
1334 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1335 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1336 M_INTMOVE(REG_ITMP1, d);
1339 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1340 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1344 /* workaround for reg alloc */
1345 if (src->regoff == iptr->dst->regoff) {
1346 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1347 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1348 M_INTMOVE(REG_ITMP1, d);
1351 M_INTMOVE(src->prev->regoff, d);
1352 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1358 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1359 /* val.i = constant */
1360 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1361 /* EAX: NO ECX: NO EDX: NO */
1363 d = reg_of_var(rd, iptr->dst, REG_NULL);
1364 i386_emit_ialuconst(cd, ALU_SUB, src, iptr);
1367 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1368 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1369 /* EAX: S|YES ECX: NO EDX: NO */
1371 d = reg_of_var(rd, iptr->dst, REG_NULL);
1372 if (iptr->dst->flags & INMEMORY) {
1373 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1374 if (src->prev->regoff == iptr->dst->regoff) {
1375 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1376 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1377 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1378 i386_alu_reg_membase(cd, ALU_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1381 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1382 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1383 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1384 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1385 i386_alu_membase_reg(cd, ALU_SBB, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1386 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1392 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1393 /* val.l = constant */
1394 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1395 /* EAX: NO ECX: NO EDX: NO */
1396 /* else path can never happen? longs stay in memory! */
1398 d = reg_of_var(rd, iptr->dst, REG_NULL);
1399 if (iptr->dst->flags & INMEMORY) {
1400 if (src->flags & INMEMORY) {
1401 if (src->regoff == iptr->dst->regoff) {
1402 i386_alu_imm_membase(cd, ALU_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1403 i386_alu_imm_membase(cd, ALU_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1406 /* TODO: could be size optimized with lea -- see gcc output */
1407 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1408 i386_alu_imm_reg(cd, ALU_SUB, iptr->val.l, REG_ITMP1);
1409 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1410 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1411 i386_alu_imm_reg(cd, ALU_SBB, iptr->val.l >> 32, REG_ITMP1);
1412 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1418 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1419 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1420 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1422 d = reg_of_var(rd, iptr->dst, REG_NULL);
1423 if (iptr->dst->flags & INMEMORY) {
1424 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1425 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1426 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1427 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1429 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1430 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1431 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1432 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1434 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1435 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1436 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1437 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1440 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1441 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1442 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1446 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1447 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1448 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1450 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1451 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1452 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1454 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1455 M_INTMOVE(src->regoff, iptr->dst->regoff);
1456 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1459 if (src->regoff == iptr->dst->regoff) {
1460 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1463 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1464 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1470 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1471 /* val.i = constant */
1472 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1473 /* EAX: YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1475 d = reg_of_var(rd, iptr->dst, REG_NULL);
1476 if (iptr->dst->flags & INMEMORY) {
1477 if (src->flags & INMEMORY) {
1478 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, REG_ITMP1);
1479 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1482 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1483 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1487 if (src->flags & INMEMORY) {
1488 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, iptr->dst->regoff);
1491 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1496 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1497 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1498 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1500 d = reg_of_var(rd, iptr->dst, REG_NULL);
1501 if (iptr->dst->flags & INMEMORY) {
1502 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1503 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX); /* mem -> EAX */
1504 /* optimize move EAX -> REG_ITMP3 is slower??? */
1505 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1506 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1508 /* TODO: optimize move EAX -> REG_ITMP3 */
1509 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); /* mem -> ITMP3 */
1510 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1511 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1513 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP2); /* mem -> ITMP3 */
1514 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1516 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1517 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1518 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1523 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1524 /* val.l = constant */
1525 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1526 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1528 d = reg_of_var(rd, iptr->dst, REG_NULL);
1529 if (iptr->dst->flags & INMEMORY) {
1530 if (src->flags & INMEMORY) {
1531 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1532 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1533 /* TODO: optimize move EAX -> REG_ITMP3 */
1534 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1535 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1537 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1538 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1539 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1541 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1542 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1543 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1548 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1549 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1550 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX */
1552 d = reg_of_var(rd, iptr->dst, REG_NULL);
1553 var_to_reg_int(s1, src, REG_ITMP2);
1555 if (src->prev->flags & INMEMORY) {
1556 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1559 M_INTMOVE(src->prev->regoff, EAX);
1562 /* check as described in jvm spec */
1564 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1565 i386_jcc(cd, I386_CC_NE, 3 + 6);
1566 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1567 i386_jcc(cd, I386_CC_E, 1 + 2);
1570 i386_idiv_reg(cd, s1);
1572 if (iptr->dst->flags & INMEMORY) {
1573 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1576 M_INTMOVE(EAX, iptr->dst->regoff);
1580 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1581 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1582 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EDX */
1585 d = reg_of_var(rd, iptr->dst, REG_NULL);
1586 var_to_reg_int(s1, src, REG_ITMP2);
1588 if (src->prev->flags & INMEMORY) {
1589 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1592 M_INTMOVE(src->prev->regoff, EAX);
1595 /* check as described in jvm spec */
1597 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1598 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1599 i386_alu_reg_reg(cd, ALU_XOR, EDX, EDX);
1600 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1601 i386_jcc(cd, I386_CC_E, 1 + 2);
1604 i386_idiv_reg(cd, s1);
1606 if (iptr->dst->flags & INMEMORY) {
1607 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4);
1610 M_INTMOVE(EDX, iptr->dst->regoff);
1614 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1615 /* val.i = constant */
1616 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1617 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL */
1619 /* TODO: optimize for `/ 2' */
1620 var_to_reg_int(s1, src, REG_ITMP1);
1621 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1624 i386_test_reg_reg(cd, d, d);
1626 CALCIMMEDIATEBYTES(disp, (1 << iptr->val.i) - 1);
1627 i386_jcc(cd, I386_CC_NS, disp);
1628 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, d);
1630 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1631 store_reg_to_var_int(iptr->dst, d);
1634 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1635 /* val.i = constant */
1636 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1637 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1639 var_to_reg_int(s1, src, REG_ITMP1);
1640 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1642 M_INTMOVE(s1, REG_ITMP1);
1649 CALCIMMEDIATEBYTES(disp, iptr->val.i);
1652 /* TODO: optimize */
1654 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1655 i386_test_reg_reg(cd, s1, s1);
1656 i386_jcc(cd, I386_CC_GE, disp);
1657 i386_mov_reg_reg(cd, s1, d);
1658 i386_neg_reg(cd, d);
1659 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1660 i386_neg_reg(cd, d);
1662 /* M_INTMOVE(s1, EAX); */
1663 /* i386_cltd(cd); */
1664 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1665 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1666 /* i386_alu_reg_reg(cd, ALU_AND, iptr->val.i, EAX); */
1667 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1668 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1669 /* M_INTMOVE(EAX, d); */
1671 /* i386_alu_reg_reg(cd, ALU_XOR, d, d); */
1672 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1673 /* i386_shrd_reg_reg(cd, s1, d); */
1674 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1676 store_reg_to_var_int(iptr->dst, d);
1679 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1680 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1682 d = reg_of_var(rd, iptr->dst, REG_NULL);
1683 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4);
1684 M_OR_MEMBASE(REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1687 codegen_addxdivrefs(cd, cd->mcodeptr);
1692 M_ILD(REG_ITMP1, REG_SP, src->prev->regoff * 4);
1693 M_ILD(REG_ITMP2, REG_SP, src->prev->regoff * 4 + 4);
1694 M_IST(REG_ITMP1, REG_SP, 0 * 4);
1695 M_IST(REG_ITMP2, REG_SP, 0 * 4 + 4);
1697 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
1698 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4 + 4);
1699 M_IST(REG_ITMP1, REG_SP, 2 * 4);
1700 M_IST(REG_ITMP2, REG_SP, 2 * 4 + 4);
1702 M_MOV_IMM((ptrint) bte->fp, REG_ITMP3);
1705 M_IST(REG_RESULT, REG_SP, iptr->dst->regoff * 4);
1706 M_IST(REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
1709 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1710 /* val.i = constant */
1711 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1712 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1714 d = reg_of_var(rd, iptr->dst, REG_NULL);
1715 if (iptr->dst->flags & INMEMORY) {
1716 if (src->flags & INMEMORY) {
1718 CALCIMMEDIATEBYTES(disp, (1 << iptr->val.i) - 1);
1720 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1721 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1723 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1724 i386_jcc(cd, I386_CC_NS, disp);
1725 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1726 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1727 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1728 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1730 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1731 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1736 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1737 /* val.l = constant */
1738 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1739 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1741 d = reg_of_var(rd, iptr->dst, REG_NULL);
1742 if (iptr->dst->flags & INMEMORY) {
1743 if (src->flags & INMEMORY) {
1744 /* Intel algorithm -- does not work, because constant is wrong */
1745 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1); */
1746 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3); */
1748 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1749 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1750 /* i386_jcc(cd, I386_CC_NS, offset); */
1751 /* i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1752 /* i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP3); */
1754 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1755 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1756 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1758 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1760 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1); */
1761 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); */
1762 /* i386_alu_reg_reg(cd, ALU_SBB, REG_ITMP3, REG_ITMP2); */
1764 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1765 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1767 /* Alpha algorithm */
1769 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1771 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4 + 4);
1777 /* TODO: hmm, don't know if this is always correct */
1779 CALCIMMEDIATEBYTES(disp, iptr->val.l & 0x00000000ffffffff);
1781 CALCIMMEDIATEBYTES(disp, iptr->val.l >> 32);
1787 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1788 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1790 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1791 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1792 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4 + 4);
1793 i386_jcc(cd, I386_CC_GE, disp);
1795 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1796 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1798 i386_neg_reg(cd, REG_ITMP1);
1799 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1800 i386_neg_reg(cd, REG_ITMP2);
1802 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1803 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1805 i386_neg_reg(cd, REG_ITMP1);
1806 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1807 i386_neg_reg(cd, REG_ITMP2);
1809 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1810 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1815 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1816 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1817 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1819 d = reg_of_var(rd, iptr->dst, REG_NULL);
1820 i386_emit_ishift(cd, I386_SHL, src, iptr);
1823 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1824 /* val.i = constant */
1825 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1826 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1828 d = reg_of_var(rd, iptr->dst, REG_NULL);
1829 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1832 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1833 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1834 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1836 d = reg_of_var(rd, iptr->dst, REG_NULL);
1837 i386_emit_ishift(cd, I386_SAR, src, iptr);
1840 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1841 /* val.i = constant */
1842 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1843 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1845 d = reg_of_var(rd, iptr->dst, REG_NULL);
1846 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1849 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1850 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1851 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1853 d = reg_of_var(rd, iptr->dst, REG_NULL);
1854 i386_emit_ishift(cd, I386_SHR, src, iptr);
1857 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1858 /* val.i = constant */
1859 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1860 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1862 d = reg_of_var(rd, iptr->dst, REG_NULL);
1863 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1866 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1867 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1868 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
1870 d = reg_of_var(rd, iptr->dst, REG_NULL);
1871 if (iptr->dst->flags & INMEMORY ){
1872 if (src->prev->flags & INMEMORY) {
1873 /* if (src->prev->regoff == iptr->dst->regoff) { */
1874 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1876 /* if (src->flags & INMEMORY) { */
1877 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1879 /* M_INTMOVE(src->regoff, ECX); */
1882 /* i386_test_imm_reg(cd, 32, ECX); */
1883 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1884 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1885 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1); */
1887 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 4 + 4); */
1888 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 4); */
1891 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1892 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1894 if (src->flags & INMEMORY) {
1895 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1897 M_INTMOVE(src->regoff, ECX);
1900 i386_test_imm_reg(cd, 32, ECX);
1901 i386_jcc(cd, I386_CC_E, 2 + 2);
1902 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1903 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1905 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1906 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1907 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1908 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
1914 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1915 /* val.i = constant */
1916 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1917 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1919 d = reg_of_var(rd, iptr->dst, REG_NULL);
1920 if (iptr->dst->flags & INMEMORY ) {
1921 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1922 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1924 if (iptr->val.i & 0x20) {
1925 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1926 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1927 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1930 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1931 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1934 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1935 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1939 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1940 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1941 /* EAX: S|YES ECX: YES S|EDX: YES OUTPUT: REG_NULL*/
1943 d = reg_of_var(rd, iptr->dst, REG_NULL);
1944 if (iptr->dst->flags & INMEMORY ){
1945 if (src->prev->flags & INMEMORY) {
1946 /* if (src->prev->regoff == iptr->dst->regoff) { */
1947 /* TODO: optimize */
1948 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1949 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
1951 /* if (src->flags & INMEMORY) { */
1952 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1954 /* M_INTMOVE(src->regoff, ECX); */
1957 /* i386_test_imm_reg(cd, 32, ECX); */
1958 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1959 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1960 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1962 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1963 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1964 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1965 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1968 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1969 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1971 if (src->flags & INMEMORY) {
1972 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1974 M_INTMOVE(src->regoff, ECX);
1977 i386_test_imm_reg(cd, 32, ECX);
1978 i386_jcc(cd, I386_CC_E, 2 + 3);
1979 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1980 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1982 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1983 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1984 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1985 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
1991 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1992 /* val.i = constant */
1993 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1994 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1996 d = reg_of_var(rd, iptr->dst, REG_NULL);
1997 if (iptr->dst->flags & INMEMORY ) {
1998 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1999 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
2001 if (iptr->val.i & 0x20) {
2002 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2003 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
2004 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2007 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2008 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
2011 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2012 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
2016 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
2017 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2018 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
2020 d = reg_of_var(rd, iptr->dst, REG_NULL);
2021 if (iptr->dst->flags & INMEMORY ){
2022 if (src->prev->flags & INMEMORY) {
2023 /* if (src->prev->regoff == iptr->dst->regoff) { */
2024 /* TODO: optimize */
2025 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
2026 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
2028 /* if (src->flags & INMEMORY) { */
2029 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
2031 /* M_INTMOVE(src->regoff, ECX); */
2034 /* i386_test_imm_reg(cd, 32, ECX); */
2035 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
2036 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2037 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2); */
2039 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2040 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
2041 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
2042 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
2045 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
2046 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
2048 if (src->flags & INMEMORY) {
2049 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
2051 M_INTMOVE(src->regoff, ECX);
2054 i386_test_imm_reg(cd, 32, ECX);
2055 i386_jcc(cd, I386_CC_E, 2 + 2);
2056 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2057 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP3, REG_ITMP3);
2059 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2060 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
2061 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2062 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2068 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
2069 /* val.l = constant */
2070 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2071 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
2073 d = reg_of_var(rd, iptr->dst, REG_NULL);
2074 if (iptr->dst->flags & INMEMORY ) {
2075 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
2076 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
2078 if (iptr->val.i & 0x20) {
2079 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2080 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
2081 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2084 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2085 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
2088 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2089 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
2093 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2094 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2095 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2097 d = reg_of_var(rd, iptr->dst, REG_NULL);
2098 i386_emit_ialu(cd, ALU_AND, src, iptr);
2101 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
2102 /* val.i = constant */
2103 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2104 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2106 d = reg_of_var(rd, iptr->dst, REG_NULL);
2107 i386_emit_ialuconst(cd, ALU_AND, src, iptr);
2110 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2111 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2112 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2114 d = reg_of_var(rd, iptr->dst, REG_NULL);
2115 i386_emit_lalu(cd, ALU_AND, src, iptr);
2118 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
2119 /* val.l = constant */
2120 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2121 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2123 d = reg_of_var(rd, iptr->dst, REG_NULL);
2124 i386_emit_laluconst(cd, ALU_AND, src, iptr);
2127 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2128 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2129 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2131 d = reg_of_var(rd, iptr->dst, REG_NULL);
2132 i386_emit_ialu(cd, ALU_OR, src, iptr);
2135 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2136 /* val.i = constant */
2137 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2138 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2140 d = reg_of_var(rd, iptr->dst, REG_NULL);
2141 i386_emit_ialuconst(cd, ALU_OR, src, iptr);
2144 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2145 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2146 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2148 d = reg_of_var(rd, iptr->dst, REG_NULL);
2149 i386_emit_lalu(cd, ALU_OR, src, iptr);
2152 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2153 /* val.l = constant */
2154 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2155 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2157 d = reg_of_var(rd, iptr->dst, REG_NULL);
2158 i386_emit_laluconst(cd, ALU_OR, src, iptr);
2161 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2162 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2163 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2165 d = reg_of_var(rd, iptr->dst, REG_NULL);
2166 i386_emit_ialu(cd, ALU_XOR, src, iptr);
2169 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2170 /* val.i = constant */
2171 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2172 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2174 d = reg_of_var(rd, iptr->dst, REG_NULL);
2175 i386_emit_ialuconst(cd, ALU_XOR, src, iptr);
2178 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2179 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2180 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2182 d = reg_of_var(rd, iptr->dst, REG_NULL);
2183 i386_emit_lalu(cd, ALU_XOR, src, iptr);
2186 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2187 /* val.l = constant */
2188 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2189 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2191 d = reg_of_var(rd, iptr->dst, REG_NULL);
2192 i386_emit_laluconst(cd, ALU_XOR, src, iptr);
2195 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2196 /* op1 = variable, val.i = constant */
2197 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2198 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL */
2200 var = &(rd->locals[iptr->op1][TYPE_INT]);
2201 if (var->flags & INMEMORY)
2202 M_IADD_IMM_MEMBASE(iptr->val.i, REG_SP, var->regoff * 4);
2204 /* `inc reg' is slower on p4's (regarding to ia32
2205 optimization reference manual and benchmarks) and
2206 as fast on athlon's. */
2207 M_IADD_IMM(iptr->val.i, var->regoff);
2212 /* floating operations ************************************************/
2214 #define ROUND_TO_SINGLE \
2215 i386_fstps_membase(cd, REG_SP, -8); \
2216 i386_flds_membase(cd, REG_SP, -8);
2218 #define ROUND_TO_DOUBLE \
2219 i386_fstpl_membase(cd, REG_SP, -8); \
2220 i386_fldl_membase(cd, REG_SP, -8);
2222 #define FPU_SET_24BIT_MODE \
2223 if (!fpu_in_24bit_mode) { \
2224 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2225 fpu_in_24bit_mode = 1; \
2228 #define FPU_SET_53BIT_MODE \
2229 if (fpu_in_24bit_mode) { \
2230 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2231 fpu_in_24bit_mode = 0; \
2234 #define ROUND_TO_SINGLE
2235 #define ROUND_TO_DOUBLE
2236 #define FPU_SET_24BIT_MODE
2237 #define FPU_SET_53BIT_MODE
2239 case ICMD_FNEG: /* ..., value ==> ..., - value */
2240 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2241 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2244 var_to_reg_flt(s1, src, REG_FTMP1);
2245 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2247 store_reg_to_var_flt(iptr->dst, d);
2250 case ICMD_DNEG: /* ..., value ==> ..., - value */
2251 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2252 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2255 var_to_reg_flt(s1, src, REG_FTMP1);
2256 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2258 store_reg_to_var_flt(iptr->dst, d);
2261 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2262 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2263 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2266 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2267 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2268 var_to_reg_flt(s2, src, REG_FTMP2);
2271 store_reg_to_var_flt(iptr->dst, d);
2274 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2275 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2276 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2279 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2280 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2281 var_to_reg_flt(s2, src, REG_FTMP2);
2284 store_reg_to_var_flt(iptr->dst, d);
2287 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2288 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2289 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2292 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2293 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2294 var_to_reg_flt(s2, src, REG_FTMP2);
2297 store_reg_to_var_flt(iptr->dst, d);
2300 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2301 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2302 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2305 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2306 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2307 var_to_reg_flt(s2, src, REG_FTMP2);
2310 store_reg_to_var_flt(iptr->dst, d);
2313 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2314 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2315 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2318 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2319 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2320 var_to_reg_flt(s2, src, REG_FTMP2);
2324 store_reg_to_var_flt(iptr->dst, d);
2327 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2328 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2329 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2332 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2333 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2335 /* i386_fldt_mem(cd, subnormal_bias1); */
2336 /* i386_fmulp(cd); */
2338 var_to_reg_flt(s2, src, REG_FTMP2);
2343 /* i386_fldt_mem(cd, subnormal_bias2); */
2344 /* i386_fmulp(cd); */
2346 store_reg_to_var_flt(iptr->dst, d);
2349 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2350 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2351 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2354 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2355 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2356 var_to_reg_flt(s2, src, REG_FTMP2);
2360 store_reg_to_var_flt(iptr->dst, d);
2363 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2364 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2365 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2368 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2369 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2371 /* i386_fldt_mem(cd, subnormal_bias1); */
2372 /* i386_fmulp(cd); */
2374 var_to_reg_flt(s2, src, REG_FTMP2);
2379 /* i386_fldt_mem(cd, subnormal_bias2); */
2380 /* i386_fmulp(cd); */
2382 store_reg_to_var_flt(iptr->dst, d);
2385 case ICMD_FREM: /* ..., 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 /* exchanged to skip fxch */
2391 var_to_reg_flt(s2, src, REG_FTMP2);
2392 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2393 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2394 /* i386_fxch(cd); */
2399 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2400 store_reg_to_var_flt(iptr->dst, d);
2401 i386_ffree_reg(cd, 0);
2406 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2407 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2408 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2411 /* exchanged to skip fxch */
2412 var_to_reg_flt(s2, src, REG_FTMP2);
2413 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2414 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2415 /* i386_fxch(cd); */
2420 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2421 store_reg_to_var_flt(iptr->dst, d);
2422 i386_ffree_reg(cd, 0);
2427 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2428 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2429 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2430 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2432 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2433 if (src->flags & INMEMORY) {
2434 i386_fildl_membase(cd, REG_SP, src->regoff * 4);
2438 disp = dseg_adds4(cd, 0);
2439 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2440 dseg_adddata(cd, cd->mcodeptr);
2441 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, disp);
2442 i386_fildl_membase(cd, REG_ITMP1, disp);
2445 store_reg_to_var_flt(iptr->dst, d);
2448 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2449 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2450 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2451 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2453 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2454 if (src->flags & INMEMORY) {
2455 i386_fildll_membase(cd, REG_SP, src->regoff * 4);
2459 log_text("L2F: longs have to be in memory");
2462 store_reg_to_var_flt(iptr->dst, d);
2465 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2466 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2467 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2469 var_to_reg_flt(s1, src, REG_FTMP1);
2470 d = reg_of_var(rd, iptr->dst, REG_NULL);
2472 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2473 dseg_adddata(cd, cd->mcodeptr);
2475 /* Round to zero, 53-bit mode, exception masked */
2476 disp = dseg_adds4(cd, 0x0e7f);
2477 i386_fldcw_membase(cd, REG_ITMP1, disp);
2479 if (iptr->dst->flags & INMEMORY) {
2480 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2483 /* Round to nearest, 53-bit mode, exceptions masked */
2484 disp = dseg_adds4(cd, 0x027f);
2485 i386_fldcw_membase(cd, REG_ITMP1, disp);
2487 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2490 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2492 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2495 disp = dseg_adds4(cd, 0);
2496 i386_fistpl_membase(cd, REG_ITMP1, disp);
2498 i386_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2500 /* Round to nearest, 53-bit mode, exceptions masked */
2501 disp = dseg_adds4(cd, 0x027f);
2502 i386_fldcw_membase(cd, REG_ITMP1, disp);
2504 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2507 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2508 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2511 i386_jcc(cd, I386_CC_NE, disp);
2513 /* XXX: change this when we use registers */
2514 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2515 i386_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP1);
2516 i386_call_reg(cd, REG_ITMP1);
2518 if (iptr->dst->flags & INMEMORY) {
2519 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2522 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2526 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2527 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2528 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2530 var_to_reg_flt(s1, src, REG_FTMP1);
2531 d = reg_of_var(rd, iptr->dst, REG_NULL);
2533 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2534 dseg_adddata(cd, cd->mcodeptr);
2536 /* Round to zero, 53-bit mode, exception masked */
2537 disp = dseg_adds4(cd, 0x0e7f);
2538 i386_fldcw_membase(cd, REG_ITMP1, disp);
2540 if (iptr->dst->flags & INMEMORY) {
2541 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2544 /* Round to nearest, 53-bit mode, exceptions masked */
2545 disp = dseg_adds4(cd, 0x027f);
2546 i386_fldcw_membase(cd, REG_ITMP1, disp);
2548 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2551 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2553 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2556 disp = dseg_adds4(cd, 0);
2557 i386_fistpl_membase(cd, REG_ITMP1, disp);
2559 i386_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2561 /* Round to nearest, 53-bit mode, exceptions masked */
2562 disp = dseg_adds4(cd, 0x027f);
2563 i386_fldcw_membase(cd, REG_ITMP1, disp);
2565 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2568 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2569 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2572 i386_jcc(cd, I386_CC_NE, disp);
2574 /* XXX: change this when we use registers */
2575 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2576 i386_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP1);
2577 i386_call_reg(cd, REG_ITMP1);
2579 if (iptr->dst->flags & INMEMORY) {
2580 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2582 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2586 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2587 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2588 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2590 var_to_reg_flt(s1, src, REG_FTMP1);
2591 d = reg_of_var(rd, iptr->dst, REG_NULL);
2593 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2594 dseg_adddata(cd, cd->mcodeptr);
2596 /* Round to zero, 53-bit mode, exception masked */
2597 disp = dseg_adds4(cd, 0x0e7f);
2598 i386_fldcw_membase(cd, REG_ITMP1, disp);
2600 if (iptr->dst->flags & INMEMORY) {
2601 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2604 /* Round to nearest, 53-bit mode, exceptions masked */
2605 disp = dseg_adds4(cd, 0x027f);
2606 i386_fldcw_membase(cd, REG_ITMP1, disp);
2608 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2611 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2613 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2616 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2618 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2620 i386_jcc(cd, I386_CC_NE, disp);
2622 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2625 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2627 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2629 i386_jcc(cd, I386_CC_NE, disp);
2631 /* XXX: change this when we use registers */
2632 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2633 i386_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP1);
2634 i386_call_reg(cd, REG_ITMP1);
2635 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2636 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2639 log_text("F2L: longs have to be in memory");
2644 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2645 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2646 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2648 var_to_reg_flt(s1, src, REG_FTMP1);
2649 d = reg_of_var(rd, iptr->dst, REG_NULL);
2651 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2652 dseg_adddata(cd, cd->mcodeptr);
2654 /* Round to zero, 53-bit mode, exception masked */
2655 disp = dseg_adds4(cd, 0x0e7f);
2656 i386_fldcw_membase(cd, REG_ITMP1, disp);
2658 if (iptr->dst->flags & INMEMORY) {
2659 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2662 /* Round to nearest, 53-bit mode, exceptions masked */
2663 disp = dseg_adds4(cd, 0x027f);
2664 i386_fldcw_membase(cd, REG_ITMP1, disp);
2666 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2669 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2671 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2674 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2676 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2678 i386_jcc(cd, I386_CC_NE, disp);
2680 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2683 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2685 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2687 i386_jcc(cd, I386_CC_NE, disp);
2689 /* XXX: change this when we use registers */
2690 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2691 i386_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP1);
2692 i386_call_reg(cd, REG_ITMP1);
2693 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2694 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2697 log_text("D2L: longs have to be in memory");
2702 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2703 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2704 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2706 var_to_reg_flt(s1, src, REG_FTMP1);
2707 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2709 store_reg_to_var_flt(iptr->dst, d);
2712 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2713 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2714 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2716 var_to_reg_flt(s1, src, REG_FTMP1);
2717 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2719 store_reg_to_var_flt(iptr->dst, d);
2722 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2724 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2725 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2727 /* exchanged to skip fxch */
2728 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2729 var_to_reg_flt(s1, src, REG_FTMP2);
2730 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2731 /* i386_fxch(cd); */
2735 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2736 i386_jcc(cd, I386_CC_E, 6);
2737 i386_alu_imm_reg(cd, ALU_AND, 0x000000ff, EAX);
2739 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2740 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2741 i386_jcc(cd, I386_CC_B, 3 + 5);
2742 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2743 i386_jmp_imm(cd, 3);
2744 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2745 store_reg_to_var_int(iptr->dst, d);
2748 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2750 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2751 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2753 /* exchanged to skip fxch */
2754 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2755 var_to_reg_flt(s1, src, REG_FTMP2);
2756 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2757 /* i386_fxch(cd); */
2761 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2762 i386_jcc(cd, I386_CC_E, 3);
2763 i386_movb_imm_reg(cd, 1, REG_AH);
2765 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2766 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2767 i386_jcc(cd, I386_CC_B, 3 + 5);
2768 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2769 i386_jmp_imm(cd, 3);
2770 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2771 store_reg_to_var_int(iptr->dst, d);
2775 /* memory operations **************************************************/
2777 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2778 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2779 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2781 var_to_reg_int(s1, src, REG_ITMP1);
2782 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2783 gen_nullptr_check(s1);
2784 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2785 store_reg_to_var_int(iptr->dst, d);
2788 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2789 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2790 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2792 var_to_reg_int(s1, src->prev, REG_ITMP1);
2793 var_to_reg_int(s2, src, REG_ITMP2);
2794 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2795 if (iptr->op1 == 0) {
2796 gen_nullptr_check(s1);
2799 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2800 store_reg_to_var_int(iptr->dst, d);
2803 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2804 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2805 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2807 var_to_reg_int(s1, src->prev, REG_ITMP1);
2808 var_to_reg_int(s2, src, REG_ITMP2);
2809 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2810 if (iptr->op1 == 0) {
2811 gen_nullptr_check(s1);
2815 if (iptr->dst->flags & INMEMORY) {
2816 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2817 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4);
2818 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2819 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2823 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2824 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2825 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2827 var_to_reg_int(s1, src->prev, REG_ITMP1);
2828 var_to_reg_int(s2, src, REG_ITMP2);
2829 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2830 if (iptr->op1 == 0) {
2831 gen_nullptr_check(s1);
2834 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2835 store_reg_to_var_int(iptr->dst, d);
2838 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2839 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2840 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2842 var_to_reg_int(s1, src->prev, REG_ITMP1);
2843 var_to_reg_int(s2, src, REG_ITMP2);
2844 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2845 if (iptr->op1 == 0) {
2846 gen_nullptr_check(s1);
2849 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2851 store_reg_to_var_flt(iptr->dst, d);
2854 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2855 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2856 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2858 var_to_reg_int(s1, src->prev, REG_ITMP1);
2859 var_to_reg_int(s2, src, REG_ITMP2);
2860 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2861 if (iptr->op1 == 0) {
2862 gen_nullptr_check(s1);
2865 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2867 store_reg_to_var_flt(iptr->dst, d);
2870 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2871 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2872 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2874 var_to_reg_int(s1, src->prev, REG_ITMP1);
2875 var_to_reg_int(s2, src, REG_ITMP2);
2876 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2877 if (iptr->op1 == 0) {
2878 gen_nullptr_check(s1);
2881 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2882 store_reg_to_var_int(iptr->dst, d);
2885 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2886 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2887 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2889 var_to_reg_int(s1, src->prev, REG_ITMP1);
2890 var_to_reg_int(s2, src, REG_ITMP2);
2891 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2892 if (iptr->op1 == 0) {
2893 gen_nullptr_check(s1);
2896 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2897 store_reg_to_var_int(iptr->dst, d);
2900 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2901 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2902 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2904 var_to_reg_int(s1, src->prev, REG_ITMP1);
2905 var_to_reg_int(s2, src, REG_ITMP2);
2906 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2907 if (iptr->op1 == 0) {
2908 gen_nullptr_check(s1);
2911 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2912 store_reg_to_var_int(iptr->dst, d);
2916 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2917 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2918 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
2920 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2921 var_to_reg_int(s2, src->prev, REG_ITMP2);
2922 if (iptr->op1 == 0) {
2923 gen_nullptr_check(s1);
2927 if (src->flags & INMEMORY) {
2928 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP3);
2929 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2930 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
2931 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2935 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2936 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2937 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2939 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2940 var_to_reg_int(s2, src->prev, REG_ITMP2);
2941 if (iptr->op1 == 0) {
2942 gen_nullptr_check(s1);
2945 var_to_reg_int(s3, src, REG_ITMP3);
2946 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2949 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2950 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2951 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2953 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2954 var_to_reg_int(s2, src->prev, REG_ITMP2);
2955 if (iptr->op1 == 0) {
2956 gen_nullptr_check(s1);
2959 var_to_reg_flt(s3, src, REG_FTMP1);
2960 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2964 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2965 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2966 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2968 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2969 var_to_reg_int(s2, src->prev, REG_ITMP2);
2970 if (iptr->op1 == 0) {
2971 gen_nullptr_check(s1);
2974 var_to_reg_flt(s3, src, REG_FTMP1);
2975 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2979 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2980 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2981 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2983 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2984 var_to_reg_int(s2, src->prev, REG_ITMP2);
2985 if (iptr->op1 == 0) {
2986 gen_nullptr_check(s1);
2989 var_to_reg_int(s3, src, REG_ITMP3);
2990 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2993 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2994 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2995 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2997 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2998 var_to_reg_int(s2, src->prev, REG_ITMP2);
2999 if (iptr->op1 == 0) {
3000 gen_nullptr_check(s1);
3003 var_to_reg_int(s3, src, REG_ITMP3);
3004 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3007 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
3008 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3009 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3011 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3012 var_to_reg_int(s2, src->prev, REG_ITMP2);
3013 if (iptr->op1 == 0) {
3014 gen_nullptr_check(s1);
3017 var_to_reg_int(s3, src, REG_ITMP3);
3018 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
3019 M_INTMOVE(s3, REG_ITMP3);
3022 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3025 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
3027 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3028 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
3030 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3031 var_to_reg_int(s2, src->prev, REG_ITMP2);
3032 if (iptr->op1 == 0) {
3033 gen_nullptr_check(s1);
3036 var_to_reg_int(s3, src, REG_ITMP3);
3038 M_AST(s1, REG_SP, 0 * 4);
3039 M_AST(s3, REG_SP, 1 * 4);
3040 M_MOV_IMM((ptrint) BUILTIN_canstore, REG_ITMP1);
3044 codegen_addxstorerefs(cd, cd->mcodeptr);
3046 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3047 var_to_reg_int(s2, src->prev, REG_ITMP2);
3048 var_to_reg_int(s3, src, REG_ITMP3);
3049 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3052 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
3053 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3054 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3056 var_to_reg_int(s1, src->prev, REG_ITMP1);
3057 var_to_reg_int(s2, src, REG_ITMP2);
3058 if (iptr->op1 == 0) {
3059 gen_nullptr_check(s1);
3062 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
3065 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
3066 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3067 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3069 var_to_reg_int(s1, src->prev, REG_ITMP1);
3070 var_to_reg_int(s2, src, REG_ITMP2);
3071 if (iptr->op1 == 0) {
3072 gen_nullptr_check(s1);
3076 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
3077 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
3080 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
3081 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3082 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3084 var_to_reg_int(s1, src->prev, REG_ITMP1);
3085 var_to_reg_int(s2, src, REG_ITMP2);
3086 if (iptr->op1 == 0) {
3087 gen_nullptr_check(s1);
3090 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3093 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
3094 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3095 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3097 var_to_reg_int(s1, src->prev, REG_ITMP1);
3098 var_to_reg_int(s2, src, REG_ITMP2);
3099 if (iptr->op1 == 0) {
3100 gen_nullptr_check(s1);
3103 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3106 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
3107 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3108 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3110 var_to_reg_int(s1, src->prev, REG_ITMP1);
3111 var_to_reg_int(s2, src, REG_ITMP2);
3112 if (iptr->op1 == 0) {
3113 gen_nullptr_check(s1);
3116 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
3119 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
3120 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3121 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3123 var_to_reg_int(s1, src->prev, REG_ITMP1);
3124 var_to_reg_int(s2, src, REG_ITMP2);
3125 if (iptr->op1 == 0) {
3126 gen_nullptr_check(s1);
3129 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3133 case ICMD_GETSTATIC: /* ... ==> ..., value */
3134 /* op1 = type, val.a = field address */
3135 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3136 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX*/
3138 if (iptr->val.a == NULL) {
3139 codegen_addpatchref(cd, cd->mcodeptr,
3140 PATCHER_get_putstatic,
3141 (unresolved_field *) iptr->target, 0);
3143 if (opt_showdisassemble) {
3144 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3150 fieldinfo *fi = iptr->val.a;
3152 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3153 codegen_addpatchref(cd, cd->mcodeptr,
3154 PATCHER_clinit, fi->class, 0);
3156 if (opt_showdisassemble) {
3157 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3161 disp = (ptrint) &(fi->value);
3164 M_MOV_IMM(disp, REG_ITMP1);
3165 switch (iptr->op1) {
3168 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3169 M_ILD(d, REG_ITMP1, 0);
3170 store_reg_to_var_int(iptr->dst, d);
3173 d = reg_of_var(rd, iptr->dst, REG_NULL);
3174 if (iptr->dst->flags & INMEMORY) {
3175 /* Using both REG_ITMP2 and REG_ITMP3 is faster
3176 than only using REG_ITMP2 alternating. */
3177 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP2);
3178 i386_mov_membase_reg(cd, REG_ITMP1, 4, REG_ITMP3);
3179 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4);
3180 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
3182 log_text("GETSTATIC: longs have to be in memory");
3187 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3188 i386_flds_membase(cd, REG_ITMP1, 0);
3190 store_reg_to_var_flt(iptr->dst, d);
3193 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3194 i386_fldl_membase(cd, REG_ITMP1, 0);
3196 store_reg_to_var_flt(iptr->dst, d);
3201 case ICMD_PUTSTATIC: /* ..., value ==> ... */
3202 /* op1 = type, val.a = field address */
3203 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3204 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3206 if (iptr->val.a == NULL) {
3207 codegen_addpatchref(cd, cd->mcodeptr,
3208 PATCHER_get_putstatic,
3209 (unresolved_field *) iptr->target, 0);
3211 if (opt_showdisassemble) {
3212 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3218 fieldinfo *fi = iptr->val.a;
3220 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3221 codegen_addpatchref(cd, cd->mcodeptr,
3222 PATCHER_clinit, fi->class, 0);
3224 if (opt_showdisassemble) {
3225 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3229 disp = (ptrint) &(fi->value);
3232 M_MOV_IMM(disp, REG_ITMP1);
3233 switch (iptr->op1) {
3236 var_to_reg_int(s2, src, REG_ITMP2);
3237 M_IST(s2, REG_ITMP1, 0);
3240 if (src->flags & INMEMORY) {
3241 /* Using both REG_ITMP2 and REG_ITMP3 is faster
3242 than only using REG_ITMP2 alternating. */
3245 i386_mov_membase_reg(cd, REG_SP, s2 * 4, REG_ITMP2);
3246 i386_mov_membase_reg(cd, REG_SP, s2 * 4 + 4, REG_ITMP3);
3247 i386_mov_reg_membase(cd, REG_ITMP2, REG_ITMP1, 0);
3248 i386_mov_reg_membase(cd, REG_ITMP3, REG_ITMP1, 4);
3250 log_text("PUTSTATIC: longs have to be in memory");
3255 var_to_reg_flt(s2, src, REG_FTMP1);
3256 i386_fstps_membase(cd, REG_ITMP1, 0);
3260 var_to_reg_flt(s2, src, REG_FTMP1);
3261 i386_fstpl_membase(cd, REG_ITMP1, 0);
3267 case ICMD_PUTSTATICCONST: /* ... ==> ... */
3268 /* val = value (in current instruction) */
3269 /* op1 = type, val.a = field address (in */
3270 /* following NOP) */
3271 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3272 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3274 if (iptr[1].val.a == NULL) {
3275 codegen_addpatchref(cd, cd->mcodeptr,
3276 PATCHER_get_putstatic,
3277 (unresolved_field *) iptr[1].target, 0);
3279 if (opt_showdisassemble) {
3280 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3286 fieldinfo *fi = iptr[1].val.a;
3288 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3289 codegen_addpatchref(cd, cd->mcodeptr,
3290 PATCHER_clinit, fi->class, 0);
3292 if (opt_showdisassemble) {
3293 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3297 disp = (ptrint) &(fi->value);
3300 M_MOV_IMM(disp, REG_ITMP1);
3301 switch (iptr[1].op1) {
3305 i386_mov_imm_membase(cd, iptr->val.i, REG_ITMP1, 0);
3309 i386_mov_imm_membase(cd, iptr->val.l, REG_ITMP1, 0);
3310 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_ITMP1, 4);
3315 case ICMD_GETFIELD: /* .., objectref. ==> ..., value */
3316 /* op1 = type, val.i = field offset */
3317 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3318 /* EAX: YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
3320 var_to_reg_int(s1, src, REG_ITMP1);
3321 gen_nullptr_check(s1);
3323 if (iptr->val.a == NULL) {
3324 codegen_addpatchref(cd, cd->mcodeptr,
3326 (unresolved_field *) iptr->target, 0);
3328 if (opt_showdisassemble) {
3329 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3335 disp = ((fieldinfo *) (iptr->val.a))->offset;
3338 switch (iptr->op1) {
3341 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3342 i386_mov_membase32_reg(cd, s1, disp, d);
3343 store_reg_to_var_int(iptr->dst, d);
3346 d = reg_of_var(rd, iptr->dst, REG_NULL);
3347 i386_mov_membase32_reg(cd, s1, disp, REG_ITMP2);
3348 i386_mov_membase32_reg(cd, s1, disp + 4, REG_ITMP3);
3349 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4);
3350 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
3353 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3354 i386_flds_membase32(cd, s1, disp);
3356 store_reg_to_var_flt(iptr->dst, d);
3359 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3360 i386_fldl_membase32(cd, s1, disp);
3362 store_reg_to_var_flt(iptr->dst, d);
3367 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
3368 /* op1 = type, val.a = field address */
3369 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3370 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3372 var_to_reg_int(s1, src->prev, REG_ITMP1);
3373 gen_nullptr_check(s1);
3375 if ((iptr->op1 == TYPE_INT) || IS_ADR_TYPE(iptr->op1)) {
3376 var_to_reg_int(s2, src, REG_ITMP2);
3377 } else if (IS_FLT_DBL_TYPE(iptr->op1)) {
3378 var_to_reg_flt(s2, src, REG_FTMP2);
3381 if (iptr->val.a == NULL) {
3382 codegen_addpatchref(cd, cd->mcodeptr,
3384 (unresolved_field *) iptr->target, 0);
3386 if (opt_showdisassemble) {
3387 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3393 disp = ((fieldinfo *) (iptr->val.a))->offset;
3396 switch (iptr->op1) {
3399 i386_mov_reg_membase32(cd, s2, s1, disp);
3402 if (src->flags & INMEMORY) {
3403 i386_mov_membase32_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2);
3404 i386_mov_membase32_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
3405 i386_mov_reg_membase32(cd, REG_ITMP2, s1, disp);
3406 i386_mov_reg_membase32(cd, REG_ITMP3, s1, disp + 4);
3408 log_text("PUTFIELD: longs have to be in memory");
3413 i386_fstps_membase32(cd, s1, disp);
3417 i386_fstpl_membase32(cd, s1, disp);
3423 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
3424 /* val = value (in current instruction) */
3425 /* op1 = type, val.a = field address (in */
3426 /* following NOP) */
3427 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3428 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3430 var_to_reg_int(s1, src, REG_ITMP1);
3431 gen_nullptr_check(s1);
3433 if (iptr[1].val.a == NULL) {
3434 codegen_addpatchref(cd, cd->mcodeptr,
3435 PATCHER_putfieldconst,
3436 (unresolved_field *) iptr[1].target, 0);
3438 if (opt_showdisassemble) {
3439 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3445 disp = ((fieldinfo *) (iptr[1].val.a))->offset;
3448 switch (iptr[1].op1) {
3452 i386_mov_imm_membase32(cd, iptr->val.i, s1, disp);
3456 i386_mov_imm_membase32(cd, iptr->val.l, s1, disp);
3457 i386_mov_imm_membase32(cd, iptr->val.l >> 32, s1, disp + 4);
3463 /* branch operations **************************************************/
3465 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3466 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3467 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
3469 var_to_reg_int(s1, src, REG_ITMP1);
3470 M_INTMOVE(s1, REG_ITMP1_XPTR);
3472 #ifdef ENABLE_VERIFIER
3474 codegen_addpatchref(cd, cd->mcodeptr,
3475 PATCHER_athrow_areturn,
3476 (unresolved_class *) iptr->val.a, 0);
3478 if (opt_showdisassemble) {
3479 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3482 #endif /* ENABLE_VERIFIER */
3484 M_CALL_IMM(0); /* passing exception pc */
3485 M_POP(REG_ITMP2_XPC);
3487 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
3491 case ICMD_INLINE_GOTO:
3492 M_COPY(src,iptr->dst);
3494 case ICMD_GOTO: /* ... ==> ... */
3495 /* op1 = target JavaVM pc */
3496 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3497 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3499 i386_jmp_imm(cd, 0);
3500 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3503 case ICMD_JSR: /* ... ==> ... */
3504 /* op1 = target JavaVM pc */
3505 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3506 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3508 i386_call_imm(cd, 0);
3509 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3512 case ICMD_RET: /* ... ==> ... */
3513 /* op1 = local variable */
3514 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3515 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3517 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3518 var_to_reg_int(s1, var, REG_ITMP1);
3519 i386_jmp_reg(cd, s1);
3522 case ICMD_IFNULL: /* ..., value ==> ... */
3523 /* op1 = target JavaVM pc */
3524 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3525 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3527 if (src->flags & INMEMORY) {
3528 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3531 i386_test_reg_reg(cd, src->regoff, src->regoff);
3533 i386_jcc(cd, I386_CC_E, 0);
3534 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3537 case ICMD_IFNONNULL: /* ..., value ==> ... */
3538 /* op1 = target JavaVM pc */
3539 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3540 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3542 if (src->flags & INMEMORY) {
3543 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3546 i386_test_reg_reg(cd, src->regoff, src->regoff);
3548 i386_jcc(cd, I386_CC_NE, 0);
3549 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3552 case ICMD_IFEQ: /* ..., value ==> ... */
3553 /* op1 = target JavaVM pc, val.i = constant */
3554 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3555 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3557 if (src->flags & INMEMORY) {
3558 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3561 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3563 i386_jcc(cd, I386_CC_E, 0);
3564 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3567 case ICMD_IFLT: /* ..., value ==> ... */
3568 /* op1 = target JavaVM pc, val.i = constant */
3569 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3570 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3572 if (src->flags & INMEMORY) {
3573 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3576 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3578 i386_jcc(cd, I386_CC_L, 0);
3579 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3582 case ICMD_IFLE: /* ..., value ==> ... */
3583 /* op1 = target JavaVM pc, val.i = constant */
3584 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3585 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3587 if (src->flags & INMEMORY) {
3588 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3591 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3593 i386_jcc(cd, I386_CC_LE, 0);
3594 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3597 case ICMD_IFNE: /* ..., value ==> ... */
3598 /* op1 = target JavaVM pc, val.i = constant */
3599 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3600 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3602 if (src->flags & INMEMORY) {
3603 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3606 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3608 i386_jcc(cd, I386_CC_NE, 0);
3609 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3612 case ICMD_IFGT: /* ..., value ==> ... */
3613 /* op1 = target JavaVM pc, val.i = constant */
3614 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3615 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3617 if (src->flags & INMEMORY) {
3618 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3621 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3623 i386_jcc(cd, I386_CC_G, 0);
3624 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3627 case ICMD_IFGE: /* ..., value ==> ... */
3628 /* op1 = target JavaVM pc, val.i = constant */
3629 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3630 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3632 if (src->flags & INMEMORY) {
3633 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3636 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3638 i386_jcc(cd, I386_CC_GE, 0);
3639 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3642 case ICMD_IF_LEQ: /* ..., value ==> ... */
3643 /* op1 = target JavaVM pc, val.l = constant */
3644 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3645 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3647 if (src->flags & INMEMORY) {
3648 if (iptr->val.l == 0) {
3649 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3650 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3653 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3654 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l >> 32, REG_ITMP2);
3655 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3656 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l, REG_ITMP1);
3657 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3660 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3661 i386_jcc(cd, I386_CC_E, 0);
3662 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3665 case ICMD_IF_LLT: /* ..., value ==> ... */
3666 /* op1 = target JavaVM pc, val.l = constant */
3667 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3668 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3670 if (src->flags & INMEMORY) {
3671 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3672 i386_jcc(cd, I386_CC_L, 0);
3673 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3676 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3677 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3679 i386_jcc(cd, I386_CC_G, disp);
3681 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3682 i386_jcc(cd, I386_CC_B, 0);
3683 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3687 case ICMD_IF_LLE: /* ..., value ==> ... */
3688 /* op1 = target JavaVM pc, val.l = constant */
3689 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3690 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3692 if (src->flags & INMEMORY) {
3693 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3694 i386_jcc(cd, I386_CC_L, 0);
3695 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3698 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3699 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3701 i386_jcc(cd, I386_CC_G, disp);
3703 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3704 i386_jcc(cd, I386_CC_BE, 0);
3705 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3709 case ICMD_IF_LNE: /* ..., value ==> ... */
3710 /* op1 = target JavaVM pc, val.l = constant */
3711 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3712 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3714 if (src->flags & INMEMORY) {
3715 if (iptr->val.l == 0) {
3716 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3717 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3720 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3721 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3722 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3723 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3724 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3727 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3728 i386_jcc(cd, I386_CC_NE, 0);
3729 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3732 case ICMD_IF_LGT: /* ..., value ==> ... */
3733 /* op1 = target JavaVM pc, val.l = constant */
3734 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3735 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3737 if (src->flags & INMEMORY) {
3738 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3739 i386_jcc(cd, I386_CC_G, 0);
3740 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3743 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3744 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3746 i386_jcc(cd, I386_CC_L, disp);
3748 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3749 i386_jcc(cd, I386_CC_A, 0);
3750 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3754 case ICMD_IF_LGE: /* ..., value ==> ... */
3755 /* op1 = target JavaVM pc, val.l = constant */
3756 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3757 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3759 if (src->flags & INMEMORY) {
3760 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3761 i386_jcc(cd, I386_CC_G, 0);
3762 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3765 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3766 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3768 i386_jcc(cd, I386_CC_L, disp);
3770 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3771 i386_jcc(cd, I386_CC_AE, 0);
3772 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3776 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3777 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3778 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3779 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3781 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3782 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3783 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3785 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3786 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3788 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3789 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3792 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3794 i386_jcc(cd, I386_CC_E, 0);
3795 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3798 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3799 /* op1 = target JavaVM pc */
3800 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3801 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3803 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3804 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3805 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3806 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3807 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3808 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3809 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3811 i386_jcc(cd, I386_CC_E, 0);
3812 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3815 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3816 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3817 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3818 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3820 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3821 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3822 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3824 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3825 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3827 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3828 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3831 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3833 i386_jcc(cd, I386_CC_NE, 0);
3834 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3837 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3838 /* op1 = target JavaVM pc */
3839 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3840 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3842 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3843 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3844 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3845 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3846 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3847 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3848 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3850 i386_jcc(cd, I386_CC_NE, 0);
3851 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3854 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3855 /* op1 = target JavaVM pc */
3856 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3857 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3859 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3860 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3861 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3863 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3864 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3866 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3867 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3870 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3872 i386_jcc(cd, I386_CC_L, 0);
3873 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3876 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3877 /* op1 = target JavaVM pc */
3878 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3879 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3881 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3882 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3883 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3885 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3888 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3889 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3893 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3894 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3895 i386_jcc(cd, I386_CC_B, 0);
3896 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3900 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3901 /* op1 = target JavaVM pc */
3902 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3903 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3905 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3906 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3907 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3909 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3910 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3912 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3913 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3916 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3919 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3922 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3923 /* op1 = target JavaVM pc */
3924 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3925 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3927 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3928 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3929 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3931 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3934 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3935 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3939 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3940 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3941 i386_jcc(cd, I386_CC_A, 0);
3942 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3946 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3947 /* op1 = target JavaVM pc */
3948 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3949 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3951 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3952 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3953 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3955 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3956 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3958 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3959 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3962 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3965 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3968 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3969 /* op1 = target JavaVM pc */
3970 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3971 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3973 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3974 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3975 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3977 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3980 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3981 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3985 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3986 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3988 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3992 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3993 /* op1 = target JavaVM pc */
3994 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3995 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3997 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3998 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3999 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
4001 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
4002 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
4004 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
4005 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
4008 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
4011 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4014 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
4015 /* op1 = target JavaVM pc */
4016 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4017 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4019 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
4020 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
4021 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
4023 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4026 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
4027 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
4031 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
4032 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
4034 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4038 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
4040 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
4041 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4042 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4045 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
4046 /* val.i = constant */
4047 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4048 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4050 d = reg_of_var(rd, iptr->dst, REG_NULL);
4051 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
4054 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
4055 /* val.i = constant */
4056 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4057 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4059 d = reg_of_var(rd, iptr->dst, REG_NULL);
4060 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
4063 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
4064 /* val.i = constant */
4065 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4066 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4068 d = reg_of_var(rd, iptr->dst, REG_NULL);
4069 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
4072 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
4073 /* val.i = constant */
4074 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4075 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4077 d = reg_of_var(rd, iptr->dst, REG_NULL);
4078 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
4081 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
4082 /* val.i = constant */
4083 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4084 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4086 d = reg_of_var(rd, iptr->dst, REG_NULL);
4087 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
4090 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
4091 /* val.i = constant */
4092 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4093 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4095 d = reg_of_var(rd, iptr->dst, REG_NULL);
4096 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
4100 case ICMD_IRETURN: /* ..., retvalue ==> ... */
4101 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4102 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4104 var_to_reg_int(s1, src, REG_RESULT);
4105 M_INTMOVE(s1, REG_RESULT);
4106 goto nowperformreturn;
4108 case ICMD_LRETURN: /* ..., retvalue ==> ... */
4109 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4110 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4112 if (src->flags & INMEMORY) {
4113 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_RESULT);
4114 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_RESULT2);
4117 log_text("LRETURN: longs have to be in memory");
4120 goto nowperformreturn;
4122 case ICMD_ARETURN: /* ..., retvalue ==> ... */
4123 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4124 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4126 var_to_reg_int(s1, src, REG_RESULT);
4127 M_INTMOVE(s1, REG_RESULT);
4129 #ifdef ENABLE_VERIFIER
4131 codegen_addpatchref(cd, cd->mcodeptr,
4132 PATCHER_athrow_areturn,
4133 (unresolved_class *) iptr->val.a, 0);
4135 if (opt_showdisassemble) {
4136 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4139 #endif /* ENABLE_VERIFIER */
4140 goto nowperformreturn;
4142 case ICMD_FRETURN: /* ..., retvalue ==> ... */
4144 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4145 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4147 var_to_reg_flt(s1, src, REG_FRESULT);
4148 /* this may be an early return -- keep the offset correct for the
4151 goto nowperformreturn;
4153 case ICMD_RETURN: /* ... ==> ... */
4154 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4155 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4161 p = parentargs_base;
4163 /* call trace function */
4165 i386_alu_imm_reg(cd, ALU_SUB, 4 + 8 + 8 + 4, REG_SP);
4167 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
4169 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
4170 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
4172 i386_fstl_membase(cd, REG_SP, 4 + 8);
4173 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
4175 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
4176 i386_call_reg(cd, REG_ITMP1);
4178 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
4179 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
4181 i386_alu_imm_reg(cd, ALU_ADD, 4 + 8 + 8 + 4, REG_SP);
4184 #if defined(USE_THREADS)
4185 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
4186 M_ALD(REG_ITMP2, REG_SP, rd->memuse * 4);
4188 /* we need to save the proper return value */
4189 switch (iptr->opc) {
4192 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4196 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4197 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4201 i386_fstps_membase(cd, REG_SP, rd->memuse * 4);
4205 i386_fstpl_membase(cd, REG_SP, rd->memuse * 4);
4209 M_AST(REG_ITMP2, REG_SP, 0);
4210 M_MOV_IMM((ptrint) BUILTIN_monitorexit, REG_ITMP1);
4213 /* and now restore the proper return value */
4214 switch (iptr->opc) {
4217 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4221 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4222 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4226 i386_flds_membase(cd, REG_SP, rd->memuse * 4);
4230 i386_fldl_membase(cd, REG_SP, rd->memuse * 4);
4236 /* restore saved registers */
4238 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
4239 p--; M_ALD(rd->savintregs[i], REG_SP, p * 4);
4242 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
4244 i386_fldl_membase(cd, REG_SP, p * 4);
4246 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
4247 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
4249 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
4254 /* deallocate stack */
4256 if (parentargs_base)
4257 M_AADD_IMM(parentargs_base * 4, REG_SP);
4264 case ICMD_TABLESWITCH: /* ..., index ==> ... */
4265 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4266 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4271 tptr = (void **) iptr->target;
4273 s4ptr = iptr->val.a;
4274 l = s4ptr[1]; /* low */
4275 i = s4ptr[2]; /* high */
4277 var_to_reg_int(s1, src, REG_ITMP1);
4278 M_INTMOVE(s1, REG_ITMP1);
4280 i386_alu_imm_reg(cd, ALU_SUB, l, REG_ITMP1);
4286 i386_alu_imm_reg(cd, ALU_CMP, i - 1, REG_ITMP1);
4287 i386_jcc(cd, I386_CC_A, 0);
4289 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4291 /* build jump table top down and use address of lowest entry */
4296 dseg_addtarget(cd, (basicblock *) tptr[0]);
4300 /* length of dataseg after last dseg_addtarget is used by load */
4302 i386_mov_imm_reg(cd, 0, REG_ITMP2);
4303 dseg_adddata(cd, cd->mcodeptr);
4304 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
4305 i386_jmp_reg(cd, REG_ITMP1);
4310 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
4311 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4312 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4314 s4 i, l, val, *s4ptr;
4317 tptr = (void **) iptr->target;
4319 s4ptr = iptr->val.a;
4320 l = s4ptr[0]; /* default */
4321 i = s4ptr[1]; /* count */
4323 MCODECHECK((i<<2)+8);
4324 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
4330 i386_alu_imm_reg(cd, ALU_CMP, val, s1);
4331 i386_jcc(cd, I386_CC_E, 0);
4332 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4335 i386_jmp_imm(cd, 0);
4337 tptr = (void **) iptr->target;
4338 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4342 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
4343 /* op1 = arg count val.a = builtintable entry */
4344 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4345 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4351 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
4352 /* op1 = arg count, val.a = method pointer */
4354 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
4355 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
4356 case ICMD_INVOKEINTERFACE:
4358 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4359 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
4364 unresolved_method *um = iptr->target;
4365 md = um->methodref->parseddesc.md;
4367 md = lm->parseddesc;
4371 s3 = md->paramcount;
4373 MCODECHECK((s3 << 1) + 64);
4375 /* copy arguments to registers or stack location */
4377 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
4378 if (src->varkind == ARGVAR)
4380 if (IS_INT_LNG_TYPE(src->type)) {
4381 if (!md->params[s3].inmemory) {
4382 log_text("No integer argument registers available!");
4385 if (!IS_2_WORD_TYPE(src->type)) {
4386 if (src->flags & INMEMORY) {
4387 i386_mov_membase_reg(
4388 cd, REG_SP, src->regoff * 4, REG_ITMP1);
4389 i386_mov_reg_membase(
4390 cd, REG_ITMP1, REG_SP,
4391 md->params[s3].regoff * 4);
4393 i386_mov_reg_membase(
4394 cd, src->regoff, REG_SP,
4395 md->params[s3].regoff * 4);
4399 if (src->flags & INMEMORY) {
4401 src->regoff, md->params[s3].regoff);
4403 log_text("copy arguments: longs have to be in memory");
4409 if (!md->params[s3].inmemory) {
4410 log_text("No float argument registers available!");
4413 var_to_reg_flt(d, src, REG_FTMP1);
4414 if (src->type == TYPE_FLT) {
4416 cd, REG_SP, md->params[s3].regoff * 4);
4420 cd, REG_SP, md->params[s3].regoff * 4);
4426 switch (iptr->opc) {
4428 disp = (ptrint) bte->fp;
4429 d = md->returntype.type;
4431 M_MOV_IMM(disp, REG_ITMP1);
4434 /* if op1 == true, we need to check for an exception */
4436 if (iptr->op1 == true) {
4439 codegen_addxexceptionrefs(cd, cd->mcodeptr);
4443 case ICMD_INVOKESPECIAL:
4444 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
4445 gen_nullptr_check(REG_ITMP1);
4447 /* access memory for hardware nullptr */
4448 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1);
4452 case ICMD_INVOKESTATIC:
4454 unresolved_method *um = iptr->target;
4456 codegen_addpatchref(cd, cd->mcodeptr,
4457 PATCHER_invokestatic_special, um, 0);
4459 if (opt_showdisassemble) {
4460 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4464 d = md->returntype.type;
4467 disp = (ptrint) lm->stubroutine;
4468 d = lm->parseddesc->returntype.type;
4471 M_MOV_IMM(disp, REG_ITMP2);
4475 case ICMD_INVOKEVIRTUAL:
4476 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4477 gen_nullptr_check(REG_ITMP1);
4480 unresolved_method *um = iptr->target;
4482 codegen_addpatchref(cd, cd->mcodeptr,
4483 PATCHER_invokevirtual, um, 0);
4485 if (opt_showdisassemble) {
4486 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4490 d = md->returntype.type;
4493 s1 = OFFSET(vftbl_t, table[0]) +
4494 sizeof(methodptr) * lm->vftblindex;
4495 d = md->returntype.type;
4498 M_ALD(REG_ITMP2, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4499 i386_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP1);
4503 case ICMD_INVOKEINTERFACE:
4504 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4505 gen_nullptr_check(REG_ITMP1);
4508 unresolved_method *um = iptr->target;
4510 codegen_addpatchref(cd, cd->mcodeptr,
4511 PATCHER_invokeinterface, um, 0);
4513 if (opt_showdisassemble) {
4514 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4519 d = md->returntype.type;
4522 s1 = OFFSET(vftbl_t, interfacetable[0]) -
4523 sizeof(methodptr) * lm->class->index;
4525 s2 = sizeof(methodptr) * (lm - lm->class->methods);
4527 d = md->returntype.type;
4530 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4531 i386_mov_membase32_reg(cd, REG_ITMP1, s1, REG_ITMP2);
4532 i386_mov_membase32_reg(cd, REG_ITMP2, s2, REG_ITMP1);
4537 /* d contains return type */
4539 if (d != TYPE_VOID) {
4540 d = reg_of_var(rd, iptr->dst, REG_NULL);
4542 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
4543 if (IS_2_WORD_TYPE(iptr->dst->type)) {
4544 if (iptr->dst->flags & INMEMORY) {
4545 i386_mov_reg_membase(
4546 cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4547 i386_mov_reg_membase(
4548 cd, REG_RESULT2, REG_SP,
4549 iptr->dst->regoff * 4 + 4);
4551 log_text("RETURN: longs have to be in memory");
4556 if (iptr->dst->flags & INMEMORY) {
4557 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4560 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
4565 /* fld from called function -- has other fpu_st_offset counter */
4567 store_reg_to_var_flt(iptr->dst, d);
4573 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4574 /* op1: 0 == array, 1 == class */
4575 /* val.a: (classinfo*) superclass */
4577 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4578 /* EAX: YES ECX: I|YES EDX: I|YES OUTPUT: REG_NULL */
4580 /* superclass is an interface:
4582 * OK if ((sub == NULL) ||
4583 * (sub->vftbl->interfacetablelength > super->index) &&
4584 * (sub->vftbl->interfacetable[-super->index] != NULL));
4586 * superclass is a class:
4588 * OK if ((sub == NULL) || (0
4589 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4590 * super->vftbl->diffval));
4593 if (iptr->op1 == 1) {
4594 /* object type cast-check */
4597 vftbl_t *supervftbl;
4600 super = (classinfo *) iptr->val.a;
4607 superindex = super->index;
4608 supervftbl = super->vftbl;
4611 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4612 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4614 var_to_reg_int(s1, src, REG_ITMP1);
4616 /* calculate interface checkcast code size */
4618 s2 = 2; /* mov_membase_reg */
4619 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4621 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ +
4622 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4623 2 /* test */ + 6 /* jcc */);
4626 s2 += (opt_showdisassemble ? 5 : 0);
4628 /* calculate class checkcast code size */
4630 s3 = 2; /* mov_membase_reg */
4631 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4633 s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */;
4636 if (s1 != REG_ITMP1) {
4638 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
4641 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
4648 s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ +
4649 5 /* mov_imm_reg */ + 2 /* mov_membase_reg */);
4650 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
4653 s3 += 2 /* cmp */ + 6 /* jcc */;
4656 s3 += (opt_showdisassemble ? 5 : 0);
4658 /* if class is not resolved, check which code to call */
4661 i386_test_reg_reg(cd, s1, s1);
4662 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4664 codegen_addpatchref(cd, cd->mcodeptr,
4665 PATCHER_checkcast_instanceof_flags,
4666 (constant_classref *) iptr->target, 0);
4668 if (opt_showdisassemble) {
4669 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4672 i386_mov_imm_reg(cd, 0, REG_ITMP2); /* super->flags */
4673 i386_alu_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP2);
4674 i386_jcc(cd, I386_CC_Z, s2 + 5);
4677 /* interface checkcast code */
4679 if (!super || (super->flags & ACC_INTERFACE)) {
4681 i386_test_reg_reg(cd, s1, s1);
4682 i386_jcc(cd, I386_CC_Z, s2);
4685 i386_mov_membase_reg(cd, s1,
4686 OFFSET(java_objectheader, vftbl),
4690 codegen_addpatchref(cd, cd->mcodeptr,
4691 PATCHER_checkcast_instanceof_interface,
4692 (constant_classref *) iptr->target, 0);
4694 if (opt_showdisassemble) {
4695 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4699 i386_mov_membase32_reg(cd, REG_ITMP2,
4700 OFFSET(vftbl_t, interfacetablelength),
4702 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4703 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4704 i386_jcc(cd, I386_CC_LE, 0);
4705 codegen_addxcastrefs(cd, cd->mcodeptr);
4706 i386_mov_membase32_reg(cd, REG_ITMP2,
4707 OFFSET(vftbl_t, interfacetable[0]) -
4708 superindex * sizeof(methodptr*),
4710 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4711 i386_jcc(cd, I386_CC_E, 0);
4712 codegen_addxcastrefs(cd, cd->mcodeptr);
4715 i386_jmp_imm(cd, s3);
4718 /* class checkcast code */
4720 if (!super || !(super->flags & ACC_INTERFACE)) {
4722 i386_test_reg_reg(cd, s1, s1);
4723 i386_jcc(cd, I386_CC_Z, s3);
4726 i386_mov_membase_reg(cd, s1,
4727 OFFSET(java_objectheader, vftbl),
4731 codegen_addpatchref(cd, cd->mcodeptr,
4732 PATCHER_checkcast_class,
4733 (constant_classref *) iptr->target, 0);
4735 if (opt_showdisassemble) {
4736 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4740 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4741 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4742 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4744 i386_mov_membase32_reg(cd, REG_ITMP2,
4745 OFFSET(vftbl_t, baseval),
4748 /* if (s1 != REG_ITMP1) { */
4749 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
4750 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
4751 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
4752 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
4754 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
4757 i386_mov_membase32_reg(cd, REG_ITMP3,
4758 OFFSET(vftbl_t, baseval),
4760 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP3, REG_ITMP2);
4761 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4762 i386_mov_membase_reg(cd, REG_ITMP3,
4763 OFFSET(vftbl_t, diffval),
4765 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4766 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4770 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP2);
4771 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
4772 codegen_addxcastrefs(cd, cd->mcodeptr);
4774 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4777 /* array type cast-check */
4779 var_to_reg_int(s1, src, REG_ITMP1);
4780 M_AST(s1, REG_SP, 0 * 4);
4782 if (iptr->val.a == NULL) {
4783 codegen_addpatchref(cd, cd->mcodeptr,
4784 PATCHER_builtin_arraycheckcast,
4787 if (opt_showdisassemble) {
4788 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4792 M_AST_IMM((ptrint) iptr->val.a, REG_SP, 1 * 4);
4793 M_MOV_IMM((ptrint) BUILTIN_arraycheckcast, REG_ITMP3);
4797 codegen_addxcastrefs(cd, cd->mcodeptr);
4799 var_to_reg_int(s1, src, REG_ITMP1);
4800 d = reg_of_var(rd, iptr->dst, s1);
4803 store_reg_to_var_int(iptr->dst, d);
4806 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
4808 /* op1: 0 == array, 1 == class */
4809 /* val.a: (classinfo*) superclass */
4810 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4811 /* EAX: S|D|YES ECX: YES S|D|EDX: S|D|YES OUTPUT: REG_NULL*/
4812 /* ????? Really necessary to block all ????? */
4814 /* superclass is an interface:
4816 * return (sub != NULL) &&
4817 * (sub->vftbl->interfacetablelength > super->index) &&
4818 * (sub->vftbl->interfacetable[-super->index] != NULL);
4820 * superclass is a class:
4822 * return ((sub != NULL) && (0
4823 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4824 * super->vftbl->diffvall));
4829 vftbl_t *supervftbl;
4832 super = (classinfo *) iptr->val.a;
4839 superindex = super->index;
4840 supervftbl = super->vftbl;
4843 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4844 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4847 var_to_reg_int(s1, src, REG_ITMP1);
4848 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
4850 M_INTMOVE(s1, REG_ITMP1);
4854 /* calculate interface instanceof code size */
4856 s2 = 2; /* mov_membase_reg */
4857 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4859 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
4860 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4861 2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4864 s2 += (opt_showdisassemble ? 5 : 0);
4866 /* calculate class instanceof code size */
4868 s3 = 2; /* mov_membase_reg */
4869 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4870 s3 += 5; /* mov_imm_reg */
4872 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
4874 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
4876 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
4878 s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
4879 2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4882 s3 += (opt_showdisassemble ? 5 : 0);
4884 i386_alu_reg_reg(cd, ALU_XOR, d, d);
4886 /* if class is not resolved, check which code to call */
4889 i386_test_reg_reg(cd, s1, s1);
4890 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4892 codegen_addpatchref(cd, cd->mcodeptr,
4893 PATCHER_checkcast_instanceof_flags,
4894 (constant_classref *) iptr->target, 0);
4896 if (opt_showdisassemble) {
4897 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4900 i386_mov_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
4901 i386_alu_imm32_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
4902 i386_jcc(cd, I386_CC_Z, s2 + 5);
4905 /* interface instanceof code */
4907 if (!super || (super->flags & ACC_INTERFACE)) {
4913 i386_mov_membase_reg(cd, s1,
4914 OFFSET(java_objectheader, vftbl),
4918 codegen_addpatchref(cd, cd->mcodeptr,
4919 PATCHER_checkcast_instanceof_interface,
4920 (constant_classref *) iptr->target, 0);
4922 if (opt_showdisassemble) {
4923 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4927 i386_mov_membase32_reg(cd, REG_ITMP1,
4928 OFFSET(vftbl_t, interfacetablelength),
4930 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4931 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4933 disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
4934 6 /* jcc */ + 5 /* mov_imm_reg */);
4937 i386_mov_membase32_reg(cd, REG_ITMP1,
4938 OFFSET(vftbl_t, interfacetable[0]) -
4939 superindex * sizeof(methodptr*),
4942 /* i386_setcc_reg(cd, I386_CC_A, d); */
4943 /* i386_jcc(cd, I386_CC_BE, 5); */
4951 /* class instanceof code */
4953 if (!super || !(super->flags & ACC_INTERFACE)) {
4959 i386_mov_membase_reg(cd, s1,
4960 OFFSET(java_objectheader, vftbl),
4964 codegen_addpatchref(cd, cd->mcodeptr,
4965 PATCHER_instanceof_class,
4966 (constant_classref *) iptr->target, 0);
4968 if (opt_showdisassemble) {
4969 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4973 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
4974 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4975 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4977 i386_mov_membase_reg(cd, REG_ITMP1,
4978 OFFSET(vftbl_t, baseval),
4980 i386_mov_membase_reg(cd, REG_ITMP2,
4981 OFFSET(vftbl_t, diffval),
4983 i386_mov_membase_reg(cd, REG_ITMP2,
4984 OFFSET(vftbl_t, baseval),
4986 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4987 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4989 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
4990 i386_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
4991 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
4992 i386_jcc(cd, I386_CC_A, 5);
4993 i386_mov_imm_reg(cd, 1, d);
4995 store_reg_to_var_int(iptr->dst, d);
5001 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
5002 /* op1 = dimension, val.a = class */
5003 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
5004 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
5006 /* check for negative sizes and copy sizes to stack if necessary */
5008 MCODECHECK((iptr->op1 << 1) + 64);
5010 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
5011 /* copy SAVEDVAR sizes to stack */
5013 if (src->varkind != ARGVAR) {
5014 if (src->flags & INMEMORY) {
5015 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
5016 M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4);
5019 M_IST(src->regoff, REG_SP, (s1 + 3) * 4);
5024 /* is a patcher function set? */
5026 if (iptr->val.a == NULL) {
5027 codegen_addpatchref(cd, cd->mcodeptr,
5028 PATCHER_builtin_multianewarray,
5029 (constant_classref *) iptr->target, 0);
5031 if (opt_showdisassemble) {
5032 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5038 disp = (ptrint) iptr->val.a;
5041 /* a0 = dimension count */
5043 M_IST_IMM(iptr->op1, REG_SP, 0 * 4);
5045 /* a1 = arraydescriptor */
5047 M_IST_IMM(disp, REG_SP, 1 * 4);
5049 /* a2 = pointer to dimensions = stack pointer */
5051 M_MOV(REG_SP, REG_ITMP1);
5052 M_AADD_IMM(3 * 4, REG_ITMP1);
5053 M_AST(REG_ITMP1, REG_SP, 2 * 4);
5055 M_MOV_IMM((ptrint) BUILTIN_multianewarray, REG_ITMP1);
5058 /* check for exception before result assignment */
5062 codegen_addxexceptionrefs(cd, cd->mcodeptr);
5064 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
5065 M_INTMOVE(REG_RESULT, s1);
5066 store_reg_to_var_int(iptr->dst, s1);
5071 new_internalerror("Unknown ICMD %d", iptr->opc);
5075 } /* for instruction */
5077 /* copy values to interface registers */
5079 src = bptr->outstack;
5080 len = bptr->outdepth;
5082 #if defined(ENABLE_LSRA)
5087 if ((src->varkind != STACKVAR)) {
5089 if (IS_FLT_DBL_TYPE(s2)) {
5090 var_to_reg_flt(s1, src, REG_FTMP1);
5091 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5092 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
5095 log_text("double store");
5097 /* M_DST(s1, REG_SP, 4 * interfaces[len][s2].regoff); */
5101 var_to_reg_int(s1, src, REG_ITMP1);
5102 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
5103 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5104 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
5107 i386_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5111 if (rd->interfaces[len][s2].flags & INMEMORY) {
5112 M_LNGMEMMOVE(s1, rd->interfaces[len][s2].regoff);
5115 log_text("copy interface registers: longs have to be in memory (end)");
5124 /* At the end of a basic block we may have to append some nops,
5125 because the patcher stub calling code might be longer than the
5126 actual instruction. So codepatching does not change the
5127 following block unintentionally. */
5129 if (cd->mcodeptr < cd->lastmcodeptr) {
5130 while (cd->mcodeptr < cd->lastmcodeptr) {
5135 } /* if (bptr -> flags >= BBREACHED) */
5136 } /* for basic block */
5138 dseg_createlinenumbertable(cd);
5145 /* generate ArithmeticException stubs */
5149 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
5150 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5152 cd->mcodeptr - cd->mcodebase);
5156 M_MOV_IMM(0, REG_ITMP2_XPC);
5157 dseg_adddata(cd, cd->mcodeptr);
5158 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5160 if (xcodeptr != NULL) {
5161 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5164 xcodeptr = cd->mcodeptr;
5166 M_ASUB_IMM(4 * 4, REG_SP);
5168 M_AST_IMM(0, REG_SP, 0 * 4);
5169 dseg_adddata(cd, cd->mcodeptr);
5170 M_MOV(REG_SP, REG_ITMP3);
5171 M_AADD_IMM(4 * 4, REG_ITMP3);
5172 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5173 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5174 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5175 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5177 M_MOV_IMM((ptrint) stacktrace_inline_arithmeticexception,
5181 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5182 M_AADD_IMM(4 * 4, REG_SP);
5184 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5189 /* generate ArrayIndexOutOfBoundsException stubs */
5193 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
5194 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5196 cd->mcodeptr - cd->mcodebase);
5200 /* move index register into REG_ITMP1 */
5202 M_INTMOVE(bref->reg, REG_ITMP1);
5204 M_MOV_IMM(0, REG_ITMP2_XPC);
5205 dseg_adddata(cd, cd->mcodeptr);
5206 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5208 if (xcodeptr != NULL) {
5209 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5212 xcodeptr = cd->mcodeptr;
5214 M_ASUB_IMM(5 * 4, REG_SP);
5216 M_AST_IMM(0, REG_SP, 0 * 4);
5217 dseg_adddata(cd, cd->mcodeptr);
5218 M_MOV(REG_SP, REG_ITMP3);
5219 M_AADD_IMM(5 * 4, REG_ITMP3);
5220 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5221 M_ALD(REG_ITMP3, REG_SP, (5 + parentargs_base) * 4);
5222 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5223 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5224 M_AST(REG_ITMP1, REG_SP, 4 * 4); /* don't use REG_ITMP1 till here */
5226 M_MOV_IMM((ptrint) stacktrace_inline_arrayindexoutofboundsexception,
5230 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5231 M_AADD_IMM(5 * 4, REG_SP);
5233 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5238 /* generate ArrayStoreException stubs */
5242 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
5243 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5245 cd->mcodeptr - cd->mcodebase);
5249 M_MOV_IMM(0, REG_ITMP2_XPC);
5250 dseg_adddata(cd, cd->mcodeptr);
5251 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5253 if (xcodeptr != NULL) {
5254 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5257 xcodeptr = cd->mcodeptr;
5259 M_ASUB_IMM(4 * 4, REG_SP);
5261 M_AST_IMM(0, REG_SP, 0 * 4);
5262 dseg_adddata(cd, cd->mcodeptr);
5263 M_MOV(REG_SP, REG_ITMP3);
5264 M_AADD_IMM(4 * 4, REG_ITMP3);
5265 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5266 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5267 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5268 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5270 M_MOV_IMM((ptrint) stacktrace_inline_arraystoreexception,
5274 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5275 M_AADD_IMM(4 * 4, REG_SP);
5277 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5282 /* generate ClassCastException stubs */
5286 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
5287 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5289 cd->mcodeptr - cd->mcodebase);
5293 M_MOV_IMM(0, REG_ITMP2_XPC);
5294 dseg_adddata(cd, cd->mcodeptr);
5295 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5297 if (xcodeptr != NULL) {
5298 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5301 xcodeptr = cd->mcodeptr;
5303 M_ASUB_IMM(4 * 4, REG_SP);
5305 M_AST_IMM(0, REG_SP, 0 * 4);
5306 dseg_adddata(cd, cd->mcodeptr);
5307 M_MOV(REG_SP, REG_ITMP3);
5308 M_AADD_IMM(4 * 4, REG_ITMP3);
5309 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5310 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5311 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5312 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5314 M_MOV_IMM((ptrint) stacktrace_inline_classcastexception, REG_ITMP3);
5317 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5318 M_AADD_IMM(4 * 4, REG_SP);
5320 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5325 /* generate NullPointerException stubs */
5329 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
5330 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5332 cd->mcodeptr - cd->mcodebase);
5336 M_MOV_IMM(0, REG_ITMP2_XPC);
5337 dseg_adddata(cd, cd->mcodeptr);
5338 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5340 if (xcodeptr != NULL) {
5341 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5344 xcodeptr = cd->mcodeptr;
5346 M_ASUB_IMM(4 * 4, REG_SP);
5348 M_AST_IMM(0, REG_SP, 0 * 4);
5349 dseg_adddata(cd, cd->mcodeptr);
5350 M_MOV(REG_SP, REG_ITMP3);
5351 M_AADD_IMM(4 * 4, REG_ITMP3);
5352 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5353 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5354 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5355 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5357 M_MOV_IMM((ptrint) stacktrace_inline_nullpointerexception,
5361 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5362 M_AADD_IMM(4 * 4, REG_SP);
5364 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5369 /* generate exception check stubs */
5373 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
5374 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5376 cd->mcodeptr - cd->mcodebase);
5380 M_MOV_IMM(0, REG_ITMP2_XPC);
5381 dseg_adddata(cd, cd->mcodeptr);
5382 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5384 if (xcodeptr != NULL) {
5385 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5388 xcodeptr = cd->mcodeptr;
5390 M_ASUB_IMM(4 * 4, REG_SP);
5392 M_AST_IMM(0, REG_SP, 0 * 4);
5393 dseg_adddata(cd, cd->mcodeptr);
5394 M_MOV(REG_SP, REG_ITMP3);
5395 M_AADD_IMM(4 * 4, REG_ITMP3);
5396 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5397 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5398 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5399 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5401 M_MOV_IMM((ptrint) stacktrace_inline_fillInStackTrace, REG_ITMP3);
5404 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5405 M_AADD_IMM(4 * 4, REG_SP);
5407 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5412 /* generate code patching stub call code */
5419 tmpcd = DNEW(codegendata);
5421 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5422 /* check code segment size */
5426 /* Get machine code which is patched back in later. A */
5427 /* `call rel32' is 5 bytes long. */
5429 xcodeptr = cd->mcodebase + pref->branchpos;
5430 mcode = *((u8 *) xcodeptr);
5432 /* patch in `call rel32' to call the following code */
5434 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5435 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5437 /* move pointer to java_objectheader onto stack */
5439 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5440 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
5441 off = dseg_addaddress(cd, NULL); /* vftbl */
5443 M_MOV_IMM(0, REG_ITMP3);
5444 dseg_adddata(cd, cd->mcodeptr);
5445 M_AADD_IMM(off, REG_ITMP3);
5451 /* move machine code bytes and classinfo pointer into registers */
5453 M_PUSH_IMM((ptrint) (mcode >> 32));
5454 M_PUSH_IMM((ptrint) mcode);
5455 M_PUSH_IMM((ptrint) pref->ref);
5456 M_PUSH_IMM((ptrint) pref->patcher);
5458 M_MOV_IMM((ptrint) asm_wrapper_patcher, REG_ITMP3);
5464 codegen_finish(m, cd, (ptrint) (cd->mcodeptr - cd->mcodebase));
5466 /* everything's ok */
5472 /* createcompilerstub **********************************************************
5474 Creates a stub routine which calls the compiler.
5476 *******************************************************************************/
5478 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
5479 #define COMPILERSTUB_CODESIZE 12
5481 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
5484 u1 *createcompilerstub(methodinfo *m)
5486 u1 *s; /* memory to hold the stub */
5491 s = CNEW(u1, COMPILERSTUB_SIZE);
5493 /* set data pointer and code pointer */
5496 s = s + COMPILERSTUB_DATASIZE;
5498 /* mark start of dump memory area */
5500 dumpsize = dump_size();
5502 cd = DNEW(codegendata);
5505 /* Store the methodinfo* in the same place as in the methodheader
5506 for compiled methods. */
5508 d[0] = (ptrint) asm_call_jit_compiler;
5511 M_MOV_IMM((ptrint) m, REG_ITMP1);
5513 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
5514 M_MOV_IMM((ptrint) asm_call_jit_compiler, REG_ITMP3);
5517 #if defined(ENABLE_STATISTICS)
5519 count_cstub_len += COMPILERSTUB_SIZE;
5522 /* release dump area */
5524 dump_release(dumpsize);
5530 /* createnativestub ************************************************************
5532 Creates a stub routine which calls a native method.
5534 *******************************************************************************/
5536 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5537 /* this way we can call the function directly with a memory call */
5539 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
5542 u1 *createnativestub(functionptr f, methodinfo *m, codegendata *cd,
5543 registerdata *rd, methoddesc *nmd)
5548 s4 i, j; /* count variables */
5552 /* set some variables */
5555 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
5557 /* calculate stackframe size */
5560 sizeof(stackframeinfo) / SIZEOF_VOID_P +
5561 sizeof(localref_table) / SIZEOF_VOID_P +
5562 1 + /* function pointer */
5563 4 * 4 + /* 4 arguments (start_native_call) */
5566 /* create method header */
5568 (void) dseg_addaddress(cd, m); /* MethodPointer */
5569 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
5570 (void) dseg_adds4(cd, 0); /* IsSync */
5571 (void) dseg_adds4(cd, 0); /* IsLeaf */
5572 (void) dseg_adds4(cd, 0); /* IntSave */
5573 (void) dseg_adds4(cd, 0); /* FltSave */
5574 (void) dseg_addlinenumbertablesize(cd);
5575 (void) dseg_adds4(cd, 0); /* ExTableSize */
5577 /* initialize mcode variables */
5579 cd->mcodeptr = (u1 *) cd->mcodebase;
5580 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
5582 /* generate native method profiling code */
5585 /* count frequency */
5587 M_MOV_IMM((ptrint) m, REG_ITMP1);
5588 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(methodinfo, frequency));
5591 /* calculate stackframe size for native function */
5593 M_ASUB_IMM(stackframesize * 4, REG_SP);
5598 disp = stackframesize * 4;
5600 M_ASUB_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5602 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
5603 t = md->paramtypes[p].type;
5604 if (IS_INT_LNG_TYPE(t)) {
5605 if (IS_2_WORD_TYPE(t)) {
5606 M_ILD(REG_ITMP1, REG_SP,
5607 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5608 M_ILD(REG_ITMP2, REG_SP,
5609 4 + TRACE_ARGS_NUM * 8 + 4 + disp + 4);
5610 M_IST(REG_ITMP1, REG_SP, p * 8);
5611 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5613 } else if (t == TYPE_ADR) {
5614 M_ALD(REG_ITMP1, REG_SP,
5615 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5617 M_AST(REG_ITMP1, REG_SP, p * 8);
5618 M_AST(REG_ITMP2, REG_SP, p * 8 + 4);
5621 M_ILD(EAX, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5623 M_IST(EAX, REG_SP, p * 8);
5624 M_IST(EDX, REG_SP, p * 8 + 4);
5628 if (!IS_2_WORD_TYPE(t)) {
5629 i386_flds_membase(cd, REG_SP,
5630 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5631 i386_fstps_membase(cd, REG_SP, p * 8);
5632 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
5633 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5636 i386_fldl_membase(cd, REG_SP,
5637 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5638 i386_fstpl_membase(cd, REG_SP, p * 8);
5641 disp += (IS_2_WORD_TYPE(t)) ? 8 : 4;
5645 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
5646 M_IST(REG_ITMP1, REG_SP, p * 8);
5647 M_IST(REG_ITMP1, REG_SP, p * 8 + 4);
5650 M_AST_IMM((ptrint) m, REG_SP, TRACE_ARGS_NUM * 8);
5652 M_MOV_IMM((ptrint) builtin_trace_args, REG_ITMP1);
5655 M_AADD_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5658 /* get function address (this must happen before the stackframeinfo) */
5660 #if !defined(ENABLE_STATICVM)
5662 codegen_addpatchref(cd, cd->mcodeptr, PATCHER_resolve_native, m, 0);
5664 if (opt_showdisassemble) {
5665 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5670 M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
5672 /* Mark the whole fpu stack as free for native functions (only for saved */
5673 /* register count == 0). */
5675 i386_ffree_reg(cd, 0);
5676 i386_ffree_reg(cd, 1);
5677 i386_ffree_reg(cd, 2);
5678 i386_ffree_reg(cd, 3);
5679 i386_ffree_reg(cd, 4);
5680 i386_ffree_reg(cd, 5);
5681 i386_ffree_reg(cd, 6);
5682 i386_ffree_reg(cd, 7);
5684 /* prepare data structures for native function call */
5686 M_MOV(REG_SP, REG_ITMP1);
5687 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5689 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5690 M_IST_IMM(0, REG_SP, 1 * 4);
5691 dseg_adddata(cd, cd->mcodeptr);
5693 M_MOV(REG_SP, REG_ITMP2);
5694 M_AADD_IMM(stackframesize * 4 + SIZEOF_VOID_P, REG_ITMP2);
5696 M_AST(REG_ITMP2, REG_SP, 2 * 4);
5697 M_ALD(REG_ITMP3, REG_SP, stackframesize * 4);
5698 M_AST(REG_ITMP3, REG_SP, 3 * 4);
5699 M_MOV_IMM((ptrint) codegen_start_native_call, REG_ITMP1);
5702 M_ALD(REG_ITMP3, REG_SP, 4 * 4);
5704 /* copy arguments into new stackframe */
5706 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
5707 t = md->paramtypes[i].type;
5709 if (!md->params[i].inmemory) {
5710 /* no integer argument registers */
5711 } else { /* float/double in memory can be copied like int/longs */
5712 s1 = (md->params[i].regoff + stackframesize + 1) * 4;
5713 s2 = nmd->params[j].regoff * 4;
5715 M_ILD(REG_ITMP1, REG_SP, s1);
5716 M_IST(REG_ITMP1, REG_SP, s2);
5717 if (IS_2_WORD_TYPE(t)) {
5718 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
5719 M_IST(REG_ITMP1, REG_SP, s2 + 4);
5724 /* if function is static, put class into second argument */
5726 if (m->flags & ACC_STATIC)
5727 M_AST_IMM((ptrint) m->class, REG_SP, 1 * 4);
5729 /* put env into first argument */
5731 M_AST_IMM((ptrint) &env, REG_SP, 0 * 4);
5733 /* call the native function */
5737 /* save return value */
5739 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5740 if (IS_2_WORD_TYPE(md->returntype.type))
5741 M_IST(REG_RESULT2, REG_SP, 2 * 4);
5742 M_IST(REG_RESULT, REG_SP, 1 * 4);
5745 if (IS_2_WORD_TYPE(md->returntype.type))
5746 i386_fstl_membase(cd, REG_SP, 1 * 4);
5748 i386_fsts_membase(cd, REG_SP, 1 * 4);
5751 /* remove data structures for native function call */
5753 M_MOV(REG_SP, REG_ITMP1);
5754 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5756 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5757 M_MOV_IMM((ptrint) codegen_finish_native_call, REG_ITMP1);
5761 /* restore return value */
5763 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5764 if (IS_2_WORD_TYPE(md->returntype.type))
5765 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5766 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5769 if (IS_2_WORD_TYPE(md->returntype.type))
5770 i386_fldl_membase(cd, REG_SP, 1 * 4);
5772 i386_flds_membase(cd, REG_SP, 1 * 4);
5775 M_ASUB_IMM(4 + 8 + 8 + 4, REG_SP);
5777 M_AST_IMM((ptrint) m, REG_SP, 0);
5779 M_IST(REG_RESULT, REG_SP, 4);
5780 M_IST(REG_RESULT2, REG_SP, 4 + 4);
5782 i386_fstl_membase(cd, REG_SP, 4 + 8);
5783 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5785 M_MOV_IMM((ptrint) builtin_displaymethodstop, REG_ITMP1);
5788 M_AADD_IMM(4 + 8 + 8 + 4, REG_SP);
5791 /* check for exception */
5793 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5794 /* i386_call_mem(cd, (ptrint) builtin_get_exceptionptrptr); */
5795 i386_call_mem(cd, (ptrint) &callgetexceptionptrptr);
5797 M_MOV_IMM((ptrint) &_exceptionptr, REG_RESULT);
5799 /* we can't use REG_ITMP3 == REG_RESULT2 */
5800 M_ALD(REG_ITMP2, REG_RESULT, 0);
5802 /* restore return value */
5804 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5805 if (IS_2_WORD_TYPE(md->returntype.type))
5806 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5807 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5810 if (IS_2_WORD_TYPE(md->returntype.type))
5811 i386_fldl_membase(cd, REG_SP, 1 * 4);
5813 i386_flds_membase(cd, REG_SP, 1 * 4);
5816 M_AADD_IMM(stackframesize * 4, REG_SP);
5823 /* handle exception */
5825 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5826 i386_push_reg(cd, REG_ITMP2);
5827 /* i386_call_mem(cd, (ptrint) builtin_get_exceptionptrptr); */
5828 i386_call_mem(cd, (ptrint) &callgetexceptionptrptr);
5829 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5830 i386_pop_reg(cd, REG_ITMP1_XPTR);
5832 M_MOV(REG_ITMP2, REG_ITMP1_XPTR);
5833 M_MOV_IMM((ptrint) &_exceptionptr, REG_ITMP2);
5834 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5836 M_ALD(REG_ITMP2_XPC, REG_SP, 0);
5837 M_ASUB_IMM(2, REG_ITMP2_XPC);
5839 M_MOV_IMM((ptrint) asm_handle_nat_exception, REG_ITMP3);
5843 /* process patcher calls **************************************************/
5851 tmpcd = DNEW(codegendata);
5853 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5854 /* Get machine code which is patched back in later. A */
5855 /* `call rel32' is 5 bytes long. */
5857 xcodeptr = cd->mcodebase + pref->branchpos;
5858 mcode = *((u8 *) xcodeptr);
5860 /* patch in `call rel32' to call the following code */
5862 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5863 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5865 /* move pointer to java_objectheader onto stack */
5867 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5868 /* create a virtual java_objectheader */
5870 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
5871 disp = dseg_addaddress(cd, NULL); /* vftbl */
5873 M_MOV_IMM(0, REG_ITMP3);
5874 dseg_adddata(cd, cd->mcodeptr);
5875 M_AADD_IMM(disp, REG_ITMP3);
5881 /* move machine code bytes and classinfo pointer onto stack */
5883 M_PUSH_IMM((ptrint) (mcode >> 32));
5884 M_PUSH_IMM((ptrint) mcode);
5885 M_PUSH_IMM((ptrint) pref->ref);
5886 M_PUSH_IMM((ptrint) pref->patcher);
5888 M_MOV_IMM((ptrint) asm_wrapper_patcher, REG_ITMP3);
5893 codegen_finish(m, cd, (s4) ((u1 *) cd->mcodeptr - cd->mcodebase));
5895 return m->entrypoint;
5900 * These are local overrides for various environment variables in Emacs.
5901 * Please do not remove this and leave it at the end of the file, where
5902 * Emacs will automagically detect them.
5903 * ---------------------------------------------------------------------
5906 * indent-tabs-mode: t