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 4357 2006-01-22 23:33:38Z 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;
93 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
94 builtintable_entry *bte;
101 s4 savedregs_num = 0;
104 /* space to save used callee saved registers */
106 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
108 /* float register are saved on 2 4-byte stackslots */
109 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
111 parentargs_base = rd->memuse + savedregs_num;
114 #if defined(USE_THREADS)
115 /* space to save argument of monitor_enter */
117 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
118 /* reserve 2 slots for long/double return values for monitorexit */
120 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
121 parentargs_base += 2;
127 /* create method header */
129 (void) dseg_addaddress(cd, m); /* MethodPointer */
130 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
132 #if defined(USE_THREADS)
133 /* IsSync contains the offset relative to the stack pointer for the
134 argument of monitor_exit used in the exception handler. Since the
135 offset could be zero and give a wrong meaning of the flag it is
139 if (checksync && (m->flags & ACC_SYNCHRONIZED))
140 (void) dseg_adds4(cd, (rd->memuse + 1) * 4); /* IsSync */
143 (void) dseg_adds4(cd, 0); /* IsSync */
145 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
146 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
147 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
149 /* adds a reference for the length of the line number counter. We don't
150 know the size yet, since we evaluate the information during code
151 generation, to save one additional iteration over the whole
152 instructions. During code optimization the position could have changed
153 to the information gotten from the class file */
154 (void) dseg_addlinenumbertablesize(cd);
156 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
158 /* create exception table */
160 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
161 dseg_addtarget(cd, ex->start);
162 dseg_addtarget(cd, ex->end);
163 dseg_addtarget(cd, ex->handler);
164 (void) dseg_addaddress(cd, ex->catchtype.cls);
168 /* initialize mcode variables */
170 cd->mcodeptr = cd->mcodebase;
171 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
172 MCODECHECK(128 + m->paramcount);
174 /* initialize the last patcher pointer */
176 cd->lastmcodeptr = cd->mcodeptr;
178 /* create stack frame (if necessary) */
181 M_ASUB_IMM(parentargs_base * 4, REG_SP);
183 /* save return address and used callee saved registers */
186 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
187 p--; M_AST(rd->savintregs[i], REG_SP, p * 4);
189 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
190 p-=2; i386_fld_reg(cd, rd->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 4);
193 /* take arguments out of register or stack frame */
198 for (p = 0, l = 0; p < md->paramcount; p++) {
199 t = md->paramtypes[p].type;
200 var = &(rd->locals[l][t]);
202 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
206 s1 = md->params[p].regoff;
207 if (IS_INT_LNG_TYPE(t)) { /* integer args */
208 if (!md->params[p].inmemory) { /* register arguments */
209 log_text("integer register argument");
211 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
212 /* rd->argintregs[md->params[p].regoff -> var->regoff */
213 } else { /* reg arg -> spilled */
214 /* rd->argintregs[md->params[p].regoff -> var->regoff * 4 */
216 } else { /* stack arguments */
217 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
218 i386_mov_membase_reg( /* + 4 for return address */
219 cd, REG_SP, (parentargs_base + s1) * 4 + 4, var->regoff);
220 /* + 4 for return address */
221 } else { /* stack arg -> spilled */
222 if (!IS_2_WORD_TYPE(t)) {
224 i386_mov_membase_reg( /* + 4 for return address */
225 cd, REG_SP, (parentargs_base + s1) * 4 + 4,
227 i386_mov_reg_membase(
228 cd, REG_ITMP1, REG_SP, var->regoff * 4);
230 /* reuse Stackslotand avoid copying */
231 var->regoff = parentargs_base + s1 + 1;
236 i386_mov_membase_reg( /* + 4 for return address */
237 cd, REG_SP, (parentargs_base + s1) * 4 + 4,
239 i386_mov_reg_membase(
240 cd, REG_ITMP1, REG_SP, var->regoff * 4);
241 i386_mov_membase_reg( /* + 4 for return address */
242 cd, REG_SP, (parentargs_base + s1) * 4 + 4 + 4,
244 i386_mov_reg_membase(
245 cd, REG_ITMP1, REG_SP, var->regoff * 4 + 4);
247 /* reuse Stackslotand avoid copying */
248 var->regoff = parentargs_base + s1 + 1;
254 } else { /* floating args */
255 if (!md->params[p].inmemory) { /* register arguments */
256 log_text("There are no float argument registers!");
258 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
259 /* rd->argfltregs[md->params[p].regoff -> var->regoff */
260 } else { /* reg arg -> spilled */
261 /* rd->argfltregs[md->params[p].regoff -> var->regoff * 4 */
264 } else { /* stack arguments */
265 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
268 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
270 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
275 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
277 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
281 } else { /* stack-arg -> spilled */
283 i386_mov_membase_reg(
284 cd, REG_SP, (parentargs_base + s1) * 4 + 4, REG_ITMP1);
285 i386_mov_reg_membase(
286 cd, REG_ITMP1, REG_SP, var->regoff * 4);
289 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
290 i386_fstps_membase(cd, REG_SP, var->regoff * 4);
293 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
294 i386_fstpl_membase(cd, REG_SP, var->regoff * 4);
297 /* reuse Stackslotand avoid copying */
298 var->regoff = parentargs_base + s1 + 1;
305 /* call monitorenter function */
307 #if defined(USE_THREADS)
308 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
311 if (m->flags & ACC_STATIC) {
312 i386_mov_imm_reg(cd, (ptrint) m->class, REG_ITMP1);
313 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s1 * 4);
314 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
315 i386_mov_imm_reg(cd, (ptrint) BUILTIN_staticmonitorenter, REG_ITMP1);
316 i386_call_reg(cd, REG_ITMP1);
319 i386_mov_membase_reg(cd, REG_SP, parentargs_base * 4 + 4, REG_ITMP1);
320 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
321 i386_jcc(cd, I386_CC_Z, 0);
322 codegen_addxnullrefs(cd, cd->mcodeptr);
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_monitorenter, REG_ITMP1);
326 i386_call_reg(cd, REG_ITMP1);
331 /* copy argument registers to stack and call trace function with pointer
332 to arguments on stack.
337 s1 = INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4 + 4 + parentargs_base * 4;
339 M_ISUB_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
341 /* save temporary registers for leaf methods */
343 for (p = 0; p < INT_TMP_CNT; p++)
344 M_IST(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
346 for (p = 0, l = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
347 t = md->paramtypes[p].type;
349 if (IS_INT_LNG_TYPE(t)) {
350 if (IS_2_WORD_TYPE(t)) {
351 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
352 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
353 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off + 4, REG_ITMP1);
354 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
356 } else if (t == TYPE_ADR) {
358 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
359 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
360 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
361 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
364 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, EAX);
366 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
367 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
371 if (!IS_2_WORD_TYPE(t)) {
372 i386_flds_membase(cd, REG_SP, s1 + stack_off);
373 i386_fstps_membase(cd, REG_SP, p * 8);
374 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
375 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
378 i386_fldl_membase(cd, REG_SP, s1 + stack_off);
379 i386_fstpl_membase(cd, REG_SP, p * 8);
382 stack_off += (IS_2_WORD_TYPE(t)) ? 8 : 4;
385 /* fill up the remaining arguments */
386 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
387 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
388 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
389 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
392 i386_mov_imm_membase(cd, (ptrint) m, REG_SP, TRACE_ARGS_NUM * 8);
393 i386_mov_imm_reg(cd, (ptrint) builtin_trace_args, REG_ITMP1);
394 i386_call_reg(cd, REG_ITMP1);
396 /* restore temporary registers for leaf methods */
398 for (p = 0; p < INT_TMP_CNT; p++)
399 M_ILD(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
401 M_IADD_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
406 /* end of header generation */
408 /* walk through all basic blocks */
409 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
411 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
413 if (bptr->flags >= BBREACHED) {
415 /* branch resolving */
418 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
419 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
424 /* copy interface registers to their destination */
430 #if defined(ENABLE_LSRA)
432 while (src != NULL) {
434 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
435 if (!IS_2_WORD_TYPE(src->type)) {
436 if (bptr->type == BBTYPE_SBR) {
437 /* d = reg_of_var(m, src, REG_ITMP1); */
438 if (!(src->flags & INMEMORY))
444 store_reg_to_var_int(src, d);
446 } else if (bptr->type == BBTYPE_EXH) {
447 /* d = reg_of_var(m, src, REG_ITMP1); */
448 if (!(src->flags & INMEMORY))
452 M_INTMOVE(REG_ITMP1, d);
453 store_reg_to_var_int(src, d);
457 log_text("copy interface registers(EXH, SBR): longs have to be in memory (begin 1)");
466 while (src != NULL) {
468 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
469 if (!IS_2_WORD_TYPE(src->type)) {
470 if (bptr->type == BBTYPE_SBR) {
471 d = reg_of_var(rd, src, REG_ITMP1);
473 store_reg_to_var_int(src, d);
474 } else if (bptr->type == BBTYPE_EXH) {
475 d = reg_of_var(rd, src, REG_ITMP1);
476 M_INTMOVE(REG_ITMP1, d);
477 store_reg_to_var_int(src, d);
481 log_text("copy interface registers: longs have to be in memory (begin 1)");
486 d = reg_of_var(rd, src, REG_ITMP1);
487 if ((src->varkind != STACKVAR)) {
489 if (IS_FLT_DBL_TYPE(s2)) {
490 s1 = rd->interfaces[len][s2].regoff;
491 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
495 if (s2 == TYPE_FLT) {
496 i386_flds_membase(cd, REG_SP, s1 * 4);
499 i386_fldl_membase(cd, REG_SP, s1 * 4);
502 store_reg_to_var_flt(src, d);
505 s1 = rd->interfaces[len][s2].regoff;
506 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
507 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
511 i386_mov_membase_reg(cd, REG_SP, s1 * 4, d);
513 store_reg_to_var_int(src, d);
516 if (rd->interfaces[len][s2].flags & INMEMORY) {
517 M_LNGMEMMOVE(s1, src->regoff);
520 log_text("copy interface registers: longs have to be in memory (begin 2)");
529 #if defined(ENABLE_LSRA)
533 /* walk through all instructions */
538 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
539 if (iptr->line != currentline) {
540 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
541 currentline = iptr->line;
544 MCODECHECK(100); /* XXX are 100 bytes enough? */
547 case ICMD_INLINE_START:
548 case ICMD_INLINE_END:
549 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
550 /* EAX: NO ECX: NO EDX: NO */
553 case ICMD_NOP: /* ... ==> ... */
554 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
555 /* EAX: NO ECX: NO EDX: NO */
558 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
559 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
560 /* EAX: NO ECX: NO EDX: NO */
561 if (src->flags & INMEMORY) {
562 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
565 i386_test_reg_reg(cd, src->regoff, src->regoff);
567 i386_jcc(cd, I386_CC_Z, 0);
568 codegen_addxnullrefs(cd, cd->mcodeptr);
571 /* constant operations ************************************************/
573 case ICMD_ICONST: /* ... ==> ..., constant */
574 /* op1 = 0, val.i = constant */
576 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
577 /* EAX: NO ECX: NO EDX: NO */
579 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
580 if (iptr->dst->flags & INMEMORY) {
581 M_IST_IMM(iptr->val.i, REG_SP, iptr->dst->regoff * 4);
584 if (iptr->val.i == 0) {
588 M_MOV_IMM(iptr->val.i, d);
593 case ICMD_LCONST: /* ... ==> ..., constant */
594 /* op1 = 0, val.l = constant */
596 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
597 /* EAX: NO ECX: NO EDX: NO */
599 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
600 if (iptr->dst->flags & INMEMORY) {
601 M_IST_IMM(iptr->val.l, REG_SP, iptr->dst->regoff * 4);
602 M_IST_IMM(iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
605 log_text("LCONST: longs have to be in memory");
610 case ICMD_FCONST: /* ... ==> ..., constant */
611 /* op1 = 0, val.f = constant */
613 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
614 /* EAX: YES ECX: NO EDX: NO */
616 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
617 if (iptr->val.f == 0.0) {
622 if (iptr->val.i == 0x80000000) {
626 } else if (iptr->val.f == 1.0) {
630 } else if (iptr->val.f == 2.0) {
637 a = dseg_addfloat(cd, iptr->val.f);
638 i386_mov_imm_reg(cd, 0, REG_ITMP1);
639 dseg_adddata(cd, cd->mcodeptr);
640 i386_flds_membase(cd, REG_ITMP1, a);
643 store_reg_to_var_flt(iptr->dst, d);
646 case ICMD_DCONST: /* ... ==> ..., constant */
647 /* op1 = 0, val.d = constant */
649 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
650 /* EAX: YES ECX: NO EDX: NO */
652 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
653 if (iptr->val.d == 0.0) {
658 if (iptr->val.l == 0x8000000000000000LL) {
662 } else if (iptr->val.d == 1.0) {
666 } else if (iptr->val.d == 2.0) {
673 a = dseg_adddouble(cd, iptr->val.d);
674 i386_mov_imm_reg(cd, 0, REG_ITMP1);
675 dseg_adddata(cd, cd->mcodeptr);
676 i386_fldl_membase(cd, REG_ITMP1, a);
679 store_reg_to_var_flt(iptr->dst, d);
682 case ICMD_ACONST: /* ... ==> ..., constant */
683 /* op1 = 0, val.a = constant */
685 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
686 /* EAX: YES ECX: NO EDX: NO */
688 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
690 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
691 codegen_addpatchref(cd, cd->mcodeptr,
693 (unresolved_class *) iptr->target, 0);
695 if (opt_showdisassemble) {
696 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
699 M_MOV_IMM((ptrint) iptr->val.a, d);
700 store_reg_to_var_int(iptr->dst, d);
703 if (iptr->dst->flags & INMEMORY) {
704 M_AST_IMM((ptrint) iptr->val.a, REG_SP, iptr->dst->regoff * 4);
707 if ((ptrint) iptr->val.a == 0) {
710 M_MOV_IMM((ptrint) iptr->val.a, d);
717 /* load/store operations **********************************************/
719 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
720 case ICMD_ALOAD: /* op1 = local variable */
721 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
722 /* EAX: YES ECX: NO EDX: NO */
724 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
725 if ((iptr->dst->varkind == LOCALVAR) &&
726 (iptr->dst->varnum == iptr->op1)) {
729 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
730 if (iptr->dst->flags & INMEMORY) {
731 if (var->flags & INMEMORY) {
732 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP1);
733 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
736 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 4);
740 if (var->flags & INMEMORY) {
741 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, iptr->dst->regoff);
744 M_INTMOVE(var->regoff, iptr->dst->regoff);
749 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
750 /* op1 = local variable */
751 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
752 /* EAX: NO ECX: NO EDX: NO */
754 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
755 if ((iptr->dst->varkind == LOCALVAR) &&
756 (iptr->dst->varnum == iptr->op1)) {
759 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
760 if (iptr->dst->flags & INMEMORY) {
761 if (var->flags & INMEMORY) {
762 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
765 log_text("LLOAD: longs have to be in memory");
770 log_text("LLOAD: longs have to be in memory");
775 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
776 /* op1 = local variable */
777 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
778 /* EAX: NO ECX: NO EDX: NO */
780 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
781 if ((iptr->dst->varkind == LOCALVAR) &&
782 (iptr->dst->varnum == iptr->op1)) {
785 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
786 if (var->flags & INMEMORY) {
787 i386_flds_membase(cd, REG_SP, var->regoff * 4);
790 i386_fld_reg(cd, var->regoff + fpu_st_offset);
793 store_reg_to_var_flt(iptr->dst, d);
796 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
797 /* op1 = local variable */
798 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
799 /* EAX: NO ECX: NO EDX: NO */
801 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
802 if ((iptr->dst->varkind == LOCALVAR) &&
803 (iptr->dst->varnum == iptr->op1)) {
806 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
807 if (var->flags & INMEMORY) {
808 i386_fldl_membase(cd, REG_SP, var->regoff * 4);
811 i386_fld_reg(cd, var->regoff + fpu_st_offset);
814 store_reg_to_var_flt(iptr->dst, d);
817 case ICMD_ISTORE: /* ..., value ==> ... */
818 case ICMD_ASTORE: /* op1 = local variable */
819 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
820 /* EAX: YES ECX: NO EDX: NO */
822 if ((src->varkind == LOCALVAR) &&
823 (src->varnum == iptr->op1)) {
826 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
827 if (var->flags & INMEMORY) {
828 if (src->flags & INMEMORY) {
829 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
830 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 4);
833 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 4);
837 var_to_reg_int(s1, src, var->regoff);
838 M_INTMOVE(s1, var->regoff);
842 case ICMD_LSTORE: /* ..., value ==> ... */
843 /* op1 = local variable */
844 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
845 /* EAX: NO ECX: NO EDX: NO */
847 if ((src->varkind == LOCALVAR) &&
848 (src->varnum == iptr->op1)) {
851 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
852 if (var->flags & INMEMORY) {
853 if (src->flags & INMEMORY) {
854 M_LNGMEMMOVE(src->regoff, var->regoff);
857 log_text("LSTORE: longs have to be in memory");
862 log_text("LSTORE: longs have to be in memory");
867 case ICMD_FSTORE: /* ..., value ==> ... */
868 /* op1 = local variable */
869 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
870 /* EAX: NO ECX: NO EDX: NO */
872 if ((src->varkind == LOCALVAR) &&
873 (src->varnum == iptr->op1)) {
876 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
877 if (var->flags & INMEMORY) {
878 var_to_reg_flt(s1, src, REG_FTMP1);
879 i386_fstps_membase(cd, REG_SP, var->regoff * 4);
882 var_to_reg_flt(s1, src, var->regoff);
883 /* M_FLTMOVE(s1, var->regoff); */
884 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
889 case ICMD_DSTORE: /* ..., value ==> ... */
890 /* op1 = local variable */
891 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
892 /* EAX: NO ECX: NO EDX: NO */
894 if ((src->varkind == LOCALVAR) &&
895 (src->varnum == iptr->op1)) {
898 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
899 if (var->flags & INMEMORY) {
900 var_to_reg_flt(s1, src, REG_FTMP1);
901 i386_fstpl_membase(cd, REG_SP, var->regoff * 4);
904 var_to_reg_flt(s1, src, var->regoff);
905 /* M_FLTMOVE(s1, var->regoff); */
906 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
912 /* pop/dup/swap operations ********************************************/
914 /* attention: double and longs are only one entry in CACAO ICMDs */
916 case ICMD_POP: /* ..., value ==> ... */
917 case ICMD_POP2: /* ..., value, value ==> ... */
918 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
919 /* EAX: NO ECX: NO EDX: NO */
922 case ICMD_DUP: /* ..., a ==> ..., a, a */
923 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
924 /* EAX: YES ECX: NO EDX: NO */
925 M_COPY(src, iptr->dst);
928 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
929 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
930 /* EAX: YES ECX: NO EDX: NO */
932 M_COPY(src, iptr->dst);
933 M_COPY(src->prev, iptr->dst->prev);
936 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
937 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
938 /* EAX: YES ECX: NO EDX: NO */
940 M_COPY(src, iptr->dst);
941 M_COPY(src->prev, iptr->dst->prev);
942 M_COPY(iptr->dst, iptr->dst->prev->prev);
945 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
947 M_COPY(src, iptr->dst);
948 M_COPY(src->prev, iptr->dst->prev);
949 M_COPY(src->prev->prev, iptr->dst->prev->prev);
950 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
953 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
954 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
955 /* EAX: YES ECX: NO EDX: NO */
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);
961 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
964 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
965 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
966 /* EAX: YES ECX: NO EDX: NO */
968 M_COPY(src, iptr->dst);
969 M_COPY(src->prev, iptr->dst->prev);
970 M_COPY(src->prev->prev, iptr->dst->prev->prev);
971 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
972 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
973 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
976 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
977 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
978 /* EAX: YES ECX: NO EDX: NO */
980 M_COPY(src, iptr->dst->prev);
981 M_COPY(src->prev, iptr->dst);
985 /* integer operations *************************************************/
987 case ICMD_INEG: /* ..., value ==> ..., - value */
988 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
989 /* EAX: YES ECX: NO EDX: NO */
991 d = reg_of_var(rd, iptr->dst, REG_NULL);
992 if (iptr->dst->flags & INMEMORY) {
993 if (src->flags & INMEMORY) {
994 if (src->regoff == iptr->dst->regoff) {
995 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
998 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
999 i386_neg_reg(cd, REG_ITMP1);
1000 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1004 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1005 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1009 if (src->flags & INMEMORY) {
1010 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1011 i386_neg_reg(cd, iptr->dst->regoff);
1014 M_INTMOVE(src->regoff, iptr->dst->regoff);
1015 i386_neg_reg(cd, iptr->dst->regoff);
1020 case ICMD_LNEG: /* ..., value ==> ..., - value */
1021 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1022 /* EAX: YES ECX: NO EDX: NO */
1024 d = reg_of_var(rd, iptr->dst, REG_NULL);
1025 if (iptr->dst->flags & INMEMORY) {
1026 if (src->flags & INMEMORY) {
1027 if (src->regoff == iptr->dst->regoff) {
1028 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1029 i386_alu_imm_membase(cd, ALU_ADC, 0, REG_SP, iptr->dst->regoff * 4 + 4);
1030 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4 + 4);
1033 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1034 i386_neg_reg(cd, REG_ITMP1);
1035 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1036 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1037 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP1);
1038 i386_neg_reg(cd, REG_ITMP1);
1039 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1045 case ICMD_I2L: /* ..., value ==> ..., value */
1046 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1047 /* EAX: YES ECX: NO EDX: YES */
1049 d = reg_of_var(rd, iptr->dst, REG_NULL);
1050 if (iptr->dst->flags & INMEMORY) {
1051 if (src->flags & INMEMORY) {
1052 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, EAX);
1054 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1055 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1058 M_INTMOVE(src->regoff, EAX);
1060 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1061 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1066 case ICMD_L2I: /* ..., value ==> ..., value */
1067 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1068 /* EAX: YES ECX: NO EDX: NO */
1070 d = reg_of_var(rd, iptr->dst, REG_NULL);
1071 if (iptr->dst->flags & INMEMORY) {
1072 if (src->flags & INMEMORY) {
1073 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1074 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1078 if (src->flags & INMEMORY) {
1079 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1084 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1085 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1086 /* EAX: YES ECX: NO EDX: NO */
1088 d = reg_of_var(rd, iptr->dst, REG_NULL);
1089 if (iptr->dst->flags & INMEMORY) {
1090 if (src->flags & INMEMORY) {
1091 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1092 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1093 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1094 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1097 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1098 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 4);
1099 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 4);
1103 if (src->flags & INMEMORY) {
1104 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1105 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1106 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1109 M_INTMOVE(src->regoff, iptr->dst->regoff);
1110 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1111 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1116 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1117 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1118 /* EAX: YES ECX: NO EDX: NO */
1120 d = reg_of_var(rd, iptr->dst, REG_NULL);
1121 if (iptr->dst->flags & INMEMORY) {
1122 if (src->flags & INMEMORY) {
1123 if (src->regoff == iptr->dst->regoff) {
1124 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1127 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1128 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, REG_ITMP1);
1129 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1133 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1134 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1138 if (src->flags & INMEMORY) {
1139 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1140 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1143 M_INTMOVE(src->regoff, iptr->dst->regoff);
1144 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1149 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1150 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1151 /* EAX: YES ECX: NO EDX: NO */
1153 d = reg_of_var(rd, iptr->dst, REG_NULL);
1154 if (iptr->dst->flags & INMEMORY) {
1155 if (src->flags & INMEMORY) {
1156 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1157 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1158 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1159 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1162 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1163 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 4);
1164 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 4);
1168 if (src->flags & INMEMORY) {
1169 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1170 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1171 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1174 M_INTMOVE(src->regoff, iptr->dst->regoff);
1175 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1176 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1182 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1183 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1184 /* EAX: S|YES ECX: NO EDX: NO */
1186 d = reg_of_var(rd, iptr->dst, REG_NULL);
1187 i386_emit_ialu(cd, ALU_ADD, src, iptr);
1190 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1191 /* val.i = constant */
1192 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1193 /* EAX: NO ECX: NO EDX: NO */
1195 d = reg_of_var(rd, iptr->dst, REG_NULL);
1196 i386_emit_ialuconst(cd, ALU_ADD, src, iptr);
1199 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1200 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1201 /* EAX: S|YES ECX: NO EDX: NO */
1203 d = reg_of_var(rd, iptr->dst, REG_NULL);
1204 if (iptr->dst->flags & INMEMORY) {
1205 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1206 if (src->regoff == iptr->dst->regoff) {
1207 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1208 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1209 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1210 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1212 } else if (src->prev->regoff == iptr->dst->regoff) {
1213 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1214 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1215 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1216 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1219 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1220 i386_alu_membase_reg(cd, ALU_ADD, REG_SP, src->regoff * 4, REG_ITMP1);
1221 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1222 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1223 i386_alu_membase_reg(cd, ALU_ADC, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1224 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1231 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1232 /* val.l = constant */
1233 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1234 /* EAX: NO ECX: NO EDX: NO */
1235 /* else path can never happen? longs stay in memory! */
1237 d = reg_of_var(rd, iptr->dst, REG_NULL);
1238 if (iptr->dst->flags & INMEMORY) {
1239 if (src->flags & INMEMORY) {
1240 if (src->regoff == iptr->dst->regoff) {
1241 i386_alu_imm_membase(cd, ALU_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1242 i386_alu_imm_membase(cd, ALU_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1245 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1246 i386_alu_imm_reg(cd, ALU_ADD, iptr->val.l, REG_ITMP1);
1247 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1248 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1249 i386_alu_imm_reg(cd, ALU_ADC, iptr->val.l >> 32, REG_ITMP1);
1250 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1256 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1257 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1258 /* EAX: S|YES ECX: NO EDX: NO */
1260 d = reg_of_var(rd, iptr->dst, REG_NULL);
1261 if (iptr->dst->flags & INMEMORY) {
1262 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1263 if (src->prev->regoff == iptr->dst->regoff) {
1264 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1265 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1268 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1269 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1270 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1273 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1274 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1275 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1276 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1278 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1279 if (src->prev->regoff == iptr->dst->regoff) {
1280 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1283 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1284 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1285 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1289 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 4);
1290 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1294 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1295 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1296 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1298 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1299 M_INTMOVE(src->prev->regoff, d);
1300 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1302 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1303 /* workaround for reg alloc */
1304 if (src->regoff == iptr->dst->regoff) {
1305 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1306 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1307 M_INTMOVE(REG_ITMP1, d);
1310 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1311 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1315 /* workaround for reg alloc */
1316 if (src->regoff == iptr->dst->regoff) {
1317 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1318 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1319 M_INTMOVE(REG_ITMP1, d);
1322 M_INTMOVE(src->prev->regoff, d);
1323 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1329 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1330 /* val.i = constant */
1331 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1332 /* EAX: NO ECX: NO EDX: NO */
1334 d = reg_of_var(rd, iptr->dst, REG_NULL);
1335 i386_emit_ialuconst(cd, ALU_SUB, src, iptr);
1338 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1339 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1340 /* EAX: S|YES ECX: NO EDX: NO */
1342 d = reg_of_var(rd, iptr->dst, REG_NULL);
1343 if (iptr->dst->flags & INMEMORY) {
1344 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1345 if (src->prev->regoff == iptr->dst->regoff) {
1346 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1347 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1348 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1349 i386_alu_reg_membase(cd, ALU_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1352 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1353 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1354 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1355 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1356 i386_alu_membase_reg(cd, ALU_SBB, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1357 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1363 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1364 /* val.l = constant */
1365 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1366 /* EAX: NO ECX: NO EDX: NO */
1367 /* else path can never happen? longs stay in memory! */
1369 d = reg_of_var(rd, iptr->dst, REG_NULL);
1370 if (iptr->dst->flags & INMEMORY) {
1371 if (src->flags & INMEMORY) {
1372 if (src->regoff == iptr->dst->regoff) {
1373 i386_alu_imm_membase(cd, ALU_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1374 i386_alu_imm_membase(cd, ALU_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1377 /* TODO: could be size optimized with lea -- see gcc output */
1378 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1379 i386_alu_imm_reg(cd, ALU_SUB, iptr->val.l, REG_ITMP1);
1380 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1381 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1382 i386_alu_imm_reg(cd, ALU_SBB, iptr->val.l >> 32, REG_ITMP1);
1383 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1389 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1390 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1391 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1393 d = reg_of_var(rd, iptr->dst, REG_NULL);
1394 if (iptr->dst->flags & INMEMORY) {
1395 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1396 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1397 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1398 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1400 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1401 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1402 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1403 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1405 } else 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_reg_reg(cd, src->regoff, REG_ITMP1);
1408 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1411 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1412 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1413 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1417 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1418 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1419 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1421 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1422 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1423 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1425 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1426 M_INTMOVE(src->regoff, iptr->dst->regoff);
1427 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1430 if (src->regoff == iptr->dst->regoff) {
1431 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1434 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1435 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1441 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1442 /* val.i = constant */
1443 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1444 /* EAX: YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1446 d = reg_of_var(rd, iptr->dst, REG_NULL);
1447 if (iptr->dst->flags & INMEMORY) {
1448 if (src->flags & INMEMORY) {
1449 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, REG_ITMP1);
1450 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1453 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1454 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1458 if (src->flags & INMEMORY) {
1459 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, iptr->dst->regoff);
1462 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1467 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1468 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1469 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1471 d = reg_of_var(rd, iptr->dst, REG_NULL);
1472 if (iptr->dst->flags & INMEMORY) {
1473 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1474 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX); /* mem -> EAX */
1475 /* optimize move EAX -> REG_ITMP3 is slower??? */
1476 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1477 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1479 /* TODO: optimize move EAX -> REG_ITMP3 */
1480 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); /* mem -> ITMP3 */
1481 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1482 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1484 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP2); /* mem -> ITMP3 */
1485 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1487 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1488 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1489 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1494 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1495 /* val.l = constant */
1496 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1497 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1499 d = reg_of_var(rd, iptr->dst, REG_NULL);
1500 if (iptr->dst->flags & INMEMORY) {
1501 if (src->flags & INMEMORY) {
1502 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1503 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1504 /* TODO: optimize move EAX -> REG_ITMP3 */
1505 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1506 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1508 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1509 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1510 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1512 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1513 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1514 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1519 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1520 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1521 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX */
1523 d = reg_of_var(rd, iptr->dst, REG_NULL);
1524 var_to_reg_int(s1, src, REG_ITMP2);
1526 if (src->prev->flags & INMEMORY) {
1527 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1530 M_INTMOVE(src->prev->regoff, EAX);
1533 /* check as described in jvm spec */
1535 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1536 i386_jcc(cd, I386_CC_NE, 3 + 6);
1537 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1538 i386_jcc(cd, I386_CC_E, 1 + 2);
1541 i386_idiv_reg(cd, s1);
1543 if (iptr->dst->flags & INMEMORY) {
1544 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1547 M_INTMOVE(EAX, iptr->dst->regoff);
1551 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1552 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1553 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EDX */
1556 d = reg_of_var(rd, iptr->dst, REG_NULL);
1557 var_to_reg_int(s1, src, REG_ITMP2);
1559 if (src->prev->flags & INMEMORY) {
1560 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1563 M_INTMOVE(src->prev->regoff, EAX);
1566 /* check as described in jvm spec */
1568 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1569 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1570 i386_alu_reg_reg(cd, ALU_XOR, EDX, EDX);
1571 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1572 i386_jcc(cd, I386_CC_E, 1 + 2);
1575 i386_idiv_reg(cd, s1);
1577 if (iptr->dst->flags & INMEMORY) {
1578 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4);
1581 M_INTMOVE(EDX, iptr->dst->regoff);
1585 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1586 /* val.i = constant */
1587 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1588 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL */
1590 /* TODO: optimize for `/ 2' */
1591 var_to_reg_int(s1, src, REG_ITMP1);
1592 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1595 i386_test_reg_reg(cd, d, d);
1597 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1598 i386_jcc(cd, I386_CC_NS, a);
1599 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, d);
1601 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1602 store_reg_to_var_int(iptr->dst, d);
1605 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1606 /* val.i = constant */
1607 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1608 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1610 var_to_reg_int(s1, src, REG_ITMP1);
1611 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1613 M_INTMOVE(s1, REG_ITMP1);
1620 CALCIMMEDIATEBYTES(a, iptr->val.i);
1623 /* TODO: optimize */
1625 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1626 i386_test_reg_reg(cd, s1, s1);
1627 i386_jcc(cd, I386_CC_GE, a);
1628 i386_mov_reg_reg(cd, s1, d);
1629 i386_neg_reg(cd, d);
1630 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1631 i386_neg_reg(cd, d);
1633 /* M_INTMOVE(s1, EAX); */
1634 /* i386_cltd(cd); */
1635 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1636 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1637 /* i386_alu_reg_reg(cd, ALU_AND, iptr->val.i, EAX); */
1638 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1639 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1640 /* M_INTMOVE(EAX, d); */
1642 /* i386_alu_reg_reg(cd, ALU_XOR, d, d); */
1643 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1644 /* i386_shrd_reg_reg(cd, s1, d); */
1645 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1647 store_reg_to_var_int(iptr->dst, d);
1650 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1651 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1653 d = reg_of_var(rd, iptr->dst, REG_NULL);
1654 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4);
1655 M_OR_MEMBASE(REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1658 codegen_addxdivrefs(cd, cd->mcodeptr);
1663 M_ILD(REG_ITMP1, REG_SP, src->prev->regoff * 4);
1664 M_ILD(REG_ITMP2, REG_SP, src->prev->regoff * 4 + 4);
1665 M_IST(REG_ITMP1, REG_SP, 0 * 4);
1666 M_IST(REG_ITMP2, REG_SP, 0 * 4 + 4);
1668 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
1669 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4 + 4);
1670 M_IST(REG_ITMP1, REG_SP, 2 * 4);
1671 M_IST(REG_ITMP2, REG_SP, 2 * 4 + 4);
1673 M_MOV_IMM((ptrint) bte->fp, REG_ITMP3);
1676 M_IST(REG_RESULT, REG_SP, iptr->dst->regoff * 4);
1677 M_IST(REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
1680 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1681 /* val.i = constant */
1682 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1683 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1685 d = reg_of_var(rd, iptr->dst, REG_NULL);
1686 if (iptr->dst->flags & INMEMORY) {
1687 if (src->flags & INMEMORY) {
1689 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1691 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1692 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1694 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1695 i386_jcc(cd, I386_CC_NS, a);
1696 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1697 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1698 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1699 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1701 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1702 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1707 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1708 /* val.l = constant */
1709 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1710 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1712 d = reg_of_var(rd, iptr->dst, REG_NULL);
1713 if (iptr->dst->flags & INMEMORY) {
1714 if (src->flags & INMEMORY) {
1715 /* Intel algorithm -- does not work, because constant is wrong */
1716 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1); */
1717 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3); */
1719 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1720 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1721 /* i386_jcc(cd, I386_CC_NS, offset); */
1722 /* i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1723 /* i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP3); */
1725 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1726 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1727 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1729 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1731 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1); */
1732 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); */
1733 /* i386_alu_reg_reg(cd, ALU_SBB, REG_ITMP3, REG_ITMP2); */
1735 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1736 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1738 /* Alpha algorithm */
1740 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
1742 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4 + 4);
1748 /* TODO: hmm, don't know if this is always correct */
1750 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1752 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1758 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1759 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1761 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1762 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1763 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4 + 4);
1764 i386_jcc(cd, I386_CC_GE, a);
1766 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1767 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1769 i386_neg_reg(cd, REG_ITMP1);
1770 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1771 i386_neg_reg(cd, REG_ITMP2);
1773 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1774 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1776 i386_neg_reg(cd, REG_ITMP1);
1777 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1778 i386_neg_reg(cd, REG_ITMP2);
1780 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1781 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1786 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1787 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1788 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1790 d = reg_of_var(rd, iptr->dst, REG_NULL);
1791 i386_emit_ishift(cd, I386_SHL, src, iptr);
1794 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1795 /* val.i = constant */
1796 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1797 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1799 d = reg_of_var(rd, iptr->dst, REG_NULL);
1800 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1803 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1804 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1805 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1807 d = reg_of_var(rd, iptr->dst, REG_NULL);
1808 i386_emit_ishift(cd, I386_SAR, src, iptr);
1811 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1812 /* val.i = constant */
1813 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1814 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1816 d = reg_of_var(rd, iptr->dst, REG_NULL);
1817 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1820 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1821 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1822 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1824 d = reg_of_var(rd, iptr->dst, REG_NULL);
1825 i386_emit_ishift(cd, I386_SHR, src, iptr);
1828 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1829 /* val.i = constant */
1830 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1831 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1833 d = reg_of_var(rd, iptr->dst, REG_NULL);
1834 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1837 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1838 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1839 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
1841 d = reg_of_var(rd, iptr->dst, REG_NULL);
1842 if (iptr->dst->flags & INMEMORY ){
1843 if (src->prev->flags & INMEMORY) {
1844 /* if (src->prev->regoff == iptr->dst->regoff) { */
1845 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1847 /* if (src->flags & INMEMORY) { */
1848 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1850 /* M_INTMOVE(src->regoff, ECX); */
1853 /* i386_test_imm_reg(cd, 32, ECX); */
1854 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1855 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1856 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1); */
1858 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 4 + 4); */
1859 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 4); */
1862 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1863 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1865 if (src->flags & INMEMORY) {
1866 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1868 M_INTMOVE(src->regoff, ECX);
1871 i386_test_imm_reg(cd, 32, ECX);
1872 i386_jcc(cd, I386_CC_E, 2 + 2);
1873 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1874 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1876 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1877 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1878 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1879 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
1885 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1886 /* val.i = constant */
1887 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1888 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1890 d = reg_of_var(rd, iptr->dst, REG_NULL);
1891 if (iptr->dst->flags & INMEMORY ) {
1892 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1893 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1895 if (iptr->val.i & 0x20) {
1896 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1897 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1898 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1901 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1902 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1905 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1906 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1910 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1911 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1912 /* EAX: S|YES ECX: YES S|EDX: YES OUTPUT: REG_NULL*/
1914 d = reg_of_var(rd, iptr->dst, REG_NULL);
1915 if (iptr->dst->flags & INMEMORY ){
1916 if (src->prev->flags & INMEMORY) {
1917 /* if (src->prev->regoff == iptr->dst->regoff) { */
1918 /* TODO: optimize */
1919 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1920 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
1922 /* if (src->flags & INMEMORY) { */
1923 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1925 /* M_INTMOVE(src->regoff, ECX); */
1928 /* i386_test_imm_reg(cd, 32, ECX); */
1929 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1930 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1931 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1933 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1934 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1935 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1936 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1939 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1940 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1942 if (src->flags & INMEMORY) {
1943 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1945 M_INTMOVE(src->regoff, ECX);
1948 i386_test_imm_reg(cd, 32, ECX);
1949 i386_jcc(cd, I386_CC_E, 2 + 3);
1950 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1951 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1953 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1954 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1955 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1956 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
1962 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1963 /* val.i = constant */
1964 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1965 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1967 d = reg_of_var(rd, iptr->dst, REG_NULL);
1968 if (iptr->dst->flags & INMEMORY ) {
1969 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1970 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1972 if (iptr->val.i & 0x20) {
1973 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1974 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
1975 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1978 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1979 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1982 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1983 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1987 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1988 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1989 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
1991 d = reg_of_var(rd, iptr->dst, REG_NULL);
1992 if (iptr->dst->flags & INMEMORY ){
1993 if (src->prev->flags & INMEMORY) {
1994 /* if (src->prev->regoff == iptr->dst->regoff) { */
1995 /* TODO: optimize */
1996 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1997 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
1999 /* if (src->flags & INMEMORY) { */
2000 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
2002 /* M_INTMOVE(src->regoff, ECX); */
2005 /* i386_test_imm_reg(cd, 32, ECX); */
2006 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
2007 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2008 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2); */
2010 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2011 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
2012 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
2013 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
2016 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
2017 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
2019 if (src->flags & INMEMORY) {
2020 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
2022 M_INTMOVE(src->regoff, ECX);
2025 i386_test_imm_reg(cd, 32, ECX);
2026 i386_jcc(cd, I386_CC_E, 2 + 2);
2027 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2028 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP3, REG_ITMP3);
2030 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2031 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
2032 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2033 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2039 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
2040 /* val.l = constant */
2041 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2042 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
2044 d = reg_of_var(rd, iptr->dst, REG_NULL);
2045 if (iptr->dst->flags & INMEMORY ) {
2046 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
2047 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
2049 if (iptr->val.i & 0x20) {
2050 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2051 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
2052 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2055 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2056 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
2059 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2060 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
2064 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2065 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2066 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2068 d = reg_of_var(rd, iptr->dst, REG_NULL);
2069 i386_emit_ialu(cd, ALU_AND, src, iptr);
2072 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
2073 /* val.i = constant */
2074 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2075 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2077 d = reg_of_var(rd, iptr->dst, REG_NULL);
2078 i386_emit_ialuconst(cd, ALU_AND, src, iptr);
2081 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2082 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2083 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2085 d = reg_of_var(rd, iptr->dst, REG_NULL);
2086 i386_emit_lalu(cd, ALU_AND, src, iptr);
2089 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
2090 /* val.l = constant */
2091 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2092 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2094 d = reg_of_var(rd, iptr->dst, REG_NULL);
2095 i386_emit_laluconst(cd, ALU_AND, src, iptr);
2098 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2099 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2100 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2102 d = reg_of_var(rd, iptr->dst, REG_NULL);
2103 i386_emit_ialu(cd, ALU_OR, src, iptr);
2106 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2107 /* val.i = constant */
2108 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2109 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2111 d = reg_of_var(rd, iptr->dst, REG_NULL);
2112 i386_emit_ialuconst(cd, ALU_OR, src, iptr);
2115 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2116 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2117 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2119 d = reg_of_var(rd, iptr->dst, REG_NULL);
2120 i386_emit_lalu(cd, ALU_OR, src, iptr);
2123 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2124 /* val.l = constant */
2125 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2126 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2128 d = reg_of_var(rd, iptr->dst, REG_NULL);
2129 i386_emit_laluconst(cd, ALU_OR, src, iptr);
2132 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2133 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2134 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2136 d = reg_of_var(rd, iptr->dst, REG_NULL);
2137 i386_emit_ialu(cd, ALU_XOR, src, iptr);
2140 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2141 /* val.i = constant */
2142 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2143 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2145 d = reg_of_var(rd, iptr->dst, REG_NULL);
2146 i386_emit_ialuconst(cd, ALU_XOR, src, iptr);
2149 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2150 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2151 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2153 d = reg_of_var(rd, iptr->dst, REG_NULL);
2154 i386_emit_lalu(cd, ALU_XOR, src, iptr);
2157 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2158 /* val.l = constant */
2159 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2160 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2162 d = reg_of_var(rd, iptr->dst, REG_NULL);
2163 i386_emit_laluconst(cd, ALU_XOR, src, iptr);
2166 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2167 /* op1 = variable, val.i = constant */
2168 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2169 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2171 var = &(rd->locals[iptr->op1][TYPE_INT]);
2172 if (var->flags & INMEMORY) {
2173 i386_alu_imm_membase(cd, ALU_ADD, iptr->val.i, REG_SP, var->regoff * 4);
2176 /* `inc reg' is slower on p4's (regarding to ia32 */
2177 /* optimization reference manual and benchmarks) and as fast */
2179 i386_alu_imm_reg(cd, ALU_ADD, iptr->val.i, var->regoff);
2184 /* floating operations ************************************************/
2186 #define ROUND_TO_SINGLE \
2187 i386_fstps_membase(cd, REG_SP, -8); \
2188 i386_flds_membase(cd, REG_SP, -8);
2190 #define ROUND_TO_DOUBLE \
2191 i386_fstpl_membase(cd, REG_SP, -8); \
2192 i386_fldl_membase(cd, REG_SP, -8);
2194 #define FPU_SET_24BIT_MODE \
2195 if (!fpu_in_24bit_mode) { \
2196 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2197 fpu_in_24bit_mode = 1; \
2200 #define FPU_SET_53BIT_MODE \
2201 if (fpu_in_24bit_mode) { \
2202 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2203 fpu_in_24bit_mode = 0; \
2206 #define ROUND_TO_SINGLE
2207 #define ROUND_TO_DOUBLE
2208 #define FPU_SET_24BIT_MODE
2209 #define FPU_SET_53BIT_MODE
2211 case ICMD_FNEG: /* ..., value ==> ..., - value */
2212 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2213 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2216 var_to_reg_flt(s1, src, REG_FTMP1);
2217 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2219 store_reg_to_var_flt(iptr->dst, d);
2222 case ICMD_DNEG: /* ..., value ==> ..., - value */
2223 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2224 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2227 var_to_reg_flt(s1, src, REG_FTMP1);
2228 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2230 store_reg_to_var_flt(iptr->dst, d);
2233 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2234 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2235 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2238 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2239 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2240 var_to_reg_flt(s2, src, REG_FTMP2);
2243 store_reg_to_var_flt(iptr->dst, d);
2246 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2247 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2248 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2251 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2252 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2253 var_to_reg_flt(s2, src, REG_FTMP2);
2256 store_reg_to_var_flt(iptr->dst, d);
2259 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2260 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2261 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2264 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2265 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2266 var_to_reg_flt(s2, src, REG_FTMP2);
2269 store_reg_to_var_flt(iptr->dst, d);
2272 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2273 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2274 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2277 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2278 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2279 var_to_reg_flt(s2, src, REG_FTMP2);
2282 store_reg_to_var_flt(iptr->dst, d);
2285 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2286 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2287 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2290 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2291 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2292 var_to_reg_flt(s2, src, REG_FTMP2);
2296 store_reg_to_var_flt(iptr->dst, d);
2299 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2300 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2301 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2304 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2305 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2307 /* i386_fldt_mem(cd, subnormal_bias1); */
2308 /* i386_fmulp(cd); */
2310 var_to_reg_flt(s2, src, REG_FTMP2);
2315 /* i386_fldt_mem(cd, subnormal_bias2); */
2316 /* i386_fmulp(cd); */
2318 store_reg_to_var_flt(iptr->dst, d);
2321 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2322 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2323 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2326 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2327 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2328 var_to_reg_flt(s2, src, REG_FTMP2);
2332 store_reg_to_var_flt(iptr->dst, d);
2335 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2336 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2337 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2340 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2341 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2343 /* i386_fldt_mem(cd, subnormal_bias1); */
2344 /* i386_fmulp(cd); */
2346 var_to_reg_flt(s2, src, REG_FTMP2);
2351 /* i386_fldt_mem(cd, subnormal_bias2); */
2352 /* i386_fmulp(cd); */
2354 store_reg_to_var_flt(iptr->dst, d);
2357 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2358 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2359 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2362 /* exchanged to skip fxch */
2363 var_to_reg_flt(s2, src, REG_FTMP2);
2364 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2365 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2366 /* i386_fxch(cd); */
2371 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2372 store_reg_to_var_flt(iptr->dst, d);
2373 i386_ffree_reg(cd, 0);
2378 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2379 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2380 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2383 /* exchanged to skip fxch */
2384 var_to_reg_flt(s2, src, REG_FTMP2);
2385 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2386 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2387 /* i386_fxch(cd); */
2392 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2393 store_reg_to_var_flt(iptr->dst, d);
2394 i386_ffree_reg(cd, 0);
2399 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2400 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2401 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2402 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2404 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2405 if (src->flags & INMEMORY) {
2406 i386_fildl_membase(cd, REG_SP, src->regoff * 4);
2410 a = dseg_adds4(cd, 0);
2411 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2412 dseg_adddata(cd, cd->mcodeptr);
2413 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, a);
2414 i386_fildl_membase(cd, REG_ITMP1, a);
2417 store_reg_to_var_flt(iptr->dst, d);
2420 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2421 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2422 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2423 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2425 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2426 if (src->flags & INMEMORY) {
2427 i386_fildll_membase(cd, REG_SP, src->regoff * 4);
2431 log_text("L2F: longs have to be in memory");
2434 store_reg_to_var_flt(iptr->dst, d);
2437 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2438 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2439 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2441 var_to_reg_flt(s1, src, REG_FTMP1);
2442 d = reg_of_var(rd, iptr->dst, REG_NULL);
2444 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2445 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2446 dseg_adddata(cd, cd->mcodeptr);
2447 i386_fldcw_membase(cd, REG_ITMP1, a);
2449 if (iptr->dst->flags & INMEMORY) {
2450 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2453 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2454 i386_fldcw_membase(cd, REG_ITMP1, a);
2456 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2459 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2461 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2464 a = dseg_adds4(cd, 0);
2465 i386_fistpl_membase(cd, REG_ITMP1, a);
2467 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2469 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2470 i386_fldcw_membase(cd, REG_ITMP1, a);
2472 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2475 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2476 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2479 i386_jcc(cd, I386_CC_NE, a);
2481 /* XXX: change this when we use registers */
2482 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2483 i386_mov_imm_reg(cd, (s4) asm_builtin_f2i, REG_ITMP1);
2484 i386_call_reg(cd, REG_ITMP1);
2486 if (iptr->dst->flags & INMEMORY) {
2487 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2490 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2494 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2495 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2496 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2498 var_to_reg_flt(s1, src, REG_FTMP1);
2499 d = reg_of_var(rd, iptr->dst, REG_NULL);
2501 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2502 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2503 dseg_adddata(cd, cd->mcodeptr);
2504 i386_fldcw_membase(cd, REG_ITMP1, a);
2506 if (iptr->dst->flags & INMEMORY) {
2507 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2510 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2511 i386_fldcw_membase(cd, REG_ITMP1, a);
2513 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2516 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2518 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2521 a = dseg_adds4(cd, 0);
2522 i386_fistpl_membase(cd, REG_ITMP1, a);
2524 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2526 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2527 i386_fldcw_membase(cd, REG_ITMP1, a);
2529 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2532 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2533 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2536 i386_jcc(cd, I386_CC_NE, a);
2538 /* XXX: change this when we use registers */
2539 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2540 i386_mov_imm_reg(cd, (s4) asm_builtin_d2i, REG_ITMP1);
2541 i386_call_reg(cd, REG_ITMP1);
2543 if (iptr->dst->flags & INMEMORY) {
2544 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2546 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2550 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2551 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2552 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2554 var_to_reg_flt(s1, src, REG_FTMP1);
2555 d = reg_of_var(rd, iptr->dst, REG_NULL);
2557 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2558 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2559 dseg_adddata(cd, cd->mcodeptr);
2560 i386_fldcw_membase(cd, REG_ITMP1, a);
2562 if (iptr->dst->flags & INMEMORY) {
2563 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2566 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2567 i386_fldcw_membase(cd, REG_ITMP1, a);
2569 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2572 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2574 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2577 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2579 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4 + 4);
2581 i386_jcc(cd, I386_CC_NE, a);
2583 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2586 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2588 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2590 i386_jcc(cd, I386_CC_NE, a);
2592 /* XXX: change this when we use registers */
2593 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2594 i386_mov_imm_reg(cd, (s4) asm_builtin_f2l, REG_ITMP1);
2595 i386_call_reg(cd, REG_ITMP1);
2596 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2597 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2600 log_text("F2L: longs have to be in memory");
2605 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2606 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2607 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2609 var_to_reg_flt(s1, src, REG_FTMP1);
2610 d = reg_of_var(rd, iptr->dst, REG_NULL);
2612 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2613 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2614 dseg_adddata(cd, cd->mcodeptr);
2615 i386_fldcw_membase(cd, REG_ITMP1, a);
2617 if (iptr->dst->flags & INMEMORY) {
2618 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2621 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2622 i386_fldcw_membase(cd, REG_ITMP1, a);
2624 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2627 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2629 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2632 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2634 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4 + 4);
2636 i386_jcc(cd, I386_CC_NE, a);
2638 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2641 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2643 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2645 i386_jcc(cd, I386_CC_NE, a);
2647 /* XXX: change this when we use registers */
2648 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2649 i386_mov_imm_reg(cd, (s4) asm_builtin_d2l, REG_ITMP1);
2650 i386_call_reg(cd, REG_ITMP1);
2651 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2652 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2655 log_text("D2L: longs have to be in memory");
2660 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2661 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2662 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2664 var_to_reg_flt(s1, src, REG_FTMP1);
2665 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2667 store_reg_to_var_flt(iptr->dst, d);
2670 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2671 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2672 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2674 var_to_reg_flt(s1, src, REG_FTMP1);
2675 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2677 store_reg_to_var_flt(iptr->dst, d);
2680 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2682 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2683 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2685 /* exchanged to skip fxch */
2686 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2687 var_to_reg_flt(s1, src, REG_FTMP2);
2688 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2689 /* i386_fxch(cd); */
2693 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2694 i386_jcc(cd, I386_CC_E, 6);
2695 i386_alu_imm_reg(cd, ALU_AND, 0x000000ff, EAX);
2697 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2698 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2699 i386_jcc(cd, I386_CC_B, 3 + 5);
2700 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2701 i386_jmp_imm(cd, 3);
2702 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2703 store_reg_to_var_int(iptr->dst, d);
2706 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2708 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2709 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2711 /* exchanged to skip fxch */
2712 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2713 var_to_reg_flt(s1, src, REG_FTMP2);
2714 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2715 /* i386_fxch(cd); */
2719 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2720 i386_jcc(cd, I386_CC_E, 3);
2721 i386_movb_imm_reg(cd, 1, REG_AH);
2723 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2724 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2725 i386_jcc(cd, I386_CC_B, 3 + 5);
2726 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2727 i386_jmp_imm(cd, 3);
2728 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2729 store_reg_to_var_int(iptr->dst, d);
2733 /* memory operations **************************************************/
2735 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2736 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2737 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2739 var_to_reg_int(s1, src, REG_ITMP1);
2740 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2741 gen_nullptr_check(s1);
2742 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2743 store_reg_to_var_int(iptr->dst, d);
2746 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2747 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2748 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2750 var_to_reg_int(s1, src->prev, REG_ITMP1);
2751 var_to_reg_int(s2, src, REG_ITMP2);
2752 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2753 if (iptr->op1 == 0) {
2754 gen_nullptr_check(s1);
2757 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2758 store_reg_to_var_int(iptr->dst, d);
2761 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2762 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2763 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2765 var_to_reg_int(s1, src->prev, REG_ITMP1);
2766 var_to_reg_int(s2, src, REG_ITMP2);
2767 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2768 if (iptr->op1 == 0) {
2769 gen_nullptr_check(s1);
2773 if (iptr->dst->flags & INMEMORY) {
2774 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2775 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4);
2776 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2777 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2781 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2782 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2783 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2785 var_to_reg_int(s1, src->prev, REG_ITMP1);
2786 var_to_reg_int(s2, src, REG_ITMP2);
2787 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2788 if (iptr->op1 == 0) {
2789 gen_nullptr_check(s1);
2792 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2793 store_reg_to_var_int(iptr->dst, d);
2796 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2797 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2798 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2800 var_to_reg_int(s1, src->prev, REG_ITMP1);
2801 var_to_reg_int(s2, src, REG_ITMP2);
2802 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2803 if (iptr->op1 == 0) {
2804 gen_nullptr_check(s1);
2807 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2809 store_reg_to_var_flt(iptr->dst, d);
2812 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2813 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2814 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2816 var_to_reg_int(s1, src->prev, REG_ITMP1);
2817 var_to_reg_int(s2, src, REG_ITMP2);
2818 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2819 if (iptr->op1 == 0) {
2820 gen_nullptr_check(s1);
2823 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2825 store_reg_to_var_flt(iptr->dst, d);
2828 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2829 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2830 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2832 var_to_reg_int(s1, src->prev, REG_ITMP1);
2833 var_to_reg_int(s2, src, REG_ITMP2);
2834 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2835 if (iptr->op1 == 0) {
2836 gen_nullptr_check(s1);
2839 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2840 store_reg_to_var_int(iptr->dst, d);
2843 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2844 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2845 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2847 var_to_reg_int(s1, src->prev, REG_ITMP1);
2848 var_to_reg_int(s2, src, REG_ITMP2);
2849 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2850 if (iptr->op1 == 0) {
2851 gen_nullptr_check(s1);
2854 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2855 store_reg_to_var_int(iptr->dst, d);
2858 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2859 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2860 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2862 var_to_reg_int(s1, src->prev, REG_ITMP1);
2863 var_to_reg_int(s2, src, REG_ITMP2);
2864 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2865 if (iptr->op1 == 0) {
2866 gen_nullptr_check(s1);
2869 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2870 store_reg_to_var_int(iptr->dst, d);
2874 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2875 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2876 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
2878 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2879 var_to_reg_int(s2, src->prev, REG_ITMP2);
2880 if (iptr->op1 == 0) {
2881 gen_nullptr_check(s1);
2885 if (src->flags & INMEMORY) {
2886 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP3);
2887 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2888 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
2889 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2893 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2894 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2895 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2897 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2898 var_to_reg_int(s2, src->prev, REG_ITMP2);
2899 if (iptr->op1 == 0) {
2900 gen_nullptr_check(s1);
2903 var_to_reg_int(s3, src, REG_ITMP3);
2904 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2907 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2908 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2909 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2911 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2912 var_to_reg_int(s2, src->prev, REG_ITMP2);
2913 if (iptr->op1 == 0) {
2914 gen_nullptr_check(s1);
2917 var_to_reg_flt(s3, src, REG_FTMP1);
2918 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2922 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2923 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2924 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2926 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2927 var_to_reg_int(s2, src->prev, REG_ITMP2);
2928 if (iptr->op1 == 0) {
2929 gen_nullptr_check(s1);
2932 var_to_reg_flt(s3, src, REG_FTMP1);
2933 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2937 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2938 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2939 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2941 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2942 var_to_reg_int(s2, src->prev, REG_ITMP2);
2943 if (iptr->op1 == 0) {
2944 gen_nullptr_check(s1);
2947 var_to_reg_int(s3, src, REG_ITMP3);
2948 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2951 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2952 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2953 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2955 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2956 var_to_reg_int(s2, src->prev, REG_ITMP2);
2957 if (iptr->op1 == 0) {
2958 gen_nullptr_check(s1);
2961 var_to_reg_int(s3, src, REG_ITMP3);
2962 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2965 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2966 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2967 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2969 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2970 var_to_reg_int(s2, src->prev, REG_ITMP2);
2971 if (iptr->op1 == 0) {
2972 gen_nullptr_check(s1);
2975 var_to_reg_int(s3, src, REG_ITMP3);
2976 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2977 M_INTMOVE(s3, REG_ITMP3);
2980 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2983 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2985 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2986 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
2988 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2989 var_to_reg_int(s2, src->prev, REG_ITMP2);
2990 if (iptr->op1 == 0) {
2991 gen_nullptr_check(s1);
2994 var_to_reg_int(s3, src, REG_ITMP3);
2996 M_AST(s1, REG_SP, 0 * 4);
2997 M_AST(s3, REG_SP, 1 * 4);
2998 M_MOV_IMM((ptrint) BUILTIN_canstore, REG_ITMP1);
3002 codegen_addxstorerefs(cd, cd->mcodeptr);
3004 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
3005 var_to_reg_int(s2, src->prev, REG_ITMP2);
3006 var_to_reg_int(s3, src, REG_ITMP3);
3007 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3010 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
3011 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3012 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3014 var_to_reg_int(s1, src->prev, REG_ITMP1);
3015 var_to_reg_int(s2, src, REG_ITMP2);
3016 if (iptr->op1 == 0) {
3017 gen_nullptr_check(s1);
3020 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
3023 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
3024 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3025 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3027 var_to_reg_int(s1, src->prev, REG_ITMP1);
3028 var_to_reg_int(s2, src, REG_ITMP2);
3029 if (iptr->op1 == 0) {
3030 gen_nullptr_check(s1);
3034 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
3035 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
3038 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
3039 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3040 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3042 var_to_reg_int(s1, src->prev, REG_ITMP1);
3043 var_to_reg_int(s2, src, REG_ITMP2);
3044 if (iptr->op1 == 0) {
3045 gen_nullptr_check(s1);
3048 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3051 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
3052 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3053 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3055 var_to_reg_int(s1, src->prev, REG_ITMP1);
3056 var_to_reg_int(s2, src, REG_ITMP2);
3057 if (iptr->op1 == 0) {
3058 gen_nullptr_check(s1);
3061 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3064 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
3065 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3066 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3068 var_to_reg_int(s1, src->prev, REG_ITMP1);
3069 var_to_reg_int(s2, src, REG_ITMP2);
3070 if (iptr->op1 == 0) {
3071 gen_nullptr_check(s1);
3074 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
3077 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
3078 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3079 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3081 var_to_reg_int(s1, src->prev, REG_ITMP1);
3082 var_to_reg_int(s2, src, REG_ITMP2);
3083 if (iptr->op1 == 0) {
3084 gen_nullptr_check(s1);
3087 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3091 case ICMD_GETSTATIC: /* ... ==> ..., value */
3092 /* op1 = type, val.a = field address */
3093 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3094 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX*/
3097 codegen_addpatchref(cd, cd->mcodeptr,
3098 PATCHER_get_putstatic,
3099 (unresolved_field *) iptr->target, 0);
3101 if (opt_showdisassemble) {
3102 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3108 fieldinfo *fi = iptr->val.a;
3110 if (!(fi->class->state & CLASS_INITIALIZED)) {
3111 codegen_addpatchref(cd, cd->mcodeptr,
3112 PATCHER_clinit, fi->class, 0);
3114 if (opt_showdisassemble) {
3115 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3119 a = (ptrint) &(fi->value);
3122 i386_mov_imm_reg(cd, a, REG_ITMP1);
3123 switch (iptr->op1) {
3126 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3127 i386_mov_membase_reg(cd, REG_ITMP1, 0, d);
3128 store_reg_to_var_int(iptr->dst, d);
3131 d = reg_of_var(rd, iptr->dst, REG_NULL);
3132 if (iptr->dst->flags & INMEMORY) {
3133 /* Using both REG_ITMP2 and REG_ITMP3 is faster than only */
3134 /* using REG_ITMP2 alternating. */
3135 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP2);
3136 i386_mov_membase_reg(cd, REG_ITMP1, 4, REG_ITMP3);
3137 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4);
3138 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
3140 log_text("GETSTATIC: longs have to be in memory");
3145 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3146 i386_flds_membase(cd, REG_ITMP1, 0);
3148 store_reg_to_var_flt(iptr->dst, d);
3151 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3152 i386_fldl_membase(cd, REG_ITMP1, 0);
3154 store_reg_to_var_flt(iptr->dst, d);
3159 case ICMD_PUTSTATIC: /* ..., value ==> ... */
3160 /* op1 = type, val.a = field address */
3161 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3162 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3165 codegen_addpatchref(cd, cd->mcodeptr,
3166 PATCHER_get_putstatic,
3167 (unresolved_field *) iptr->target, 0);
3169 if (opt_showdisassemble) {
3170 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3176 fieldinfo *fi = iptr->val.a;
3178 if (!(fi->class->state & CLASS_INITIALIZED)) {
3179 codegen_addpatchref(cd, cd->mcodeptr,
3180 PATCHER_clinit, fi->class, 0);
3182 if (opt_showdisassemble) {
3183 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3187 a = (ptrint) &(fi->value);
3190 i386_mov_imm_reg(cd, a, REG_ITMP1);
3191 switch (iptr->op1) {
3194 var_to_reg_int(s2, src, REG_ITMP2);
3195 i386_mov_reg_membase(cd, s2, REG_ITMP1, 0);
3198 if (src->flags & INMEMORY) {
3199 /* Using both REG_ITMP2 and REG_ITMP3 is faster than only */
3200 /* using REG_ITMP2 alternating. */
3203 i386_mov_membase_reg(cd, REG_SP, s2 * 4, REG_ITMP2);
3204 i386_mov_membase_reg(cd, REG_SP, s2 * 4 + 4, REG_ITMP3);
3205 i386_mov_reg_membase(cd, REG_ITMP2, REG_ITMP1, 0);
3206 i386_mov_reg_membase(cd, REG_ITMP3, REG_ITMP1, 4);
3208 log_text("PUTSTATIC: longs have to be in memory");
3213 var_to_reg_flt(s2, src, REG_FTMP1);
3214 i386_fstps_membase(cd, REG_ITMP1, 0);
3218 var_to_reg_flt(s2, src, REG_FTMP1);
3219 i386_fstpl_membase(cd, REG_ITMP1, 0);
3225 case ICMD_PUTSTATICCONST: /* ... ==> ... */
3226 /* val = value (in current instruction) */
3227 /* op1 = type, val.a = field address (in */
3228 /* following NOP) */
3229 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3230 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3232 if (!iptr[1].val.a) {
3233 codegen_addpatchref(cd, cd->mcodeptr,
3234 PATCHER_get_putstatic,
3235 (unresolved_field *) iptr[1].target, 0);
3237 if (opt_showdisassemble) {
3238 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3244 fieldinfo *fi = iptr[1].val.a;
3246 if (!(fi->class->state & CLASS_INITIALIZED)) {
3247 codegen_addpatchref(cd, cd->mcodeptr,
3248 PATCHER_clinit, fi->class, 0);
3250 if (opt_showdisassemble) {
3251 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3255 a = (ptrint) &(fi->value);
3258 i386_mov_imm_reg(cd, a, REG_ITMP1);
3259 switch (iptr[1].op1) {
3263 i386_mov_imm_membase(cd, iptr->val.i, REG_ITMP1, 0);
3267 i386_mov_imm_membase(cd, iptr->val.l, REG_ITMP1, 0);
3268 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_ITMP1, 4);
3273 case ICMD_GETFIELD: /* .., objectref. ==> ..., value */
3274 /* op1 = type, val.i = field offset */
3275 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3276 /* EAX: YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
3278 var_to_reg_int(s1, src, REG_ITMP1);
3279 gen_nullptr_check(s1);
3282 codegen_addpatchref(cd, cd->mcodeptr,
3284 (unresolved_field *) iptr->target, 0);
3286 if (opt_showdisassemble) {
3287 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3293 a = ((fieldinfo *) (iptr->val.a))->offset;
3296 switch (iptr->op1) {
3299 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3300 i386_mov_membase32_reg(cd, s1, a, d);
3301 store_reg_to_var_int(iptr->dst, d);
3304 d = reg_of_var(rd, iptr->dst, REG_NULL);
3305 i386_mov_membase32_reg(cd, s1, a, REG_ITMP2);
3306 i386_mov_membase32_reg(cd, s1, a + 4, REG_ITMP3);
3307 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4);
3308 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
3311 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3312 i386_flds_membase32(cd, s1, a);
3314 store_reg_to_var_flt(iptr->dst, d);
3317 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3318 i386_fldl_membase32(cd, s1, a);
3320 store_reg_to_var_flt(iptr->dst, d);
3325 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
3326 /* op1 = type, val.a = field address */
3327 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3328 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3330 var_to_reg_int(s1, src->prev, REG_ITMP1);
3331 gen_nullptr_check(s1);
3332 if ((iptr->op1 == TYPE_INT) || IS_ADR_TYPE(iptr->op1)) {
3333 var_to_reg_int(s2, src, REG_ITMP2);
3334 } else if (IS_FLT_DBL_TYPE(iptr->op1)) {
3335 var_to_reg_flt(s2, src, REG_FTMP2);
3339 codegen_addpatchref(cd, cd->mcodeptr,
3341 (unresolved_field *) iptr->target, 0);
3343 if (opt_showdisassemble) {
3344 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3350 a = ((fieldinfo *) (iptr->val.a))->offset;
3353 switch (iptr->op1) {
3356 i386_mov_reg_membase32(cd, s2, s1, a);
3359 if (src->flags & INMEMORY) {
3360 i386_mov_membase32_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2);
3361 i386_mov_membase32_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
3362 i386_mov_reg_membase32(cd, REG_ITMP2, s1, a);
3363 i386_mov_reg_membase32(cd, REG_ITMP3, s1, a + 4);
3365 log_text("PUTFIELD: longs have to be in memory");
3370 i386_fstps_membase32(cd, s1, a);
3374 i386_fstpl_membase32(cd, s1, a);
3380 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
3381 /* val = value (in current instruction) */
3382 /* op1 = type, val.a = field address (in */
3383 /* following NOP) */
3384 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3385 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3387 var_to_reg_int(s1, src, REG_ITMP1);
3388 gen_nullptr_check(s1);
3390 if (!iptr[1].val.a) {
3391 codegen_addpatchref(cd, cd->mcodeptr,
3392 PATCHER_putfieldconst,
3393 (unresolved_field *) iptr[1].target, 0);
3395 if (opt_showdisassemble) {
3396 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3402 a = ((fieldinfo *) (iptr[1].val.a))->offset;
3405 switch (iptr[1].op1) {
3409 i386_mov_imm_membase32(cd, iptr->val.i, s1, a);
3413 i386_mov_imm_membase32(cd, iptr->val.l, s1, a);
3414 i386_mov_imm_membase32(cd, iptr->val.l >> 32, s1, a + 4);
3420 /* branch operations **************************************************/
3422 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3423 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3424 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
3426 var_to_reg_int(s1, src, REG_ITMP1);
3427 M_INTMOVE(s1, REG_ITMP1_XPTR);
3429 #ifdef ENABLE_VERIFIER
3431 codegen_addpatchref(cd, cd->mcodeptr,
3432 PATCHER_athrow_areturn,
3433 (unresolved_class *) iptr->val.a, 0);
3435 if (opt_showdisassemble) {
3436 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3439 #endif /* ENABLE_VERIFIER */
3441 M_CALL_IMM(0); /* passing exception pc */
3442 M_POP(REG_ITMP2_XPC);
3444 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
3448 case ICMD_GOTO: /* ... ==> ... */
3449 /* op1 = target JavaVM pc */
3450 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3451 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3453 i386_jmp_imm(cd, 0);
3454 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3457 case ICMD_JSR: /* ... ==> ... */
3458 /* op1 = target JavaVM pc */
3459 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3460 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3462 i386_call_imm(cd, 0);
3463 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3466 case ICMD_RET: /* ... ==> ... */
3467 /* op1 = local variable */
3468 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3469 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3471 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3472 var_to_reg_int(s1, var, REG_ITMP1);
3473 i386_jmp_reg(cd, s1);
3476 case ICMD_IFNULL: /* ..., value ==> ... */
3477 /* op1 = target JavaVM pc */
3478 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3479 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3481 if (src->flags & INMEMORY) {
3482 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3485 i386_test_reg_reg(cd, src->regoff, src->regoff);
3487 i386_jcc(cd, I386_CC_E, 0);
3488 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3491 case ICMD_IFNONNULL: /* ..., value ==> ... */
3492 /* op1 = target JavaVM pc */
3493 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3494 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3496 if (src->flags & INMEMORY) {
3497 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3500 i386_test_reg_reg(cd, src->regoff, src->regoff);
3502 i386_jcc(cd, I386_CC_NE, 0);
3503 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3506 case ICMD_IFEQ: /* ..., value ==> ... */
3507 /* op1 = target JavaVM pc, val.i = constant */
3508 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3509 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3511 if (src->flags & INMEMORY) {
3512 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3515 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3517 i386_jcc(cd, I386_CC_E, 0);
3518 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3521 case ICMD_IFLT: /* ..., value ==> ... */
3522 /* op1 = target JavaVM pc, val.i = constant */
3523 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3524 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3526 if (src->flags & INMEMORY) {
3527 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3530 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3532 i386_jcc(cd, I386_CC_L, 0);
3533 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3536 case ICMD_IFLE: /* ..., value ==> ... */
3537 /* op1 = target JavaVM pc, val.i = constant */
3538 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3539 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3541 if (src->flags & INMEMORY) {
3542 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3545 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3547 i386_jcc(cd, I386_CC_LE, 0);
3548 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3551 case ICMD_IFNE: /* ..., value ==> ... */
3552 /* op1 = target JavaVM pc, val.i = constant */
3553 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3554 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3556 if (src->flags & INMEMORY) {
3557 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3560 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3562 i386_jcc(cd, I386_CC_NE, 0);
3563 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3566 case ICMD_IFGT: /* ..., value ==> ... */
3567 /* op1 = target JavaVM pc, val.i = constant */
3568 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3569 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3571 if (src->flags & INMEMORY) {
3572 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3575 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3577 i386_jcc(cd, I386_CC_G, 0);
3578 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3581 case ICMD_IFGE: /* ..., value ==> ... */
3582 /* op1 = target JavaVM pc, val.i = constant */
3583 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3584 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3586 if (src->flags & INMEMORY) {
3587 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3590 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3592 i386_jcc(cd, I386_CC_GE, 0);
3593 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3596 case ICMD_IF_LEQ: /* ..., value ==> ... */
3597 /* op1 = target JavaVM pc, val.l = constant */
3598 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3599 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3601 if (src->flags & INMEMORY) {
3602 if (iptr->val.l == 0) {
3603 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3604 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3607 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3608 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l >> 32, REG_ITMP2);
3609 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3610 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l, REG_ITMP1);
3611 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3614 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3615 i386_jcc(cd, I386_CC_E, 0);
3616 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3619 case ICMD_IF_LLT: /* ..., value ==> ... */
3620 /* op1 = target JavaVM pc, val.l = constant */
3621 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3622 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3624 if (src->flags & INMEMORY) {
3625 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3626 i386_jcc(cd, I386_CC_L, 0);
3627 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3630 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3631 CALCIMMEDIATEBYTES(a, iptr->val.l);
3633 i386_jcc(cd, I386_CC_G, a);
3635 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3636 i386_jcc(cd, I386_CC_B, 0);
3637 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3641 case ICMD_IF_LLE: /* ..., value ==> ... */
3642 /* op1 = target JavaVM pc, val.l = constant */
3643 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3644 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3646 if (src->flags & INMEMORY) {
3647 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3648 i386_jcc(cd, I386_CC_L, 0);
3649 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3652 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3653 CALCIMMEDIATEBYTES(a, iptr->val.l);
3655 i386_jcc(cd, I386_CC_G, a);
3657 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3658 i386_jcc(cd, I386_CC_BE, 0);
3659 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3663 case ICMD_IF_LNE: /* ..., value ==> ... */
3664 /* op1 = target JavaVM pc, val.l = constant */
3665 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3666 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3668 if (src->flags & INMEMORY) {
3669 if (iptr->val.l == 0) {
3670 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3671 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3674 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3675 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3676 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3677 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3678 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3681 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3682 i386_jcc(cd, I386_CC_NE, 0);
3683 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3686 case ICMD_IF_LGT: /* ..., value ==> ... */
3687 /* op1 = target JavaVM pc, val.l = constant */
3688 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3689 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3691 if (src->flags & INMEMORY) {
3692 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3693 i386_jcc(cd, I386_CC_G, 0);
3694 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3697 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3698 CALCIMMEDIATEBYTES(a, iptr->val.l);
3700 i386_jcc(cd, I386_CC_L, a);
3702 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3703 i386_jcc(cd, I386_CC_A, 0);
3704 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3708 case ICMD_IF_LGE: /* ..., value ==> ... */
3709 /* op1 = target JavaVM pc, val.l = constant */
3710 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3711 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3713 if (src->flags & INMEMORY) {
3714 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3715 i386_jcc(cd, I386_CC_G, 0);
3716 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3719 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3720 CALCIMMEDIATEBYTES(a, iptr->val.l);
3722 i386_jcc(cd, I386_CC_L, a);
3724 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3725 i386_jcc(cd, I386_CC_AE, 0);
3726 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3730 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3731 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3732 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3733 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3735 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3736 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3737 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3739 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3740 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3742 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3743 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3746 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3748 i386_jcc(cd, I386_CC_E, 0);
3749 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3752 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3753 /* op1 = target JavaVM pc */
3754 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3755 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3757 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3758 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3759 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3760 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3761 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3762 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3763 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3765 i386_jcc(cd, I386_CC_E, 0);
3766 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3769 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3770 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3771 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3772 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3774 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3775 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3776 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3778 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3779 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3781 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3782 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3785 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3787 i386_jcc(cd, I386_CC_NE, 0);
3788 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3791 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3792 /* op1 = target JavaVM pc */
3793 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3794 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3796 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3797 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3798 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3799 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3800 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3801 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3802 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3804 i386_jcc(cd, I386_CC_NE, 0);
3805 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3808 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3809 /* op1 = target JavaVM pc */
3810 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3811 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3813 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3814 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3815 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3817 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3818 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3820 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3821 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3824 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3826 i386_jcc(cd, I386_CC_L, 0);
3827 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3830 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3831 /* op1 = target JavaVM pc */
3832 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3833 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3835 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3836 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3837 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3838 i386_jcc(cd, I386_CC_L, 0);
3839 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3842 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 4);
3843 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3845 i386_jcc(cd, I386_CC_G, a);
3847 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3848 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3849 i386_jcc(cd, I386_CC_B, 0);
3850 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3854 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3855 /* op1 = target JavaVM pc */
3856 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3857 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3859 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3860 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3861 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3863 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3864 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3866 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3867 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3870 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3872 i386_jcc(cd, I386_CC_G, 0);
3873 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3876 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3877 /* op1 = target JavaVM pc */
3878 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3879 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3881 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3882 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3883 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3884 i386_jcc(cd, I386_CC_G, 0);
3885 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3888 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 4);
3889 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3891 i386_jcc(cd, I386_CC_L, a);
3893 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3894 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3895 i386_jcc(cd, I386_CC_A, 0);
3896 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3900 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3901 /* op1 = target JavaVM pc */
3902 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3903 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3905 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3906 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3907 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3909 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3910 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3912 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3913 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3916 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3918 i386_jcc(cd, I386_CC_LE, 0);
3919 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3922 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3923 /* op1 = target JavaVM pc */
3924 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3925 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3927 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3928 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3929 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3930 i386_jcc(cd, I386_CC_L, 0);
3931 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3934 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 4);
3935 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3937 i386_jcc(cd, I386_CC_G, a);
3939 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3940 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3941 i386_jcc(cd, I386_CC_BE, 0);
3942 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3946 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3947 /* op1 = target JavaVM pc */
3948 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3949 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3951 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3952 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3953 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3955 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3956 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3958 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3959 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3962 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3964 i386_jcc(cd, I386_CC_GE, 0);
3965 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3968 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3969 /* op1 = target JavaVM pc */
3970 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3971 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3973 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3974 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3975 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3976 i386_jcc(cd, I386_CC_G, 0);
3977 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3980 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 4);
3981 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3983 i386_jcc(cd, I386_CC_L, a);
3985 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3986 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3987 i386_jcc(cd, I386_CC_AE, 0);
3988 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
3992 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3994 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3995 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3996 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3999 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
4000 /* val.i = constant */
4001 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4002 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4004 d = reg_of_var(rd, iptr->dst, REG_NULL);
4005 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
4008 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
4009 /* val.i = constant */
4010 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4011 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4013 d = reg_of_var(rd, iptr->dst, REG_NULL);
4014 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
4017 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
4018 /* val.i = constant */
4019 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4020 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4022 d = reg_of_var(rd, iptr->dst, REG_NULL);
4023 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
4026 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
4027 /* val.i = constant */
4028 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4029 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4031 d = reg_of_var(rd, iptr->dst, REG_NULL);
4032 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
4035 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
4036 /* val.i = constant */
4037 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4038 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4040 d = reg_of_var(rd, iptr->dst, REG_NULL);
4041 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
4044 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
4045 /* val.i = constant */
4046 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4047 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4049 d = reg_of_var(rd, iptr->dst, REG_NULL);
4050 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
4054 case ICMD_IRETURN: /* ..., retvalue ==> ... */
4055 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4056 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4058 var_to_reg_int(s1, src, REG_RESULT);
4059 M_INTMOVE(s1, REG_RESULT);
4060 goto nowperformreturn;
4062 case ICMD_LRETURN: /* ..., retvalue ==> ... */
4063 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4064 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4066 if (src->flags & INMEMORY) {
4067 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_RESULT);
4068 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_RESULT2);
4071 log_text("LRETURN: longs have to be in memory");
4074 goto nowperformreturn;
4076 case ICMD_ARETURN: /* ..., retvalue ==> ... */
4077 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4078 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4080 var_to_reg_int(s1, src, REG_RESULT);
4081 M_INTMOVE(s1, REG_RESULT);
4083 #ifdef ENABLE_VERIFIER
4085 codegen_addpatchref(cd, cd->mcodeptr,
4086 PATCHER_athrow_areturn,
4087 (unresolved_class *) iptr->val.a, 0);
4089 if (opt_showdisassemble) {
4090 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4093 #endif /* ENABLE_VERIFIER */
4094 goto nowperformreturn;
4096 case ICMD_FRETURN: /* ..., retvalue ==> ... */
4098 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4099 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4101 var_to_reg_flt(s1, src, REG_FRESULT);
4102 /* this may be an early return -- keep the offset correct for the
4105 goto nowperformreturn;
4107 case ICMD_RETURN: /* ... ==> ... */
4108 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4109 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4115 p = parentargs_base;
4117 /* call trace function */
4119 i386_alu_imm_reg(cd, ALU_SUB, 4 + 8 + 8 + 4, REG_SP);
4121 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
4123 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
4124 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
4126 i386_fstl_membase(cd, REG_SP, 4 + 8);
4127 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
4129 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
4130 i386_call_reg(cd, REG_ITMP1);
4132 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
4133 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
4135 i386_alu_imm_reg(cd, ALU_ADD, 4 + 8 + 8 + 4, REG_SP);
4138 #if defined(USE_THREADS)
4139 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
4140 M_ALD(REG_ITMP2, REG_SP, rd->memuse * 4);
4142 /* we need to save the proper return value */
4143 switch (iptr->opc) {
4146 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4150 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4151 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4155 i386_fstps_membase(cd, REG_SP, rd->memuse * 4);
4159 i386_fstpl_membase(cd, REG_SP, rd->memuse * 4);
4163 M_AST(REG_ITMP2, REG_SP, 0);
4164 M_MOV_IMM((ptrint) BUILTIN_monitorexit, REG_ITMP1);
4167 /* and now restore the proper return value */
4168 switch (iptr->opc) {
4171 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4175 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4176 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4180 i386_flds_membase(cd, REG_SP, rd->memuse * 4);
4184 i386_fldl_membase(cd, REG_SP, rd->memuse * 4);
4190 /* restore saved registers */
4192 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
4193 p--; M_ALD(rd->savintregs[i], REG_SP, p * 4);
4196 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
4198 i386_fldl_membase(cd, REG_SP, p * 4);
4200 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
4201 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
4203 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
4208 /* deallocate stack */
4210 if (parentargs_base)
4211 M_AADD_IMM(parentargs_base * 4, REG_SP);
4218 case ICMD_TABLESWITCH: /* ..., index ==> ... */
4219 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4220 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4225 tptr = (void **) iptr->target;
4227 s4ptr = iptr->val.a;
4228 l = s4ptr[1]; /* low */
4229 i = s4ptr[2]; /* high */
4231 var_to_reg_int(s1, src, REG_ITMP1);
4232 M_INTMOVE(s1, REG_ITMP1);
4234 i386_alu_imm_reg(cd, ALU_SUB, l, REG_ITMP1);
4240 i386_alu_imm_reg(cd, ALU_CMP, i - 1, REG_ITMP1);
4241 i386_jcc(cd, I386_CC_A, 0);
4243 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4245 /* build jump table top down and use address of lowest entry */
4250 dseg_addtarget(cd, (basicblock *) tptr[0]);
4254 /* length of dataseg after last dseg_addtarget is used by load */
4256 i386_mov_imm_reg(cd, 0, REG_ITMP2);
4257 dseg_adddata(cd, cd->mcodeptr);
4258 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
4259 i386_jmp_reg(cd, REG_ITMP1);
4264 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
4265 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4266 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4268 s4 i, l, val, *s4ptr;
4271 tptr = (void **) iptr->target;
4273 s4ptr = iptr->val.a;
4274 l = s4ptr[0]; /* default */
4275 i = s4ptr[1]; /* count */
4277 MCODECHECK((i<<2)+8);
4278 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
4284 i386_alu_imm_reg(cd, ALU_CMP, val, s1);
4285 i386_jcc(cd, I386_CC_E, 0);
4286 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4289 i386_jmp_imm(cd, 0);
4291 tptr = (void **) iptr->target;
4292 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4296 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
4297 /* op1 = arg count val.a = builtintable entry */
4298 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4299 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4305 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
4306 /* op1 = arg count, val.a = method pointer */
4308 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
4309 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
4310 case ICMD_INVOKEINTERFACE:
4312 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4313 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
4318 unresolved_method *um = iptr->target;
4319 md = um->methodref->parseddesc.md;
4321 md = lm->parseddesc;
4325 s3 = md->paramcount;
4327 MCODECHECK((s3 << 1) + 64);
4329 /* copy arguments to registers or stack location */
4331 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
4332 if (src->varkind == ARGVAR)
4334 if (IS_INT_LNG_TYPE(src->type)) {
4335 if (!md->params[s3].inmemory) {
4336 log_text("No integer argument registers available!");
4339 if (!IS_2_WORD_TYPE(src->type)) {
4340 if (src->flags & INMEMORY) {
4341 i386_mov_membase_reg(
4342 cd, REG_SP, src->regoff * 4, REG_ITMP1);
4343 i386_mov_reg_membase(
4344 cd, REG_ITMP1, REG_SP,
4345 md->params[s3].regoff * 4);
4347 i386_mov_reg_membase(
4348 cd, src->regoff, REG_SP,
4349 md->params[s3].regoff * 4);
4353 if (src->flags & INMEMORY) {
4355 src->regoff, md->params[s3].regoff);
4357 log_text("copy arguments: longs have to be in memory");
4363 if (!md->params[s3].inmemory) {
4364 log_text("No float argument registers available!");
4367 var_to_reg_flt(d, src, REG_FTMP1);
4368 if (src->type == TYPE_FLT) {
4370 cd, REG_SP, md->params[s3].regoff * 4);
4374 cd, REG_SP, md->params[s3].regoff * 4);
4380 switch (iptr->opc) {
4382 a = (ptrint) bte->fp;
4383 d = md->returntype.type;
4385 M_MOV_IMM(a, REG_ITMP1);
4388 /* if op1 == true, we need to check for an exception */
4390 if (iptr->op1 == true) {
4393 codegen_addxexceptionrefs(cd, cd->mcodeptr);
4397 case ICMD_INVOKESPECIAL:
4398 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
4399 gen_nullptr_check(REG_ITMP1);
4401 /* access memory for hardware nullptr */
4402 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1);
4406 case ICMD_INVOKESTATIC:
4408 unresolved_method *um = iptr->target;
4410 codegen_addpatchref(cd, cd->mcodeptr,
4411 PATCHER_invokestatic_special, um, 0);
4413 if (opt_showdisassemble) {
4414 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4418 d = md->returntype.type;
4421 a = (ptrint) lm->stubroutine;
4422 d = lm->parseddesc->returntype.type;
4425 M_MOV_IMM(a, REG_ITMP2);
4429 case ICMD_INVOKEVIRTUAL:
4430 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4431 gen_nullptr_check(REG_ITMP1);
4434 unresolved_method *um = iptr->target;
4436 codegen_addpatchref(cd, cd->mcodeptr,
4437 PATCHER_invokevirtual, um, 0);
4439 if (opt_showdisassemble) {
4440 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4444 d = md->returntype.type;
4447 s1 = OFFSET(vftbl_t, table[0]) +
4448 sizeof(methodptr) * lm->vftblindex;
4449 d = md->returntype.type;
4452 M_ALD(REG_ITMP2, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4453 i386_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP1);
4457 case ICMD_INVOKEINTERFACE:
4458 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4459 gen_nullptr_check(REG_ITMP1);
4462 unresolved_method *um = iptr->target;
4464 codegen_addpatchref(cd, cd->mcodeptr,
4465 PATCHER_invokeinterface, um, 0);
4467 if (opt_showdisassemble) {
4468 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4473 d = md->returntype.type;
4476 s1 = OFFSET(vftbl_t, interfacetable[0]) -
4477 sizeof(methodptr) * lm->class->index;
4479 s2 = sizeof(methodptr) * (lm - lm->class->methods);
4481 d = md->returntype.type;
4484 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4485 i386_mov_membase32_reg(cd, REG_ITMP1, s1, REG_ITMP2);
4486 i386_mov_membase32_reg(cd, REG_ITMP2, s2, REG_ITMP1);
4491 /* d contains return type */
4493 if (d != TYPE_VOID) {
4494 d = reg_of_var(rd, iptr->dst, REG_NULL);
4496 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
4497 if (IS_2_WORD_TYPE(iptr->dst->type)) {
4498 if (iptr->dst->flags & INMEMORY) {
4499 i386_mov_reg_membase(
4500 cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4501 i386_mov_reg_membase(
4502 cd, REG_RESULT2, REG_SP,
4503 iptr->dst->regoff * 4 + 4);
4505 log_text("RETURN: longs have to be in memory");
4510 if (iptr->dst->flags & INMEMORY) {
4511 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4514 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
4519 /* fld from called function -- has other fpu_st_offset counter */
4521 store_reg_to_var_flt(iptr->dst, d);
4527 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4528 /* op1: 0 == array, 1 == class */
4529 /* val.a: (classinfo*) superclass */
4531 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4532 /* EAX: YES ECX: I|YES EDX: I|YES OUTPUT: REG_NULL */
4534 /* superclass is an interface:
4536 * OK if ((sub == NULL) ||
4537 * (sub->vftbl->interfacetablelength > super->index) &&
4538 * (sub->vftbl->interfacetable[-super->index] != NULL));
4540 * superclass is a class:
4542 * OK if ((sub == NULL) || (0
4543 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4544 * super->vftbl->diffval));
4547 if (iptr->op1 == 1) {
4548 /* object type cast-check */
4551 vftbl_t *supervftbl;
4554 super = (classinfo *) iptr->val.a;
4561 superindex = super->index;
4562 supervftbl = super->vftbl;
4565 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4566 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4568 var_to_reg_int(s1, src, REG_ITMP1);
4570 /* calculate interface checkcast code size */
4572 s2 = 2; /* mov_membase_reg */
4573 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4575 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ +
4576 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4577 2 /* test */ + 6 /* jcc */);
4580 s2 += (opt_showdisassemble ? 5 : 0);
4582 /* calculate class checkcast code size */
4584 s3 = 2; /* mov_membase_reg */
4585 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4587 s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */;
4590 if (s1 != REG_ITMP1) {
4592 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
4595 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
4602 s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ +
4603 5 /* mov_imm_reg */ + 2 /* mov_membase_reg */);
4604 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
4607 s3 += 2 /* cmp */ + 6 /* jcc */;
4610 s3 += (opt_showdisassemble ? 5 : 0);
4612 /* if class is not resolved, check which code to call */
4615 i386_test_reg_reg(cd, s1, s1);
4616 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4618 codegen_addpatchref(cd, cd->mcodeptr,
4619 PATCHER_checkcast_instanceof_flags,
4620 (constant_classref *) iptr->target, 0);
4622 if (opt_showdisassemble) {
4623 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4626 i386_mov_imm_reg(cd, 0, REG_ITMP2); /* super->flags */
4627 i386_alu_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP2);
4628 i386_jcc(cd, I386_CC_Z, s2 + 5);
4631 /* interface checkcast code */
4633 if (!super || (super->flags & ACC_INTERFACE)) {
4635 i386_test_reg_reg(cd, s1, s1);
4636 i386_jcc(cd, I386_CC_Z, s2);
4639 i386_mov_membase_reg(cd, s1,
4640 OFFSET(java_objectheader, vftbl),
4644 codegen_addpatchref(cd, cd->mcodeptr,
4645 PATCHER_checkcast_instanceof_interface,
4646 (constant_classref *) iptr->target, 0);
4648 if (opt_showdisassemble) {
4649 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4653 i386_mov_membase32_reg(cd, REG_ITMP2,
4654 OFFSET(vftbl_t, interfacetablelength),
4656 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4657 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4658 i386_jcc(cd, I386_CC_LE, 0);
4659 codegen_addxcastrefs(cd, cd->mcodeptr);
4660 i386_mov_membase32_reg(cd, REG_ITMP2,
4661 OFFSET(vftbl_t, interfacetable[0]) -
4662 superindex * sizeof(methodptr*),
4664 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4665 i386_jcc(cd, I386_CC_E, 0);
4666 codegen_addxcastrefs(cd, cd->mcodeptr);
4669 i386_jmp_imm(cd, s3);
4672 /* class checkcast code */
4674 if (!super || !(super->flags & ACC_INTERFACE)) {
4676 i386_test_reg_reg(cd, s1, s1);
4677 i386_jcc(cd, I386_CC_Z, s3);
4680 i386_mov_membase_reg(cd, s1,
4681 OFFSET(java_objectheader, vftbl),
4685 codegen_addpatchref(cd, cd->mcodeptr,
4686 PATCHER_checkcast_class,
4687 (constant_classref *) iptr->target, 0);
4689 if (opt_showdisassemble) {
4690 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4694 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4695 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4696 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4698 i386_mov_membase32_reg(cd, REG_ITMP2,
4699 OFFSET(vftbl_t, baseval),
4702 /* if (s1 != REG_ITMP1) { */
4703 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
4704 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
4705 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
4706 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
4708 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
4711 i386_mov_membase32_reg(cd, REG_ITMP3,
4712 OFFSET(vftbl_t, baseval),
4714 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP3, REG_ITMP2);
4715 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4716 i386_mov_membase_reg(cd, REG_ITMP3,
4717 OFFSET(vftbl_t, diffval),
4719 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4720 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4724 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP2);
4725 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
4726 codegen_addxcastrefs(cd, cd->mcodeptr);
4728 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4731 /* array type cast-check */
4733 var_to_reg_int(s1, src, REG_ITMP1);
4734 M_AST(s1, REG_SP, 0 * 4);
4736 if (iptr->val.a == NULL) {
4737 codegen_addpatchref(cd, cd->mcodeptr,
4738 PATCHER_builtin_arraycheckcast,
4741 if (opt_showdisassemble) {
4742 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4746 M_AST_IMM((ptrint) iptr->val.a, REG_SP, 1 * 4);
4747 M_MOV_IMM((ptrint) BUILTIN_arraycheckcast, REG_ITMP3);
4751 codegen_addxcastrefs(cd, cd->mcodeptr);
4753 var_to_reg_int(s1, src, REG_ITMP1);
4754 d = reg_of_var(rd, iptr->dst, s1);
4757 store_reg_to_var_int(iptr->dst, d);
4760 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
4762 /* op1: 0 == array, 1 == class */
4763 /* val.a: (classinfo*) superclass */
4764 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4765 /* EAX: S|D|YES ECX: YES S|D|EDX: S|D|YES OUTPUT: REG_NULL*/
4766 /* ????? Really necessary to block all ????? */
4768 /* superclass is an interface:
4770 * return (sub != NULL) &&
4771 * (sub->vftbl->interfacetablelength > super->index) &&
4772 * (sub->vftbl->interfacetable[-super->index] != NULL);
4774 * superclass is a class:
4776 * return ((sub != NULL) && (0
4777 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4778 * super->vftbl->diffvall));
4783 vftbl_t *supervftbl;
4786 super = (classinfo *) iptr->val.a;
4793 superindex = super->index;
4794 supervftbl = super->vftbl;
4797 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4798 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4801 var_to_reg_int(s1, src, REG_ITMP1);
4802 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
4804 M_INTMOVE(s1, REG_ITMP1);
4808 /* calculate interface instanceof code size */
4810 s2 = 2; /* mov_membase_reg */
4811 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4813 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
4814 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4815 2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4818 s2 += (opt_showdisassemble ? 5 : 0);
4820 /* calculate class instanceof code size */
4822 s3 = 2; /* mov_membase_reg */
4823 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4824 s3 += 5; /* mov_imm_reg */
4826 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
4828 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
4830 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
4832 s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
4833 2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4836 s3 += (opt_showdisassemble ? 5 : 0);
4838 i386_alu_reg_reg(cd, ALU_XOR, d, d);
4840 /* if class is not resolved, check which code to call */
4843 i386_test_reg_reg(cd, s1, s1);
4844 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4846 codegen_addpatchref(cd, cd->mcodeptr,
4847 PATCHER_checkcast_instanceof_flags,
4848 (constant_classref *) iptr->target, 0);
4850 if (opt_showdisassemble) {
4851 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4854 i386_mov_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
4855 i386_alu_imm32_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
4856 i386_jcc(cd, I386_CC_Z, s2 + 5);
4859 /* interface instanceof code */
4861 if (!super || (super->flags & ACC_INTERFACE)) {
4863 i386_test_reg_reg(cd, s1, s1);
4864 i386_jcc(cd, I386_CC_Z, s2);
4867 i386_mov_membase_reg(cd, s1,
4868 OFFSET(java_objectheader, vftbl),
4872 codegen_addpatchref(cd, cd->mcodeptr,
4873 PATCHER_checkcast_instanceof_interface,
4874 (constant_classref *) iptr->target, 0);
4876 if (opt_showdisassemble) {
4877 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4881 i386_mov_membase32_reg(cd, REG_ITMP1,
4882 OFFSET(vftbl_t, interfacetablelength),
4884 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4885 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4887 a = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
4888 6 /* jcc */ + 5 /* mov_imm_reg */);
4890 i386_jcc(cd, I386_CC_LE, a);
4891 i386_mov_membase32_reg(cd, REG_ITMP1,
4892 OFFSET(vftbl_t, interfacetable[0]) -
4893 superindex * sizeof(methodptr*),
4895 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
4896 /* i386_setcc_reg(cd, I386_CC_A, d); */
4897 /* i386_jcc(cd, I386_CC_BE, 5); */
4898 i386_jcc(cd, I386_CC_E, 5);
4899 i386_mov_imm_reg(cd, 1, d);
4902 i386_jmp_imm(cd, s3);
4905 /* class instanceof code */
4907 if (!super || !(super->flags & ACC_INTERFACE)) {
4909 i386_test_reg_reg(cd, s1, s1);
4910 i386_jcc(cd, I386_CC_Z, s3);
4913 i386_mov_membase_reg(cd, s1,
4914 OFFSET(java_objectheader, vftbl),
4918 codegen_addpatchref(cd, cd->mcodeptr,
4919 PATCHER_instanceof_class,
4920 (constant_classref *) iptr->target, 0);
4922 if (opt_showdisassemble) {
4923 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4927 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
4928 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4929 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4931 i386_mov_membase_reg(cd, REG_ITMP1,
4932 OFFSET(vftbl_t, baseval),
4934 i386_mov_membase_reg(cd, REG_ITMP2,
4935 OFFSET(vftbl_t, diffval),
4937 i386_mov_membase_reg(cd, REG_ITMP2,
4938 OFFSET(vftbl_t, baseval),
4940 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4941 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4943 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
4944 i386_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
4945 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
4946 i386_jcc(cd, I386_CC_A, 5);
4947 i386_mov_imm_reg(cd, 1, d);
4949 store_reg_to_var_int(iptr->dst, d);
4955 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4956 /* op1 = dimension, val.a = class */
4957 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4958 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
4960 /* check for negative sizes and copy sizes to stack if necessary */
4962 MCODECHECK((iptr->op1 << 1) + 64);
4964 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4965 /* copy SAVEDVAR sizes to stack */
4967 if (src->varkind != ARGVAR) {
4968 if (src->flags & INMEMORY) {
4969 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
4970 M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4);
4973 M_IST(src->regoff, REG_SP, (s1 + 3) * 4);
4978 /* is a patcher function set? */
4980 if (iptr->val.a == NULL) {
4981 codegen_addpatchref(cd, cd->mcodeptr,
4982 PATCHER_builtin_multianewarray,
4983 (constant_classref *) iptr->target, 0);
4985 if (opt_showdisassemble) {
4986 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4992 a = (ptrint) iptr->val.a;
4995 /* a0 = dimension count */
4997 i386_mov_imm_membase(cd, iptr->op1, REG_SP, 0 * 4);
4999 /* a1 = arraydescriptor */
5001 i386_mov_imm_membase(cd, a, REG_SP, 1 * 4);
5003 /* a2 = pointer to dimensions = stack pointer */
5005 M_MOV(REG_SP, REG_ITMP1);
5006 M_AADD_IMM(3 * 4, REG_ITMP1);
5007 M_AST(REG_ITMP1, REG_SP, 2 * 4);
5009 M_MOV_IMM((ptrint) BUILTIN_multianewarray, REG_ITMP1);
5012 /* check for exception before result assignment */
5016 codegen_addxexceptionrefs(cd, cd->mcodeptr);
5018 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
5019 M_INTMOVE(REG_RESULT, s1);
5020 store_reg_to_var_int(iptr->dst, s1);
5025 new_internalerror("Unknown ICMD %d", iptr->opc);
5029 } /* for instruction */
5031 /* copy values to interface registers */
5033 src = bptr->outstack;
5034 len = bptr->outdepth;
5036 #if defined(ENABLE_LSRA)
5041 if ((src->varkind != STACKVAR)) {
5043 if (IS_FLT_DBL_TYPE(s2)) {
5044 var_to_reg_flt(s1, src, REG_FTMP1);
5045 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5046 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
5049 log_text("double store");
5051 /* M_DST(s1, REG_SP, 4 * interfaces[len][s2].regoff); */
5055 var_to_reg_int(s1, src, REG_ITMP1);
5056 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
5057 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5058 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
5061 i386_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5065 if (rd->interfaces[len][s2].flags & INMEMORY) {
5066 M_LNGMEMMOVE(s1, rd->interfaces[len][s2].regoff);
5069 log_text("copy interface registers: longs have to be in memory (end)");
5078 /* At the end of a basic block we may have to append some nops,
5079 because the patcher stub calling code might be longer than the
5080 actual instruction. So codepatching does not change the
5081 following block unintentionally. */
5083 if (cd->mcodeptr < cd->lastmcodeptr) {
5084 while (cd->mcodeptr < cd->lastmcodeptr) {
5089 } /* if (bptr -> flags >= BBREACHED) */
5090 } /* for basic block */
5092 dseg_createlinenumbertable(cd);
5099 /* generate ArithmeticException stubs */
5103 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
5104 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5106 cd->mcodeptr - cd->mcodebase);
5110 M_MOV_IMM(0, REG_ITMP2_XPC);
5111 dseg_adddata(cd, cd->mcodeptr);
5112 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5114 if (xcodeptr != NULL) {
5115 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5118 xcodeptr = cd->mcodeptr;
5120 M_ASUB_IMM(4 * 4, REG_SP);
5122 M_AST_IMM(0, REG_SP, 0 * 4);
5123 dseg_adddata(cd, cd->mcodeptr);
5124 M_MOV(REG_SP, REG_ITMP3);
5125 M_AADD_IMM(4 * 4, REG_ITMP3);
5126 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5127 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5128 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5129 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5131 M_MOV_IMM((ptrint) stacktrace_inline_arithmeticexception,
5135 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5136 M_AADD_IMM(4 * 4, REG_SP);
5138 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5143 /* generate ArrayIndexOutOfBoundsException stubs */
5147 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
5148 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5150 cd->mcodeptr - cd->mcodebase);
5154 /* move index register into REG_ITMP1 */
5156 M_INTMOVE(bref->reg, REG_ITMP1);
5158 M_MOV_IMM(0, REG_ITMP2_XPC);
5159 dseg_adddata(cd, cd->mcodeptr);
5160 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5162 if (xcodeptr != NULL) {
5163 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5166 xcodeptr = cd->mcodeptr;
5168 M_ASUB_IMM(5 * 4, REG_SP);
5170 M_AST_IMM(0, REG_SP, 0 * 4);
5171 dseg_adddata(cd, cd->mcodeptr);
5172 M_MOV(REG_SP, REG_ITMP3);
5173 M_AADD_IMM(5 * 4, REG_ITMP3);
5174 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5175 M_ALD(REG_ITMP3, REG_SP, (5 + parentargs_base) * 4);
5176 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5177 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5178 M_AST(REG_ITMP1, REG_SP, 4 * 4); /* don't use REG_ITMP1 till here */
5180 M_MOV_IMM((ptrint) stacktrace_inline_arrayindexoutofboundsexception,
5184 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5185 M_AADD_IMM(5 * 4, REG_SP);
5187 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5192 /* generate ArrayStoreException stubs */
5196 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
5197 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5199 cd->mcodeptr - cd->mcodebase);
5203 M_MOV_IMM(0, REG_ITMP2_XPC);
5204 dseg_adddata(cd, cd->mcodeptr);
5205 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5207 if (xcodeptr != NULL) {
5208 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5211 xcodeptr = cd->mcodeptr;
5213 M_ASUB_IMM(4 * 4, REG_SP);
5215 M_AST_IMM(0, REG_SP, 0 * 4);
5216 dseg_adddata(cd, cd->mcodeptr);
5217 M_MOV(REG_SP, REG_ITMP3);
5218 M_AADD_IMM(4 * 4, REG_ITMP3);
5219 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5220 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5221 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5222 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5224 M_MOV_IMM((ptrint) stacktrace_inline_arraystoreexception,
5228 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5229 M_AADD_IMM(4 * 4, REG_SP);
5231 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5236 /* generate ClassCastException stubs */
5240 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
5241 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5243 cd->mcodeptr - cd->mcodebase);
5247 M_MOV_IMM(0, REG_ITMP2_XPC);
5248 dseg_adddata(cd, cd->mcodeptr);
5249 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5251 if (xcodeptr != NULL) {
5252 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5255 xcodeptr = cd->mcodeptr;
5257 M_ASUB_IMM(4 * 4, REG_SP);
5259 M_AST_IMM(0, REG_SP, 0 * 4);
5260 dseg_adddata(cd, cd->mcodeptr);
5261 M_MOV(REG_SP, REG_ITMP3);
5262 M_AADD_IMM(4 * 4, REG_ITMP3);
5263 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5264 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5265 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5266 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5268 M_MOV_IMM((ptrint) stacktrace_inline_classcastexception, REG_ITMP3);
5271 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5272 M_AADD_IMM(4 * 4, REG_SP);
5274 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5279 /* generate NullPointerException stubs */
5283 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
5284 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5286 cd->mcodeptr - cd->mcodebase);
5290 M_MOV_IMM(0, REG_ITMP2_XPC);
5291 dseg_adddata(cd, cd->mcodeptr);
5292 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5294 if (xcodeptr != NULL) {
5295 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5298 xcodeptr = cd->mcodeptr;
5300 M_ASUB_IMM(4 * 4, REG_SP);
5302 M_AST_IMM(0, REG_SP, 0 * 4);
5303 dseg_adddata(cd, cd->mcodeptr);
5304 M_MOV(REG_SP, REG_ITMP3);
5305 M_AADD_IMM(4 * 4, REG_ITMP3);
5306 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5307 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5308 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5309 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5311 M_MOV_IMM((ptrint) stacktrace_inline_nullpointerexception,
5315 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5316 M_AADD_IMM(4 * 4, REG_SP);
5318 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5323 /* generate exception check stubs */
5327 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
5328 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5330 cd->mcodeptr - cd->mcodebase);
5334 M_MOV_IMM(0, REG_ITMP2_XPC);
5335 dseg_adddata(cd, cd->mcodeptr);
5336 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC);
5338 if (xcodeptr != NULL) {
5339 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5342 xcodeptr = cd->mcodeptr;
5344 M_ASUB_IMM(4 * 4, REG_SP);
5346 M_AST_IMM(0, REG_SP, 0 * 4);
5347 dseg_adddata(cd, cd->mcodeptr);
5348 M_MOV(REG_SP, REG_ITMP3);
5349 M_AADD_IMM(4 * 4, REG_ITMP3);
5350 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5351 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5352 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5353 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5355 M_MOV_IMM((ptrint) stacktrace_inline_fillInStackTrace, REG_ITMP3);
5358 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5359 M_AADD_IMM(4 * 4, REG_SP);
5361 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5366 /* generate code patching stub call code */
5373 tmpcd = DNEW(codegendata);
5375 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5376 /* check code segment size */
5380 /* Get machine code which is patched back in later. A */
5381 /* `call rel32' is 5 bytes long. */
5383 xcodeptr = cd->mcodebase + pref->branchpos;
5384 mcode = *((u8 *) xcodeptr);
5386 /* patch in `call rel32' to call the following code */
5388 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5389 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5391 /* move pointer to java_objectheader onto stack */
5393 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5394 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
5395 off = dseg_addaddress(cd, NULL); /* vftbl */
5397 M_MOV_IMM(0, REG_ITMP3);
5398 dseg_adddata(cd, cd->mcodeptr);
5399 M_AADD_IMM(off, REG_ITMP3);
5405 /* move machine code bytes and classinfo pointer into registers */
5407 M_PUSH_IMM((ptrint) (mcode >> 32));
5408 M_PUSH_IMM((ptrint) mcode);
5409 M_PUSH_IMM((ptrint) pref->ref);
5410 M_PUSH_IMM((ptrint) pref->patcher);
5412 M_MOV_IMM((ptrint) asm_wrapper_patcher, REG_ITMP3);
5418 codegen_finish(m, cd, (ptrint) (cd->mcodeptr - cd->mcodebase));
5420 /* everything's ok */
5426 /* createcompilerstub **********************************************************
5428 Creates a stub routine which calls the compiler.
5430 *******************************************************************************/
5432 #define COMPILERSTUB_SIZE 12
5434 u1 *createcompilerstub(methodinfo *m)
5436 u1 *s; /* memory to hold the stub */
5440 s = CNEW(u1, COMPILERSTUB_SIZE);
5442 /* mark start of dump memory area */
5444 dumpsize = dump_size();
5446 cd = DNEW(codegendata);
5449 i386_mov_imm_reg(cd, (ptrint) m, REG_ITMP1);
5451 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
5452 i386_mov_imm_reg(cd, (ptrint) asm_call_jit_compiler, REG_ITMP3);
5453 i386_jmp_reg(cd, REG_ITMP3);
5455 #if defined(ENABLE_STATISTICS)
5457 count_cstub_len += COMPILERSTUB_SIZE;
5460 /* release dump area */
5462 dump_release(dumpsize);
5468 /* createnativestub ************************************************************
5470 Creates a stub routine which calls a native method.
5472 *******************************************************************************/
5474 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5475 /* this way we can call the function directly with a memory call */
5477 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
5480 u1 *createnativestub(functionptr f, methodinfo *m, codegendata *cd,
5481 registerdata *rd, methoddesc *nmd)
5486 s4 i, j; /* count variables */
5490 /* set some variables */
5493 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
5495 /* calculate stackframe size */
5498 sizeof(stackframeinfo) / SIZEOF_VOID_P +
5499 sizeof(localref_table) / SIZEOF_VOID_P +
5500 1 + /* function pointer */
5501 4 * 4 + /* 4 arguments (start_native_call) */
5505 /* create method header */
5507 (void) dseg_addaddress(cd, m); /* MethodPointer */
5508 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
5509 (void) dseg_adds4(cd, 0); /* IsSync */
5510 (void) dseg_adds4(cd, 0); /* IsLeaf */
5511 (void) dseg_adds4(cd, 0); /* IntSave */
5512 (void) dseg_adds4(cd, 0); /* FltSave */
5513 (void) dseg_addlinenumbertablesize(cd);
5514 (void) dseg_adds4(cd, 0); /* ExTableSize */
5517 /* initialize mcode variables */
5519 cd->mcodeptr = (u1 *) cd->mcodebase;
5520 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
5523 /* calculate stackframe size for native function */
5525 M_ASUB_IMM(stackframesize * 4, REG_SP);
5531 disp = stackframesize * 4;
5533 M_ASUB_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5535 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
5536 t = md->paramtypes[p].type;
5537 if (IS_INT_LNG_TYPE(t)) {
5538 if (IS_2_WORD_TYPE(t)) {
5539 M_ILD(REG_ITMP1, REG_SP,
5540 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5541 M_ILD(REG_ITMP2, REG_SP,
5542 4 + TRACE_ARGS_NUM * 8 + 4 + disp + 4);
5543 M_IST(REG_ITMP1, REG_SP, p * 8);
5544 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5546 } else if (t == TYPE_ADR) {
5547 M_ALD(REG_ITMP1, REG_SP,
5548 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5550 M_AST(REG_ITMP1, REG_SP, p * 8);
5551 M_AST(REG_ITMP2, REG_SP, p * 8 + 4);
5554 M_ILD(EAX, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5556 M_IST(EAX, REG_SP, p * 8);
5557 M_IST(EDX, REG_SP, p * 8 + 4);
5561 if (!IS_2_WORD_TYPE(t)) {
5562 i386_flds_membase(cd, REG_SP,
5563 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5564 i386_fstps_membase(cd, REG_SP, p * 8);
5565 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
5566 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5569 i386_fldl_membase(cd, REG_SP,
5570 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5571 i386_fstpl_membase(cd, REG_SP, p * 8);
5574 disp += (IS_2_WORD_TYPE(t)) ? 8 : 4;
5578 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
5579 M_IST(REG_ITMP1, REG_SP, p * 8);
5580 M_IST(REG_ITMP1, REG_SP, p * 8 + 4);
5583 M_AST_IMM((ptrint) m, REG_SP, TRACE_ARGS_NUM * 8);
5585 M_MOV_IMM((ptrint) builtin_trace_args, REG_ITMP1);
5588 M_AADD_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5591 /* get function address (this must happen before the stackframeinfo) */
5593 #if !defined(ENABLE_STATICVM)
5595 codegen_addpatchref(cd, cd->mcodeptr, PATCHER_resolve_native, m, 0);
5597 if (opt_showdisassemble) {
5598 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5603 M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
5605 /* Mark the whole fpu stack as free for native functions (only for saved */
5606 /* register count == 0). */
5608 i386_ffree_reg(cd, 0);
5609 i386_ffree_reg(cd, 1);
5610 i386_ffree_reg(cd, 2);
5611 i386_ffree_reg(cd, 3);
5612 i386_ffree_reg(cd, 4);
5613 i386_ffree_reg(cd, 5);
5614 i386_ffree_reg(cd, 6);
5615 i386_ffree_reg(cd, 7);
5617 /* prepare data structures for native function call */
5619 M_MOV(REG_SP, REG_ITMP1);
5620 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5622 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5623 M_IST_IMM(0, REG_SP, 1 * 4);
5624 dseg_adddata(cd, cd->mcodeptr);
5626 M_MOV(REG_SP, REG_ITMP2);
5627 M_AADD_IMM(stackframesize * 4 + SIZEOF_VOID_P, REG_ITMP2);
5629 M_AST(REG_ITMP2, REG_SP, 2 * 4);
5630 M_ALD(REG_ITMP3, REG_SP, stackframesize * 4);
5631 M_AST(REG_ITMP3, REG_SP, 3 * 4);
5632 M_MOV_IMM((ptrint) codegen_start_native_call, REG_ITMP1);
5635 M_ALD(REG_ITMP3, REG_SP, 4 * 4);
5637 /* copy arguments into new stackframe */
5639 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
5640 t = md->paramtypes[i].type;
5642 if (!md->params[i].inmemory) {
5643 /* no integer argument registers */
5644 } else { /* float/double in memory can be copied like int/longs */
5645 s1 = (md->params[i].regoff + stackframesize + 1) * 4;
5646 s2 = nmd->params[j].regoff * 4;
5648 M_ILD(REG_ITMP1, REG_SP, s1);
5649 M_IST(REG_ITMP1, REG_SP, s2);
5650 if (IS_2_WORD_TYPE(t)) {
5651 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
5652 M_IST(REG_ITMP1, REG_SP, s2 + 4);
5657 /* if function is static, put class into second argument */
5659 if (m->flags & ACC_STATIC)
5660 M_AST_IMM((ptrint) m->class, REG_SP, 1 * 4);
5662 /* put env into first argument */
5664 M_AST_IMM((ptrint) &env, REG_SP, 0 * 4);
5666 /* call the native function */
5670 /* save return value */
5672 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5673 if (IS_2_WORD_TYPE(md->returntype.type))
5674 M_IST(REG_RESULT2, REG_SP, 2 * 4);
5675 M_IST(REG_RESULT, REG_SP, 1 * 4);
5678 if (IS_2_WORD_TYPE(md->returntype.type))
5679 i386_fstl_membase(cd, REG_SP, 1 * 4);
5681 i386_fsts_membase(cd, REG_SP, 1 * 4);
5684 /* remove data structures for native function call */
5686 M_MOV(REG_SP, REG_ITMP1);
5687 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5689 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5690 M_MOV_IMM((ptrint) codegen_finish_native_call, REG_ITMP1);
5694 /* restore return value */
5696 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5697 if (IS_2_WORD_TYPE(md->returntype.type))
5698 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5699 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5702 if (IS_2_WORD_TYPE(md->returntype.type))
5703 i386_fldl_membase(cd, REG_SP, 1 * 4);
5705 i386_flds_membase(cd, REG_SP, 1 * 4);
5708 M_ASUB_IMM(4 + 8 + 8 + 4, REG_SP);
5710 M_AST_IMM((ptrint) m, REG_SP, 0);
5712 M_IST(REG_RESULT, REG_SP, 4);
5713 M_IST(REG_RESULT2, REG_SP, 4 + 4);
5715 i386_fstl_membase(cd, REG_SP, 4 + 8);
5716 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5718 M_MOV_IMM((ptrint) builtin_displaymethodstop, REG_ITMP1);
5721 M_AADD_IMM(4 + 8 + 8 + 4, REG_SP);
5724 /* check for exception */
5726 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5727 /* i386_call_mem(cd, (ptrint) builtin_get_exceptionptrptr); */
5728 i386_call_mem(cd, (ptrint) &callgetexceptionptrptr);
5730 M_MOV_IMM((ptrint) &_exceptionptr, REG_RESULT);
5732 /* we can't use REG_ITMP3 == REG_RESULT2 */
5733 M_ALD(REG_ITMP2, REG_RESULT, 0);
5735 /* restore return value */
5737 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5738 if (IS_2_WORD_TYPE(md->returntype.type))
5739 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5740 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5743 if (IS_2_WORD_TYPE(md->returntype.type))
5744 i386_fldl_membase(cd, REG_SP, 1 * 4);
5746 i386_flds_membase(cd, REG_SP, 1 * 4);
5749 M_AADD_IMM(stackframesize * 4, REG_SP);
5756 /* handle exception */
5758 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5759 i386_push_reg(cd, REG_ITMP2);
5760 /* i386_call_mem(cd, (ptrint) builtin_get_exceptionptrptr); */
5761 i386_call_mem(cd, (ptrint) &callgetexceptionptrptr);
5762 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5763 i386_pop_reg(cd, REG_ITMP1_XPTR);
5765 M_MOV(REG_ITMP2, REG_ITMP1_XPTR);
5766 M_MOV_IMM((ptrint) &_exceptionptr, REG_ITMP2);
5767 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5769 M_ALD(REG_ITMP2_XPC, REG_SP, 0);
5770 M_ASUB_IMM(2, REG_ITMP2_XPC);
5772 M_MOV_IMM((ptrint) asm_handle_nat_exception, REG_ITMP3);
5776 /* process patcher calls **************************************************/
5784 tmpcd = DNEW(codegendata);
5786 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5787 /* Get machine code which is patched back in later. A */
5788 /* `call rel32' is 5 bytes long. */
5790 xcodeptr = cd->mcodebase + pref->branchpos;
5791 mcode = *((u8 *) xcodeptr);
5793 /* patch in `call rel32' to call the following code */
5795 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5796 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5798 /* move pointer to java_objectheader onto stack */
5800 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5801 /* create a virtual java_objectheader */
5803 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
5804 disp = dseg_addaddress(cd, NULL); /* vftbl */
5806 M_MOV_IMM(0, REG_ITMP3);
5807 dseg_adddata(cd, cd->mcodeptr);
5808 M_AADD_IMM(disp, REG_ITMP3);
5814 /* move machine code bytes and classinfo pointer onto stack */
5816 M_PUSH_IMM((ptrint) (mcode >> 32));
5817 M_PUSH_IMM((ptrint) mcode);
5818 M_PUSH_IMM((ptrint) pref->ref);
5819 M_PUSH_IMM((ptrint) pref->patcher);
5821 M_MOV_IMM((ptrint) asm_wrapper_patcher, REG_ITMP3);
5826 codegen_finish(m, cd, (s4) ((u1 *) cd->mcodeptr - cd->mcodebase));
5828 return m->entrypoint;
5833 * These are local overrides for various environment variables in Emacs.
5834 * Please do not remove this and leave it at the end of the file, where
5835 * Emacs will automagically detect them.
5836 * ---------------------------------------------------------------------
5839 * indent-tabs-mode: t