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 4393 2006-01-31 15:41:22Z 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 profiling code */
184 M_MOV_IMM((ptrint) m, REG_ITMP1);
185 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(methodinfo, executioncount));
188 /* create stack frame (if necessary) */
191 M_ASUB_IMM(parentargs_base * 4, REG_SP);
193 /* save return address and used callee saved registers */
196 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
197 p--; M_AST(rd->savintregs[i], REG_SP, p * 4);
199 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
200 p-=2; i386_fld_reg(cd, rd->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 4);
203 /* take arguments out of register or stack frame */
208 for (p = 0, l = 0; p < md->paramcount; p++) {
209 t = md->paramtypes[p].type;
210 var = &(rd->locals[l][t]);
212 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
216 s1 = md->params[p].regoff;
217 if (IS_INT_LNG_TYPE(t)) { /* integer args */
218 if (!md->params[p].inmemory) { /* register arguments */
219 log_text("integer register argument");
221 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
222 /* rd->argintregs[md->params[p].regoff -> var->regoff */
223 } else { /* reg arg -> spilled */
224 /* rd->argintregs[md->params[p].regoff -> var->regoff * 4 */
226 } else { /* stack arguments */
227 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
228 i386_mov_membase_reg( /* + 4 for return address */
229 cd, REG_SP, (parentargs_base + s1) * 4 + 4, var->regoff);
230 /* + 4 for return address */
231 } else { /* stack arg -> spilled */
232 if (!IS_2_WORD_TYPE(t)) {
234 i386_mov_membase_reg( /* + 4 for return address */
235 cd, REG_SP, (parentargs_base + s1) * 4 + 4,
237 i386_mov_reg_membase(
238 cd, REG_ITMP1, REG_SP, var->regoff * 4);
240 /* reuse Stackslotand avoid copying */
241 var->regoff = parentargs_base + s1 + 1;
246 i386_mov_membase_reg( /* + 4 for return address */
247 cd, REG_SP, (parentargs_base + s1) * 4 + 4,
249 i386_mov_reg_membase(
250 cd, REG_ITMP1, REG_SP, var->regoff * 4);
251 i386_mov_membase_reg( /* + 4 for return address */
252 cd, REG_SP, (parentargs_base + s1) * 4 + 4 + 4,
254 i386_mov_reg_membase(
255 cd, REG_ITMP1, REG_SP, var->regoff * 4 + 4);
257 /* reuse Stackslotand avoid copying */
258 var->regoff = parentargs_base + s1 + 1;
264 } else { /* floating args */
265 if (!md->params[p].inmemory) { /* register arguments */
266 log_text("There are no float argument registers!");
268 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
269 /* rd->argfltregs[md->params[p].regoff -> var->regoff */
270 } else { /* reg arg -> spilled */
271 /* rd->argfltregs[md->params[p].regoff -> var->regoff * 4 */
274 } else { /* stack arguments */
275 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
278 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
280 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
285 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
287 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
291 } else { /* stack-arg -> spilled */
293 i386_mov_membase_reg(
294 cd, REG_SP, (parentargs_base + s1) * 4 + 4, REG_ITMP1);
295 i386_mov_reg_membase(
296 cd, REG_ITMP1, REG_SP, var->regoff * 4);
299 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
300 i386_fstps_membase(cd, REG_SP, var->regoff * 4);
303 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
304 i386_fstpl_membase(cd, REG_SP, var->regoff * 4);
307 /* reuse Stackslotand avoid copying */
308 var->regoff = parentargs_base + s1 + 1;
315 /* call monitorenter function */
317 #if defined(USE_THREADS)
318 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
321 if (m->flags & ACC_STATIC) {
322 i386_mov_imm_reg(cd, (ptrint) m->class, REG_ITMP1);
323 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s1 * 4);
324 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
325 i386_mov_imm_reg(cd, (ptrint) BUILTIN_staticmonitorenter, REG_ITMP1);
326 i386_call_reg(cd, REG_ITMP1);
329 i386_mov_membase_reg(cd, REG_SP, parentargs_base * 4 + 4, REG_ITMP1);
330 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
331 i386_jcc(cd, I386_CC_Z, 0);
332 codegen_addxnullrefs(cd, cd->mcodeptr);
333 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s1 * 4);
334 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
335 i386_mov_imm_reg(cd, (ptrint) BUILTIN_monitorenter, REG_ITMP1);
336 i386_call_reg(cd, REG_ITMP1);
341 /* copy argument registers to stack and call trace function with pointer
342 to arguments on stack.
347 s1 = INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4 + 4 + parentargs_base * 4;
349 M_ISUB_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
351 /* save temporary registers for leaf methods */
353 for (p = 0; p < INT_TMP_CNT; p++)
354 M_IST(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
356 for (p = 0, l = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
357 t = md->paramtypes[p].type;
359 if (IS_INT_LNG_TYPE(t)) {
360 if (IS_2_WORD_TYPE(t)) {
361 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
362 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
363 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off + 4, REG_ITMP1);
364 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
366 } else if (t == TYPE_ADR) {
368 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
369 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
370 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
371 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
374 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, EAX);
376 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
377 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
381 if (!IS_2_WORD_TYPE(t)) {
382 i386_flds_membase(cd, REG_SP, s1 + stack_off);
383 i386_fstps_membase(cd, REG_SP, p * 8);
384 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
385 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
388 i386_fldl_membase(cd, REG_SP, s1 + stack_off);
389 i386_fstpl_membase(cd, REG_SP, p * 8);
392 stack_off += (IS_2_WORD_TYPE(t)) ? 8 : 4;
395 /* fill up the remaining arguments */
396 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
397 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
398 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
399 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
402 i386_mov_imm_membase(cd, (ptrint) m, REG_SP, TRACE_ARGS_NUM * 8);
403 i386_mov_imm_reg(cd, (ptrint) builtin_trace_args, REG_ITMP1);
404 i386_call_reg(cd, REG_ITMP1);
406 /* restore temporary registers for leaf methods */
408 for (p = 0; p < INT_TMP_CNT; p++)
409 M_ILD(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
411 M_IADD_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
416 /* end of header generation */
418 /* walk through all basic blocks */
419 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
421 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
423 if (bptr->flags >= BBREACHED) {
425 /* branch resolving */
428 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
429 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
434 /* copy interface registers to their destination */
440 #if defined(ENABLE_LSRA)
442 while (src != NULL) {
444 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
445 if (!IS_2_WORD_TYPE(src->type)) {
446 if (bptr->type == BBTYPE_SBR) {
447 /* d = reg_of_var(m, src, REG_ITMP1); */
448 if (!(src->flags & INMEMORY))
454 store_reg_to_var_int(src, d);
456 } else if (bptr->type == BBTYPE_EXH) {
457 /* d = reg_of_var(m, src, REG_ITMP1); */
458 if (!(src->flags & INMEMORY))
462 M_INTMOVE(REG_ITMP1, d);
463 store_reg_to_var_int(src, d);
467 log_text("copy interface registers(EXH, SBR): longs have to be in memory (begin 1)");
476 while (src != NULL) {
478 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
479 if (!IS_2_WORD_TYPE(src->type)) {
480 if (bptr->type == BBTYPE_SBR) {
481 d = reg_of_var(rd, src, REG_ITMP1);
483 store_reg_to_var_int(src, d);
484 } else if (bptr->type == BBTYPE_EXH) {
485 d = reg_of_var(rd, src, REG_ITMP1);
486 M_INTMOVE(REG_ITMP1, d);
487 store_reg_to_var_int(src, d);
491 log_text("copy interface registers: longs have to be in memory (begin 1)");
496 d = reg_of_var(rd, src, REG_ITMP1);
497 if ((src->varkind != STACKVAR)) {
499 if (IS_FLT_DBL_TYPE(s2)) {
500 s1 = rd->interfaces[len][s2].regoff;
501 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
505 if (s2 == TYPE_FLT) {
506 i386_flds_membase(cd, REG_SP, s1 * 4);
509 i386_fldl_membase(cd, REG_SP, s1 * 4);
512 store_reg_to_var_flt(src, d);
515 s1 = rd->interfaces[len][s2].regoff;
516 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
517 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
521 i386_mov_membase_reg(cd, REG_SP, s1 * 4, d);
523 store_reg_to_var_int(src, d);
526 if (rd->interfaces[len][s2].flags & INMEMORY) {
527 M_LNGMEMMOVE(s1, src->regoff);
530 log_text("copy interface registers: longs have to be in memory (begin 2)");
539 #if defined(ENABLE_LSRA)
543 /* walk through all instructions */
548 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
549 if (iptr->line != currentline) {
550 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
551 currentline = iptr->line;
554 MCODECHECK(100); /* XXX are 100 bytes enough? */
557 case ICMD_INLINE_START:
558 case ICMD_INLINE_END:
559 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
560 /* EAX: NO ECX: NO EDX: NO */
563 case ICMD_NOP: /* ... ==> ... */
564 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
565 /* EAX: NO ECX: NO EDX: NO */
568 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
569 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
570 /* EAX: NO ECX: NO EDX: NO */
571 if (src->flags & INMEMORY) {
572 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
575 i386_test_reg_reg(cd, src->regoff, src->regoff);
577 i386_jcc(cd, I386_CC_Z, 0);
578 codegen_addxnullrefs(cd, cd->mcodeptr);
581 /* constant operations ************************************************/
583 case ICMD_ICONST: /* ... ==> ..., constant */
584 /* op1 = 0, val.i = constant */
586 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
587 /* EAX: NO ECX: NO EDX: NO */
589 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
590 if (iptr->dst->flags & INMEMORY) {
591 M_IST_IMM(iptr->val.i, REG_SP, iptr->dst->regoff * 4);
594 if (iptr->val.i == 0) {
598 M_MOV_IMM(iptr->val.i, d);
603 case ICMD_LCONST: /* ... ==> ..., constant */
604 /* op1 = 0, val.l = constant */
606 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
607 /* EAX: NO ECX: NO EDX: NO */
609 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
610 if (iptr->dst->flags & INMEMORY) {
611 M_IST_IMM(iptr->val.l, REG_SP, iptr->dst->regoff * 4);
612 M_IST_IMM(iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
615 log_text("LCONST: longs have to be in memory");
620 case ICMD_FCONST: /* ... ==> ..., constant */
621 /* op1 = 0, val.f = constant */
623 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
624 /* EAX: YES ECX: NO EDX: NO */
626 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
627 if (iptr->val.f == 0.0) {
632 if (iptr->val.i == 0x80000000) {
636 } else if (iptr->val.f == 1.0) {
640 } else if (iptr->val.f == 2.0) {
647 disp = dseg_addfloat(cd, iptr->val.f);
648 i386_mov_imm_reg(cd, 0, REG_ITMP1);
649 dseg_adddata(cd, cd->mcodeptr);
650 i386_flds_membase(cd, REG_ITMP1, disp);
653 store_reg_to_var_flt(iptr->dst, d);
656 case ICMD_DCONST: /* ... ==> ..., constant */
657 /* op1 = 0, val.d = constant */
659 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
660 /* EAX: YES ECX: NO EDX: NO */
662 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
663 if (iptr->val.d == 0.0) {
668 if (iptr->val.l == 0x8000000000000000LL) {
672 } else if (iptr->val.d == 1.0) {
676 } else if (iptr->val.d == 2.0) {
683 disp = dseg_adddouble(cd, iptr->val.d);
684 i386_mov_imm_reg(cd, 0, REG_ITMP1);
685 dseg_adddata(cd, cd->mcodeptr);
686 i386_fldl_membase(cd, REG_ITMP1, disp);
689 store_reg_to_var_flt(iptr->dst, d);
692 case ICMD_ACONST: /* ... ==> ..., constant */
693 /* op1 = 0, val.a = constant */
695 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
696 /* EAX: YES ECX: NO EDX: NO */
698 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
700 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
701 codegen_addpatchref(cd, cd->mcodeptr,
703 (unresolved_class *) iptr->target, 0);
705 if (opt_showdisassemble) {
706 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
709 M_MOV_IMM((ptrint) iptr->val.a, d);
710 store_reg_to_var_int(iptr->dst, d);
713 if (iptr->dst->flags & INMEMORY) {
714 M_AST_IMM((ptrint) iptr->val.a, REG_SP, iptr->dst->regoff * 4);
717 if ((ptrint) iptr->val.a == 0) {
720 M_MOV_IMM((ptrint) iptr->val.a, d);
727 /* load/store operations **********************************************/
729 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
730 case ICMD_ALOAD: /* op1 = local variable */
731 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
732 /* EAX: YES ECX: NO EDX: NO */
734 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
735 if ((iptr->dst->varkind == LOCALVAR) &&
736 (iptr->dst->varnum == iptr->op1)) {
739 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
740 if (iptr->dst->flags & INMEMORY) {
741 if (var->flags & INMEMORY) {
742 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP1);
743 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
746 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 4);
750 if (var->flags & INMEMORY) {
751 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, iptr->dst->regoff);
754 M_INTMOVE(var->regoff, iptr->dst->regoff);
759 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
760 /* op1 = local variable */
761 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
762 /* EAX: NO ECX: NO EDX: NO */
764 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
765 if ((iptr->dst->varkind == LOCALVAR) &&
766 (iptr->dst->varnum == iptr->op1)) {
769 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
770 if (iptr->dst->flags & INMEMORY) {
771 if (var->flags & INMEMORY) {
772 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
775 log_text("LLOAD: longs have to be in memory");
780 log_text("LLOAD: longs have to be in memory");
785 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
786 /* op1 = local variable */
787 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
788 /* EAX: NO ECX: NO EDX: NO */
790 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
791 if ((iptr->dst->varkind == LOCALVAR) &&
792 (iptr->dst->varnum == iptr->op1)) {
795 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
796 if (var->flags & INMEMORY) {
797 i386_flds_membase(cd, REG_SP, var->regoff * 4);
800 i386_fld_reg(cd, var->regoff + fpu_st_offset);
803 store_reg_to_var_flt(iptr->dst, d);
806 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
807 /* op1 = local variable */
808 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
809 /* EAX: NO ECX: NO EDX: NO */
811 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
812 if ((iptr->dst->varkind == LOCALVAR) &&
813 (iptr->dst->varnum == iptr->op1)) {
816 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
817 if (var->flags & INMEMORY) {
818 i386_fldl_membase(cd, REG_SP, var->regoff * 4);
821 i386_fld_reg(cd, var->regoff + fpu_st_offset);
824 store_reg_to_var_flt(iptr->dst, d);
827 case ICMD_ISTORE: /* ..., value ==> ... */
828 case ICMD_ASTORE: /* op1 = local variable */
829 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
830 /* EAX: YES ECX: NO EDX: NO */
832 if ((src->varkind == LOCALVAR) &&
833 (src->varnum == iptr->op1)) {
836 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
837 if (var->flags & INMEMORY) {
838 if (src->flags & INMEMORY) {
839 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
840 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 4);
843 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 4);
847 var_to_reg_int(s1, src, var->regoff);
848 M_INTMOVE(s1, var->regoff);
852 case ICMD_LSTORE: /* ..., value ==> ... */
853 /* op1 = local variable */
854 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
855 /* EAX: NO ECX: NO EDX: NO */
857 if ((src->varkind == LOCALVAR) &&
858 (src->varnum == iptr->op1)) {
861 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
862 if (var->flags & INMEMORY) {
863 if (src->flags & INMEMORY) {
864 M_LNGMEMMOVE(src->regoff, var->regoff);
867 log_text("LSTORE: longs have to be in memory");
872 log_text("LSTORE: longs have to be in memory");
877 case ICMD_FSTORE: /* ..., value ==> ... */
878 /* op1 = local variable */
879 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
880 /* EAX: NO ECX: NO EDX: NO */
882 if ((src->varkind == LOCALVAR) &&
883 (src->varnum == iptr->op1)) {
886 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
887 if (var->flags & INMEMORY) {
888 var_to_reg_flt(s1, src, REG_FTMP1);
889 i386_fstps_membase(cd, REG_SP, var->regoff * 4);
892 var_to_reg_flt(s1, src, var->regoff);
893 /* M_FLTMOVE(s1, var->regoff); */
894 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
899 case ICMD_DSTORE: /* ..., value ==> ... */
900 /* op1 = local variable */
901 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
902 /* EAX: NO ECX: NO EDX: NO */
904 if ((src->varkind == LOCALVAR) &&
905 (src->varnum == iptr->op1)) {
908 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
909 if (var->flags & INMEMORY) {
910 var_to_reg_flt(s1, src, REG_FTMP1);
911 i386_fstpl_membase(cd, REG_SP, var->regoff * 4);
914 var_to_reg_flt(s1, src, var->regoff);
915 /* M_FLTMOVE(s1, var->regoff); */
916 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
922 /* pop/dup/swap operations ********************************************/
924 /* attention: double and longs are only one entry in CACAO ICMDs */
926 case ICMD_POP: /* ..., value ==> ... */
927 case ICMD_POP2: /* ..., value, value ==> ... */
928 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
929 /* EAX: NO ECX: NO EDX: NO */
932 case ICMD_DUP: /* ..., a ==> ..., a, a */
933 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
934 /* EAX: YES ECX: NO EDX: NO */
935 M_COPY(src, iptr->dst);
938 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
939 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
940 /* EAX: YES ECX: NO EDX: NO */
942 M_COPY(src, iptr->dst);
943 M_COPY(src->prev, iptr->dst->prev);
946 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
947 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
948 /* EAX: YES ECX: NO EDX: NO */
950 M_COPY(src, iptr->dst);
951 M_COPY(src->prev, iptr->dst->prev);
952 M_COPY(iptr->dst, iptr->dst->prev->prev);
955 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
957 M_COPY(src, iptr->dst);
958 M_COPY(src->prev, iptr->dst->prev);
959 M_COPY(src->prev->prev, iptr->dst->prev->prev);
960 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
963 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
964 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
965 /* EAX: YES ECX: NO EDX: NO */
967 M_COPY(src, iptr->dst);
968 M_COPY(src->prev, iptr->dst->prev);
969 M_COPY(src->prev->prev, iptr->dst->prev->prev);
970 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
971 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
974 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
975 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
976 /* EAX: YES ECX: NO EDX: NO */
978 M_COPY(src, iptr->dst);
979 M_COPY(src->prev, iptr->dst->prev);
980 M_COPY(src->prev->prev, iptr->dst->prev->prev);
981 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
982 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
983 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
986 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
987 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
988 /* EAX: YES ECX: NO EDX: NO */
990 M_COPY(src, iptr->dst->prev);
991 M_COPY(src->prev, iptr->dst);
995 /* integer operations *************************************************/
997 case ICMD_INEG: /* ..., value ==> ..., - value */
998 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
999 /* EAX: YES ECX: NO EDX: NO */
1001 d = reg_of_var(rd, iptr->dst, REG_NULL);
1002 if (iptr->dst->flags & INMEMORY) {
1003 if (src->flags & INMEMORY) {
1004 if (src->regoff == iptr->dst->regoff) {
1005 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1008 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1009 i386_neg_reg(cd, REG_ITMP1);
1010 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1014 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1015 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1019 if (src->flags & INMEMORY) {
1020 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1021 i386_neg_reg(cd, iptr->dst->regoff);
1024 M_INTMOVE(src->regoff, iptr->dst->regoff);
1025 i386_neg_reg(cd, iptr->dst->regoff);
1030 case ICMD_LNEG: /* ..., value ==> ..., - value */
1031 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1032 /* EAX: YES ECX: NO EDX: NO */
1034 d = reg_of_var(rd, iptr->dst, REG_NULL);
1035 if (iptr->dst->flags & INMEMORY) {
1036 if (src->flags & INMEMORY) {
1037 if (src->regoff == iptr->dst->regoff) {
1038 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1039 i386_alu_imm_membase(cd, ALU_ADC, 0, REG_SP, iptr->dst->regoff * 4 + 4);
1040 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4 + 4);
1043 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1044 i386_neg_reg(cd, REG_ITMP1);
1045 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1046 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1047 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP1);
1048 i386_neg_reg(cd, REG_ITMP1);
1049 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1055 case ICMD_I2L: /* ..., value ==> ..., value */
1056 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1057 /* EAX: YES ECX: NO EDX: YES */
1059 d = reg_of_var(rd, iptr->dst, REG_NULL);
1060 if (iptr->dst->flags & INMEMORY) {
1061 if (src->flags & INMEMORY) {
1062 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, EAX);
1064 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1065 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1068 M_INTMOVE(src->regoff, EAX);
1070 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1071 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1076 case ICMD_L2I: /* ..., value ==> ..., value */
1077 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1078 /* EAX: YES ECX: NO EDX: NO */
1080 d = reg_of_var(rd, iptr->dst, REG_NULL);
1081 if (iptr->dst->flags & INMEMORY) {
1082 if (src->flags & INMEMORY) {
1083 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1084 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1088 if (src->flags & INMEMORY) {
1089 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1094 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1095 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1096 /* EAX: YES ECX: NO EDX: NO */
1098 d = reg_of_var(rd, iptr->dst, REG_NULL);
1099 if (iptr->dst->flags & INMEMORY) {
1100 if (src->flags & INMEMORY) {
1101 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1102 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1103 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1104 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1107 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1108 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 4);
1109 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 4);
1113 if (src->flags & INMEMORY) {
1114 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1115 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1116 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1119 M_INTMOVE(src->regoff, iptr->dst->regoff);
1120 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1121 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1126 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1127 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1128 /* EAX: YES ECX: NO EDX: NO */
1130 d = reg_of_var(rd, iptr->dst, REG_NULL);
1131 if (iptr->dst->flags & INMEMORY) {
1132 if (src->flags & INMEMORY) {
1133 if (src->regoff == iptr->dst->regoff) {
1134 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1137 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1138 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, REG_ITMP1);
1139 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1143 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1144 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1148 if (src->flags & INMEMORY) {
1149 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1150 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1153 M_INTMOVE(src->regoff, iptr->dst->regoff);
1154 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1159 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1160 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1161 /* EAX: YES ECX: NO EDX: NO */
1163 d = reg_of_var(rd, iptr->dst, REG_NULL);
1164 if (iptr->dst->flags & INMEMORY) {
1165 if (src->flags & INMEMORY) {
1166 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1167 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1168 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1169 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1172 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1173 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 4);
1174 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 4);
1178 if (src->flags & INMEMORY) {
1179 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1180 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1181 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1184 M_INTMOVE(src->regoff, iptr->dst->regoff);
1185 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1186 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1192 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1193 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1194 /* EAX: S|YES ECX: NO EDX: NO */
1196 d = reg_of_var(rd, iptr->dst, REG_NULL);
1197 i386_emit_ialu(cd, ALU_ADD, src, iptr);
1200 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1201 /* val.i = constant */
1202 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1203 /* EAX: NO ECX: NO EDX: NO */
1205 d = reg_of_var(rd, iptr->dst, REG_NULL);
1206 i386_emit_ialuconst(cd, ALU_ADD, src, iptr);
1209 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1210 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1211 /* EAX: S|YES ECX: NO EDX: NO */
1213 d = reg_of_var(rd, iptr->dst, REG_NULL);
1214 if (iptr->dst->flags & INMEMORY) {
1215 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1216 if (src->regoff == iptr->dst->regoff) {
1217 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1218 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1219 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1220 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1222 } else if (src->prev->regoff == iptr->dst->regoff) {
1223 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1224 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1225 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1226 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1229 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1230 i386_alu_membase_reg(cd, ALU_ADD, REG_SP, src->regoff * 4, REG_ITMP1);
1231 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1232 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1233 i386_alu_membase_reg(cd, ALU_ADC, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1234 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1241 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1242 /* val.l = constant */
1243 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1244 /* EAX: NO ECX: NO EDX: NO */
1245 /* else path can never happen? longs stay in memory! */
1247 d = reg_of_var(rd, iptr->dst, REG_NULL);
1248 if (iptr->dst->flags & INMEMORY) {
1249 if (src->flags & INMEMORY) {
1250 if (src->regoff == iptr->dst->regoff) {
1251 i386_alu_imm_membase(cd, ALU_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1252 i386_alu_imm_membase(cd, ALU_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1255 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1256 i386_alu_imm_reg(cd, ALU_ADD, iptr->val.l, REG_ITMP1);
1257 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1258 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1259 i386_alu_imm_reg(cd, ALU_ADC, iptr->val.l >> 32, REG_ITMP1);
1260 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1266 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1267 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1268 /* EAX: S|YES ECX: NO EDX: NO */
1270 d = reg_of_var(rd, iptr->dst, REG_NULL);
1271 if (iptr->dst->flags & INMEMORY) {
1272 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1273 if (src->prev->regoff == iptr->dst->regoff) {
1274 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1275 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1278 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1279 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1280 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1283 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1284 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1285 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1286 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1288 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1289 if (src->prev->regoff == iptr->dst->regoff) {
1290 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1293 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1294 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1295 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1299 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 4);
1300 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1304 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1305 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1306 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1308 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1309 M_INTMOVE(src->prev->regoff, d);
1310 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1312 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1313 /* workaround for reg alloc */
1314 if (src->regoff == iptr->dst->regoff) {
1315 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1316 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1317 M_INTMOVE(REG_ITMP1, d);
1320 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1321 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1325 /* workaround for reg alloc */
1326 if (src->regoff == iptr->dst->regoff) {
1327 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1328 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1329 M_INTMOVE(REG_ITMP1, d);
1332 M_INTMOVE(src->prev->regoff, d);
1333 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1339 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1340 /* val.i = constant */
1341 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1342 /* EAX: NO ECX: NO EDX: NO */
1344 d = reg_of_var(rd, iptr->dst, REG_NULL);
1345 i386_emit_ialuconst(cd, ALU_SUB, src, iptr);
1348 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1349 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1350 /* EAX: S|YES ECX: NO EDX: NO */
1352 d = reg_of_var(rd, iptr->dst, REG_NULL);
1353 if (iptr->dst->flags & INMEMORY) {
1354 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1355 if (src->prev->regoff == iptr->dst->regoff) {
1356 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1357 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1358 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1359 i386_alu_reg_membase(cd, ALU_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1362 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1363 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1364 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1365 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1366 i386_alu_membase_reg(cd, ALU_SBB, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1367 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1373 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1374 /* val.l = constant */
1375 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1376 /* EAX: NO ECX: NO EDX: NO */
1377 /* else path can never happen? longs stay in memory! */
1379 d = reg_of_var(rd, iptr->dst, REG_NULL);
1380 if (iptr->dst->flags & INMEMORY) {
1381 if (src->flags & INMEMORY) {
1382 if (src->regoff == iptr->dst->regoff) {
1383 i386_alu_imm_membase(cd, ALU_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1384 i386_alu_imm_membase(cd, ALU_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1387 /* TODO: could be size optimized with lea -- see gcc output */
1388 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1389 i386_alu_imm_reg(cd, ALU_SUB, iptr->val.l, REG_ITMP1);
1390 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1391 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1392 i386_alu_imm_reg(cd, ALU_SBB, iptr->val.l >> 32, REG_ITMP1);
1393 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1399 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1400 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1401 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1403 d = reg_of_var(rd, iptr->dst, REG_NULL);
1404 if (iptr->dst->flags & INMEMORY) {
1405 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1406 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1407 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1408 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1410 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1411 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1412 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1413 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1415 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1416 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1417 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1418 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1421 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1422 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1423 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1427 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1428 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1429 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1431 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1432 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1433 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1435 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1436 M_INTMOVE(src->regoff, iptr->dst->regoff);
1437 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1440 if (src->regoff == iptr->dst->regoff) {
1441 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1444 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1445 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1451 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1452 /* val.i = constant */
1453 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1454 /* EAX: YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1456 d = reg_of_var(rd, iptr->dst, REG_NULL);
1457 if (iptr->dst->flags & INMEMORY) {
1458 if (src->flags & INMEMORY) {
1459 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, REG_ITMP1);
1460 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1463 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1464 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1468 if (src->flags & INMEMORY) {
1469 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, iptr->dst->regoff);
1472 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1477 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1478 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1479 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1481 d = reg_of_var(rd, iptr->dst, REG_NULL);
1482 if (iptr->dst->flags & INMEMORY) {
1483 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1484 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX); /* mem -> EAX */
1485 /* optimize move EAX -> REG_ITMP3 is slower??? */
1486 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1487 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1489 /* TODO: optimize move EAX -> REG_ITMP3 */
1490 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); /* mem -> ITMP3 */
1491 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1492 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1494 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP2); /* mem -> ITMP3 */
1495 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1497 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1498 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1499 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1504 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1505 /* val.l = constant */
1506 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1507 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1509 d = reg_of_var(rd, iptr->dst, REG_NULL);
1510 if (iptr->dst->flags & INMEMORY) {
1511 if (src->flags & INMEMORY) {
1512 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1513 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1514 /* TODO: optimize move EAX -> REG_ITMP3 */
1515 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1516 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1518 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1519 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1520 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1522 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1523 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1524 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1529 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1530 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1531 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX */
1533 d = reg_of_var(rd, iptr->dst, REG_NULL);
1534 var_to_reg_int(s1, src, REG_ITMP2);
1536 if (src->prev->flags & INMEMORY) {
1537 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1540 M_INTMOVE(src->prev->regoff, EAX);
1543 /* check as described in jvm spec */
1545 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1546 i386_jcc(cd, I386_CC_NE, 3 + 6);
1547 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1548 i386_jcc(cd, I386_CC_E, 1 + 2);
1551 i386_idiv_reg(cd, s1);
1553 if (iptr->dst->flags & INMEMORY) {
1554 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1557 M_INTMOVE(EAX, iptr->dst->regoff);
1561 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1562 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1563 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EDX */
1566 d = reg_of_var(rd, iptr->dst, REG_NULL);
1567 var_to_reg_int(s1, src, REG_ITMP2);
1569 if (src->prev->flags & INMEMORY) {
1570 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1573 M_INTMOVE(src->prev->regoff, EAX);
1576 /* check as described in jvm spec */
1578 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1579 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1580 i386_alu_reg_reg(cd, ALU_XOR, EDX, EDX);
1581 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1582 i386_jcc(cd, I386_CC_E, 1 + 2);
1585 i386_idiv_reg(cd, s1);
1587 if (iptr->dst->flags & INMEMORY) {
1588 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4);
1591 M_INTMOVE(EDX, iptr->dst->regoff);
1595 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1596 /* val.i = constant */
1597 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1598 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL */
1600 /* TODO: optimize for `/ 2' */
1601 var_to_reg_int(s1, src, REG_ITMP1);
1602 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1605 i386_test_reg_reg(cd, d, d);
1607 CALCIMMEDIATEBYTES(disp, (1 << iptr->val.i) - 1);
1608 i386_jcc(cd, I386_CC_NS, disp);
1609 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, d);
1611 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1612 store_reg_to_var_int(iptr->dst, d);
1615 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1616 /* val.i = constant */
1617 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1618 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1620 var_to_reg_int(s1, src, REG_ITMP1);
1621 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1623 M_INTMOVE(s1, REG_ITMP1);
1630 CALCIMMEDIATEBYTES(disp, iptr->val.i);
1633 /* TODO: optimize */
1635 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1636 i386_test_reg_reg(cd, s1, s1);
1637 i386_jcc(cd, I386_CC_GE, disp);
1638 i386_mov_reg_reg(cd, s1, d);
1639 i386_neg_reg(cd, d);
1640 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1641 i386_neg_reg(cd, d);
1643 /* M_INTMOVE(s1, EAX); */
1644 /* i386_cltd(cd); */
1645 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1646 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1647 /* i386_alu_reg_reg(cd, ALU_AND, iptr->val.i, EAX); */
1648 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1649 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1650 /* M_INTMOVE(EAX, d); */
1652 /* i386_alu_reg_reg(cd, ALU_XOR, d, d); */
1653 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1654 /* i386_shrd_reg_reg(cd, s1, d); */
1655 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1657 store_reg_to_var_int(iptr->dst, d);
1660 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1661 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1663 d = reg_of_var(rd, iptr->dst, REG_NULL);
1664 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4);
1665 M_OR_MEMBASE(REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1668 codegen_addxdivrefs(cd, cd->mcodeptr);
1673 M_ILD(REG_ITMP1, REG_SP, src->prev->regoff * 4);
1674 M_ILD(REG_ITMP2, REG_SP, src->prev->regoff * 4 + 4);
1675 M_IST(REG_ITMP1, REG_SP, 0 * 4);
1676 M_IST(REG_ITMP2, REG_SP, 0 * 4 + 4);
1678 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
1679 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4 + 4);
1680 M_IST(REG_ITMP1, REG_SP, 2 * 4);
1681 M_IST(REG_ITMP2, REG_SP, 2 * 4 + 4);
1683 M_MOV_IMM((ptrint) bte->fp, REG_ITMP3);
1686 M_IST(REG_RESULT, REG_SP, iptr->dst->regoff * 4);
1687 M_IST(REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
1690 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1691 /* val.i = constant */
1692 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1693 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1695 d = reg_of_var(rd, iptr->dst, REG_NULL);
1696 if (iptr->dst->flags & INMEMORY) {
1697 if (src->flags & INMEMORY) {
1699 CALCIMMEDIATEBYTES(disp, (1 << iptr->val.i) - 1);
1701 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1702 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1704 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1705 i386_jcc(cd, I386_CC_NS, disp);
1706 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1707 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1708 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1709 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1711 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1712 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1717 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1718 /* val.l = constant */
1719 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1720 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1722 d = reg_of_var(rd, iptr->dst, REG_NULL);
1723 if (iptr->dst->flags & INMEMORY) {
1724 if (src->flags & INMEMORY) {
1725 /* Intel algorithm -- does not work, because constant is wrong */
1726 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1); */
1727 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3); */
1729 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1730 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1731 /* i386_jcc(cd, I386_CC_NS, offset); */
1732 /* i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1733 /* i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP3); */
1735 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1736 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1737 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1739 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1741 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1); */
1742 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); */
1743 /* i386_alu_reg_reg(cd, ALU_SBB, REG_ITMP3, REG_ITMP2); */
1745 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1746 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1748 /* Alpha algorithm */
1750 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1752 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4 + 4);
1758 /* TODO: hmm, don't know if this is always correct */
1760 CALCIMMEDIATEBYTES(disp, iptr->val.l & 0x00000000ffffffff);
1762 CALCIMMEDIATEBYTES(disp, iptr->val.l >> 32);
1768 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1769 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1771 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1772 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1773 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4 + 4);
1774 i386_jcc(cd, I386_CC_GE, disp);
1776 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1777 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1779 i386_neg_reg(cd, REG_ITMP1);
1780 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1781 i386_neg_reg(cd, REG_ITMP2);
1783 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1784 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1786 i386_neg_reg(cd, REG_ITMP1);
1787 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1788 i386_neg_reg(cd, REG_ITMP2);
1790 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1791 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1796 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1797 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1798 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1800 d = reg_of_var(rd, iptr->dst, REG_NULL);
1801 i386_emit_ishift(cd, I386_SHL, src, iptr);
1804 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1805 /* val.i = constant */
1806 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1807 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1809 d = reg_of_var(rd, iptr->dst, REG_NULL);
1810 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1813 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1814 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1815 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1817 d = reg_of_var(rd, iptr->dst, REG_NULL);
1818 i386_emit_ishift(cd, I386_SAR, src, iptr);
1821 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1822 /* val.i = constant */
1823 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1824 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1826 d = reg_of_var(rd, iptr->dst, REG_NULL);
1827 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1830 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1831 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1832 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1834 d = reg_of_var(rd, iptr->dst, REG_NULL);
1835 i386_emit_ishift(cd, I386_SHR, src, iptr);
1838 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1839 /* val.i = constant */
1840 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1841 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1843 d = reg_of_var(rd, iptr->dst, REG_NULL);
1844 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1847 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1848 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1849 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
1851 d = reg_of_var(rd, iptr->dst, REG_NULL);
1852 if (iptr->dst->flags & INMEMORY ){
1853 if (src->prev->flags & INMEMORY) {
1854 /* if (src->prev->regoff == iptr->dst->regoff) { */
1855 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1857 /* if (src->flags & INMEMORY) { */
1858 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1860 /* M_INTMOVE(src->regoff, ECX); */
1863 /* i386_test_imm_reg(cd, 32, ECX); */
1864 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1865 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1866 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1); */
1868 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 4 + 4); */
1869 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 4); */
1872 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1873 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1875 if (src->flags & INMEMORY) {
1876 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1878 M_INTMOVE(src->regoff, ECX);
1881 i386_test_imm_reg(cd, 32, ECX);
1882 i386_jcc(cd, I386_CC_E, 2 + 2);
1883 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1884 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1886 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1887 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1888 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1889 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
1895 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1896 /* val.i = constant */
1897 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1898 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1900 d = reg_of_var(rd, iptr->dst, REG_NULL);
1901 if (iptr->dst->flags & INMEMORY ) {
1902 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1903 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1905 if (iptr->val.i & 0x20) {
1906 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1907 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1908 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1911 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1912 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1915 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1916 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1920 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1921 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1922 /* EAX: S|YES ECX: YES S|EDX: YES OUTPUT: REG_NULL*/
1924 d = reg_of_var(rd, iptr->dst, REG_NULL);
1925 if (iptr->dst->flags & INMEMORY ){
1926 if (src->prev->flags & INMEMORY) {
1927 /* if (src->prev->regoff == iptr->dst->regoff) { */
1928 /* TODO: optimize */
1929 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1930 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
1932 /* if (src->flags & INMEMORY) { */
1933 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1935 /* M_INTMOVE(src->regoff, ECX); */
1938 /* i386_test_imm_reg(cd, 32, ECX); */
1939 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1940 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1941 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1943 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1944 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1945 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1946 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1949 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1950 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1952 if (src->flags & INMEMORY) {
1953 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1955 M_INTMOVE(src->regoff, ECX);
1958 i386_test_imm_reg(cd, 32, ECX);
1959 i386_jcc(cd, I386_CC_E, 2 + 3);
1960 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1961 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1963 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1964 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1965 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1966 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
1972 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1973 /* val.i = constant */
1974 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1975 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1977 d = reg_of_var(rd, iptr->dst, REG_NULL);
1978 if (iptr->dst->flags & INMEMORY ) {
1979 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1980 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1982 if (iptr->val.i & 0x20) {
1983 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1984 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
1985 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1988 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1989 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1992 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1993 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1997 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1998 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1999 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
2001 d = reg_of_var(rd, iptr->dst, REG_NULL);
2002 if (iptr->dst->flags & INMEMORY ){
2003 if (src->prev->flags & INMEMORY) {
2004 /* if (src->prev->regoff == iptr->dst->regoff) { */
2005 /* TODO: optimize */
2006 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
2007 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
2009 /* if (src->flags & INMEMORY) { */
2010 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
2012 /* M_INTMOVE(src->regoff, ECX); */
2015 /* i386_test_imm_reg(cd, 32, ECX); */
2016 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
2017 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2018 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2); */
2020 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2021 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
2022 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
2023 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
2026 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
2027 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
2029 if (src->flags & INMEMORY) {
2030 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
2032 M_INTMOVE(src->regoff, ECX);
2035 i386_test_imm_reg(cd, 32, ECX);
2036 i386_jcc(cd, I386_CC_E, 2 + 2);
2037 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2038 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP3, REG_ITMP3);
2040 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2041 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
2042 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2043 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2049 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
2050 /* val.l = constant */
2051 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2052 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
2054 d = reg_of_var(rd, iptr->dst, REG_NULL);
2055 if (iptr->dst->flags & INMEMORY ) {
2056 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
2057 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
2059 if (iptr->val.i & 0x20) {
2060 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2061 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
2062 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2065 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2066 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
2069 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2070 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
2074 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2075 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2076 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2078 d = reg_of_var(rd, iptr->dst, REG_NULL);
2079 i386_emit_ialu(cd, ALU_AND, src, iptr);
2082 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
2083 /* val.i = constant */
2084 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2085 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2087 d = reg_of_var(rd, iptr->dst, REG_NULL);
2088 i386_emit_ialuconst(cd, ALU_AND, src, iptr);
2091 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2092 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2093 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2095 d = reg_of_var(rd, iptr->dst, REG_NULL);
2096 i386_emit_lalu(cd, ALU_AND, src, iptr);
2099 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
2100 /* val.l = constant */
2101 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2102 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2104 d = reg_of_var(rd, iptr->dst, REG_NULL);
2105 i386_emit_laluconst(cd, ALU_AND, src, iptr);
2108 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2109 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2110 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2112 d = reg_of_var(rd, iptr->dst, REG_NULL);
2113 i386_emit_ialu(cd, ALU_OR, src, iptr);
2116 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2117 /* val.i = constant */
2118 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2119 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2121 d = reg_of_var(rd, iptr->dst, REG_NULL);
2122 i386_emit_ialuconst(cd, ALU_OR, src, iptr);
2125 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2126 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2127 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2129 d = reg_of_var(rd, iptr->dst, REG_NULL);
2130 i386_emit_lalu(cd, ALU_OR, src, iptr);
2133 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2134 /* val.l = constant */
2135 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2136 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2138 d = reg_of_var(rd, iptr->dst, REG_NULL);
2139 i386_emit_laluconst(cd, ALU_OR, src, iptr);
2142 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2143 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2144 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2146 d = reg_of_var(rd, iptr->dst, REG_NULL);
2147 i386_emit_ialu(cd, ALU_XOR, src, iptr);
2150 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2151 /* val.i = constant */
2152 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2153 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2155 d = reg_of_var(rd, iptr->dst, REG_NULL);
2156 i386_emit_ialuconst(cd, ALU_XOR, src, iptr);
2159 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2160 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2161 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2163 d = reg_of_var(rd, iptr->dst, REG_NULL);
2164 i386_emit_lalu(cd, ALU_XOR, src, iptr);
2167 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2168 /* val.l = constant */
2169 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2170 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2172 d = reg_of_var(rd, iptr->dst, REG_NULL);
2173 i386_emit_laluconst(cd, ALU_XOR, src, iptr);
2176 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2177 /* op1 = variable, val.i = constant */
2178 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2179 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL */
2181 var = &(rd->locals[iptr->op1][TYPE_INT]);
2182 if (var->flags & INMEMORY)
2183 M_IADD_IMM_MEMBASE(iptr->val.i, REG_SP, var->regoff * 4);
2185 /* `inc reg' is slower on p4's (regarding to ia32
2186 optimization reference manual and benchmarks) and
2187 as fast on athlon's. */
2188 M_IADD_IMM(iptr->val.i, var->regoff);
2193 /* floating operations ************************************************/
2195 #define ROUND_TO_SINGLE \
2196 i386_fstps_membase(cd, REG_SP, -8); \
2197 i386_flds_membase(cd, REG_SP, -8);
2199 #define ROUND_TO_DOUBLE \
2200 i386_fstpl_membase(cd, REG_SP, -8); \
2201 i386_fldl_membase(cd, REG_SP, -8);
2203 #define FPU_SET_24BIT_MODE \
2204 if (!fpu_in_24bit_mode) { \
2205 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2206 fpu_in_24bit_mode = 1; \
2209 #define FPU_SET_53BIT_MODE \
2210 if (fpu_in_24bit_mode) { \
2211 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2212 fpu_in_24bit_mode = 0; \
2215 #define ROUND_TO_SINGLE
2216 #define ROUND_TO_DOUBLE
2217 #define FPU_SET_24BIT_MODE
2218 #define FPU_SET_53BIT_MODE
2220 case ICMD_FNEG: /* ..., value ==> ..., - value */
2221 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2222 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2225 var_to_reg_flt(s1, src, REG_FTMP1);
2226 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2228 store_reg_to_var_flt(iptr->dst, d);
2231 case ICMD_DNEG: /* ..., value ==> ..., - value */
2232 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2233 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2236 var_to_reg_flt(s1, src, REG_FTMP1);
2237 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2239 store_reg_to_var_flt(iptr->dst, d);
2242 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2243 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2244 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2247 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2248 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2249 var_to_reg_flt(s2, src, REG_FTMP2);
2252 store_reg_to_var_flt(iptr->dst, d);
2255 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2256 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2257 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2260 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2261 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2262 var_to_reg_flt(s2, src, REG_FTMP2);
2265 store_reg_to_var_flt(iptr->dst, d);
2268 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2269 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2270 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2273 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2274 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2275 var_to_reg_flt(s2, src, REG_FTMP2);
2278 store_reg_to_var_flt(iptr->dst, d);
2281 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2282 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2283 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2286 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2287 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2288 var_to_reg_flt(s2, src, REG_FTMP2);
2291 store_reg_to_var_flt(iptr->dst, d);
2294 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2295 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2296 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2299 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2300 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2301 var_to_reg_flt(s2, src, REG_FTMP2);
2305 store_reg_to_var_flt(iptr->dst, d);
2308 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2309 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2310 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2313 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2314 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2316 /* i386_fldt_mem(cd, subnormal_bias1); */
2317 /* i386_fmulp(cd); */
2319 var_to_reg_flt(s2, src, REG_FTMP2);
2324 /* i386_fldt_mem(cd, subnormal_bias2); */
2325 /* i386_fmulp(cd); */
2327 store_reg_to_var_flt(iptr->dst, d);
2330 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2331 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2332 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2335 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2336 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2337 var_to_reg_flt(s2, src, REG_FTMP2);
2341 store_reg_to_var_flt(iptr->dst, d);
2344 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2345 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2346 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2349 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2350 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2352 /* i386_fldt_mem(cd, subnormal_bias1); */
2353 /* i386_fmulp(cd); */
2355 var_to_reg_flt(s2, src, REG_FTMP2);
2360 /* i386_fldt_mem(cd, subnormal_bias2); */
2361 /* i386_fmulp(cd); */
2363 store_reg_to_var_flt(iptr->dst, d);
2366 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2367 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2368 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2371 /* exchanged to skip fxch */
2372 var_to_reg_flt(s2, src, REG_FTMP2);
2373 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2374 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2375 /* i386_fxch(cd); */
2380 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2381 store_reg_to_var_flt(iptr->dst, d);
2382 i386_ffree_reg(cd, 0);
2387 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2388 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2389 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2392 /* exchanged to skip fxch */
2393 var_to_reg_flt(s2, src, REG_FTMP2);
2394 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2395 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2396 /* i386_fxch(cd); */
2401 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2402 store_reg_to_var_flt(iptr->dst, d);
2403 i386_ffree_reg(cd, 0);
2408 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2409 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2410 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2411 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2413 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2414 if (src->flags & INMEMORY) {
2415 i386_fildl_membase(cd, REG_SP, src->regoff * 4);
2419 disp = dseg_adds4(cd, 0);
2420 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2421 dseg_adddata(cd, cd->mcodeptr);
2422 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, disp);
2423 i386_fildl_membase(cd, REG_ITMP1, disp);
2426 store_reg_to_var_flt(iptr->dst, d);
2429 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2430 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2431 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2432 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2434 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2435 if (src->flags & INMEMORY) {
2436 i386_fildll_membase(cd, REG_SP, src->regoff * 4);
2440 log_text("L2F: longs have to be in memory");
2443 store_reg_to_var_flt(iptr->dst, d);
2446 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2447 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2448 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2450 var_to_reg_flt(s1, src, REG_FTMP1);
2451 d = reg_of_var(rd, iptr->dst, REG_NULL);
2453 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2454 dseg_adddata(cd, cd->mcodeptr);
2456 /* Round to zero, 53-bit mode, exception masked */
2457 disp = dseg_adds4(cd, 0x0e7f);
2458 i386_fldcw_membase(cd, REG_ITMP1, disp);
2460 if (iptr->dst->flags & INMEMORY) {
2461 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2464 /* Round to nearest, 53-bit mode, exceptions masked */
2465 disp = dseg_adds4(cd, 0x027f);
2466 i386_fldcw_membase(cd, REG_ITMP1, disp);
2468 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2471 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2473 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2476 disp = dseg_adds4(cd, 0);
2477 i386_fistpl_membase(cd, REG_ITMP1, disp);
2479 i386_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2481 /* Round to nearest, 53-bit mode, exceptions masked */
2482 disp = dseg_adds4(cd, 0x027f);
2483 i386_fldcw_membase(cd, REG_ITMP1, disp);
2485 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2488 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2489 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2492 i386_jcc(cd, I386_CC_NE, disp);
2494 /* XXX: change this when we use registers */
2495 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2496 i386_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP1);
2497 i386_call_reg(cd, REG_ITMP1);
2499 if (iptr->dst->flags & INMEMORY) {
2500 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2503 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2507 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2508 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2509 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2511 var_to_reg_flt(s1, src, REG_FTMP1);
2512 d = reg_of_var(rd, iptr->dst, REG_NULL);
2514 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2515 dseg_adddata(cd, cd->mcodeptr);
2517 /* Round to zero, 53-bit mode, exception masked */
2518 disp = dseg_adds4(cd, 0x0e7f);
2519 i386_fldcw_membase(cd, REG_ITMP1, disp);
2521 if (iptr->dst->flags & INMEMORY) {
2522 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2525 /* Round to nearest, 53-bit mode, exceptions masked */
2526 disp = dseg_adds4(cd, 0x027f);
2527 i386_fldcw_membase(cd, REG_ITMP1, disp);
2529 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2532 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2534 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2537 disp = dseg_adds4(cd, 0);
2538 i386_fistpl_membase(cd, REG_ITMP1, disp);
2540 i386_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2542 /* Round to nearest, 53-bit mode, exceptions masked */
2543 disp = dseg_adds4(cd, 0x027f);
2544 i386_fldcw_membase(cd, REG_ITMP1, disp);
2546 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2549 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2550 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2553 i386_jcc(cd, I386_CC_NE, disp);
2555 /* XXX: change this when we use registers */
2556 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2557 i386_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP1);
2558 i386_call_reg(cd, REG_ITMP1);
2560 if (iptr->dst->flags & INMEMORY) {
2561 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2563 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2567 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2568 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2569 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2571 var_to_reg_flt(s1, src, REG_FTMP1);
2572 d = reg_of_var(rd, iptr->dst, REG_NULL);
2574 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2575 dseg_adddata(cd, cd->mcodeptr);
2577 /* Round to zero, 53-bit mode, exception masked */
2578 disp = dseg_adds4(cd, 0x0e7f);
2579 i386_fldcw_membase(cd, REG_ITMP1, disp);
2581 if (iptr->dst->flags & INMEMORY) {
2582 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2585 /* Round to nearest, 53-bit mode, exceptions masked */
2586 disp = dseg_adds4(cd, 0x027f);
2587 i386_fldcw_membase(cd, REG_ITMP1, disp);
2589 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2592 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2594 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2597 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2599 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2601 i386_jcc(cd, I386_CC_NE, disp);
2603 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2606 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2608 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2610 i386_jcc(cd, I386_CC_NE, disp);
2612 /* XXX: change this when we use registers */
2613 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2614 i386_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP1);
2615 i386_call_reg(cd, REG_ITMP1);
2616 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2617 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2620 log_text("F2L: longs have to be in memory");
2625 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2626 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2627 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2629 var_to_reg_flt(s1, src, REG_FTMP1);
2630 d = reg_of_var(rd, iptr->dst, REG_NULL);
2632 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2633 dseg_adddata(cd, cd->mcodeptr);
2635 /* Round to zero, 53-bit mode, exception masked */
2636 disp = dseg_adds4(cd, 0x0e7f);
2637 i386_fldcw_membase(cd, REG_ITMP1, disp);
2639 if (iptr->dst->flags & INMEMORY) {
2640 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2643 /* Round to nearest, 53-bit mode, exceptions masked */
2644 disp = dseg_adds4(cd, 0x027f);
2645 i386_fldcw_membase(cd, REG_ITMP1, disp);
2647 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2650 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2652 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2655 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2657 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2659 i386_jcc(cd, I386_CC_NE, disp);
2661 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2664 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2666 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2668 i386_jcc(cd, I386_CC_NE, disp);
2670 /* XXX: change this when we use registers */
2671 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2672 i386_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP1);
2673 i386_call_reg(cd, REG_ITMP1);
2674 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2675 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2678 log_text("D2L: longs have to be in memory");
2683 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2684 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2685 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2687 var_to_reg_flt(s1, src, REG_FTMP1);
2688 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2690 store_reg_to_var_flt(iptr->dst, d);
2693 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2694 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2695 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2697 var_to_reg_flt(s1, src, REG_FTMP1);
2698 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2700 store_reg_to_var_flt(iptr->dst, d);
2703 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2705 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2706 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2708 /* exchanged to skip fxch */
2709 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2710 var_to_reg_flt(s1, src, REG_FTMP2);
2711 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2712 /* i386_fxch(cd); */
2716 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2717 i386_jcc(cd, I386_CC_E, 6);
2718 i386_alu_imm_reg(cd, ALU_AND, 0x000000ff, EAX);
2720 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2721 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2722 i386_jcc(cd, I386_CC_B, 3 + 5);
2723 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2724 i386_jmp_imm(cd, 3);
2725 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2726 store_reg_to_var_int(iptr->dst, d);
2729 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2731 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2732 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2734 /* exchanged to skip fxch */
2735 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2736 var_to_reg_flt(s1, src, REG_FTMP2);
2737 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2738 /* i386_fxch(cd); */
2742 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2743 i386_jcc(cd, I386_CC_E, 3);
2744 i386_movb_imm_reg(cd, 1, REG_AH);
2746 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2747 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2748 i386_jcc(cd, I386_CC_B, 3 + 5);
2749 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2750 i386_jmp_imm(cd, 3);
2751 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2752 store_reg_to_var_int(iptr->dst, d);
2756 /* memory operations **************************************************/
2758 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2759 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2760 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2762 var_to_reg_int(s1, src, REG_ITMP1);
2763 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2764 gen_nullptr_check(s1);
2765 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2766 store_reg_to_var_int(iptr->dst, d);
2769 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2770 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2771 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2773 var_to_reg_int(s1, src->prev, REG_ITMP1);
2774 var_to_reg_int(s2, src, REG_ITMP2);
2775 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2776 if (iptr->op1 == 0) {
2777 gen_nullptr_check(s1);
2780 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2781 store_reg_to_var_int(iptr->dst, d);
2784 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2785 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2786 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2788 var_to_reg_int(s1, src->prev, REG_ITMP1);
2789 var_to_reg_int(s2, src, REG_ITMP2);
2790 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2791 if (iptr->op1 == 0) {
2792 gen_nullptr_check(s1);
2796 if (iptr->dst->flags & INMEMORY) {
2797 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2798 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4);
2799 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2800 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2804 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2805 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2806 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2808 var_to_reg_int(s1, src->prev, REG_ITMP1);
2809 var_to_reg_int(s2, src, REG_ITMP2);
2810 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2811 if (iptr->op1 == 0) {
2812 gen_nullptr_check(s1);
2815 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2816 store_reg_to_var_int(iptr->dst, d);
2819 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2820 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2821 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2823 var_to_reg_int(s1, src->prev, REG_ITMP1);
2824 var_to_reg_int(s2, src, REG_ITMP2);
2825 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2826 if (iptr->op1 == 0) {
2827 gen_nullptr_check(s1);
2830 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2832 store_reg_to_var_flt(iptr->dst, d);
2835 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2836 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2837 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2839 var_to_reg_int(s1, src->prev, REG_ITMP1);
2840 var_to_reg_int(s2, src, REG_ITMP2);
2841 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2842 if (iptr->op1 == 0) {
2843 gen_nullptr_check(s1);
2846 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2848 store_reg_to_var_flt(iptr->dst, d);
2851 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2852 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2853 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2855 var_to_reg_int(s1, src->prev, REG_ITMP1);
2856 var_to_reg_int(s2, src, REG_ITMP2);
2857 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2858 if (iptr->op1 == 0) {
2859 gen_nullptr_check(s1);
2862 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2863 store_reg_to_var_int(iptr->dst, d);
2866 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2867 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2868 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2870 var_to_reg_int(s1, src->prev, REG_ITMP1);
2871 var_to_reg_int(s2, src, REG_ITMP2);
2872 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2873 if (iptr->op1 == 0) {
2874 gen_nullptr_check(s1);
2877 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2878 store_reg_to_var_int(iptr->dst, d);
2881 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2882 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2883 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2885 var_to_reg_int(s1, src->prev, REG_ITMP1);
2886 var_to_reg_int(s2, src, REG_ITMP2);
2887 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2888 if (iptr->op1 == 0) {
2889 gen_nullptr_check(s1);
2892 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2893 store_reg_to_var_int(iptr->dst, d);
2897 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2898 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2899 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
2901 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2902 var_to_reg_int(s2, src->prev, REG_ITMP2);
2903 if (iptr->op1 == 0) {
2904 gen_nullptr_check(s1);
2908 if (src->flags & INMEMORY) {
2909 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP3);
2910 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2911 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
2912 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2916 case ICMD_IASTORE: /* ..., 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);
2926 var_to_reg_int(s3, src, REG_ITMP3);
2927 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2930 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2931 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2932 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2934 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2935 var_to_reg_int(s2, src->prev, REG_ITMP2);
2936 if (iptr->op1 == 0) {
2937 gen_nullptr_check(s1);
2940 var_to_reg_flt(s3, src, REG_FTMP1);
2941 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2945 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2946 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2947 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2949 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2950 var_to_reg_int(s2, src->prev, REG_ITMP2);
2951 if (iptr->op1 == 0) {
2952 gen_nullptr_check(s1);
2955 var_to_reg_flt(s3, src, REG_FTMP1);
2956 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2960 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2961 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2962 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2964 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2965 var_to_reg_int(s2, src->prev, REG_ITMP2);
2966 if (iptr->op1 == 0) {
2967 gen_nullptr_check(s1);
2970 var_to_reg_int(s3, src, REG_ITMP3);
2971 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2974 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2975 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2976 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2978 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2979 var_to_reg_int(s2, src->prev, REG_ITMP2);
2980 if (iptr->op1 == 0) {
2981 gen_nullptr_check(s1);
2984 var_to_reg_int(s3, src, REG_ITMP3);
2985 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2988 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2989 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2990 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2992 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2993 var_to_reg_int(s2, src->prev, REG_ITMP2);
2994 if (iptr->op1 == 0) {
2995 gen_nullptr_check(s1);
2998 var_to_reg_int(s3, src, REG_ITMP3);
2999 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
3000 M_INTMOVE(s3, REG_ITMP3);
3003 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3006 case ICMD_AASTORE: /* ..., 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);
3019 M_AST(s1, REG_SP, 0 * 4);
3020 M_AST(s3, REG_SP, 1 * 4);
3021 M_MOV_IMM((ptrint) BUILTIN_canstore, REG_ITMP1);
3025 codegen_addxstorerefs(cd, cd->mcodeptr);
3027 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3028 var_to_reg_int(s2, src->prev, REG_ITMP2);
3029 var_to_reg_int(s3, src, REG_ITMP3);
3030 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3033 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
3034 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3035 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3037 var_to_reg_int(s1, src->prev, REG_ITMP1);
3038 var_to_reg_int(s2, src, REG_ITMP2);
3039 if (iptr->op1 == 0) {
3040 gen_nullptr_check(s1);
3043 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
3046 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
3047 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3048 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3050 var_to_reg_int(s1, src->prev, REG_ITMP1);
3051 var_to_reg_int(s2, src, REG_ITMP2);
3052 if (iptr->op1 == 0) {
3053 gen_nullptr_check(s1);
3057 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
3058 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
3061 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
3062 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3063 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3065 var_to_reg_int(s1, src->prev, REG_ITMP1);
3066 var_to_reg_int(s2, src, REG_ITMP2);
3067 if (iptr->op1 == 0) {
3068 gen_nullptr_check(s1);
3071 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3074 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
3075 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3076 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3078 var_to_reg_int(s1, src->prev, REG_ITMP1);
3079 var_to_reg_int(s2, src, REG_ITMP2);
3080 if (iptr->op1 == 0) {
3081 gen_nullptr_check(s1);
3084 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3087 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
3088 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3089 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3091 var_to_reg_int(s1, src->prev, REG_ITMP1);
3092 var_to_reg_int(s2, src, REG_ITMP2);
3093 if (iptr->op1 == 0) {
3094 gen_nullptr_check(s1);
3097 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
3100 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
3101 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3102 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3104 var_to_reg_int(s1, src->prev, REG_ITMP1);
3105 var_to_reg_int(s2, src, REG_ITMP2);
3106 if (iptr->op1 == 0) {
3107 gen_nullptr_check(s1);
3110 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3114 case ICMD_GETSTATIC: /* ... ==> ..., value */
3115 /* op1 = type, val.a = field address */
3116 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3117 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX*/
3119 if (iptr->val.a == NULL) {
3120 codegen_addpatchref(cd, cd->mcodeptr,
3121 PATCHER_get_putstatic,
3122 (unresolved_field *) iptr->target, 0);
3124 if (opt_showdisassemble) {
3125 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3131 fieldinfo *fi = iptr->val.a;
3133 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3134 codegen_addpatchref(cd, cd->mcodeptr,
3135 PATCHER_clinit, fi->class, 0);
3137 if (opt_showdisassemble) {
3138 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3142 disp = (ptrint) &(fi->value);
3145 M_MOV_IMM(disp, REG_ITMP1);
3146 switch (iptr->op1) {
3149 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3150 M_ILD(d, REG_ITMP1, 0);
3151 store_reg_to_var_int(iptr->dst, d);
3154 d = reg_of_var(rd, iptr->dst, REG_NULL);
3155 if (iptr->dst->flags & INMEMORY) {
3156 /* Using both REG_ITMP2 and REG_ITMP3 is faster
3157 than only using REG_ITMP2 alternating. */
3158 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP2);
3159 i386_mov_membase_reg(cd, REG_ITMP1, 4, REG_ITMP3);
3160 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4);
3161 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
3163 log_text("GETSTATIC: longs have to be in memory");
3168 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3169 i386_flds_membase(cd, REG_ITMP1, 0);
3171 store_reg_to_var_flt(iptr->dst, d);
3174 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3175 i386_fldl_membase(cd, REG_ITMP1, 0);
3177 store_reg_to_var_flt(iptr->dst, d);
3182 case ICMD_PUTSTATIC: /* ..., value ==> ... */
3183 /* op1 = type, val.a = field address */
3184 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3185 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3187 if (iptr->val.a == NULL) {
3188 codegen_addpatchref(cd, cd->mcodeptr,
3189 PATCHER_get_putstatic,
3190 (unresolved_field *) iptr->target, 0);
3192 if (opt_showdisassemble) {
3193 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3199 fieldinfo *fi = iptr->val.a;
3201 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3202 codegen_addpatchref(cd, cd->mcodeptr,
3203 PATCHER_clinit, fi->class, 0);
3205 if (opt_showdisassemble) {
3206 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3210 disp = (ptrint) &(fi->value);
3213 M_MOV_IMM(disp, REG_ITMP1);
3214 switch (iptr->op1) {
3217 var_to_reg_int(s2, src, REG_ITMP2);
3218 M_IST(s2, REG_ITMP1, 0);
3221 if (src->flags & INMEMORY) {
3222 /* Using both REG_ITMP2 and REG_ITMP3 is faster
3223 than only using REG_ITMP2 alternating. */
3226 i386_mov_membase_reg(cd, REG_SP, s2 * 4, REG_ITMP2);
3227 i386_mov_membase_reg(cd, REG_SP, s2 * 4 + 4, REG_ITMP3);
3228 i386_mov_reg_membase(cd, REG_ITMP2, REG_ITMP1, 0);
3229 i386_mov_reg_membase(cd, REG_ITMP3, REG_ITMP1, 4);
3231 log_text("PUTSTATIC: longs have to be in memory");
3236 var_to_reg_flt(s2, src, REG_FTMP1);
3237 i386_fstps_membase(cd, REG_ITMP1, 0);
3241 var_to_reg_flt(s2, src, REG_FTMP1);
3242 i386_fstpl_membase(cd, REG_ITMP1, 0);
3248 case ICMD_PUTSTATICCONST: /* ... ==> ... */
3249 /* val = value (in current instruction) */
3250 /* op1 = type, val.a = field address (in */
3251 /* following NOP) */
3252 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3253 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3255 if (iptr[1].val.a == NULL) {
3256 codegen_addpatchref(cd, cd->mcodeptr,
3257 PATCHER_get_putstatic,
3258 (unresolved_field *) iptr[1].target, 0);
3260 if (opt_showdisassemble) {
3261 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3267 fieldinfo *fi = iptr[1].val.a;
3269 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3270 codegen_addpatchref(cd, cd->mcodeptr,
3271 PATCHER_clinit, fi->class, 0);
3273 if (opt_showdisassemble) {
3274 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3278 disp = (ptrint) &(fi->value);
3281 M_MOV_IMM(disp, REG_ITMP1);
3282 switch (iptr[1].op1) {
3286 i386_mov_imm_membase(cd, iptr->val.i, REG_ITMP1, 0);
3290 i386_mov_imm_membase(cd, iptr->val.l, REG_ITMP1, 0);
3291 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_ITMP1, 4);
3296 case ICMD_GETFIELD: /* .., objectref. ==> ..., value */
3297 /* op1 = type, val.i = field offset */
3298 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3299 /* EAX: YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
3301 var_to_reg_int(s1, src, REG_ITMP1);
3302 gen_nullptr_check(s1);
3304 if (iptr->val.a == NULL) {
3305 codegen_addpatchref(cd, cd->mcodeptr,
3307 (unresolved_field *) iptr->target, 0);
3309 if (opt_showdisassemble) {
3310 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3316 disp = ((fieldinfo *) (iptr->val.a))->offset;
3319 switch (iptr->op1) {
3322 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3323 i386_mov_membase32_reg(cd, s1, disp, d);
3324 store_reg_to_var_int(iptr->dst, d);
3327 d = reg_of_var(rd, iptr->dst, REG_NULL);
3328 i386_mov_membase32_reg(cd, s1, disp, REG_ITMP2);
3329 i386_mov_membase32_reg(cd, s1, disp + 4, REG_ITMP3);
3330 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4);
3331 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
3334 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3335 i386_flds_membase32(cd, s1, disp);
3337 store_reg_to_var_flt(iptr->dst, d);
3340 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3341 i386_fldl_membase32(cd, s1, disp);
3343 store_reg_to_var_flt(iptr->dst, d);
3348 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
3349 /* op1 = type, val.a = field address */
3350 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3351 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3353 var_to_reg_int(s1, src->prev, REG_ITMP1);
3354 gen_nullptr_check(s1);
3356 if ((iptr->op1 == TYPE_INT) || IS_ADR_TYPE(iptr->op1)) {
3357 var_to_reg_int(s2, src, REG_ITMP2);
3358 } else if (IS_FLT_DBL_TYPE(iptr->op1)) {
3359 var_to_reg_flt(s2, src, REG_FTMP2);
3362 if (iptr->val.a == NULL) {
3363 codegen_addpatchref(cd, cd->mcodeptr,
3365 (unresolved_field *) iptr->target, 0);
3367 if (opt_showdisassemble) {
3368 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3374 disp = ((fieldinfo *) (iptr->val.a))->offset;
3377 switch (iptr->op1) {
3380 i386_mov_reg_membase32(cd, s2, s1, disp);
3383 if (src->flags & INMEMORY) {
3384 i386_mov_membase32_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2);
3385 i386_mov_membase32_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
3386 i386_mov_reg_membase32(cd, REG_ITMP2, s1, disp);
3387 i386_mov_reg_membase32(cd, REG_ITMP3, s1, disp + 4);
3389 log_text("PUTFIELD: longs have to be in memory");
3394 i386_fstps_membase32(cd, s1, disp);
3398 i386_fstpl_membase32(cd, s1, disp);
3404 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
3405 /* val = value (in current instruction) */
3406 /* op1 = type, val.a = field address (in */
3407 /* following NOP) */
3408 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3409 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3411 var_to_reg_int(s1, src, REG_ITMP1);
3412 gen_nullptr_check(s1);
3414 if (iptr[1].val.a == NULL) {
3415 codegen_addpatchref(cd, cd->mcodeptr,
3416 PATCHER_putfieldconst,
3417 (unresolved_field *) iptr[1].target, 0);
3419 if (opt_showdisassemble) {
3420 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3426 disp = ((fieldinfo *) (iptr[1].val.a))->offset;
3429 switch (iptr[1].op1) {
3433 i386_mov_imm_membase32(cd, iptr->val.i, s1, disp);
3437 i386_mov_imm_membase32(cd, iptr->val.l, s1, disp);
3438 i386_mov_imm_membase32(cd, iptr->val.l >> 32, s1, disp + 4);
3444 /* branch operations **************************************************/
3446 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3447 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3448 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
3450 var_to_reg_int(s1, src, REG_ITMP1);
3451 M_INTMOVE(s1, REG_ITMP1_XPTR);
3453 #ifdef ENABLE_VERIFIER
3455 codegen_addpatchref(cd, cd->mcodeptr,
3456 PATCHER_athrow_areturn,
3457 (unresolved_class *) iptr->val.a, 0);
3459 if (opt_showdisassemble) {
3460 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3463 #endif /* ENABLE_VERIFIER */
3465 M_CALL_IMM(0); /* passing exception pc */
3466 M_POP(REG_ITMP2_XPC);
3468 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
3472 case ICMD_GOTO: /* ... ==> ... */
3473 /* op1 = target JavaVM pc */
3474 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3475 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3477 i386_jmp_imm(cd, 0);
3478 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3481 case ICMD_JSR: /* ... ==> ... */
3482 /* op1 = target JavaVM pc */
3483 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3484 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3486 i386_call_imm(cd, 0);
3487 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3490 case ICMD_RET: /* ... ==> ... */
3491 /* op1 = local variable */
3492 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3493 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3495 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3496 var_to_reg_int(s1, var, REG_ITMP1);
3497 i386_jmp_reg(cd, s1);
3500 case ICMD_IFNULL: /* ..., value ==> ... */
3501 /* op1 = target JavaVM pc */
3502 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3503 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3505 if (src->flags & INMEMORY) {
3506 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3509 i386_test_reg_reg(cd, src->regoff, src->regoff);
3511 i386_jcc(cd, I386_CC_E, 0);
3512 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3515 case ICMD_IFNONNULL: /* ..., value ==> ... */
3516 /* op1 = target JavaVM pc */
3517 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3518 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3520 if (src->flags & INMEMORY) {
3521 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3524 i386_test_reg_reg(cd, src->regoff, src->regoff);
3526 i386_jcc(cd, I386_CC_NE, 0);
3527 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3530 case ICMD_IFEQ: /* ..., value ==> ... */
3531 /* op1 = target JavaVM pc, val.i = constant */
3532 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3533 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3535 if (src->flags & INMEMORY) {
3536 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3539 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3541 i386_jcc(cd, I386_CC_E, 0);
3542 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3545 case ICMD_IFLT: /* ..., value ==> ... */
3546 /* op1 = target JavaVM pc, val.i = constant */
3547 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3548 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3550 if (src->flags & INMEMORY) {
3551 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3554 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3556 i386_jcc(cd, I386_CC_L, 0);
3557 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3560 case ICMD_IFLE: /* ..., value ==> ... */
3561 /* op1 = target JavaVM pc, val.i = constant */
3562 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3563 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3565 if (src->flags & INMEMORY) {
3566 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3569 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3571 i386_jcc(cd, I386_CC_LE, 0);
3572 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3575 case ICMD_IFNE: /* ..., value ==> ... */
3576 /* op1 = target JavaVM pc, val.i = constant */
3577 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3578 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3580 if (src->flags & INMEMORY) {
3581 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3584 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3586 i386_jcc(cd, I386_CC_NE, 0);
3587 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3590 case ICMD_IFGT: /* ..., value ==> ... */
3591 /* op1 = target JavaVM pc, val.i = constant */
3592 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3593 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3595 if (src->flags & INMEMORY) {
3596 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3599 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3601 i386_jcc(cd, I386_CC_G, 0);
3602 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3605 case ICMD_IFGE: /* ..., value ==> ... */
3606 /* op1 = target JavaVM pc, val.i = constant */
3607 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3608 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3610 if (src->flags & INMEMORY) {
3611 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3614 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3616 i386_jcc(cd, I386_CC_GE, 0);
3617 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3620 case ICMD_IF_LEQ: /* ..., value ==> ... */
3621 /* op1 = target JavaVM pc, val.l = constant */
3622 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3623 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3625 if (src->flags & INMEMORY) {
3626 if (iptr->val.l == 0) {
3627 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3628 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3631 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3632 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l >> 32, REG_ITMP2);
3633 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3634 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l, REG_ITMP1);
3635 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3638 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3639 i386_jcc(cd, I386_CC_E, 0);
3640 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3643 case ICMD_IF_LLT: /* ..., value ==> ... */
3644 /* op1 = target JavaVM pc, val.l = constant */
3645 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3646 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3648 if (src->flags & INMEMORY) {
3649 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3650 i386_jcc(cd, I386_CC_L, 0);
3651 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3654 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3655 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3657 i386_jcc(cd, I386_CC_G, disp);
3659 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3660 i386_jcc(cd, I386_CC_B, 0);
3661 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3665 case ICMD_IF_LLE: /* ..., 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_BE, 0);
3683 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3687 case ICMD_IF_LNE: /* ..., 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 if (iptr->val.l == 0) {
3694 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3695 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3698 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3699 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3700 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3701 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3702 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3705 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3706 i386_jcc(cd, I386_CC_NE, 0);
3707 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3710 case ICMD_IF_LGT: /* ..., value ==> ... */
3711 /* op1 = target JavaVM pc, val.l = constant */
3712 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3713 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3715 if (src->flags & INMEMORY) {
3716 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3717 i386_jcc(cd, I386_CC_G, 0);
3718 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3721 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3722 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3724 i386_jcc(cd, I386_CC_L, disp);
3726 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3727 i386_jcc(cd, I386_CC_A, 0);
3728 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3732 case ICMD_IF_LGE: /* ..., 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_AE, 0);
3750 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3754 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3755 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
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) && (src->prev->flags & INMEMORY)) {
3760 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3761 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3763 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3764 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3766 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3767 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3770 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3772 i386_jcc(cd, I386_CC_E, 0);
3773 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3776 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3777 /* 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->prev->regoff * 4, REG_ITMP1);
3783 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3784 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3785 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3786 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3787 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3789 i386_jcc(cd, I386_CC_E, 0);
3790 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3793 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3794 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3795 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3796 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3798 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3799 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3800 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3802 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3803 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3805 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3806 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3809 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3811 i386_jcc(cd, I386_CC_NE, 0);
3812 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3815 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3816 /* 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->prev->regoff * 4, REG_ITMP1);
3822 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3823 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3824 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3825 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3826 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3828 i386_jcc(cd, I386_CC_NE, 0);
3829 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3832 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3833 /* op1 = target JavaVM pc */
3834 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3835 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3837 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3838 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3839 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3841 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3842 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3844 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3845 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3848 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3850 i386_jcc(cd, I386_CC_L, 0);
3851 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3854 case ICMD_IF_LCMPLT: /* ..., 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->prev->regoff * 4 + 4, REG_ITMP1);
3861 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3863 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3866 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3867 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3871 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3872 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3873 i386_jcc(cd, I386_CC_B, 0);
3874 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3878 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3879 /* op1 = target JavaVM pc */
3880 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3881 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3883 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3884 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3885 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3887 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3888 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3890 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3891 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3894 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3897 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3900 case ICMD_IF_LCMPGT: /* ..., 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->prev->regoff * 4 + 4, REG_ITMP1);
3907 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3909 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3912 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3913 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3917 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3918 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3919 i386_jcc(cd, I386_CC_A, 0);
3920 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3924 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3925 /* op1 = target JavaVM pc */
3926 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3927 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3929 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3930 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3931 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3933 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3934 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3936 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3937 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3940 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3943 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3946 case ICMD_IF_LCMPLE: /* ..., 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->prev->regoff * 4 + 4, REG_ITMP1);
3953 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3955 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3958 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3959 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3963 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3964 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3966 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3970 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3971 /* op1 = target JavaVM pc */
3972 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3973 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3975 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3976 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3977 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3979 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3980 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3982 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3983 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3986 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3989 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3992 case ICMD_IF_LCMPGE: /* ..., 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->prev->regoff * 4 + 4, REG_ITMP1);
3999 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
4001 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4004 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
4005 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
4009 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
4010 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
4012 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
4016 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
4018 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
4019 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4020 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4023 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
4024 /* val.i = constant */
4025 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4026 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4028 d = reg_of_var(rd, iptr->dst, REG_NULL);
4029 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
4032 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
4033 /* val.i = constant */
4034 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4035 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4037 d = reg_of_var(rd, iptr->dst, REG_NULL);
4038 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
4041 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
4042 /* val.i = constant */
4043 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4044 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4046 d = reg_of_var(rd, iptr->dst, REG_NULL);
4047 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
4050 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
4051 /* val.i = constant */
4052 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4053 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4055 d = reg_of_var(rd, iptr->dst, REG_NULL);
4056 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
4059 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
4060 /* val.i = constant */
4061 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4062 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4064 d = reg_of_var(rd, iptr->dst, REG_NULL);
4065 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
4068 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
4069 /* val.i = constant */
4070 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4071 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4073 d = reg_of_var(rd, iptr->dst, REG_NULL);
4074 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
4078 case ICMD_IRETURN: /* ..., retvalue ==> ... */
4079 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4080 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4082 var_to_reg_int(s1, src, REG_RESULT);
4083 M_INTMOVE(s1, REG_RESULT);
4084 goto nowperformreturn;
4086 case ICMD_LRETURN: /* ..., retvalue ==> ... */
4087 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4088 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4090 if (src->flags & INMEMORY) {
4091 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_RESULT);
4092 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_RESULT2);
4095 log_text("LRETURN: longs have to be in memory");
4098 goto nowperformreturn;
4100 case ICMD_ARETURN: /* ..., 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);
4107 #ifdef ENABLE_VERIFIER
4109 codegen_addpatchref(cd, cd->mcodeptr,
4110 PATCHER_athrow_areturn,
4111 (unresolved_class *) iptr->val.a, 0);
4113 if (opt_showdisassemble) {
4114 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4117 #endif /* ENABLE_VERIFIER */
4118 goto nowperformreturn;
4120 case ICMD_FRETURN: /* ..., retvalue ==> ... */
4122 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4123 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4125 var_to_reg_flt(s1, src, REG_FRESULT);
4126 /* this may be an early return -- keep the offset correct for the
4129 goto nowperformreturn;
4131 case ICMD_RETURN: /* ... ==> ... */
4132 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4133 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4139 p = parentargs_base;
4141 /* call trace function */
4143 i386_alu_imm_reg(cd, ALU_SUB, 4 + 8 + 8 + 4, REG_SP);
4145 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
4147 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
4148 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
4150 i386_fstl_membase(cd, REG_SP, 4 + 8);
4151 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
4153 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
4154 i386_call_reg(cd, REG_ITMP1);
4156 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
4157 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
4159 i386_alu_imm_reg(cd, ALU_ADD, 4 + 8 + 8 + 4, REG_SP);
4162 #if defined(USE_THREADS)
4163 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
4164 M_ALD(REG_ITMP2, REG_SP, rd->memuse * 4);
4166 /* we need to save the proper return value */
4167 switch (iptr->opc) {
4170 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4174 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4175 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4179 i386_fstps_membase(cd, REG_SP, rd->memuse * 4);
4183 i386_fstpl_membase(cd, REG_SP, rd->memuse * 4);
4187 M_AST(REG_ITMP2, REG_SP, 0);
4188 M_MOV_IMM((ptrint) BUILTIN_monitorexit, REG_ITMP1);
4191 /* and now restore the proper return value */
4192 switch (iptr->opc) {
4195 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4199 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4200 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4204 i386_flds_membase(cd, REG_SP, rd->memuse * 4);
4208 i386_fldl_membase(cd, REG_SP, rd->memuse * 4);
4214 /* restore saved registers */
4216 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
4217 p--; M_ALD(rd->savintregs[i], REG_SP, p * 4);
4220 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
4222 i386_fldl_membase(cd, REG_SP, p * 4);
4224 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
4225 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
4227 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
4232 /* deallocate stack */
4234 if (parentargs_base)
4235 M_AADD_IMM(parentargs_base * 4, REG_SP);
4242 case ICMD_TABLESWITCH: /* ..., index ==> ... */
4243 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4244 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4249 tptr = (void **) iptr->target;
4251 s4ptr = iptr->val.a;
4252 l = s4ptr[1]; /* low */
4253 i = s4ptr[2]; /* high */
4255 var_to_reg_int(s1, src, REG_ITMP1);
4256 M_INTMOVE(s1, REG_ITMP1);
4258 i386_alu_imm_reg(cd, ALU_SUB, l, REG_ITMP1);
4264 i386_alu_imm_reg(cd, ALU_CMP, i - 1, REG_ITMP1);
4265 i386_jcc(cd, I386_CC_A, 0);
4267 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4269 /* build jump table top down and use address of lowest entry */
4274 dseg_addtarget(cd, (basicblock *) tptr[0]);
4278 /* length of dataseg after last dseg_addtarget is used by load */
4280 i386_mov_imm_reg(cd, 0, REG_ITMP2);
4281 dseg_adddata(cd, cd->mcodeptr);
4282 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
4283 i386_jmp_reg(cd, REG_ITMP1);
4288 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
4289 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4290 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4292 s4 i, l, val, *s4ptr;
4295 tptr = (void **) iptr->target;
4297 s4ptr = iptr->val.a;
4298 l = s4ptr[0]; /* default */
4299 i = s4ptr[1]; /* count */
4301 MCODECHECK((i<<2)+8);
4302 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
4308 i386_alu_imm_reg(cd, ALU_CMP, val, s1);
4309 i386_jcc(cd, I386_CC_E, 0);
4310 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4313 i386_jmp_imm(cd, 0);
4315 tptr = (void **) iptr->target;
4316 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4320 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
4321 /* op1 = arg count val.a = builtintable entry */
4322 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4323 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4329 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
4330 /* op1 = arg count, val.a = method pointer */
4332 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
4333 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
4334 case ICMD_INVOKEINTERFACE:
4336 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4337 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
4342 unresolved_method *um = iptr->target;
4343 md = um->methodref->parseddesc.md;
4345 md = lm->parseddesc;
4349 s3 = md->paramcount;
4351 MCODECHECK((s3 << 1) + 64);
4353 /* copy arguments to registers or stack location */
4355 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
4356 if (src->varkind == ARGVAR)
4358 if (IS_INT_LNG_TYPE(src->type)) {
4359 if (!md->params[s3].inmemory) {
4360 log_text("No integer argument registers available!");
4363 if (!IS_2_WORD_TYPE(src->type)) {
4364 if (src->flags & INMEMORY) {
4365 i386_mov_membase_reg(
4366 cd, REG_SP, src->regoff * 4, REG_ITMP1);
4367 i386_mov_reg_membase(
4368 cd, REG_ITMP1, REG_SP,
4369 md->params[s3].regoff * 4);
4371 i386_mov_reg_membase(
4372 cd, src->regoff, REG_SP,
4373 md->params[s3].regoff * 4);
4377 if (src->flags & INMEMORY) {
4379 src->regoff, md->params[s3].regoff);
4381 log_text("copy arguments: longs have to be in memory");
4387 if (!md->params[s3].inmemory) {
4388 log_text("No float argument registers available!");
4391 var_to_reg_flt(d, src, REG_FTMP1);
4392 if (src->type == TYPE_FLT) {
4394 cd, REG_SP, md->params[s3].regoff * 4);
4398 cd, REG_SP, md->params[s3].regoff * 4);
4404 switch (iptr->opc) {
4406 disp = (ptrint) bte->fp;
4407 d = md->returntype.type;
4409 M_MOV_IMM(disp, REG_ITMP1);
4412 /* if op1 == true, we need to check for an exception */
4414 if (iptr->op1 == true) {
4417 codegen_addxexceptionrefs(cd, cd->mcodeptr);
4421 case ICMD_INVOKESPECIAL:
4422 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
4423 gen_nullptr_check(REG_ITMP1);
4425 /* access memory for hardware nullptr */
4426 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1);
4430 case ICMD_INVOKESTATIC:
4432 unresolved_method *um = iptr->target;
4434 codegen_addpatchref(cd, cd->mcodeptr,
4435 PATCHER_invokestatic_special, um, 0);
4437 if (opt_showdisassemble) {
4438 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4442 d = md->returntype.type;
4445 disp = (ptrint) lm->stubroutine;
4446 d = lm->parseddesc->returntype.type;
4449 M_MOV_IMM(disp, REG_ITMP2);
4453 case ICMD_INVOKEVIRTUAL:
4454 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4455 gen_nullptr_check(REG_ITMP1);
4458 unresolved_method *um = iptr->target;
4460 codegen_addpatchref(cd, cd->mcodeptr,
4461 PATCHER_invokevirtual, um, 0);
4463 if (opt_showdisassemble) {
4464 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4468 d = md->returntype.type;
4471 s1 = OFFSET(vftbl_t, table[0]) +
4472 sizeof(methodptr) * lm->vftblindex;
4473 d = md->returntype.type;
4476 M_ALD(REG_ITMP2, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4477 i386_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP1);
4481 case ICMD_INVOKEINTERFACE:
4482 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4483 gen_nullptr_check(REG_ITMP1);
4486 unresolved_method *um = iptr->target;
4488 codegen_addpatchref(cd, cd->mcodeptr,
4489 PATCHER_invokeinterface, um, 0);
4491 if (opt_showdisassemble) {
4492 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4497 d = md->returntype.type;
4500 s1 = OFFSET(vftbl_t, interfacetable[0]) -
4501 sizeof(methodptr) * lm->class->index;
4503 s2 = sizeof(methodptr) * (lm - lm->class->methods);
4505 d = md->returntype.type;
4508 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4509 i386_mov_membase32_reg(cd, REG_ITMP1, s1, REG_ITMP2);
4510 i386_mov_membase32_reg(cd, REG_ITMP2, s2, REG_ITMP1);
4515 /* d contains return type */
4517 if (d != TYPE_VOID) {
4518 d = reg_of_var(rd, iptr->dst, REG_NULL);
4520 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
4521 if (IS_2_WORD_TYPE(iptr->dst->type)) {
4522 if (iptr->dst->flags & INMEMORY) {
4523 i386_mov_reg_membase(
4524 cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4525 i386_mov_reg_membase(
4526 cd, REG_RESULT2, REG_SP,
4527 iptr->dst->regoff * 4 + 4);
4529 log_text("RETURN: longs have to be in memory");
4534 if (iptr->dst->flags & INMEMORY) {
4535 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4538 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
4543 /* fld from called function -- has other fpu_st_offset counter */
4545 store_reg_to_var_flt(iptr->dst, d);
4551 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4552 /* op1: 0 == array, 1 == class */
4553 /* val.a: (classinfo*) superclass */
4555 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4556 /* EAX: YES ECX: I|YES EDX: I|YES OUTPUT: REG_NULL */
4558 /* superclass is an interface:
4560 * OK if ((sub == NULL) ||
4561 * (sub->vftbl->interfacetablelength > super->index) &&
4562 * (sub->vftbl->interfacetable[-super->index] != NULL));
4564 * superclass is a class:
4566 * OK if ((sub == NULL) || (0
4567 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4568 * super->vftbl->diffval));
4571 if (iptr->op1 == 1) {
4572 /* object type cast-check */
4575 vftbl_t *supervftbl;
4578 super = (classinfo *) iptr->val.a;
4585 superindex = super->index;
4586 supervftbl = super->vftbl;
4589 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4590 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4592 var_to_reg_int(s1, src, REG_ITMP1);
4594 /* calculate interface checkcast code size */
4596 s2 = 2; /* mov_membase_reg */
4597 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4599 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ +
4600 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4601 2 /* test */ + 6 /* jcc */);
4604 s2 += (opt_showdisassemble ? 5 : 0);
4606 /* calculate class checkcast code size */
4608 s3 = 2; /* mov_membase_reg */
4609 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4611 s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */;
4614 if (s1 != REG_ITMP1) {
4616 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
4619 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
4626 s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ +
4627 5 /* mov_imm_reg */ + 2 /* mov_membase_reg */);
4628 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
4631 s3 += 2 /* cmp */ + 6 /* jcc */;
4634 s3 += (opt_showdisassemble ? 5 : 0);
4636 /* if class is not resolved, check which code to call */
4639 i386_test_reg_reg(cd, s1, s1);
4640 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4642 codegen_addpatchref(cd, cd->mcodeptr,
4643 PATCHER_checkcast_instanceof_flags,
4644 (constant_classref *) iptr->target, 0);
4646 if (opt_showdisassemble) {
4647 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4650 i386_mov_imm_reg(cd, 0, REG_ITMP2); /* super->flags */
4651 i386_alu_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP2);
4652 i386_jcc(cd, I386_CC_Z, s2 + 5);
4655 /* interface checkcast code */
4657 if (!super || (super->flags & ACC_INTERFACE)) {
4659 i386_test_reg_reg(cd, s1, s1);
4660 i386_jcc(cd, I386_CC_Z, s2);
4663 i386_mov_membase_reg(cd, s1,
4664 OFFSET(java_objectheader, vftbl),
4668 codegen_addpatchref(cd, cd->mcodeptr,
4669 PATCHER_checkcast_instanceof_interface,
4670 (constant_classref *) iptr->target, 0);
4672 if (opt_showdisassemble) {
4673 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4677 i386_mov_membase32_reg(cd, REG_ITMP2,
4678 OFFSET(vftbl_t, interfacetablelength),
4680 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4681 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4682 i386_jcc(cd, I386_CC_LE, 0);
4683 codegen_addxcastrefs(cd, cd->mcodeptr);
4684 i386_mov_membase32_reg(cd, REG_ITMP2,
4685 OFFSET(vftbl_t, interfacetable[0]) -
4686 superindex * sizeof(methodptr*),
4688 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4689 i386_jcc(cd, I386_CC_E, 0);
4690 codegen_addxcastrefs(cd, cd->mcodeptr);
4693 i386_jmp_imm(cd, s3);
4696 /* class checkcast code */
4698 if (!super || !(super->flags & ACC_INTERFACE)) {
4700 i386_test_reg_reg(cd, s1, s1);
4701 i386_jcc(cd, I386_CC_Z, s3);
4704 i386_mov_membase_reg(cd, s1,
4705 OFFSET(java_objectheader, vftbl),
4709 codegen_addpatchref(cd, cd->mcodeptr,
4710 PATCHER_checkcast_class,
4711 (constant_classref *) iptr->target, 0);
4713 if (opt_showdisassemble) {
4714 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4718 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4719 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4720 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4722 i386_mov_membase32_reg(cd, REG_ITMP2,
4723 OFFSET(vftbl_t, baseval),
4726 /* if (s1 != REG_ITMP1) { */
4727 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
4728 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
4729 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
4730 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
4732 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
4735 i386_mov_membase32_reg(cd, REG_ITMP3,
4736 OFFSET(vftbl_t, baseval),
4738 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP3, REG_ITMP2);
4739 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4740 i386_mov_membase_reg(cd, REG_ITMP3,
4741 OFFSET(vftbl_t, diffval),
4743 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4744 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4748 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP2);
4749 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
4750 codegen_addxcastrefs(cd, cd->mcodeptr);
4752 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4755 /* array type cast-check */
4757 var_to_reg_int(s1, src, REG_ITMP1);
4758 M_AST(s1, REG_SP, 0 * 4);
4760 if (iptr->val.a == NULL) {
4761 codegen_addpatchref(cd, cd->mcodeptr,
4762 PATCHER_builtin_arraycheckcast,
4765 if (opt_showdisassemble) {
4766 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4770 M_AST_IMM((ptrint) iptr->val.a, REG_SP, 1 * 4);
4771 M_MOV_IMM((ptrint) BUILTIN_arraycheckcast, REG_ITMP3);
4775 codegen_addxcastrefs(cd, cd->mcodeptr);
4777 var_to_reg_int(s1, src, REG_ITMP1);
4778 d = reg_of_var(rd, iptr->dst, s1);
4781 store_reg_to_var_int(iptr->dst, d);
4784 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
4786 /* op1: 0 == array, 1 == class */
4787 /* val.a: (classinfo*) superclass */
4788 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4789 /* EAX: S|D|YES ECX: YES S|D|EDX: S|D|YES OUTPUT: REG_NULL*/
4790 /* ????? Really necessary to block all ????? */
4792 /* superclass is an interface:
4794 * return (sub != NULL) &&
4795 * (sub->vftbl->interfacetablelength > super->index) &&
4796 * (sub->vftbl->interfacetable[-super->index] != NULL);
4798 * superclass is a class:
4800 * return ((sub != NULL) && (0
4801 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4802 * super->vftbl->diffvall));
4807 vftbl_t *supervftbl;
4810 super = (classinfo *) iptr->val.a;
4817 superindex = super->index;
4818 supervftbl = super->vftbl;
4821 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4822 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4825 var_to_reg_int(s1, src, REG_ITMP1);
4826 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
4828 M_INTMOVE(s1, REG_ITMP1);
4832 /* calculate interface instanceof code size */
4834 s2 = 2; /* mov_membase_reg */
4835 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4837 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
4838 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4839 2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4842 s2 += (opt_showdisassemble ? 5 : 0);
4844 /* calculate class instanceof code size */
4846 s3 = 2; /* mov_membase_reg */
4847 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4848 s3 += 5; /* mov_imm_reg */
4850 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
4852 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
4854 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
4856 s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
4857 2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4860 s3 += (opt_showdisassemble ? 5 : 0);
4862 i386_alu_reg_reg(cd, ALU_XOR, d, d);
4864 /* if class is not resolved, check which code to call */
4867 i386_test_reg_reg(cd, s1, s1);
4868 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4870 codegen_addpatchref(cd, cd->mcodeptr,
4871 PATCHER_checkcast_instanceof_flags,
4872 (constant_classref *) iptr->target, 0);
4874 if (opt_showdisassemble) {
4875 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4878 i386_mov_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
4879 i386_alu_imm32_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
4880 i386_jcc(cd, I386_CC_Z, s2 + 5);
4883 /* interface instanceof code */
4885 if (!super || (super->flags & ACC_INTERFACE)) {
4891 i386_mov_membase_reg(cd, s1,
4892 OFFSET(java_objectheader, vftbl),
4896 codegen_addpatchref(cd, cd->mcodeptr,
4897 PATCHER_checkcast_instanceof_interface,
4898 (constant_classref *) iptr->target, 0);
4900 if (opt_showdisassemble) {
4901 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4905 i386_mov_membase32_reg(cd, REG_ITMP1,
4906 OFFSET(vftbl_t, interfacetablelength),
4908 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4909 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4911 disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
4912 6 /* jcc */ + 5 /* mov_imm_reg */);
4915 i386_mov_membase32_reg(cd, REG_ITMP1,
4916 OFFSET(vftbl_t, interfacetable[0]) -
4917 superindex * sizeof(methodptr*),
4920 /* i386_setcc_reg(cd, I386_CC_A, d); */
4921 /* i386_jcc(cd, I386_CC_BE, 5); */
4929 /* class instanceof code */
4931 if (!super || !(super->flags & ACC_INTERFACE)) {
4937 i386_mov_membase_reg(cd, s1,
4938 OFFSET(java_objectheader, vftbl),
4942 codegen_addpatchref(cd, cd->mcodeptr,
4943 PATCHER_instanceof_class,
4944 (constant_classref *) iptr->target, 0);
4946 if (opt_showdisassemble) {
4947 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4951 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
4952 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4953 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4955 i386_mov_membase_reg(cd, REG_ITMP1,
4956 OFFSET(vftbl_t, baseval),
4958 i386_mov_membase_reg(cd, REG_ITMP2,
4959 OFFSET(vftbl_t, diffval),
4961 i386_mov_membase_reg(cd, REG_ITMP2,
4962 OFFSET(vftbl_t, baseval),
4964 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4965 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4967 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
4968 i386_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
4969 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
4970 i386_jcc(cd, I386_CC_A, 5);
4971 i386_mov_imm_reg(cd, 1, d);
4973 store_reg_to_var_int(iptr->dst, d);
4979 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4980 /* op1 = dimension, val.a = class */
4981 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4982 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
4984 /* check for negative sizes and copy sizes to stack if necessary */
4986 MCODECHECK((iptr->op1 << 1) + 64);
4988 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4989 /* copy SAVEDVAR sizes to stack */
4991 if (src->varkind != ARGVAR) {
4992 if (src->flags & INMEMORY) {
4993 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
4994 M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4);
4997 M_IST(src->regoff, REG_SP, (s1 + 3) * 4);
5002 /* is a patcher function set? */
5004 if (iptr->val.a == NULL) {
5005 codegen_addpatchref(cd, cd->mcodeptr,
5006 PATCHER_builtin_multianewarray,
5007 (constant_classref *) iptr->target, 0);
5009 if (opt_showdisassemble) {
5010 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5016 disp = (ptrint) iptr->val.a;
5019 /* a0 = dimension count */
5021 M_IST_IMM(iptr->op1, REG_SP, 0 * 4);
5023 /* a1 = arraydescriptor */
5025 M_IST_IMM(disp, REG_SP, 1 * 4);
5027 /* a2 = pointer to dimensions = stack pointer */
5029 M_MOV(REG_SP, REG_ITMP1);
5030 M_AADD_IMM(3 * 4, REG_ITMP1);
5031 M_AST(REG_ITMP1, REG_SP, 2 * 4);
5033 M_MOV_IMM((ptrint) BUILTIN_multianewarray, REG_ITMP1);
5036 /* check for exception before result assignment */
5040 codegen_addxexceptionrefs(cd, cd->mcodeptr);
5042 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
5043 M_INTMOVE(REG_RESULT, s1);
5044 store_reg_to_var_int(iptr->dst, s1);
5049 new_internalerror("Unknown ICMD %d", iptr->opc);
5053 } /* for instruction */
5055 /* copy values to interface registers */
5057 src = bptr->outstack;
5058 len = bptr->outdepth;
5060 #if defined(ENABLE_LSRA)
5065 if ((src->varkind != STACKVAR)) {
5067 if (IS_FLT_DBL_TYPE(s2)) {
5068 var_to_reg_flt(s1, src, REG_FTMP1);
5069 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5070 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
5073 log_text("double store");
5075 /* M_DST(s1, REG_SP, 4 * interfaces[len][s2].regoff); */
5079 var_to_reg_int(s1, src, REG_ITMP1);
5080 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
5081 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5082 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
5085 i386_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5089 if (rd->interfaces[len][s2].flags & INMEMORY) {
5090 M_LNGMEMMOVE(s1, rd->interfaces[len][s2].regoff);
5093 log_text("copy interface registers: longs have to be in memory (end)");
5102 /* At the end of a basic block we may have to append some nops,
5103 because the patcher stub calling code might be longer than the
5104 actual instruction. So codepatching does not change the
5105 following block unintentionally. */
5107 if (cd->mcodeptr < cd->lastmcodeptr) {
5108 while (cd->mcodeptr < cd->lastmcodeptr) {
5113 } /* if (bptr -> flags >= BBREACHED) */
5114 } /* for basic block */
5116 dseg_createlinenumbertable(cd);
5123 /* generate ArithmeticException stubs */
5127 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
5128 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5130 cd->mcodeptr - cd->mcodebase);
5134 M_MOV_IMM(0, REG_ITMP2_XPC);
5135 dseg_adddata(cd, cd->mcodeptr);
5136 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5138 if (xcodeptr != NULL) {
5139 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5142 xcodeptr = cd->mcodeptr;
5144 M_ASUB_IMM(4 * 4, REG_SP);
5146 M_AST_IMM(0, REG_SP, 0 * 4);
5147 dseg_adddata(cd, cd->mcodeptr);
5148 M_MOV(REG_SP, REG_ITMP3);
5149 M_AADD_IMM(4 * 4, REG_ITMP3);
5150 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5151 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5152 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5153 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5155 M_MOV_IMM((ptrint) stacktrace_inline_arithmeticexception,
5159 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5160 M_AADD_IMM(4 * 4, REG_SP);
5162 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5167 /* generate ArrayIndexOutOfBoundsException stubs */
5171 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
5172 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5174 cd->mcodeptr - cd->mcodebase);
5178 /* move index register into REG_ITMP1 */
5180 M_INTMOVE(bref->reg, REG_ITMP1);
5182 M_MOV_IMM(0, REG_ITMP2_XPC);
5183 dseg_adddata(cd, cd->mcodeptr);
5184 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5186 if (xcodeptr != NULL) {
5187 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5190 xcodeptr = cd->mcodeptr;
5192 M_ASUB_IMM(5 * 4, REG_SP);
5194 M_AST_IMM(0, REG_SP, 0 * 4);
5195 dseg_adddata(cd, cd->mcodeptr);
5196 M_MOV(REG_SP, REG_ITMP3);
5197 M_AADD_IMM(5 * 4, REG_ITMP3);
5198 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5199 M_ALD(REG_ITMP3, REG_SP, (5 + parentargs_base) * 4);
5200 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5201 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5202 M_AST(REG_ITMP1, REG_SP, 4 * 4); /* don't use REG_ITMP1 till here */
5204 M_MOV_IMM((ptrint) stacktrace_inline_arrayindexoutofboundsexception,
5208 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5209 M_AADD_IMM(5 * 4, REG_SP);
5211 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5216 /* generate ArrayStoreException stubs */
5220 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
5221 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5223 cd->mcodeptr - cd->mcodebase);
5227 M_MOV_IMM(0, REG_ITMP2_XPC);
5228 dseg_adddata(cd, cd->mcodeptr);
5229 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5231 if (xcodeptr != NULL) {
5232 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5235 xcodeptr = cd->mcodeptr;
5237 M_ASUB_IMM(4 * 4, REG_SP);
5239 M_AST_IMM(0, REG_SP, 0 * 4);
5240 dseg_adddata(cd, cd->mcodeptr);
5241 M_MOV(REG_SP, REG_ITMP3);
5242 M_AADD_IMM(4 * 4, REG_ITMP3);
5243 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5244 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5245 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5246 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5248 M_MOV_IMM((ptrint) stacktrace_inline_arraystoreexception,
5252 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5253 M_AADD_IMM(4 * 4, REG_SP);
5255 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5260 /* generate ClassCastException stubs */
5264 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
5265 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5267 cd->mcodeptr - cd->mcodebase);
5271 M_MOV_IMM(0, REG_ITMP2_XPC);
5272 dseg_adddata(cd, cd->mcodeptr);
5273 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5275 if (xcodeptr != NULL) {
5276 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5279 xcodeptr = cd->mcodeptr;
5281 M_ASUB_IMM(4 * 4, REG_SP);
5283 M_AST_IMM(0, REG_SP, 0 * 4);
5284 dseg_adddata(cd, cd->mcodeptr);
5285 M_MOV(REG_SP, REG_ITMP3);
5286 M_AADD_IMM(4 * 4, REG_ITMP3);
5287 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5288 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5289 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5290 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5292 M_MOV_IMM((ptrint) stacktrace_inline_classcastexception, REG_ITMP3);
5295 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5296 M_AADD_IMM(4 * 4, REG_SP);
5298 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5303 /* generate NullPointerException stubs */
5307 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
5308 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5310 cd->mcodeptr - cd->mcodebase);
5314 M_MOV_IMM(0, REG_ITMP2_XPC);
5315 dseg_adddata(cd, cd->mcodeptr);
5316 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5318 if (xcodeptr != NULL) {
5319 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5322 xcodeptr = cd->mcodeptr;
5324 M_ASUB_IMM(4 * 4, REG_SP);
5326 M_AST_IMM(0, REG_SP, 0 * 4);
5327 dseg_adddata(cd, cd->mcodeptr);
5328 M_MOV(REG_SP, REG_ITMP3);
5329 M_AADD_IMM(4 * 4, REG_ITMP3);
5330 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5331 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5332 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5333 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5335 M_MOV_IMM((ptrint) stacktrace_inline_nullpointerexception,
5339 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5340 M_AADD_IMM(4 * 4, REG_SP);
5342 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5347 /* generate exception check stubs */
5351 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
5352 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5354 cd->mcodeptr - cd->mcodebase);
5358 M_MOV_IMM(0, REG_ITMP2_XPC);
5359 dseg_adddata(cd, cd->mcodeptr);
5360 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5362 if (xcodeptr != NULL) {
5363 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5366 xcodeptr = cd->mcodeptr;
5368 M_ASUB_IMM(4 * 4, REG_SP);
5370 M_AST_IMM(0, REG_SP, 0 * 4);
5371 dseg_adddata(cd, cd->mcodeptr);
5372 M_MOV(REG_SP, REG_ITMP3);
5373 M_AADD_IMM(4 * 4, REG_ITMP3);
5374 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5375 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5376 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5377 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5379 M_MOV_IMM((ptrint) stacktrace_inline_fillInStackTrace, REG_ITMP3);
5382 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5383 M_AADD_IMM(4 * 4, REG_SP);
5385 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5390 /* generate code patching stub call code */
5397 tmpcd = DNEW(codegendata);
5399 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5400 /* check code segment size */
5404 /* Get machine code which is patched back in later. A */
5405 /* `call rel32' is 5 bytes long. */
5407 xcodeptr = cd->mcodebase + pref->branchpos;
5408 mcode = *((u8 *) xcodeptr);
5410 /* patch in `call rel32' to call the following code */
5412 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5413 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5415 /* move pointer to java_objectheader onto stack */
5417 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5418 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
5419 off = dseg_addaddress(cd, NULL); /* vftbl */
5421 M_MOV_IMM(0, REG_ITMP3);
5422 dseg_adddata(cd, cd->mcodeptr);
5423 M_AADD_IMM(off, REG_ITMP3);
5429 /* move machine code bytes and classinfo pointer into registers */
5431 M_PUSH_IMM((ptrint) (mcode >> 32));
5432 M_PUSH_IMM((ptrint) mcode);
5433 M_PUSH_IMM((ptrint) pref->ref);
5434 M_PUSH_IMM((ptrint) pref->patcher);
5436 M_MOV_IMM((ptrint) asm_wrapper_patcher, REG_ITMP3);
5442 codegen_finish(m, cd, (ptrint) (cd->mcodeptr - cd->mcodebase));
5444 /* everything's ok */
5450 /* createcompilerstub **********************************************************
5452 Creates a stub routine which calls the compiler.
5454 *******************************************************************************/
5456 #define COMPILERSTUB_SIZE 12
5458 u1 *createcompilerstub(methodinfo *m)
5460 u1 *s; /* memory to hold the stub */
5464 s = CNEW(u1, COMPILERSTUB_SIZE);
5466 /* mark start of dump memory area */
5468 dumpsize = dump_size();
5470 cd = DNEW(codegendata);
5473 i386_mov_imm_reg(cd, (ptrint) m, REG_ITMP1);
5475 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
5476 i386_mov_imm_reg(cd, (ptrint) asm_call_jit_compiler, REG_ITMP3);
5477 i386_jmp_reg(cd, REG_ITMP3);
5479 #if defined(ENABLE_STATISTICS)
5481 count_cstub_len += COMPILERSTUB_SIZE;
5484 /* release dump area */
5486 dump_release(dumpsize);
5492 /* createnativestub ************************************************************
5494 Creates a stub routine which calls a native method.
5496 *******************************************************************************/
5498 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5499 /* this way we can call the function directly with a memory call */
5501 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
5504 u1 *createnativestub(functionptr f, methodinfo *m, codegendata *cd,
5505 registerdata *rd, methoddesc *nmd)
5510 s4 i, j; /* count variables */
5514 /* set some variables */
5517 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
5519 /* calculate stackframe size */
5522 sizeof(stackframeinfo) / SIZEOF_VOID_P +
5523 sizeof(localref_table) / SIZEOF_VOID_P +
5524 1 + /* function pointer */
5525 4 * 4 + /* 4 arguments (start_native_call) */
5528 /* create method header */
5530 (void) dseg_addaddress(cd, m); /* MethodPointer */
5531 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
5532 (void) dseg_adds4(cd, 0); /* IsSync */
5533 (void) dseg_adds4(cd, 0); /* IsLeaf */
5534 (void) dseg_adds4(cd, 0); /* IntSave */
5535 (void) dseg_adds4(cd, 0); /* FltSave */
5536 (void) dseg_addlinenumbertablesize(cd);
5537 (void) dseg_adds4(cd, 0); /* ExTableSize */
5539 /* initialize mcode variables */
5541 cd->mcodeptr = (u1 *) cd->mcodebase;
5542 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
5544 /* generate profiling code */
5547 M_MOV_IMM((ptrint) m, REG_ITMP1);
5548 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(methodinfo, executioncount));
5551 /* calculate stackframe size for native function */
5553 M_ASUB_IMM(stackframesize * 4, REG_SP);
5558 disp = stackframesize * 4;
5560 M_ASUB_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5562 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
5563 t = md->paramtypes[p].type;
5564 if (IS_INT_LNG_TYPE(t)) {
5565 if (IS_2_WORD_TYPE(t)) {
5566 M_ILD(REG_ITMP1, REG_SP,
5567 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5568 M_ILD(REG_ITMP2, REG_SP,
5569 4 + TRACE_ARGS_NUM * 8 + 4 + disp + 4);
5570 M_IST(REG_ITMP1, REG_SP, p * 8);
5571 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5573 } else if (t == TYPE_ADR) {
5574 M_ALD(REG_ITMP1, REG_SP,
5575 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5577 M_AST(REG_ITMP1, REG_SP, p * 8);
5578 M_AST(REG_ITMP2, REG_SP, p * 8 + 4);
5581 M_ILD(EAX, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5583 M_IST(EAX, REG_SP, p * 8);
5584 M_IST(EDX, REG_SP, p * 8 + 4);
5588 if (!IS_2_WORD_TYPE(t)) {
5589 i386_flds_membase(cd, REG_SP,
5590 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5591 i386_fstps_membase(cd, REG_SP, p * 8);
5592 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
5593 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5596 i386_fldl_membase(cd, REG_SP,
5597 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5598 i386_fstpl_membase(cd, REG_SP, p * 8);
5601 disp += (IS_2_WORD_TYPE(t)) ? 8 : 4;
5605 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
5606 M_IST(REG_ITMP1, REG_SP, p * 8);
5607 M_IST(REG_ITMP1, REG_SP, p * 8 + 4);
5610 M_AST_IMM((ptrint) m, REG_SP, TRACE_ARGS_NUM * 8);
5612 M_MOV_IMM((ptrint) builtin_trace_args, REG_ITMP1);
5615 M_AADD_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5618 /* get function address (this must happen before the stackframeinfo) */
5620 #if !defined(ENABLE_STATICVM)
5622 codegen_addpatchref(cd, cd->mcodeptr, PATCHER_resolve_native, m, 0);
5624 if (opt_showdisassemble) {
5625 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5630 M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
5632 /* Mark the whole fpu stack as free for native functions (only for saved */
5633 /* register count == 0). */
5635 i386_ffree_reg(cd, 0);
5636 i386_ffree_reg(cd, 1);
5637 i386_ffree_reg(cd, 2);
5638 i386_ffree_reg(cd, 3);
5639 i386_ffree_reg(cd, 4);
5640 i386_ffree_reg(cd, 5);
5641 i386_ffree_reg(cd, 6);
5642 i386_ffree_reg(cd, 7);
5644 /* prepare data structures for native function call */
5646 M_MOV(REG_SP, REG_ITMP1);
5647 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5649 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5650 M_IST_IMM(0, REG_SP, 1 * 4);
5651 dseg_adddata(cd, cd->mcodeptr);
5653 M_MOV(REG_SP, REG_ITMP2);
5654 M_AADD_IMM(stackframesize * 4 + SIZEOF_VOID_P, REG_ITMP2);
5656 M_AST(REG_ITMP2, REG_SP, 2 * 4);
5657 M_ALD(REG_ITMP3, REG_SP, stackframesize * 4);
5658 M_AST(REG_ITMP3, REG_SP, 3 * 4);
5659 M_MOV_IMM((ptrint) codegen_start_native_call, REG_ITMP1);
5662 M_ALD(REG_ITMP3, REG_SP, 4 * 4);
5664 /* copy arguments into new stackframe */
5666 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
5667 t = md->paramtypes[i].type;
5669 if (!md->params[i].inmemory) {
5670 /* no integer argument registers */
5671 } else { /* float/double in memory can be copied like int/longs */
5672 s1 = (md->params[i].regoff + stackframesize + 1) * 4;
5673 s2 = nmd->params[j].regoff * 4;
5675 M_ILD(REG_ITMP1, REG_SP, s1);
5676 M_IST(REG_ITMP1, REG_SP, s2);
5677 if (IS_2_WORD_TYPE(t)) {
5678 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
5679 M_IST(REG_ITMP1, REG_SP, s2 + 4);
5684 /* if function is static, put class into second argument */
5686 if (m->flags & ACC_STATIC)
5687 M_AST_IMM((ptrint) m->class, REG_SP, 1 * 4);
5689 /* put env into first argument */
5691 M_AST_IMM((ptrint) &env, REG_SP, 0 * 4);
5693 /* call the native function */
5697 /* save return value */
5699 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5700 if (IS_2_WORD_TYPE(md->returntype.type))
5701 M_IST(REG_RESULT2, REG_SP, 2 * 4);
5702 M_IST(REG_RESULT, REG_SP, 1 * 4);
5705 if (IS_2_WORD_TYPE(md->returntype.type))
5706 i386_fstl_membase(cd, REG_SP, 1 * 4);
5708 i386_fsts_membase(cd, REG_SP, 1 * 4);
5711 /* remove data structures for native function call */
5713 M_MOV(REG_SP, REG_ITMP1);
5714 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5716 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5717 M_MOV_IMM((ptrint) codegen_finish_native_call, REG_ITMP1);
5721 /* restore return value */
5723 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5724 if (IS_2_WORD_TYPE(md->returntype.type))
5725 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5726 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5729 if (IS_2_WORD_TYPE(md->returntype.type))
5730 i386_fldl_membase(cd, REG_SP, 1 * 4);
5732 i386_flds_membase(cd, REG_SP, 1 * 4);
5735 M_ASUB_IMM(4 + 8 + 8 + 4, REG_SP);
5737 M_AST_IMM((ptrint) m, REG_SP, 0);
5739 M_IST(REG_RESULT, REG_SP, 4);
5740 M_IST(REG_RESULT2, REG_SP, 4 + 4);
5742 i386_fstl_membase(cd, REG_SP, 4 + 8);
5743 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5745 M_MOV_IMM((ptrint) builtin_displaymethodstop, REG_ITMP1);
5748 M_AADD_IMM(4 + 8 + 8 + 4, REG_SP);
5751 /* check for exception */
5753 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5754 /* i386_call_mem(cd, (ptrint) builtin_get_exceptionptrptr); */
5755 i386_call_mem(cd, (ptrint) &callgetexceptionptrptr);
5757 M_MOV_IMM((ptrint) &_exceptionptr, REG_RESULT);
5759 /* we can't use REG_ITMP3 == REG_RESULT2 */
5760 M_ALD(REG_ITMP2, REG_RESULT, 0);
5762 /* restore return value */
5764 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5765 if (IS_2_WORD_TYPE(md->returntype.type))
5766 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5767 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5770 if (IS_2_WORD_TYPE(md->returntype.type))
5771 i386_fldl_membase(cd, REG_SP, 1 * 4);
5773 i386_flds_membase(cd, REG_SP, 1 * 4);
5776 M_AADD_IMM(stackframesize * 4, REG_SP);
5783 /* handle exception */
5785 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5786 i386_push_reg(cd, REG_ITMP2);
5787 /* i386_call_mem(cd, (ptrint) builtin_get_exceptionptrptr); */
5788 i386_call_mem(cd, (ptrint) &callgetexceptionptrptr);
5789 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5790 i386_pop_reg(cd, REG_ITMP1_XPTR);
5792 M_MOV(REG_ITMP2, REG_ITMP1_XPTR);
5793 M_MOV_IMM((ptrint) &_exceptionptr, REG_ITMP2);
5794 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5796 M_ALD(REG_ITMP2_XPC, REG_SP, 0);
5797 M_ASUB_IMM(2, REG_ITMP2_XPC);
5799 M_MOV_IMM((ptrint) asm_handle_nat_exception, REG_ITMP3);
5803 /* process patcher calls **************************************************/
5811 tmpcd = DNEW(codegendata);
5813 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5814 /* Get machine code which is patched back in later. A */
5815 /* `call rel32' is 5 bytes long. */
5817 xcodeptr = cd->mcodebase + pref->branchpos;
5818 mcode = *((u8 *) xcodeptr);
5820 /* patch in `call rel32' to call the following code */
5822 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5823 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5825 /* move pointer to java_objectheader onto stack */
5827 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5828 /* create a virtual java_objectheader */
5830 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
5831 disp = dseg_addaddress(cd, NULL); /* vftbl */
5833 M_MOV_IMM(0, REG_ITMP3);
5834 dseg_adddata(cd, cd->mcodeptr);
5835 M_AADD_IMM(disp, REG_ITMP3);
5841 /* move machine code bytes and classinfo pointer onto stack */
5843 M_PUSH_IMM((ptrint) (mcode >> 32));
5844 M_PUSH_IMM((ptrint) mcode);
5845 M_PUSH_IMM((ptrint) pref->ref);
5846 M_PUSH_IMM((ptrint) pref->patcher);
5848 M_MOV_IMM((ptrint) asm_wrapper_patcher, REG_ITMP3);
5853 codegen_finish(m, cd, (s4) ((u1 *) cd->mcodeptr - cd->mcodebase));
5855 return m->entrypoint;
5860 * These are local overrides for various environment variables in Emacs.
5861 * Please do not remove this and leave it at the end of the file, where
5862 * Emacs will automagically detect them.
5863 * ---------------------------------------------------------------------
5866 * indent-tabs-mode: t