1 /* src/vm/jit/i386/codegen.c - machine code generator for i386
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Andreas Krall
30 Changes: Joseph Wenninger
34 $Id: codegen.c 5040 2006-06-19 22:53:53Z twisti $
46 #include "vm/jit/i386/md-abi.h"
48 #include "vm/jit/i386/codegen.h"
49 #include "vm/jit/i386/md-emit.h"
51 #include "mm/memory.h"
52 #include "native/jni.h"
53 #include "native/native.h"
54 #include "vm/builtin.h"
55 #include "vm/exceptions.h"
56 #include "vm/global.h"
57 #include "vm/loader.h"
58 #include "vm/options.h"
59 #include "vm/stringlocal.h"
62 #include "vm/jit/asmpart.h"
63 #include "vm/jit/codegen-common.h"
64 #include "vm/jit/dseg.h"
65 #include "vm/jit/emit.h"
66 #include "vm/jit/jit.h"
67 #include "vm/jit/parse.h"
68 #include "vm/jit/patcher.h"
69 #include "vm/jit/reg.h"
70 #include "vm/jit/replace.h"
72 #if defined(ENABLE_LSRA)
73 # ifdef LSRA_USES_REG_RES
74 # include "vm/jit/i386/icmd_uses_reg_res.inc"
76 # include "vm/jit/allocator/lsra.h"
80 /* codegen *********************************************************************
82 Generates machine code.
84 *******************************************************************************/
86 bool codegen(jitdata *jd)
92 s4 len, s1, s2, s3, d, off, disp;
100 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
101 builtintable_entry *bte;
103 s4 fpu_st_offset = 0;
104 rplpoint *replacementpoint;
106 /* get required compiler data */
113 /* prevent compiler warnings */
123 s4 savedregs_num = 0;
126 /* space to save used callee saved registers */
128 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
130 /* float register are saved on 2 4-byte stackslots */
131 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
133 stackframesize = rd->memuse + savedregs_num;
136 #if defined(ENABLE_THREADS)
137 /* space to save argument of monitor_enter */
139 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
140 /* reserve 2 slots for long/double return values for monitorexit */
142 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
149 /* create method header */
151 /* Keep stack of non-leaf functions 16-byte aligned. */
153 if (!m->isleafmethod)
154 stackframesize |= 0x3;
156 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
157 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
159 #if defined(ENABLE_THREADS)
160 /* IsSync contains the offset relative to the stack pointer for the
161 argument of monitor_exit used in the exception handler. Since the
162 offset could be zero and give a wrong meaning of the flag it is
166 if (checksync && (m->flags & ACC_SYNCHRONIZED))
167 (void) dseg_adds4(cd, (rd->memuse + 1) * 4); /* IsSync */
170 (void) dseg_adds4(cd, 0); /* IsSync */
172 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
173 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
174 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
176 /* adds a reference for the length of the line number counter. We don't
177 know the size yet, since we evaluate the information during code
178 generation, to save one additional iteration over the whole
179 instructions. During code optimization the position could have changed
180 to the information gotten from the class file */
181 (void) dseg_addlinenumbertablesize(cd);
183 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
185 /* create exception table */
187 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
188 dseg_addtarget(cd, ex->start);
189 dseg_addtarget(cd, ex->end);
190 dseg_addtarget(cd, ex->handler);
191 (void) dseg_addaddress(cd, ex->catchtype.cls);
194 /* generate method profiling code */
197 /* count frequency */
199 M_MOV_IMM(m, REG_ITMP1);
200 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(methodinfo, frequency));
203 /* create stack frame (if necessary) */
206 M_ASUB_IMM(stackframesize * 4, REG_SP);
208 /* save return address and used callee saved registers */
211 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
212 p--; M_AST(rd->savintregs[i], REG_SP, p * 4);
214 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
215 p-=2; i386_fld_reg(cd, rd->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 4);
218 /* take arguments out of register or stack frame */
223 for (p = 0, l = 0; p < md->paramcount; p++) {
224 t = md->paramtypes[p].type;
225 var = &(rd->locals[l][t]);
227 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
231 s1 = md->params[p].regoff;
232 if (IS_INT_LNG_TYPE(t)) { /* integer args */
233 if (!md->params[p].inmemory) { /* register arguments */
234 log_text("integer register argument");
236 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
237 /* rd->argintregs[md->params[p].regoff -> var->regoff */
238 } else { /* reg arg -> spilled */
239 /* rd->argintregs[md->params[p].regoff -> var->regoff * 4 */
241 } else { /* stack arguments */
242 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
243 i386_mov_membase_reg( /* + 4 for return address */
244 cd, REG_SP, (stackframesize + s1) * 4 + 4, var->regoff);
245 /* + 4 for return address */
246 } else { /* stack arg -> spilled */
247 if (!IS_2_WORD_TYPE(t)) {
249 i386_mov_membase_reg( /* + 4 for return address */
250 cd, REG_SP, (stackframesize + s1) * 4 + 4,
252 i386_mov_reg_membase(
253 cd, REG_ITMP1, REG_SP, var->regoff * 4);
255 /* reuse Stackslotand avoid copying */
256 var->regoff = stackframesize + s1 + 1;
261 i386_mov_membase_reg( /* + 4 for return address */
262 cd, REG_SP, (stackframesize + s1) * 4 + 4,
264 i386_mov_reg_membase(
265 cd, REG_ITMP1, REG_SP, var->regoff * 4);
266 i386_mov_membase_reg( /* + 4 for return address */
267 cd, REG_SP, (stackframesize + s1) * 4 + 4 + 4,
269 i386_mov_reg_membase(
270 cd, REG_ITMP1, REG_SP, var->regoff * 4 + 4);
272 /* reuse Stackslotand avoid copying */
273 var->regoff = stackframesize + s1 + 1;
279 } else { /* floating args */
280 if (!md->params[p].inmemory) { /* register arguments */
281 log_text("There are no float argument registers!");
283 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
284 /* rd->argfltregs[md->params[p].regoff -> var->regoff */
285 } else { /* reg arg -> spilled */
286 /* rd->argfltregs[md->params[p].regoff -> var->regoff * 4 */
289 } else { /* stack arguments */
290 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
293 cd, REG_SP, (stackframesize + s1) * 4 + 4);
295 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
300 cd, REG_SP, (stackframesize + s1) * 4 + 4);
302 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
306 } else { /* stack-arg -> spilled */
308 i386_mov_membase_reg(
309 cd, REG_SP, (stackframesize + s1) * 4 + 4, REG_ITMP1);
310 i386_mov_reg_membase(
311 cd, REG_ITMP1, REG_SP, var->regoff * 4);
314 cd, REG_SP, (stackframesize + s1) * 4 + 4);
315 i386_fstps_membase(cd, REG_SP, var->regoff * 4);
318 cd, REG_SP, (stackframesize + s1) * 4 + 4);
319 i386_fstpl_membase(cd, REG_SP, var->regoff * 4);
322 /* reuse Stackslotand avoid copying */
323 var->regoff = stackframesize + s1 + 1;
330 /* call monitorenter function */
332 #if defined(ENABLE_THREADS)
333 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
336 if (m->flags & ACC_STATIC) {
337 M_MOV_IMM(m->class, REG_ITMP1);
338 M_AST(REG_ITMP1, REG_SP, s1 * 4);
339 M_AST(REG_ITMP1, REG_SP, 0 * 4);
340 M_MOV_IMM(BUILTIN_staticmonitorenter, REG_ITMP1);
344 M_ALD(REG_ITMP1, REG_SP, stackframesize * 4 + 4);
347 codegen_add_nullpointerexception_ref(cd);
348 M_AST(REG_ITMP1, REG_SP, s1 * 4);
349 M_AST(REG_ITMP1, REG_SP, 0 * 4);
350 M_MOV_IMM(BUILTIN_monitorenter, REG_ITMP1);
356 /* copy argument registers to stack and call trace function with pointer
357 to arguments on stack.
361 if (opt_verbosecall) {
363 s1 = INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4 + 4 + stackframesize * 4;
365 M_ISUB_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
367 /* save temporary registers for leaf methods */
369 for (p = 0; p < INT_TMP_CNT; p++)
370 M_IST(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
372 for (p = 0, l = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
373 t = md->paramtypes[p].type;
375 if (IS_INT_LNG_TYPE(t)) {
376 if (IS_2_WORD_TYPE(t)) {
377 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
378 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
379 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off + 4, REG_ITMP1);
380 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
382 } else if (t == TYPE_ADR) {
384 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
385 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
386 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
387 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
390 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, EAX);
392 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
393 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
397 if (!IS_2_WORD_TYPE(t)) {
398 i386_flds_membase(cd, REG_SP, s1 + stack_off);
399 i386_fstps_membase(cd, REG_SP, p * 8);
400 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
401 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
404 i386_fldl_membase(cd, REG_SP, s1 + stack_off);
405 i386_fstpl_membase(cd, REG_SP, p * 8);
408 stack_off += (IS_2_WORD_TYPE(t)) ? 8 : 4;
411 /* fill up the remaining arguments */
412 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
413 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
414 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
415 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
418 i386_mov_imm_membase(cd, (ptrint) m, REG_SP, TRACE_ARGS_NUM * 8);
419 i386_mov_imm_reg(cd, (ptrint) builtin_trace_args, REG_ITMP1);
420 i386_call_reg(cd, REG_ITMP1);
422 /* restore temporary registers for leaf methods */
424 for (p = 0; p < INT_TMP_CNT; p++)
425 M_ILD(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
427 M_IADD_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
429 #endif /* !defined(NDEBUG) */
433 /* end of header generation */
435 replacementpoint = jd->code->rplpoints;
437 /* walk through all basic blocks */
438 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
440 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
442 if (bptr->flags >= BBREACHED) {
444 /* branch resolving */
447 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
448 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
453 /* handle replacement points */
455 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
456 replacementpoint->pc = (u1*)bptr->mpc; /* will be resolved later */
460 assert(cd->lastmcodeptr <= cd->mcodeptr);
461 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
464 /* copy interface registers to their destination */
470 /* generate basic block profiling code */
473 /* count frequency */
475 M_MOV_IMM(m->bbfrequency, REG_ITMP1);
476 M_IADD_IMM_MEMBASE(1, REG_ITMP1, bptr->debug_nr * 4);
480 #if defined(ENABLE_LSRA)
482 while (src != NULL) {
484 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
485 if (!IS_2_WORD_TYPE(src->type)) {
486 if (bptr->type == BBTYPE_SBR) {
487 /* d = reg_of_var(m, src, REG_ITMP1); */
488 if (!(src->flags & INMEMORY))
494 emit_store(jd, NULL, src, d);
496 } else if (bptr->type == BBTYPE_EXH) {
497 /* d = reg_of_var(m, src, REG_ITMP1); */
498 if (!(src->flags & INMEMORY))
502 M_INTMOVE(REG_ITMP1, d);
503 emit_store(jd, NULL, src, d);
507 log_text("copy interface registers(EXH, SBR): longs have to be in memory (begin 1)");
516 while (src != NULL) {
518 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
519 if (!IS_2_WORD_TYPE(src->type)) {
520 if (bptr->type == BBTYPE_SBR) {
521 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
523 emit_store(jd, NULL, src, d);
524 } else if (bptr->type == BBTYPE_EXH) {
525 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
526 M_INTMOVE(REG_ITMP1, d);
527 emit_store(jd, NULL, src, d);
531 log_text("copy interface registers: longs have to be in memory (begin 1)");
536 if (IS_LNG_TYPE(src->type))
537 d = codegen_reg_of_var(rd, 0, src, PACK_REGS(REG_ITMP1, REG_ITMP2));
539 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
540 /* d = codegen_reg_of_var(rd, 0, src, REG_IFTMP); */
542 if ((src->varkind != STACKVAR)) {
544 s1 = rd->interfaces[len][s2].regoff;
546 if (IS_FLT_DBL_TYPE(s2)) {
547 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
551 if (IS_2_WORD_TYPE(s2))
552 M_DLD(d, REG_SP, s1 * 4);
554 M_FLD(d, REG_SP, s1 * 4);
558 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
559 if (IS_2_WORD_TYPE(s2))
565 if (IS_2_WORD_TYPE(s2))
566 M_LLD(d, REG_SP, s1 * 4);
568 M_ILD(d, REG_SP, s1 * 4);
572 emit_store(jd, NULL, src, d);
577 #if defined(ENABLE_LSRA)
581 /* walk through all instructions */
586 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
587 if (iptr->line != currentline) {
588 dseg_addlinenumber(cd, iptr->line);
589 currentline = iptr->line;
592 MCODECHECK(1024); /* 1kB should be enough */
595 case ICMD_INLINE_START:
597 insinfo_inline *insinfo = (insinfo_inline *) iptr->target;
598 #if defined(ENABLE_THREADS)
599 if (insinfo->synchronize) {
600 /* add monitor enter code */
601 if (insinfo->method->flags & ACC_STATIC) {
602 M_MOV_IMM(insinfo->method->class, REG_ITMP1);
603 M_AST(REG_ITMP1, REG_SP, 0 * 4);
604 M_MOV_IMM(BUILTIN_staticmonitorenter, REG_ITMP1);
608 /* nullpointer check must have been performed before */
609 /* (XXX not done, yet) */
610 var = &(rd->locals[insinfo->synclocal][TYPE_ADR]);
611 if (var->flags & INMEMORY) {
612 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP1);
613 M_AST(REG_ITMP1, REG_SP, 0 * 4);
616 M_AST(var->regoff, REG_SP, 0 * 4);
618 M_MOV_IMM(BUILTIN_monitorenter, REG_ITMP1);
623 dseg_addlinenumber_inline_start(cd, iptr);
627 case ICMD_INLINE_END:
629 insinfo_inline *insinfo = (insinfo_inline *) iptr->target;
631 dseg_addlinenumber_inline_end(cd, iptr);
632 dseg_addlinenumber(cd, iptr->line);
634 #if defined(ENABLE_THREADS)
635 if (insinfo->synchronize) {
636 /* add monitor exit code */
637 if (insinfo->method->flags & ACC_STATIC) {
638 M_MOV_IMM(insinfo->method->class, REG_ITMP1);
639 M_AST(REG_ITMP1, REG_SP, 0 * 4);
640 M_MOV_IMM(BUILTIN_monitorexit, REG_ITMP1);
644 var = &(rd->locals[insinfo->synclocal][TYPE_ADR]);
645 if (var->flags & INMEMORY) {
646 M_ALD(REG_ITMP1, REG_SP, var->regoff * 4);
647 M_AST(REG_ITMP1, REG_SP, 0 * 4);
650 M_AST(var->regoff, REG_SP, 0 * 4);
652 M_MOV_IMM(BUILTIN_monitorexit, REG_ITMP1);
660 case ICMD_NOP: /* ... ==> ... */
661 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
662 /* EAX: NO ECX: NO EDX: NO */
665 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
666 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
667 /* EAX: NO ECX: NO EDX: NO */
669 if (src->flags & INMEMORY)
670 M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 4);
674 codegen_add_nullpointerexception_ref(cd);
677 /* constant operations ************************************************/
679 case ICMD_ICONST: /* ... ==> ..., constant */
680 /* op1 = 0, val.i = constant */
682 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
683 /* EAX: NO ECX: NO EDX: NO */
685 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
686 if (iptr->dst->flags & INMEMORY) {
687 M_IST_IMM(iptr->val.i, REG_SP, iptr->dst->regoff * 4);
689 if (iptr->val.i == 0) {
692 M_MOV_IMM(iptr->val.i, d);
697 case ICMD_LCONST: /* ... ==> ..., constant */
698 /* op1 = 0, val.l = constant */
700 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
701 /* EAX: NO ECX: NO EDX: NO */
703 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
704 if (iptr->dst->flags & INMEMORY) {
705 M_IST_IMM(iptr->val.l, REG_SP, iptr->dst->regoff * 4);
706 M_IST_IMM(iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
708 log_text("LCONST: longs have to be in memory");
713 case ICMD_FCONST: /* ... ==> ..., constant */
714 /* op1 = 0, val.f = constant */
716 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
717 /* EAX: YES ECX: NO EDX: NO */
719 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
720 if (iptr->val.f == 0.0) {
725 if (iptr->val.i == 0x80000000) {
729 } else if (iptr->val.f == 1.0) {
733 } else if (iptr->val.f == 2.0) {
740 disp = dseg_addfloat(cd, iptr->val.f);
741 i386_mov_imm_reg(cd, 0, REG_ITMP1);
743 i386_flds_membase(cd, REG_ITMP1, disp);
746 emit_store(jd, iptr, iptr->dst, d);
749 case ICMD_DCONST: /* ... ==> ..., constant */
750 /* op1 = 0, val.d = constant */
752 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
753 /* EAX: YES ECX: NO EDX: NO */
755 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
756 if (iptr->val.d == 0.0) {
761 if (iptr->val.l == 0x8000000000000000LL) {
765 } else if (iptr->val.d == 1.0) {
769 } else if (iptr->val.d == 2.0) {
776 disp = dseg_adddouble(cd, iptr->val.d);
777 i386_mov_imm_reg(cd, 0, REG_ITMP1);
779 i386_fldl_membase(cd, REG_ITMP1, disp);
782 emit_store(jd, iptr, iptr->dst, d);
785 case ICMD_ACONST: /* ... ==> ..., constant */
786 /* op1 = 0, val.a = constant */
788 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
789 /* EAX: YES ECX: NO EDX: NO */
791 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
793 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
794 codegen_addpatchref(cd, PATCHER_aconst,
795 ICMD_ACONST_UNRESOLVED_CLASSREF(iptr), 0);
797 if (opt_showdisassemble) {
798 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
802 emit_store(jd, iptr, iptr->dst, d);
805 if (iptr->dst->flags & INMEMORY) {
806 M_AST_IMM((ptrint) iptr->val.a, REG_SP, iptr->dst->regoff * 4);
809 if ((ptrint) iptr->val.a == 0) {
812 M_MOV_IMM(iptr->val.a, d);
819 /* load/store operations **********************************************/
821 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
822 case ICMD_ALOAD: /* op1 = local variable */
823 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
824 /* EAX: YES ECX: NO EDX: NO */
826 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
827 if ((iptr->dst->varkind == LOCALVAR) &&
828 (iptr->dst->varnum == iptr->op1))
830 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
831 if (var->flags & INMEMORY)
832 M_ILD(d, REG_SP, var->regoff * 4);
834 M_INTMOVE(var->regoff, d);
835 emit_store(jd, iptr, iptr->dst, d);
838 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
839 /* op1 = local variable */
840 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
841 /* EAX: NO ECX: NO EDX: NO */
843 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP1, REG_ITMP2));
844 if ((iptr->dst->varkind == LOCALVAR) &&
845 (iptr->dst->varnum == iptr->op1))
847 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
848 if (var->flags & INMEMORY)
849 M_LLD(d, REG_SP, var->regoff * 4);
851 M_LNGMOVE(var->regoff, d);
852 emit_store(jd, iptr, iptr->dst, d);
855 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
856 /* op1 = local variable */
857 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
858 /* EAX: NO ECX: NO EDX: NO */
860 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
861 if ((iptr->dst->varkind == LOCALVAR) &&
862 (iptr->dst->varnum == iptr->op1))
864 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
865 if (var->flags & INMEMORY)
866 M_FLD(d, REG_SP, var->regoff * 4);
868 M_FLTMOVE(var->regoff, d);
869 emit_store(jd, iptr, iptr->dst, d);
872 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
873 /* op1 = local variable */
874 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
875 /* EAX: NO ECX: NO EDX: NO */
877 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
878 if ((iptr->dst->varkind == LOCALVAR) &&
879 (iptr->dst->varnum == iptr->op1))
881 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
882 if (var->flags & INMEMORY)
883 M_DLD(d, REG_SP, var->regoff * 4);
885 M_FLTMOVE(var->regoff, d);
886 emit_store(jd, iptr, iptr->dst, d);
889 case ICMD_ISTORE: /* ..., value ==> ... */
890 case ICMD_ASTORE: /* op1 = local variable */
891 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
892 /* EAX: YES ECX: NO EDX: NO */
894 if ((src->varkind == LOCALVAR) &&
895 (src->varnum == iptr->op1))
897 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
898 if (var->flags & INMEMORY) {
899 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
900 M_IST(s1, REG_SP, var->regoff * 4);
902 s1 = emit_load_s1(jd, iptr, src, var->regoff);
903 M_INTMOVE(s1, var->regoff);
907 case ICMD_LSTORE: /* ..., value ==> ... */
908 /* op1 = local variable */
909 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
910 /* EAX: NO ECX: NO EDX: NO */
912 if ((src->varkind == LOCALVAR) &&
913 (src->varnum == iptr->op1))
915 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
916 if (var->flags & INMEMORY) {
917 s1 = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP1, REG_ITMP2));
918 M_LST(s1, REG_SP, var->regoff * 4);
920 s1 = emit_load_s1(jd, iptr, src, var->regoff);
921 M_LNGMOVE(s1, var->regoff);
925 case ICMD_FSTORE: /* ..., value ==> ... */
926 /* op1 = local variable */
927 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
928 /* EAX: NO ECX: NO EDX: NO */
930 if ((src->varkind == LOCALVAR) &&
931 (src->varnum == iptr->op1))
933 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
934 if (var->flags & INMEMORY) {
935 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
936 M_FST(s1, REG_SP, var->regoff * 4);
938 s1 = emit_load_s1(jd, iptr, src, var->regoff);
939 M_FLTMOVE(s1, var->regoff);
943 case ICMD_DSTORE: /* ..., value ==> ... */
944 /* op1 = local variable */
945 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
946 /* EAX: NO ECX: NO EDX: NO */
948 if ((src->varkind == LOCALVAR) &&
949 (src->varnum == iptr->op1))
951 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
952 if (var->flags & INMEMORY) {
953 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
954 M_DST(s1, REG_SP, var->regoff * 4);
956 s1 = emit_load_s1(jd, iptr, src, var->regoff);
957 M_FLTMOVE(s1, var->regoff);
962 /* pop/dup/swap operations ********************************************/
964 /* attention: double and longs are only one entry in CACAO ICMDs */
966 case ICMD_POP: /* ..., value ==> ... */
967 case ICMD_POP2: /* ..., value, value ==> ... */
968 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
969 /* EAX: NO ECX: NO EDX: NO */
972 case ICMD_DUP: /* ..., a ==> ..., a, a */
973 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
974 /* EAX: YES ECX: NO EDX: NO */
975 M_COPY(src, iptr->dst);
978 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
979 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
980 /* EAX: YES ECX: NO EDX: NO */
982 M_COPY(src, iptr->dst);
983 M_COPY(src->prev, iptr->dst->prev);
986 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
987 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
988 /* EAX: YES ECX: NO EDX: NO */
990 M_COPY(src, iptr->dst);
991 M_COPY(src->prev, iptr->dst->prev);
992 M_COPY(iptr->dst, iptr->dst->prev->prev);
995 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
997 M_COPY(src, iptr->dst);
998 M_COPY(src->prev, iptr->dst->prev);
999 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1000 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
1003 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
1004 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1005 /* EAX: YES ECX: NO EDX: NO */
1007 M_COPY(src, iptr->dst);
1008 M_COPY(src->prev, iptr->dst->prev);
1009 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1010 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
1011 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
1014 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
1015 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1016 /* EAX: YES ECX: NO EDX: NO */
1018 M_COPY(src, iptr->dst);
1019 M_COPY(src->prev, iptr->dst->prev);
1020 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1021 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
1022 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
1023 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
1026 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1027 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1028 /* EAX: YES ECX: NO EDX: NO */
1030 M_COPY(src, iptr->dst->prev);
1031 M_COPY(src->prev, iptr->dst);
1035 /* integer operations *************************************************/
1037 case ICMD_INEG: /* ..., value ==> ..., - value */
1038 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1039 /* EAX: YES ECX: NO EDX: NO */
1041 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1042 if (iptr->dst->flags & INMEMORY) {
1043 if (src->flags & INMEMORY) {
1044 if (src->regoff == iptr->dst->regoff) {
1045 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1048 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1049 i386_neg_reg(cd, REG_ITMP1);
1050 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1054 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1055 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1059 if (src->flags & INMEMORY) {
1060 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1061 i386_neg_reg(cd, iptr->dst->regoff);
1064 M_INTMOVE(src->regoff, iptr->dst->regoff);
1065 i386_neg_reg(cd, iptr->dst->regoff);
1070 case ICMD_LNEG: /* ..., value ==> ..., - value */
1071 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1072 /* EAX: YES ECX: NO EDX: NO */
1074 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1075 if (iptr->dst->flags & INMEMORY) {
1076 if (src->flags & INMEMORY) {
1077 if (src->regoff == iptr->dst->regoff) {
1078 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1079 i386_alu_imm_membase(cd, ALU_ADC, 0, REG_SP, iptr->dst->regoff * 4 + 4);
1080 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4 + 4);
1083 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1084 i386_neg_reg(cd, REG_ITMP1);
1085 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1086 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1087 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP1);
1088 i386_neg_reg(cd, REG_ITMP1);
1089 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1095 case ICMD_I2L: /* ..., value ==> ..., value */
1096 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1097 /* EAX: YES ECX: NO EDX: YES */
1099 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1100 if (iptr->dst->flags & INMEMORY) {
1101 if (src->flags & INMEMORY) {
1102 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, EAX);
1104 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1105 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1108 M_INTMOVE(src->regoff, EAX);
1110 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1111 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1116 case ICMD_L2I: /* ..., value ==> ..., value */
1117 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1118 /* EAX: YES ECX: NO EDX: NO */
1120 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1121 if (iptr->dst->flags & INMEMORY) {
1122 if (src->flags & INMEMORY) {
1123 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1124 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1128 if (src->flags & INMEMORY) {
1129 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1134 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1135 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1136 /* EAX: YES ECX: NO EDX: NO */
1138 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1139 if (iptr->dst->flags & INMEMORY) {
1140 if (src->flags & INMEMORY) {
1141 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1142 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1143 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1144 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1147 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1148 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 4);
1149 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 4);
1153 if (src->flags & INMEMORY) {
1154 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1155 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1156 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1159 M_INTMOVE(src->regoff, iptr->dst->regoff);
1160 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1161 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1166 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1167 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1168 /* EAX: YES ECX: NO EDX: NO */
1170 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1171 if (iptr->dst->flags & INMEMORY) {
1172 if (src->flags & INMEMORY) {
1173 if (src->regoff == iptr->dst->regoff) {
1174 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1177 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1178 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, REG_ITMP1);
1179 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1183 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1184 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1188 if (src->flags & INMEMORY) {
1189 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1190 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1193 M_INTMOVE(src->regoff, iptr->dst->regoff);
1194 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1199 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1200 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1201 /* EAX: YES ECX: NO EDX: NO */
1203 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1204 if (iptr->dst->flags & INMEMORY) {
1205 if (src->flags & INMEMORY) {
1206 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1207 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1208 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1209 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1212 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1213 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 4);
1214 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 4);
1218 if (src->flags & INMEMORY) {
1219 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1220 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1221 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1224 M_INTMOVE(src->regoff, iptr->dst->regoff);
1225 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1226 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1232 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1233 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1234 /* EAX: S|YES ECX: NO EDX: NO */
1236 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1237 i386_emit_ialu(cd, ALU_ADD, src, iptr);
1240 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1241 /* val.i = constant */
1242 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1243 /* EAX: NO ECX: NO EDX: NO */
1245 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1246 i386_emit_ialuconst(cd, ALU_ADD, src, iptr);
1249 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1250 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1251 /* EAX: S|YES ECX: NO EDX: NO */
1253 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1254 if (iptr->dst->flags & INMEMORY) {
1255 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1256 if (src->regoff == iptr->dst->regoff) {
1257 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1258 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1259 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1260 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1262 } else if (src->prev->regoff == iptr->dst->regoff) {
1263 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1264 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1265 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1266 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1269 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1270 i386_alu_membase_reg(cd, ALU_ADD, REG_SP, src->regoff * 4, REG_ITMP1);
1271 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1272 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1273 i386_alu_membase_reg(cd, ALU_ADC, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1274 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1281 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1282 /* val.l = constant */
1283 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1284 /* EAX: NO ECX: NO EDX: NO */
1285 /* else path can never happen? longs stay in memory! */
1287 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1288 if (iptr->dst->flags & INMEMORY) {
1289 if (src->flags & INMEMORY) {
1290 if (src->regoff == iptr->dst->regoff) {
1291 i386_alu_imm_membase(cd, ALU_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1292 i386_alu_imm_membase(cd, ALU_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1295 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1296 i386_alu_imm_reg(cd, ALU_ADD, iptr->val.l, REG_ITMP1);
1297 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1298 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1299 i386_alu_imm_reg(cd, ALU_ADC, iptr->val.l >> 32, REG_ITMP1);
1300 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1306 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1307 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1308 /* EAX: S|YES ECX: NO EDX: NO */
1310 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1311 if (iptr->dst->flags & INMEMORY) {
1312 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1313 if (src->prev->regoff == iptr->dst->regoff) {
1314 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1315 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1318 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1319 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1320 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1323 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1324 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1325 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1326 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1328 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1329 if (src->prev->regoff == iptr->dst->regoff) {
1330 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1333 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1334 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1335 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1339 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 4);
1340 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1344 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1345 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1346 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1348 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1349 M_INTMOVE(src->prev->regoff, d);
1350 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1352 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1353 /* workaround for reg alloc */
1354 if (src->regoff == iptr->dst->regoff) {
1355 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1356 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1357 M_INTMOVE(REG_ITMP1, d);
1360 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1361 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1365 /* workaround for reg alloc */
1366 if (src->regoff == iptr->dst->regoff) {
1367 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1368 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1369 M_INTMOVE(REG_ITMP1, d);
1372 M_INTMOVE(src->prev->regoff, d);
1373 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1379 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1380 /* val.i = constant */
1381 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1382 /* EAX: NO ECX: NO EDX: NO */
1384 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1385 i386_emit_ialuconst(cd, ALU_SUB, src, iptr);
1388 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1389 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1390 /* EAX: S|YES ECX: NO EDX: NO */
1392 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1393 if (iptr->dst->flags & INMEMORY) {
1394 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1395 if (src->prev->regoff == iptr->dst->regoff) {
1396 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1397 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1398 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1399 i386_alu_reg_membase(cd, ALU_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1402 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1403 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1404 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1405 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1406 i386_alu_membase_reg(cd, ALU_SBB, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1407 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1413 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1414 /* val.l = constant */
1415 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1416 /* EAX: NO ECX: NO EDX: NO */
1417 /* else path can never happen? longs stay in memory! */
1419 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1420 if (iptr->dst->flags & INMEMORY) {
1421 if (src->flags & INMEMORY) {
1422 if (src->regoff == iptr->dst->regoff) {
1423 i386_alu_imm_membase(cd, ALU_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1424 i386_alu_imm_membase(cd, ALU_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1427 /* TODO: could be size optimized with lea -- see gcc output */
1428 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1429 i386_alu_imm_reg(cd, ALU_SUB, iptr->val.l, REG_ITMP1);
1430 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1431 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1432 i386_alu_imm_reg(cd, ALU_SBB, iptr->val.l >> 32, REG_ITMP1);
1433 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1439 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1440 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1441 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1443 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1444 if (iptr->dst->flags & INMEMORY) {
1445 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1446 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1447 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1448 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1450 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1451 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1452 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1453 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1455 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1456 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1457 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1458 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1461 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1462 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1463 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1467 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1468 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1469 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1471 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1472 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1473 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1475 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1476 M_INTMOVE(src->regoff, iptr->dst->regoff);
1477 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1480 if (src->regoff == iptr->dst->regoff) {
1481 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1484 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1485 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1491 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1492 /* val.i = constant */
1493 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1494 /* EAX: YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1496 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1497 if (iptr->dst->flags & INMEMORY) {
1498 if (src->flags & INMEMORY) {
1499 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, REG_ITMP1);
1500 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1503 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1504 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1508 if (src->flags & INMEMORY) {
1509 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, iptr->dst->regoff);
1512 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1517 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1518 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1519 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1521 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1522 if (iptr->dst->flags & INMEMORY) {
1523 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1524 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX); /* mem -> EAX */
1525 /* optimize move EAX -> REG_ITMP3 is slower??? */
1526 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1527 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1529 /* TODO: optimize move EAX -> REG_ITMP3 */
1530 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); /* mem -> ITMP3 */
1531 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1532 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1534 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP2); /* mem -> ITMP3 */
1535 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1537 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1538 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1539 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1544 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1545 /* val.l = constant */
1546 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1547 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1549 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1550 if (iptr->dst->flags & INMEMORY) {
1551 if (src->flags & INMEMORY) {
1552 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1553 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1554 /* TODO: optimize move EAX -> REG_ITMP3 */
1555 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1556 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1558 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1559 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1560 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1562 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1563 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1564 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1569 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1570 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1571 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX */
1573 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1574 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
1576 if (src->prev->flags & INMEMORY) {
1577 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1580 M_INTMOVE(src->prev->regoff, EAX);
1583 /* check as described in jvm spec */
1585 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1586 i386_jcc(cd, I386_CC_NE, 3 + 6);
1587 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1588 i386_jcc(cd, I386_CC_E, 1 + 2);
1591 i386_idiv_reg(cd, s1);
1593 if (iptr->dst->flags & INMEMORY) {
1594 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1597 M_INTMOVE(EAX, iptr->dst->regoff);
1601 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1602 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1603 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EDX */
1606 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1607 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
1609 if (src->prev->flags & INMEMORY) {
1610 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1613 M_INTMOVE(src->prev->regoff, EAX);
1616 /* check as described in jvm spec */
1618 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1619 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1620 i386_alu_reg_reg(cd, ALU_XOR, EDX, EDX);
1621 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1622 i386_jcc(cd, I386_CC_E, 1 + 2);
1625 i386_idiv_reg(cd, s1);
1627 if (iptr->dst->flags & INMEMORY) {
1628 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4);
1631 M_INTMOVE(EDX, iptr->dst->regoff);
1635 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1636 /* val.i = constant */
1637 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1638 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL */
1640 /* TODO: optimize for `/ 2' */
1641 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1642 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1645 i386_test_reg_reg(cd, d, d);
1647 CALCIMMEDIATEBYTES(disp, (1 << iptr->val.i) - 1);
1648 i386_jcc(cd, I386_CC_NS, disp);
1649 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, d);
1651 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1652 emit_store(jd, iptr, iptr->dst, d);
1655 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1656 /* val.i = constant */
1657 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1658 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1660 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1661 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1663 M_INTMOVE(s1, REG_ITMP1);
1670 CALCIMMEDIATEBYTES(disp, iptr->val.i);
1673 /* TODO: optimize */
1675 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1676 i386_test_reg_reg(cd, s1, s1);
1677 i386_jcc(cd, I386_CC_GE, disp);
1678 i386_mov_reg_reg(cd, s1, d);
1679 i386_neg_reg(cd, d);
1680 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1681 i386_neg_reg(cd, d);
1683 /* M_INTMOVE(s1, EAX); */
1684 /* i386_cltd(cd); */
1685 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1686 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1687 /* i386_alu_reg_reg(cd, ALU_AND, iptr->val.i, EAX); */
1688 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1689 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1690 /* M_INTMOVE(EAX, d); */
1692 /* i386_alu_reg_reg(cd, ALU_XOR, d, d); */
1693 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1694 /* i386_shrd_reg_reg(cd, s1, d); */
1695 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1697 emit_store(jd, iptr, iptr->dst, d);
1700 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1701 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1703 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1704 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4);
1705 M_OR_MEMBASE(REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1708 codegen_add_arithmeticexception_ref(cd);
1713 M_ILD(REG_ITMP1, REG_SP, src->prev->regoff * 4);
1714 M_ILD(REG_ITMP2, REG_SP, src->prev->regoff * 4 + 4);
1715 M_IST(REG_ITMP1, REG_SP, 0 * 4);
1716 M_IST(REG_ITMP2, REG_SP, 0 * 4 + 4);
1718 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
1719 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4 + 4);
1720 M_IST(REG_ITMP1, REG_SP, 2 * 4);
1721 M_IST(REG_ITMP2, REG_SP, 2 * 4 + 4);
1723 M_MOV_IMM(bte->fp, REG_ITMP3);
1726 M_IST(REG_RESULT, REG_SP, iptr->dst->regoff * 4);
1727 M_IST(REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
1730 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1731 /* val.i = constant */
1732 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1733 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1735 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1736 if (iptr->dst->flags & INMEMORY) {
1737 if (src->flags & INMEMORY) {
1739 CALCIMMEDIATEBYTES(disp, (1 << iptr->val.i) - 1);
1741 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1742 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1744 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1745 i386_jcc(cd, I386_CC_NS, disp);
1746 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1747 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1748 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1749 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1751 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1752 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1757 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1758 /* val.l = constant */
1759 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1760 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1762 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1763 if (iptr->dst->flags & INMEMORY) {
1764 if (src->flags & INMEMORY) {
1765 /* Intel algorithm -- does not work, because constant is wrong */
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_ITMP3); */
1769 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1770 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1771 /* i386_jcc(cd, I386_CC_NS, offset); */
1772 /* i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1773 /* i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP3); */
1775 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1776 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1777 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1779 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1781 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1); */
1782 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); */
1783 /* i386_alu_reg_reg(cd, ALU_SBB, REG_ITMP3, REG_ITMP2); */
1785 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1786 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1788 /* Alpha algorithm */
1790 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1792 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4 + 4);
1798 /* TODO: hmm, don't know if this is always correct */
1800 CALCIMMEDIATEBYTES(disp, iptr->val.l & 0x00000000ffffffff);
1802 CALCIMMEDIATEBYTES(disp, iptr->val.l >> 32);
1808 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1809 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1811 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1812 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1813 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4 + 4);
1814 i386_jcc(cd, I386_CC_GE, disp);
1816 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1817 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1819 i386_neg_reg(cd, REG_ITMP1);
1820 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1821 i386_neg_reg(cd, REG_ITMP2);
1823 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1824 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1826 i386_neg_reg(cd, REG_ITMP1);
1827 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1828 i386_neg_reg(cd, REG_ITMP2);
1830 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1831 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1836 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1837 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1838 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1840 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1841 i386_emit_ishift(cd, I386_SHL, src, iptr);
1844 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1845 /* val.i = constant */
1846 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1847 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1849 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1850 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1853 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1854 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1855 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1857 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1858 i386_emit_ishift(cd, I386_SAR, src, iptr);
1861 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1862 /* val.i = constant */
1863 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1864 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1866 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1867 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1870 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1871 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1872 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1874 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1875 i386_emit_ishift(cd, I386_SHR, src, iptr);
1878 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1879 /* val.i = constant */
1880 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1881 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1883 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1884 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1887 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1888 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1889 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
1891 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1892 if (iptr->dst->flags & INMEMORY ){
1893 if (src->prev->flags & INMEMORY) {
1894 /* if (src->prev->regoff == iptr->dst->regoff) { */
1895 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1897 /* if (src->flags & INMEMORY) { */
1898 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1900 /* M_INTMOVE(src->regoff, ECX); */
1903 /* i386_test_imm_reg(cd, 32, ECX); */
1904 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1905 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1906 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1); */
1908 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 4 + 4); */
1909 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 4); */
1912 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1913 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1915 if (src->flags & INMEMORY) {
1916 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1918 M_INTMOVE(src->regoff, ECX);
1921 i386_test_imm_reg(cd, 32, ECX);
1922 i386_jcc(cd, I386_CC_E, 2 + 2);
1923 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1924 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1926 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1927 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1928 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1929 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
1935 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1936 /* val.i = constant */
1937 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1938 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1940 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1941 if (iptr->dst->flags & INMEMORY ) {
1942 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1943 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1945 if (iptr->val.i & 0x20) {
1946 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1947 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1948 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1951 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1952 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1955 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1956 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1960 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1961 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1962 /* EAX: S|YES ECX: YES S|EDX: YES OUTPUT: REG_NULL*/
1964 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1965 if (iptr->dst->flags & INMEMORY ){
1966 if (src->prev->flags & INMEMORY) {
1967 /* if (src->prev->regoff == iptr->dst->regoff) { */
1968 /* TODO: optimize */
1969 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1970 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
1972 /* if (src->flags & INMEMORY) { */
1973 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1975 /* M_INTMOVE(src->regoff, ECX); */
1978 /* i386_test_imm_reg(cd, 32, ECX); */
1979 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1980 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1981 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1983 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1984 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1985 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1986 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1989 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1990 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1992 if (src->flags & INMEMORY) {
1993 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1995 M_INTMOVE(src->regoff, ECX);
1998 i386_test_imm_reg(cd, 32, ECX);
1999 i386_jcc(cd, I386_CC_E, 2 + 3);
2000 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2001 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
2003 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2004 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
2005 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2006 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2012 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
2013 /* val.i = constant */
2014 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2015 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
2017 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2018 if (iptr->dst->flags & INMEMORY ) {
2019 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
2020 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
2022 if (iptr->val.i & 0x20) {
2023 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2024 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
2025 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2028 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2029 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
2032 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2033 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
2037 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
2038 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2039 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
2041 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2042 if (iptr->dst->flags & INMEMORY ){
2043 if (src->prev->flags & INMEMORY) {
2044 /* if (src->prev->regoff == iptr->dst->regoff) { */
2045 /* TODO: optimize */
2046 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
2047 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
2049 /* if (src->flags & INMEMORY) { */
2050 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
2052 /* M_INTMOVE(src->regoff, ECX); */
2055 /* i386_test_imm_reg(cd, 32, ECX); */
2056 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
2057 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2058 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2); */
2060 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2061 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
2062 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
2063 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
2066 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
2067 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
2069 if (src->flags & INMEMORY) {
2070 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
2072 M_INTMOVE(src->regoff, ECX);
2075 i386_test_imm_reg(cd, 32, ECX);
2076 i386_jcc(cd, I386_CC_E, 2 + 2);
2077 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2078 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP3, REG_ITMP3);
2080 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2081 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
2082 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2083 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2089 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
2090 /* val.l = constant */
2091 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2092 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
2094 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2095 if (iptr->dst->flags & INMEMORY ) {
2096 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
2097 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
2099 if (iptr->val.i & 0x20) {
2100 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2101 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
2102 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2105 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2106 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
2109 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2110 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
2114 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2115 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2116 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2118 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2119 i386_emit_ialu(cd, ALU_AND, src, iptr);
2122 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
2123 /* val.i = constant */
2124 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2125 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2127 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2128 i386_emit_ialuconst(cd, ALU_AND, src, iptr);
2131 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2132 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2133 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2135 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2136 i386_emit_lalu(cd, ALU_AND, src, iptr);
2139 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
2140 /* val.l = constant */
2141 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2142 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2144 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2145 i386_emit_laluconst(cd, ALU_AND, src, iptr);
2148 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2149 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2150 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2152 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2153 i386_emit_ialu(cd, ALU_OR, src, iptr);
2156 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2157 /* val.i = constant */
2158 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2159 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2161 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2162 i386_emit_ialuconst(cd, ALU_OR, src, iptr);
2165 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2166 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2167 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2169 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2170 i386_emit_lalu(cd, ALU_OR, src, iptr);
2173 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2174 /* val.l = constant */
2175 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2176 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2178 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2179 i386_emit_laluconst(cd, ALU_OR, src, iptr);
2182 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2183 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2184 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2186 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2187 i386_emit_ialu(cd, ALU_XOR, src, iptr);
2190 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2191 /* val.i = constant */
2192 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2193 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2195 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2196 i386_emit_ialuconst(cd, ALU_XOR, src, iptr);
2199 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2200 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2201 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2203 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2204 i386_emit_lalu(cd, ALU_XOR, src, iptr);
2207 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2208 /* val.l = constant */
2209 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2210 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2212 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2213 i386_emit_laluconst(cd, ALU_XOR, src, iptr);
2216 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2217 /* op1 = variable, val.i = constant */
2218 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2219 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL */
2221 var = &(rd->locals[iptr->op1][TYPE_INT]);
2222 if (var->flags & INMEMORY)
2223 M_IADD_IMM_MEMBASE(iptr->val.i, REG_SP, var->regoff * 4);
2225 /* `inc reg' is slower on p4's (regarding to ia32
2226 optimization reference manual and benchmarks) and
2227 as fast on athlon's. */
2228 M_IADD_IMM(iptr->val.i, var->regoff);
2233 /* floating operations ************************************************/
2235 #define ROUND_TO_SINGLE \
2236 i386_fstps_membase(cd, REG_SP, -8); \
2237 i386_flds_membase(cd, REG_SP, -8);
2239 #define ROUND_TO_DOUBLE \
2240 i386_fstpl_membase(cd, REG_SP, -8); \
2241 i386_fldl_membase(cd, REG_SP, -8);
2243 #define FPU_SET_24BIT_MODE \
2244 if (!fpu_in_24bit_mode) { \
2245 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2246 fpu_in_24bit_mode = 1; \
2249 #define FPU_SET_53BIT_MODE \
2250 if (fpu_in_24bit_mode) { \
2251 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2252 fpu_in_24bit_mode = 0; \
2255 #define ROUND_TO_SINGLE
2256 #define ROUND_TO_DOUBLE
2257 #define FPU_SET_24BIT_MODE
2258 #define FPU_SET_53BIT_MODE
2260 case ICMD_FNEG: /* ..., value ==> ..., - value */
2261 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2262 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2265 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2266 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2268 emit_store(jd, iptr, iptr->dst, d);
2271 case ICMD_DNEG: /* ..., value ==> ..., - value */
2272 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2273 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2276 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2277 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2279 emit_store(jd, iptr, iptr->dst, d);
2282 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2283 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2284 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2287 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2288 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2289 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2292 emit_store(jd, iptr, iptr->dst, d);
2295 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2296 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2297 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2300 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2301 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2302 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2305 emit_store(jd, iptr, iptr->dst, d);
2308 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2309 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2310 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2313 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2314 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2315 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2318 emit_store(jd, iptr, iptr->dst, d);
2321 case ICMD_DSUB: /* ..., 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 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2327 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2328 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2331 emit_store(jd, iptr, iptr->dst, d);
2334 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2335 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2336 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2339 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2340 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2341 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2345 emit_store(jd, iptr, iptr->dst, d);
2348 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2349 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2350 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2353 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2354 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2356 /* i386_fldt_mem(cd, subnormal_bias1); */
2357 /* i386_fmulp(cd); */
2359 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2364 /* i386_fldt_mem(cd, subnormal_bias2); */
2365 /* i386_fmulp(cd); */
2367 emit_store(jd, iptr, iptr->dst, d);
2370 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2371 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2372 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2375 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2376 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2377 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2381 emit_store(jd, iptr, iptr->dst, d);
2384 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2385 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2386 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2389 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2390 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2392 /* i386_fldt_mem(cd, subnormal_bias1); */
2393 /* i386_fmulp(cd); */
2395 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2400 /* i386_fldt_mem(cd, subnormal_bias2); */
2401 /* i386_fmulp(cd); */
2403 emit_store(jd, iptr, iptr->dst, d);
2406 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2407 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2408 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2411 /* exchanged to skip fxch */
2412 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2413 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2414 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2415 /* i386_fxch(cd); */
2420 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2421 emit_store(jd, iptr, iptr->dst, d);
2422 i386_ffree_reg(cd, 0);
2427 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2428 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2429 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2432 /* exchanged to skip fxch */
2433 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2434 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2435 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2436 /* i386_fxch(cd); */
2441 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2442 emit_store(jd, iptr, iptr->dst, d);
2443 i386_ffree_reg(cd, 0);
2448 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2449 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2450 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2451 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2453 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2454 if (src->flags & INMEMORY) {
2455 i386_fildl_membase(cd, REG_SP, src->regoff * 4);
2459 disp = dseg_adds4(cd, 0);
2460 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2462 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, disp);
2463 i386_fildl_membase(cd, REG_ITMP1, disp);
2466 emit_store(jd, iptr, iptr->dst, d);
2469 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2470 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2471 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2472 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2474 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2475 if (src->flags & INMEMORY) {
2476 i386_fildll_membase(cd, REG_SP, src->regoff * 4);
2480 log_text("L2F: longs have to be in memory");
2483 emit_store(jd, iptr, iptr->dst, d);
2486 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2487 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2488 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2490 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2491 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2493 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2496 /* Round to zero, 53-bit mode, exception masked */
2497 disp = dseg_adds4(cd, 0x0e7f);
2498 i386_fldcw_membase(cd, REG_ITMP1, disp);
2500 if (iptr->dst->flags & INMEMORY) {
2501 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2504 /* Round to nearest, 53-bit mode, exceptions masked */
2505 disp = dseg_adds4(cd, 0x027f);
2506 i386_fldcw_membase(cd, REG_ITMP1, disp);
2508 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2511 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2513 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2516 disp = dseg_adds4(cd, 0);
2517 i386_fistpl_membase(cd, REG_ITMP1, disp);
2519 i386_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2521 /* Round to nearest, 53-bit mode, exceptions masked */
2522 disp = dseg_adds4(cd, 0x027f);
2523 i386_fldcw_membase(cd, REG_ITMP1, disp);
2525 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2528 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2529 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2532 i386_jcc(cd, I386_CC_NE, disp);
2534 /* XXX: change this when we use registers */
2535 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2536 i386_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP1);
2537 i386_call_reg(cd, REG_ITMP1);
2539 if (iptr->dst->flags & INMEMORY) {
2540 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2543 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2547 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2548 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2549 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2551 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2552 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2554 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2557 /* Round to zero, 53-bit mode, exception masked */
2558 disp = dseg_adds4(cd, 0x0e7f);
2559 i386_fldcw_membase(cd, REG_ITMP1, disp);
2561 if (iptr->dst->flags & INMEMORY) {
2562 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2565 /* Round to nearest, 53-bit mode, exceptions masked */
2566 disp = dseg_adds4(cd, 0x027f);
2567 i386_fldcw_membase(cd, REG_ITMP1, disp);
2569 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2572 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2574 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2577 disp = dseg_adds4(cd, 0);
2578 i386_fistpl_membase(cd, REG_ITMP1, disp);
2580 i386_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2582 /* Round to nearest, 53-bit mode, exceptions masked */
2583 disp = dseg_adds4(cd, 0x027f);
2584 i386_fldcw_membase(cd, REG_ITMP1, disp);
2586 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2589 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2590 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2593 i386_jcc(cd, I386_CC_NE, disp);
2595 /* XXX: change this when we use registers */
2596 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2597 i386_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP1);
2598 i386_call_reg(cd, REG_ITMP1);
2600 if (iptr->dst->flags & INMEMORY) {
2601 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2603 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2607 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2608 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2609 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2611 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2612 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2614 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2617 /* Round to zero, 53-bit mode, exception masked */
2618 disp = dseg_adds4(cd, 0x0e7f);
2619 i386_fldcw_membase(cd, REG_ITMP1, disp);
2621 if (iptr->dst->flags & INMEMORY) {
2622 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2625 /* Round to nearest, 53-bit mode, exceptions masked */
2626 disp = dseg_adds4(cd, 0x027f);
2627 i386_fldcw_membase(cd, REG_ITMP1, disp);
2629 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2632 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2634 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2637 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2639 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2641 i386_jcc(cd, I386_CC_NE, disp);
2643 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2646 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2648 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2650 i386_jcc(cd, I386_CC_NE, disp);
2652 /* XXX: change this when we use registers */
2653 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2654 i386_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP1);
2655 i386_call_reg(cd, REG_ITMP1);
2656 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2657 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2660 log_text("F2L: longs have to be in memory");
2665 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2666 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2667 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2669 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2670 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2672 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2675 /* Round to zero, 53-bit mode, exception masked */
2676 disp = dseg_adds4(cd, 0x0e7f);
2677 i386_fldcw_membase(cd, REG_ITMP1, disp);
2679 if (iptr->dst->flags & INMEMORY) {
2680 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2683 /* Round to nearest, 53-bit mode, exceptions masked */
2684 disp = dseg_adds4(cd, 0x027f);
2685 i386_fldcw_membase(cd, REG_ITMP1, disp);
2687 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2690 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2692 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2695 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2697 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2699 i386_jcc(cd, I386_CC_NE, disp);
2701 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2704 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2706 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2708 i386_jcc(cd, I386_CC_NE, disp);
2710 /* XXX: change this when we use registers */
2711 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2712 i386_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP1);
2713 i386_call_reg(cd, REG_ITMP1);
2714 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2715 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2718 log_text("D2L: longs have to be in memory");
2723 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2724 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2725 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2727 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2728 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2730 emit_store(jd, iptr, iptr->dst, d);
2733 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2734 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2735 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2737 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2738 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2740 emit_store(jd, iptr, iptr->dst, d);
2743 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2745 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2746 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2748 /* exchanged to skip fxch */
2749 s2 = emit_load_s2(jd, iptr, src->prev, REG_FTMP1);
2750 s1 = emit_load_s1(jd, iptr, src, REG_FTMP2);
2751 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2752 /* i386_fxch(cd); */
2756 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2757 i386_jcc(cd, I386_CC_E, 6);
2758 i386_alu_imm_reg(cd, ALU_AND, 0x000000ff, EAX);
2760 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2761 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2762 i386_jcc(cd, I386_CC_B, 3 + 5);
2763 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2764 i386_jmp_imm(cd, 3);
2765 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2766 emit_store(jd, iptr, iptr->dst, d);
2769 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2771 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2772 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2774 /* exchanged to skip fxch */
2775 s2 = emit_load_s2(jd, iptr, src->prev, REG_FTMP1);
2776 s1 = emit_load_s1(jd, iptr, src, REG_FTMP2);
2777 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2778 /* i386_fxch(cd); */
2782 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2783 i386_jcc(cd, I386_CC_E, 3);
2784 i386_movb_imm_reg(cd, 1, REG_AH);
2786 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2787 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2788 i386_jcc(cd, I386_CC_B, 3 + 5);
2789 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2790 i386_jmp_imm(cd, 3);
2791 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2792 emit_store(jd, iptr, iptr->dst, d);
2796 /* memory operations **************************************************/
2798 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2799 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2800 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2802 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2803 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2804 gen_nullptr_check(s1);
2805 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2806 emit_store(jd, iptr, iptr->dst, d);
2809 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2810 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2811 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2813 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2814 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2815 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2816 if (iptr->op1 == 0) {
2817 gen_nullptr_check(s1);
2820 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2821 emit_store(jd, iptr, iptr->dst, d);
2824 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2825 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2826 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2828 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2829 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2830 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2831 if (iptr->op1 == 0) {
2832 gen_nullptr_check(s1);
2836 if (iptr->dst->flags & INMEMORY) {
2837 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2838 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4);
2839 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2840 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2844 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2845 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2846 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2848 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2849 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2850 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2851 if (iptr->op1 == 0) {
2852 gen_nullptr_check(s1);
2855 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2856 emit_store(jd, iptr, iptr->dst, d);
2859 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2860 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2861 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2863 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2864 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2865 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2866 if (iptr->op1 == 0) {
2867 gen_nullptr_check(s1);
2870 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2872 emit_store(jd, iptr, iptr->dst, d);
2875 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2876 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2877 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2879 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2880 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2881 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2882 if (iptr->op1 == 0) {
2883 gen_nullptr_check(s1);
2886 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2888 emit_store(jd, iptr, iptr->dst, d);
2891 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2892 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2893 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2895 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2896 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2897 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2898 if (iptr->op1 == 0) {
2899 gen_nullptr_check(s1);
2902 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2903 emit_store(jd, iptr, iptr->dst, d);
2906 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2907 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2908 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2910 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2911 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2912 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2913 if (iptr->op1 == 0) {
2914 gen_nullptr_check(s1);
2917 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2918 emit_store(jd, iptr, iptr->dst, d);
2921 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2922 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2923 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2925 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2926 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2927 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2928 if (iptr->op1 == 0) {
2929 gen_nullptr_check(s1);
2932 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2933 emit_store(jd, iptr, iptr->dst, d);
2937 case ICMD_LASTORE: /* ..., 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 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2942 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2943 if (iptr->op1 == 0) {
2944 gen_nullptr_check(s1);
2948 if (src->flags & INMEMORY) {
2949 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP3);
2950 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2951 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
2952 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2956 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2957 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2958 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2960 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2961 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2962 if (iptr->op1 == 0) {
2963 gen_nullptr_check(s1);
2966 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2967 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2970 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2971 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2972 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2974 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2975 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2976 if (iptr->op1 == 0) {
2977 gen_nullptr_check(s1);
2980 s3 = emit_load_s3(jd, iptr, src, REG_FTMP1);
2981 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2985 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2986 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2987 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2989 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2990 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2991 if (iptr->op1 == 0) {
2992 gen_nullptr_check(s1);
2995 s3 = emit_load_s3(jd, iptr, src, REG_FTMP1);
2996 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
3000 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
3001 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3002 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3004 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
3005 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
3006 if (iptr->op1 == 0) {
3007 gen_nullptr_check(s1);
3010 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
3011 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
3014 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
3015 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3016 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3018 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
3019 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
3020 if (iptr->op1 == 0) {
3021 gen_nullptr_check(s1);
3024 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
3025 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3028 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
3029 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3030 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3032 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
3033 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
3034 if (iptr->op1 == 0) {
3035 gen_nullptr_check(s1);
3038 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
3039 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
3040 M_INTMOVE(s3, REG_ITMP3);
3043 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3046 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
3048 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3049 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
3051 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
3052 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
3053 if (iptr->op1 == 0) {
3054 gen_nullptr_check(s1);
3057 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
3059 M_AST(s1, REG_SP, 0 * 4);
3060 M_AST(s3, REG_SP, 1 * 4);
3061 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
3065 codegen_add_arraystoreexception_ref(cd);
3067 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
3068 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
3069 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
3070 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3073 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
3074 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3075 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3077 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3078 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3079 if (iptr->op1 == 0) {
3080 gen_nullptr_check(s1);
3083 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
3086 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
3087 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3088 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3090 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3091 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3092 if (iptr->op1 == 0) {
3093 gen_nullptr_check(s1);
3097 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
3098 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
3101 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
3102 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3103 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3105 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3106 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3107 if (iptr->op1 == 0) {
3108 gen_nullptr_check(s1);
3111 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3114 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
3115 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3116 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3118 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3119 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3120 if (iptr->op1 == 0) {
3121 gen_nullptr_check(s1);
3124 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3127 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
3128 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3129 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3131 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3132 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3133 if (iptr->op1 == 0) {
3134 gen_nullptr_check(s1);
3137 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
3140 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
3141 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3142 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3144 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3145 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3146 if (iptr->op1 == 0) {
3147 gen_nullptr_check(s1);
3150 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3154 case ICMD_GETSTATIC: /* ... ==> ..., value */
3155 /* op1 = type, val.a = field address */
3156 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3157 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX*/
3159 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3160 codegen_addpatchref(cd, PATCHER_get_putstatic,
3161 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
3163 if (opt_showdisassemble) {
3164 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3170 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
3172 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3173 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
3175 if (opt_showdisassemble) {
3176 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3180 disp = (ptrint) &(fi->value);
3183 M_MOV_IMM(disp, REG_ITMP1);
3184 switch (iptr->op1) {
3187 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3188 M_ILD(d, REG_ITMP1, 0);
3191 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
3192 M_LLD(d, REG_ITMP1, 0);
3195 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
3196 M_FLD(d, REG_ITMP1, 0);
3199 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
3200 M_DLD(d, REG_ITMP1, 0);
3203 emit_store(jd, iptr, iptr->dst, d);
3206 case ICMD_PUTSTATIC: /* ..., value ==> ... */
3207 /* op1 = type, val.a = field address */
3208 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3209 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3211 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3212 codegen_addpatchref(cd, PATCHER_get_putstatic,
3213 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
3215 if (opt_showdisassemble) {
3216 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3222 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
3224 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3225 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
3227 if (opt_showdisassemble) {
3228 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3232 disp = (ptrint) &(fi->value);
3235 M_MOV_IMM(disp, REG_ITMP1);
3236 switch (iptr->op1) {
3239 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3240 M_IST(s2, REG_ITMP1, 0);
3243 if (src->flags & INMEMORY) {
3244 /* Using both REG_ITMP2 and REG_ITMP3 is faster
3245 than only using REG_ITMP2 alternating. */
3248 i386_mov_membase_reg(cd, REG_SP, s2 * 4, REG_ITMP2);
3249 i386_mov_membase_reg(cd, REG_SP, s2 * 4 + 4, REG_ITMP3);
3250 i386_mov_reg_membase(cd, REG_ITMP2, REG_ITMP1, 0);
3251 i386_mov_reg_membase(cd, REG_ITMP3, REG_ITMP1, 4);
3253 log_text("PUTSTATIC: longs have to be in memory");
3258 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
3259 i386_fstps_membase(cd, REG_ITMP1, 0);
3263 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
3264 i386_fstpl_membase(cd, REG_ITMP1, 0);
3270 case ICMD_PUTSTATICCONST: /* ... ==> ... */
3271 /* val = value (in current instruction) */
3272 /* op1 = type, val.a = field address (in */
3273 /* following NOP) */
3274 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3275 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3277 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
3278 codegen_addpatchref(cd, PATCHER_get_putstatic,
3279 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
3281 if (opt_showdisassemble) {
3282 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3288 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1);
3290 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3291 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
3293 if (opt_showdisassemble) {
3294 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3298 disp = (ptrint) &(fi->value);
3301 M_MOV_IMM(disp, REG_ITMP1);
3302 switch (iptr[1].op1) {
3306 i386_mov_imm_membase(cd, iptr->val.i, REG_ITMP1, 0);
3310 i386_mov_imm_membase(cd, iptr->val.l, REG_ITMP1, 0);
3311 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_ITMP1, 4);
3316 case ICMD_GETFIELD: /* .., objectref. ==> ..., value */
3317 /* op1 = type, val.i = field offset */
3318 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3319 /* EAX: YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
3321 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3322 gen_nullptr_check(s1);
3324 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3325 codegen_addpatchref(cd, PATCHER_getfield,
3326 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
3328 if (opt_showdisassemble) {
3329 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3335 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
3338 switch (iptr->op1) {
3341 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3342 M_ILD32(d, s1, disp);
3345 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
3346 M_LLD32(d, s1, disp);
3349 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
3350 M_FLD32(d, s1, disp);
3353 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
3354 M_DLD32(d, s1, disp);
3357 emit_store(jd, iptr, iptr->dst, d);
3360 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
3361 /* op1 = type, val.a = field address */
3362 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3363 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3365 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3366 gen_nullptr_check(s1);
3368 /* must be done here because of code patching */
3370 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
3371 if (IS_2_WORD_TYPE(iptr->op1))
3372 s2 = emit_load_s2(jd, iptr, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
3374 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3376 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
3378 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3379 codegen_addpatchref(cd, PATCHER_putfield,
3380 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
3382 if (opt_showdisassemble) {
3383 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3389 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
3392 switch (iptr->op1) {
3395 M_IST32(s2, s1, disp);
3398 M_LST32(s2, s1, disp);
3401 i386_fstps_membase32(cd, s1, disp);
3405 i386_fstpl_membase32(cd, s1, disp);
3411 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
3412 /* val = value (in current instruction) */
3413 /* op1 = type, val.a = field address (in */
3414 /* following NOP) */
3415 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3416 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3418 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3419 gen_nullptr_check(s1);
3421 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
3422 codegen_addpatchref(cd, PATCHER_putfieldconst,
3423 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
3425 if (opt_showdisassemble) {
3426 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3432 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1)->offset;
3435 switch (iptr[1].op1) {
3439 M_IST32_IMM(iptr->val.i, s1, disp);
3443 M_LST32_IMM(iptr->val.l, s1, disp);
3449 /* branch operations **************************************************/
3451 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3452 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3453 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
3455 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3456 M_INTMOVE(s1, REG_ITMP1_XPTR);
3458 #ifdef ENABLE_VERIFIER
3460 codegen_addpatchref(cd, PATCHER_athrow_areturn,
3461 (unresolved_class *) iptr->val.a, 0);
3463 if (opt_showdisassemble) {
3464 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3467 #endif /* ENABLE_VERIFIER */
3469 M_CALL_IMM(0); /* passing exception pc */
3470 M_POP(REG_ITMP2_XPC);
3472 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
3476 case ICMD_INLINE_GOTO:
3478 M_COPY(src,iptr->dst);
3481 case ICMD_GOTO: /* ... ==> ... */
3482 /* op1 = target JavaVM pc */
3483 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3484 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3487 codegen_addreference(cd, (basicblock *) iptr->target);
3491 case ICMD_JSR: /* ... ==> ... */
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*/
3497 codegen_addreference(cd, (basicblock *) iptr->target);
3500 case ICMD_RET: /* ... ==> ... */
3501 /* op1 = local variable */
3502 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3503 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3505 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3506 if (var->flags & INMEMORY) {
3507 M_ALD(REG_ITMP1, REG_SP, var->regoff * 4);
3513 case ICMD_IFNULL: /* ..., value ==> ... */
3514 /* op1 = target JavaVM pc */
3515 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3516 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3518 if (src->flags & INMEMORY) {
3519 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3522 i386_test_reg_reg(cd, src->regoff, src->regoff);
3524 i386_jcc(cd, I386_CC_E, 0);
3525 codegen_addreference(cd, (basicblock *) iptr->target);
3528 case ICMD_IFNONNULL: /* ..., value ==> ... */
3529 /* op1 = target JavaVM pc */
3530 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3531 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3533 if (src->flags & INMEMORY) {
3534 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3537 i386_test_reg_reg(cd, src->regoff, src->regoff);
3539 i386_jcc(cd, I386_CC_NE, 0);
3540 codegen_addreference(cd, (basicblock *) iptr->target);
3543 case ICMD_IFEQ: /* ..., value ==> ... */
3544 /* op1 = target JavaVM pc, val.i = constant */
3545 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3546 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3548 if (src->flags & INMEMORY) {
3549 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3552 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3554 i386_jcc(cd, I386_CC_E, 0);
3555 codegen_addreference(cd, (basicblock *) iptr->target);
3558 case ICMD_IFLT: /* ..., value ==> ... */
3559 /* op1 = target JavaVM pc, val.i = constant */
3560 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3561 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3563 if (src->flags & INMEMORY) {
3564 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3567 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3569 i386_jcc(cd, I386_CC_L, 0);
3570 codegen_addreference(cd, (basicblock *) iptr->target);
3573 case ICMD_IFLE: /* ..., value ==> ... */
3574 /* op1 = target JavaVM pc, val.i = constant */
3575 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3576 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3578 if (src->flags & INMEMORY) {
3579 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3582 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3584 i386_jcc(cd, I386_CC_LE, 0);
3585 codegen_addreference(cd, (basicblock *) iptr->target);
3588 case ICMD_IFNE: /* ..., value ==> ... */
3589 /* op1 = target JavaVM pc, val.i = constant */
3590 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3591 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3593 if (src->flags & INMEMORY) {
3594 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3597 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3599 i386_jcc(cd, I386_CC_NE, 0);
3600 codegen_addreference(cd, (basicblock *) iptr->target);
3603 case ICMD_IFGT: /* ..., value ==> ... */
3604 /* op1 = target JavaVM pc, val.i = constant */
3605 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3606 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3608 if (src->flags & INMEMORY) {
3609 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3612 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3614 i386_jcc(cd, I386_CC_G, 0);
3615 codegen_addreference(cd, (basicblock *) iptr->target);
3618 case ICMD_IFGE: /* ..., value ==> ... */
3619 /* op1 = target JavaVM pc, val.i = constant */
3620 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3621 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3623 if (src->flags & INMEMORY) {
3624 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3627 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3629 i386_jcc(cd, I386_CC_GE, 0);
3630 codegen_addreference(cd, (basicblock *) iptr->target);
3633 case ICMD_IF_LEQ: /* ..., value ==> ... */
3634 /* op1 = target JavaVM pc, val.l = constant */
3635 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3636 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3638 if (src->flags & INMEMORY) {
3639 if (iptr->val.l == 0) {
3640 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3641 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3644 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3645 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l >> 32, REG_ITMP2);
3646 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3647 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l, REG_ITMP1);
3648 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3651 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3652 i386_jcc(cd, I386_CC_E, 0);
3653 codegen_addreference(cd, (basicblock *) iptr->target);
3656 case ICMD_IF_LLT: /* ..., value ==> ... */
3657 /* op1 = target JavaVM pc, val.l = constant */
3658 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3659 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3661 if (src->flags & INMEMORY) {
3662 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3663 i386_jcc(cd, I386_CC_L, 0);
3664 codegen_addreference(cd, (basicblock *) iptr->target);
3667 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3668 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3670 i386_jcc(cd, I386_CC_G, disp);
3672 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3673 i386_jcc(cd, I386_CC_B, 0);
3674 codegen_addreference(cd, (basicblock *) iptr->target);
3678 case ICMD_IF_LLE: /* ..., value ==> ... */
3679 /* op1 = target JavaVM pc, val.l = constant */
3680 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3681 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3683 if (src->flags & INMEMORY) {
3684 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3685 i386_jcc(cd, I386_CC_L, 0);
3686 codegen_addreference(cd, (basicblock *) iptr->target);
3689 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3690 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3692 i386_jcc(cd, I386_CC_G, disp);
3694 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3695 i386_jcc(cd, I386_CC_BE, 0);
3696 codegen_addreference(cd, (basicblock *) iptr->target);
3700 case ICMD_IF_LNE: /* ..., value ==> ... */
3701 /* op1 = target JavaVM pc, val.l = constant */
3702 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3703 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3705 if (src->flags & INMEMORY) {
3706 if (iptr->val.l == 0) {
3707 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3708 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3711 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3712 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3713 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3714 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3715 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3718 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3719 i386_jcc(cd, I386_CC_NE, 0);
3720 codegen_addreference(cd, (basicblock *) iptr->target);
3723 case ICMD_IF_LGT: /* ..., value ==> ... */
3724 /* op1 = target JavaVM pc, val.l = constant */
3725 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3726 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3728 if (src->flags & INMEMORY) {
3729 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3730 i386_jcc(cd, I386_CC_G, 0);
3731 codegen_addreference(cd, (basicblock *) iptr->target);
3734 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3735 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3737 i386_jcc(cd, I386_CC_L, disp);
3739 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3740 i386_jcc(cd, I386_CC_A, 0);
3741 codegen_addreference(cd, (basicblock *) iptr->target);
3745 case ICMD_IF_LGE: /* ..., value ==> ... */
3746 /* op1 = target JavaVM pc, val.l = constant */
3747 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3748 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3750 if (src->flags & INMEMORY) {
3751 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3752 i386_jcc(cd, I386_CC_G, 0);
3753 codegen_addreference(cd, (basicblock *) iptr->target);
3756 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3757 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3759 i386_jcc(cd, I386_CC_L, disp);
3761 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3762 i386_jcc(cd, I386_CC_AE, 0);
3763 codegen_addreference(cd, (basicblock *) iptr->target);
3767 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3768 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3769 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3770 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3772 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3773 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3774 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3776 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3777 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3779 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3780 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3783 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3785 i386_jcc(cd, I386_CC_E, 0);
3786 codegen_addreference(cd, (basicblock *) iptr->target);
3789 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3790 /* op1 = target JavaVM pc */
3791 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3792 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3794 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3795 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3796 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3797 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3798 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3799 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3800 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3802 i386_jcc(cd, I386_CC_E, 0);
3803 codegen_addreference(cd, (basicblock *) iptr->target);
3806 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3807 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3808 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3809 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3811 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3812 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3813 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3815 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3816 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3818 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3819 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3822 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3824 i386_jcc(cd, I386_CC_NE, 0);
3825 codegen_addreference(cd, (basicblock *) iptr->target);
3828 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3829 /* op1 = target JavaVM pc */
3830 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3831 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3833 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3834 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3835 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3836 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3837 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3838 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3839 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3841 i386_jcc(cd, I386_CC_NE, 0);
3842 codegen_addreference(cd, (basicblock *) iptr->target);
3845 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3846 /* op1 = target JavaVM pc */
3847 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3848 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3850 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3851 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3852 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3854 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3855 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3857 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3858 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3861 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3863 i386_jcc(cd, I386_CC_L, 0);
3864 codegen_addreference(cd, (basicblock *) iptr->target);
3867 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3868 /* op1 = target JavaVM pc */
3869 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3870 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3872 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3873 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3874 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3876 codegen_addreference(cd, (basicblock *) iptr->target);
3879 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3880 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3884 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3885 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3886 i386_jcc(cd, I386_CC_B, 0);
3887 codegen_addreference(cd, (basicblock *) iptr->target);
3891 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3892 /* op1 = target JavaVM pc */
3893 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3894 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3896 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3897 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3898 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3900 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3901 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3903 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3904 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3907 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3910 codegen_addreference(cd, (basicblock *) iptr->target);
3913 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3914 /* op1 = target JavaVM pc */
3915 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3916 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3918 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3919 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3920 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3922 codegen_addreference(cd, (basicblock *) iptr->target);
3925 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3926 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3930 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3931 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3932 i386_jcc(cd, I386_CC_A, 0);
3933 codegen_addreference(cd, (basicblock *) iptr->target);
3937 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3938 /* op1 = target JavaVM pc */
3939 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3940 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3942 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3943 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3944 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3946 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3947 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3949 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3950 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3953 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3956 codegen_addreference(cd, (basicblock *) iptr->target);
3959 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3960 /* op1 = target JavaVM pc */
3961 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3962 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3964 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3965 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3966 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3968 codegen_addreference(cd, (basicblock *) iptr->target);
3971 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3972 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3976 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3977 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3979 codegen_addreference(cd, (basicblock *) iptr->target);
3983 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3984 /* op1 = target JavaVM pc */
3985 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3986 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3988 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3989 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3990 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3992 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3993 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3995 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3996 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3999 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
4002 codegen_addreference(cd, (basicblock *) iptr->target);
4005 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
4006 /* op1 = target JavaVM pc */
4007 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4008 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4010 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
4011 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
4012 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
4014 codegen_addreference(cd, (basicblock *) iptr->target);
4017 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
4018 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
4022 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
4023 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
4025 codegen_addreference(cd, (basicblock *) iptr->target);
4029 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
4031 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
4032 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4033 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4036 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
4037 /* val.i = constant */
4038 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4039 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4041 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4042 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
4045 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
4046 /* val.i = constant */
4047 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4048 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4050 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4051 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
4054 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
4055 /* val.i = constant */
4056 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4057 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4059 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4060 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
4063 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
4064 /* val.i = constant */
4065 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4066 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4068 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4069 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
4072 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
4073 /* val.i = constant */
4074 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4075 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4077 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4078 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
4081 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
4082 /* val.i = constant */
4083 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4084 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4086 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4087 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
4091 case ICMD_IRETURN: /* ..., retvalue ==> ... */
4092 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4093 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4095 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
4096 M_INTMOVE(s1, REG_RESULT);
4097 goto nowperformreturn;
4099 case ICMD_LRETURN: /* ..., retvalue ==> ... */
4100 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4101 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4103 if (src->flags & INMEMORY) {
4104 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_RESULT);
4105 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_RESULT2);
4108 log_text("LRETURN: longs have to be in memory");
4111 goto nowperformreturn;
4113 case ICMD_ARETURN: /* ..., retvalue ==> ... */
4114 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4115 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4117 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
4118 M_INTMOVE(s1, REG_RESULT);
4120 #ifdef ENABLE_VERIFIER
4122 codegen_addpatchref(cd, PATCHER_athrow_areturn,
4123 (unresolved_class *) iptr->val.a, 0);
4125 if (opt_showdisassemble) {
4126 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4129 #endif /* ENABLE_VERIFIER */
4130 goto nowperformreturn;
4132 case ICMD_FRETURN: /* ..., retvalue ==> ... */
4134 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4135 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4137 s1 = emit_load_s1(jd, iptr, src, REG_FRESULT);
4138 /* this may be an early return -- keep the offset correct for the
4141 goto nowperformreturn;
4143 case ICMD_RETURN: /* ... ==> ... */
4144 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4145 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4153 #if !defined(NDEBUG)
4154 /* call trace function */
4155 if (opt_verbosecall) {
4156 i386_alu_imm_reg(cd, ALU_SUB, 4 + 8 + 8 + 4, REG_SP);
4158 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
4160 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
4161 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
4163 i386_fstl_membase(cd, REG_SP, 4 + 8);
4164 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
4166 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
4167 i386_call_reg(cd, REG_ITMP1);
4169 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
4170 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
4172 i386_alu_imm_reg(cd, ALU_ADD, 4 + 8 + 8 + 4, REG_SP);
4174 #endif /* !defined(NDEBUG) */
4176 #if defined(ENABLE_THREADS)
4177 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
4178 M_ALD(REG_ITMP2, REG_SP, rd->memuse * 4);
4180 /* we need to save the proper return value */
4181 switch (iptr->opc) {
4184 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4188 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4189 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4193 i386_fstps_membase(cd, REG_SP, rd->memuse * 4);
4197 i386_fstpl_membase(cd, REG_SP, rd->memuse * 4);
4201 M_AST(REG_ITMP2, REG_SP, 0);
4202 M_MOV_IMM(BUILTIN_monitorexit, REG_ITMP1);
4205 /* and now restore the proper return value */
4206 switch (iptr->opc) {
4209 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4213 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4214 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4218 i386_flds_membase(cd, REG_SP, rd->memuse * 4);
4222 i386_fldl_membase(cd, REG_SP, rd->memuse * 4);
4228 /* restore saved registers */
4230 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
4231 p--; M_ALD(rd->savintregs[i], REG_SP, p * 4);
4234 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
4236 i386_fldl_membase(cd, REG_SP, p * 4);
4238 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
4239 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
4241 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
4246 /* deallocate stack */
4249 M_AADD_IMM(stackframesize * 4, REG_SP);
4256 case ICMD_TABLESWITCH: /* ..., index ==> ... */
4257 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4258 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4263 tptr = (void **) iptr->target;
4265 s4ptr = iptr->val.a;
4266 l = s4ptr[1]; /* low */
4267 i = s4ptr[2]; /* high */
4269 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4270 M_INTMOVE(s1, REG_ITMP1);
4272 i386_alu_imm_reg(cd, ALU_SUB, l, REG_ITMP1);
4278 i386_alu_imm_reg(cd, ALU_CMP, i - 1, REG_ITMP1);
4279 i386_jcc(cd, I386_CC_A, 0);
4281 codegen_addreference(cd, (basicblock *) tptr[0]);
4283 /* build jump table top down and use address of lowest entry */
4288 dseg_addtarget(cd, (basicblock *) tptr[0]);
4292 /* length of dataseg after last dseg_addtarget is used by load */
4294 i386_mov_imm_reg(cd, 0, REG_ITMP2);
4296 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
4297 i386_jmp_reg(cd, REG_ITMP1);
4302 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
4303 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4304 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4306 s4 i, l, val, *s4ptr;
4309 tptr = (void **) iptr->target;
4311 s4ptr = iptr->val.a;
4312 l = s4ptr[0]; /* default */
4313 i = s4ptr[1]; /* count */
4315 MCODECHECK((i<<2)+8);
4316 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1); /* reg compare should always be faster */
4322 i386_alu_imm_reg(cd, ALU_CMP, val, s1);
4323 i386_jcc(cd, I386_CC_E, 0);
4324 codegen_addreference(cd, (basicblock *) tptr[0]);
4327 i386_jmp_imm(cd, 0);
4329 tptr = (void **) iptr->target;
4330 codegen_addreference(cd, (basicblock *) tptr[0]);
4334 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
4335 /* op1 = arg count val.a = builtintable entry */
4336 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4337 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4343 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
4344 /* op1 = arg count, val.a = method pointer */
4346 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
4347 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
4348 case ICMD_INVOKEINTERFACE:
4350 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4351 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
4353 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
4354 md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
4358 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
4359 md = lm->parseddesc;
4363 s3 = md->paramcount;
4365 MCODECHECK((s3 << 1) + 64);
4367 /* copy arguments to registers or stack location */
4369 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
4370 if (src->varkind == ARGVAR)
4372 if (IS_INT_LNG_TYPE(src->type)) {
4373 if (!md->params[s3].inmemory) {
4374 log_text("No integer argument registers available!");
4378 if (IS_2_WORD_TYPE(src->type)) {
4379 d = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP1, REG_ITMP2));
4380 M_LST(d, REG_SP, md->params[s3].regoff * 4);
4382 d = emit_load_s1(jd, iptr, src, REG_ITMP1);
4383 M_IST(d, REG_SP, md->params[s3].regoff * 4);
4388 if (!md->params[s3].inmemory) {
4389 s1 = rd->argfltregs[md->params[s3].regoff];
4390 d = emit_load_s1(jd, iptr, src, s1);
4394 d = emit_load_s1(jd, iptr, src, REG_FTMP1);
4395 if (IS_2_WORD_TYPE(src->type))
4396 M_DST(d, REG_SP, md->params[s3].regoff * 4);
4398 M_FST(d, REG_SP, md->params[s3].regoff * 4);
4403 switch (iptr->opc) {
4405 disp = (ptrint) bte->fp;
4406 d = md->returntype.type;
4408 M_MOV_IMM(disp, REG_ITMP1);
4411 /* if op1 == true, we need to check for an exception */
4413 if (iptr->op1 == true) {
4416 codegen_add_fillinstacktrace_ref(cd);
4420 case ICMD_INVOKESPECIAL:
4421 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
4422 gen_nullptr_check(REG_ITMP1);
4424 /* access memory for hardware nullptr */
4425 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1);
4429 case ICMD_INVOKESTATIC:
4431 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
4433 codegen_addpatchref(cd, PATCHER_invokestatic_special,
4436 if (opt_showdisassemble) {
4437 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4441 d = md->returntype.type;
4444 disp = (ptrint) lm->stubroutine;
4445 d = lm->parseddesc->returntype.type;
4448 M_MOV_IMM(disp, REG_ITMP2);
4452 case ICMD_INVOKEVIRTUAL:
4453 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4454 gen_nullptr_check(REG_ITMP1);
4457 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
4459 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
4461 if (opt_showdisassemble) {
4462 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4466 d = md->returntype.type;
4469 s1 = OFFSET(vftbl_t, table[0]) +
4470 sizeof(methodptr) * lm->vftblindex;
4471 d = md->returntype.type;
4474 M_ALD(REG_ITMP2, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4475 i386_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP1);
4479 case ICMD_INVOKEINTERFACE:
4480 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4481 gen_nullptr_check(REG_ITMP1);
4484 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
4486 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
4488 if (opt_showdisassemble) {
4489 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4494 d = md->returntype.type;
4497 s1 = OFFSET(vftbl_t, interfacetable[0]) -
4498 sizeof(methodptr) * lm->class->index;
4500 s2 = sizeof(methodptr) * (lm - lm->class->methods);
4502 d = md->returntype.type;
4505 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4506 i386_mov_membase32_reg(cd, REG_ITMP1, s1, REG_ITMP2);
4507 i386_mov_membase32_reg(cd, REG_ITMP2, s2, REG_ITMP1);
4512 /* d contains return type */
4514 if (d != TYPE_VOID) {
4515 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4517 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
4518 if (IS_2_WORD_TYPE(iptr->dst->type)) {
4519 if (iptr->dst->flags & INMEMORY) {
4520 i386_mov_reg_membase(
4521 cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4522 i386_mov_reg_membase(
4523 cd, REG_RESULT2, REG_SP,
4524 iptr->dst->regoff * 4 + 4);
4526 log_text("RETURN: longs have to be in memory");
4531 if (iptr->dst->flags & INMEMORY) {
4532 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4535 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
4540 /* fld from called function -- has other fpu_st_offset counter */
4542 emit_store(jd, iptr, iptr->dst, d);
4548 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4549 /* op1: 0 == array, 1 == class */
4550 /* val.a: (classinfo*) superclass */
4552 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4553 /* EAX: YES ECX: I|YES EDX: I|YES OUTPUT: REG_NULL */
4555 /* superclass is an interface:
4557 * OK if ((sub == NULL) ||
4558 * (sub->vftbl->interfacetablelength > super->index) &&
4559 * (sub->vftbl->interfacetable[-super->index] != NULL));
4561 * superclass is a class:
4563 * OK if ((sub == NULL) || (0
4564 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4565 * super->vftbl->diffval));
4568 if (iptr->op1 == 1) {
4569 /* object type cast-check */
4572 vftbl_t *supervftbl;
4575 super = (classinfo *) iptr->val.a;
4582 superindex = super->index;
4583 supervftbl = super->vftbl;
4586 #if defined(ENABLE_THREADS)
4587 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4589 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4591 /* calculate interface checkcast code size */
4593 s2 = 2; /* mov_membase_reg */
4594 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4596 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ +
4597 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4598 2 /* test */ + 6 /* jcc */);
4601 s2 += (opt_showdisassemble ? 5 : 0);
4603 /* calculate class checkcast code size */
4605 s3 = 2; /* mov_membase_reg */
4606 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4608 s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */;
4611 if (s1 != REG_ITMP1) {
4613 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
4616 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
4623 s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ +
4624 5 /* mov_imm_reg */ + 2 /* mov_membase_reg */);
4625 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
4628 s3 += 2 /* cmp */ + 6 /* jcc */;
4631 s3 += (opt_showdisassemble ? 5 : 0);
4633 /* if class is not resolved, check which code to call */
4636 i386_test_reg_reg(cd, s1, s1);
4637 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4639 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
4640 (constant_classref *) iptr->target, 0);
4642 if (opt_showdisassemble) {
4643 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4646 i386_mov_imm_reg(cd, 0, REG_ITMP2); /* super->flags */
4647 i386_alu_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP2);
4648 i386_jcc(cd, I386_CC_Z, s2 + 5);
4651 /* interface checkcast code */
4653 if (!super || (super->flags & ACC_INTERFACE)) {
4655 i386_test_reg_reg(cd, s1, s1);
4656 i386_jcc(cd, I386_CC_Z, s2);
4659 i386_mov_membase_reg(cd, s1,
4660 OFFSET(java_objectheader, vftbl),
4664 codegen_addpatchref(cd,
4665 PATCHER_checkcast_instanceof_interface,
4666 (constant_classref *) iptr->target, 0);
4668 if (opt_showdisassemble) {
4669 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4673 i386_mov_membase32_reg(cd, REG_ITMP2,
4674 OFFSET(vftbl_t, interfacetablelength),
4676 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4677 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4678 i386_jcc(cd, I386_CC_LE, 0);
4679 codegen_add_classcastexception_ref(cd);
4680 i386_mov_membase32_reg(cd, REG_ITMP2,
4681 OFFSET(vftbl_t, interfacetable[0]) -
4682 superindex * sizeof(methodptr*),
4684 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4685 i386_jcc(cd, I386_CC_E, 0);
4686 codegen_add_classcastexception_ref(cd);
4689 i386_jmp_imm(cd, s3);
4692 /* class checkcast code */
4694 if (!super || !(super->flags & ACC_INTERFACE)) {
4696 i386_test_reg_reg(cd, s1, s1);
4697 i386_jcc(cd, I386_CC_Z, s3);
4700 i386_mov_membase_reg(cd, s1,
4701 OFFSET(java_objectheader, vftbl),
4705 codegen_addpatchref(cd, PATCHER_checkcast_class,
4706 (constant_classref *) iptr->target,
4709 if (opt_showdisassemble) {
4710 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4714 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4715 #if defined(ENABLE_THREADS)
4716 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4718 i386_mov_membase32_reg(cd, REG_ITMP2,
4719 OFFSET(vftbl_t, baseval),
4722 /* if (s1 != REG_ITMP1) { */
4723 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
4724 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
4725 /* #if defined(ENABLE_THREADS) */
4726 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
4728 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
4731 i386_mov_membase32_reg(cd, REG_ITMP3,
4732 OFFSET(vftbl_t, baseval),
4734 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP3, REG_ITMP2);
4735 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4736 i386_mov_membase_reg(cd, REG_ITMP3,
4737 OFFSET(vftbl_t, diffval),
4739 #if defined(ENABLE_THREADS)
4740 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4744 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP2);
4745 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
4746 codegen_add_classcastexception_ref(cd);
4748 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
4751 /* array type cast-check */
4753 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4754 M_AST(s1, REG_SP, 0 * 4);
4756 if (iptr->val.a == NULL) {
4757 codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
4760 if (opt_showdisassemble) {
4761 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4765 M_AST_IMM(iptr->val.a, REG_SP, 1 * 4);
4766 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP3);
4770 codegen_add_classcastexception_ref(cd);
4772 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4773 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
4776 emit_store(jd, iptr, iptr->dst, d);
4779 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
4781 /* op1: 0 == array, 1 == class */
4782 /* val.a: (classinfo*) superclass */
4783 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4784 /* EAX: S|D|YES ECX: YES S|D|EDX: S|D|YES OUTPUT: REG_NULL*/
4785 /* ????? Really necessary to block all ????? */
4787 /* superclass is an interface:
4789 * return (sub != NULL) &&
4790 * (sub->vftbl->interfacetablelength > super->index) &&
4791 * (sub->vftbl->interfacetable[-super->index] != NULL);
4793 * superclass is a class:
4795 * return ((sub != NULL) && (0
4796 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4797 * super->vftbl->diffvall));
4802 vftbl_t *supervftbl;
4805 super = (classinfo *) iptr->val.a;
4812 superindex = super->index;
4813 supervftbl = super->vftbl;
4816 #if defined(ENABLE_THREADS)
4817 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4820 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4821 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
4823 M_INTMOVE(s1, REG_ITMP1);
4827 /* calculate interface instanceof code size */
4829 s2 = 2; /* mov_membase_reg */
4830 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4832 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
4833 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4834 2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4837 s2 += (opt_showdisassemble ? 5 : 0);
4839 /* calculate class instanceof code size */
4841 s3 = 2; /* mov_membase_reg */
4842 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4843 s3 += 5; /* mov_imm_reg */
4845 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
4847 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
4849 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
4851 s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
4852 2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4855 s3 += (opt_showdisassemble ? 5 : 0);
4857 i386_alu_reg_reg(cd, ALU_XOR, d, d);
4859 /* if class is not resolved, check which code to call */
4862 i386_test_reg_reg(cd, s1, s1);
4863 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4865 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
4866 (constant_classref *) iptr->target, 0);
4868 if (opt_showdisassemble) {
4869 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4872 i386_mov_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
4873 i386_alu_imm32_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
4874 i386_jcc(cd, I386_CC_Z, s2 + 5);
4877 /* interface instanceof code */
4879 if (!super || (super->flags & ACC_INTERFACE)) {
4885 i386_mov_membase_reg(cd, s1,
4886 OFFSET(java_objectheader, vftbl),
4890 codegen_addpatchref(cd,
4891 PATCHER_checkcast_instanceof_interface,
4892 (constant_classref *) iptr->target, 0);
4894 if (opt_showdisassemble) {
4895 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4899 i386_mov_membase32_reg(cd, REG_ITMP1,
4900 OFFSET(vftbl_t, interfacetablelength),
4902 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4903 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4905 disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
4906 6 /* jcc */ + 5 /* mov_imm_reg */);
4909 i386_mov_membase32_reg(cd, REG_ITMP1,
4910 OFFSET(vftbl_t, interfacetable[0]) -
4911 superindex * sizeof(methodptr*),
4914 /* i386_setcc_reg(cd, I386_CC_A, d); */
4915 /* i386_jcc(cd, I386_CC_BE, 5); */
4923 /* class instanceof code */
4925 if (!super || !(super->flags & ACC_INTERFACE)) {
4931 i386_mov_membase_reg(cd, s1,
4932 OFFSET(java_objectheader, vftbl),
4936 codegen_addpatchref(cd, PATCHER_instanceof_class,
4937 (constant_classref *) iptr->target, 0);
4939 if (opt_showdisassemble) {
4940 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4944 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
4945 #if defined(ENABLE_THREADS)
4946 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4948 i386_mov_membase_reg(cd, REG_ITMP1,
4949 OFFSET(vftbl_t, baseval),
4951 i386_mov_membase_reg(cd, REG_ITMP2,
4952 OFFSET(vftbl_t, diffval),
4954 i386_mov_membase_reg(cd, REG_ITMP2,
4955 OFFSET(vftbl_t, baseval),
4957 #if defined(ENABLE_THREADS)
4958 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4960 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
4961 i386_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
4962 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
4963 i386_jcc(cd, I386_CC_A, 5);
4964 i386_mov_imm_reg(cd, 1, d);
4966 emit_store(jd, iptr, iptr->dst, d);
4972 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4973 /* op1 = dimension, val.a = class */
4974 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4975 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
4977 /* check for negative sizes and copy sizes to stack if necessary */
4979 MCODECHECK((iptr->op1 << 1) + 64);
4981 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4982 /* copy SAVEDVAR sizes to stack */
4984 if (src->varkind != ARGVAR) {
4985 if (src->flags & INMEMORY) {
4986 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
4987 M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4);
4990 M_IST(src->regoff, REG_SP, (s1 + 3) * 4);
4995 /* is a patcher function set? */
4997 if (iptr->val.a == NULL) {
4998 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
4999 (constant_classref *) iptr->target, 0);
5001 if (opt_showdisassemble) {
5002 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5008 disp = (ptrint) iptr->val.a;
5011 /* a0 = dimension count */
5013 M_IST_IMM(iptr->op1, REG_SP, 0 * 4);
5015 /* a1 = arraydescriptor */
5017 M_IST_IMM(disp, REG_SP, 1 * 4);
5019 /* a2 = pointer to dimensions = stack pointer */
5021 M_MOV(REG_SP, REG_ITMP1);
5022 M_AADD_IMM(3 * 4, REG_ITMP1);
5023 M_AST(REG_ITMP1, REG_SP, 2 * 4);
5025 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
5028 /* check for exception before result assignment */
5032 codegen_add_fillinstacktrace_ref(cd);
5034 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
5035 M_INTMOVE(REG_RESULT, s1);
5036 emit_store(jd, iptr, iptr->dst, s1);
5041 new_internalerror("Unknown ICMD %d", iptr->opc);
5045 } /* for instruction */
5047 /* copy values to interface registers */
5049 src = bptr->outstack;
5050 len = bptr->outdepth;
5052 #if defined(ENABLE_LSRA)
5057 if ((src->varkind != STACKVAR)) {
5059 if (IS_FLT_DBL_TYPE(s2)) {
5060 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
5061 if (!(rd->interfaces[len][s2].flags & INMEMORY))
5062 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
5064 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5067 if (IS_2_WORD_TYPE(s2))
5069 /* s1 = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP1, REG_ITMP2)); */
5071 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
5073 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5074 if (IS_2_WORD_TYPE(s2))
5075 M_LNGMOVE(s1, rd->interfaces[len][s2].regoff);
5077 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
5080 if (IS_2_WORD_TYPE(s2))
5081 M_LST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5083 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5090 /* At the end of a basic block we may have to append some nops,
5091 because the patcher stub calling code might be longer than the
5092 actual instruction. So codepatching does not change the
5093 following block unintentionally. */
5095 if (cd->mcodeptr < cd->lastmcodeptr) {
5096 while (cd->mcodeptr < cd->lastmcodeptr) {
5101 } /* if (bptr -> flags >= BBREACHED) */
5102 } /* for basic block */
5104 dseg_createlinenumbertable(cd);
5107 /* generate exception and patcher stubs */
5116 savedmcodeptr = NULL;
5118 /* generate exception stubs */
5120 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
5121 gen_resolvebranch(cd->mcodebase + eref->branchpos,
5123 cd->mcodeptr - cd->mcodebase);
5127 /* Check if the exception is an
5128 ArrayIndexOutOfBoundsException. If so, move index register
5131 if (eref->reg != -1)
5132 M_INTMOVE(eref->reg, REG_ITMP1);
5134 /* calcuate exception address */
5136 M_MOV_IMM(0, REG_ITMP2_XPC);
5138 M_AADD_IMM32(eref->branchpos - 6, REG_ITMP2_XPC);
5140 /* move function to call into REG_ITMP3 */
5142 M_MOV_IMM(eref->function, REG_ITMP3);
5144 if (savedmcodeptr != NULL) {
5145 M_JMP_IMM((savedmcodeptr - cd->mcodeptr) - 5);
5148 savedmcodeptr = cd->mcodeptr;
5150 M_ASUB_IMM(5 * 4, REG_SP);
5152 /* first save REG_ITMP1 so we can use it */
5154 M_AST(REG_ITMP1, REG_SP, 4 * 4); /* for AIOOBE */
5156 M_AST_IMM(0, REG_SP, 0 * 4);
5158 M_MOV(REG_SP, REG_ITMP1);
5159 M_AADD_IMM(5 * 4, REG_ITMP1);
5160 M_AST(REG_ITMP1, REG_SP, 1 * 4);
5161 M_ALD(REG_ITMP1, REG_SP, (5 + stackframesize) * 4);
5162 M_AST(REG_ITMP1, REG_SP, 2 * 4);
5163 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5167 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5168 M_AADD_IMM(5 * 4, REG_SP);
5170 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
5176 /* generate code patching stub call code */
5178 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5179 /* check code segment size */
5183 /* Get machine code which is patched back in later. A
5184 `call rel32' is 5 bytes long. */
5186 savedmcodeptr = cd->mcodebase + pref->branchpos;
5187 mcode = *((u8 *) savedmcodeptr);
5189 /* patch in `call rel32' to call the following code */
5191 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
5192 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
5194 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
5196 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
5198 /* save REG_ITMP3 */
5202 /* move pointer to java_objectheader onto stack */
5204 #if defined(ENABLE_THREADS)
5205 (void) dseg_addaddress(cd, NULL); /* flcword */
5206 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
5207 off = dseg_addaddress(cd, NULL); /* vftbl */
5209 M_MOV_IMM(0, REG_ITMP3);
5211 M_AADD_IMM(off, REG_ITMP3);
5217 /* move machine code bytes and classinfo pointer into registers */
5219 M_PUSH_IMM(mcode >> 32);
5221 M_PUSH_IMM(pref->ref);
5222 M_PUSH_IMM(pref->patcher);
5224 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
5229 /* generate replacement-out stubs */
5234 replacementpoint = jd->code->rplpoints;
5236 for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
5237 /* check code segment size */
5241 /* note start of stub code */
5243 replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
5245 /* make machine code for patching */
5247 disp = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
5248 replacementpoint->mcode = 0xe9 | ((u8)disp << 8);
5250 /* push address of `rplpoint` struct */
5252 M_PUSH_IMM(replacementpoint);
5254 /* jump to replacement function */
5256 M_PUSH_IMM(asm_replacement_out);
5263 /* everything's ok */
5269 /* createcompilerstub **********************************************************
5271 Creates a stub routine which calls the compiler.
5273 *******************************************************************************/
5275 #define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P
5276 #define COMPILERSTUB_CODESIZE 12
5278 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
5281 u1 *createcompilerstub(methodinfo *m)
5283 u1 *s; /* memory to hold the stub */
5289 s = CNEW(u1, COMPILERSTUB_SIZE);
5291 /* set data pointer and code pointer */
5294 s = s + COMPILERSTUB_DATASIZE;
5296 /* mark start of dump memory area */
5298 dumpsize = dump_size();
5300 cd = DNEW(codegendata);
5303 /* Store the codeinfo pointer in the same place as in the
5304 methodheader for compiled methods. */
5306 code = code_codeinfo_new(m);
5308 d[0] = (ptrint) asm_call_jit_compiler;
5310 d[2] = (ptrint) code;
5312 M_MOV_IMM(m, REG_ITMP1);
5314 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
5315 M_MOV_IMM(asm_call_jit_compiler, REG_ITMP3);
5318 #if defined(ENABLE_STATISTICS)
5320 count_cstub_len += COMPILERSTUB_SIZE;
5323 /* release dump area */
5325 dump_release(dumpsize);
5331 /* createnativestub ************************************************************
5333 Creates a stub routine which calls a native method.
5335 *******************************************************************************/
5337 #if defined(ENABLE_THREADS)
5338 /* this way we can call the function directly with a memory call */
5340 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
5343 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
5352 s4 i, j; /* count variables */
5356 /* get required compiler data */
5363 /* set some variables */
5366 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
5368 /* calculate stackframe size */
5371 sizeof(stackframeinfo) / SIZEOF_VOID_P +
5372 sizeof(localref_table) / SIZEOF_VOID_P +
5373 1 + /* function pointer */
5374 4 * 4 + /* 4 arguments (start_native_call) */
5377 /* create method header */
5379 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
5380 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
5381 (void) dseg_adds4(cd, 0); /* IsSync */
5382 (void) dseg_adds4(cd, 0); /* IsLeaf */
5383 (void) dseg_adds4(cd, 0); /* IntSave */
5384 (void) dseg_adds4(cd, 0); /* FltSave */
5385 (void) dseg_addlinenumbertablesize(cd);
5386 (void) dseg_adds4(cd, 0); /* ExTableSize */
5388 /* generate native method profiling code */
5391 /* count frequency */
5393 M_MOV_IMM(m, REG_ITMP1);
5394 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(methodinfo, frequency));
5397 /* calculate stackframe size for native function */
5399 M_ASUB_IMM(stackframesize * 4, REG_SP);
5401 #if !defined(NDEBUG)
5402 if (opt_verbosecall) {
5405 disp = stackframesize * 4;
5407 M_ASUB_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5409 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
5410 t = md->paramtypes[p].type;
5411 if (IS_INT_LNG_TYPE(t)) {
5412 if (IS_2_WORD_TYPE(t)) {
5413 M_ILD(REG_ITMP1, REG_SP,
5414 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5415 M_ILD(REG_ITMP2, REG_SP,
5416 4 + TRACE_ARGS_NUM * 8 + 4 + disp + 4);
5417 M_IST(REG_ITMP1, REG_SP, p * 8);
5418 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5420 } else if (t == TYPE_ADR) {
5421 M_ALD(REG_ITMP1, REG_SP,
5422 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5424 M_AST(REG_ITMP1, REG_SP, p * 8);
5425 M_AST(REG_ITMP2, REG_SP, p * 8 + 4);
5428 M_ILD(EAX, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5430 M_IST(EAX, REG_SP, p * 8);
5431 M_IST(EDX, REG_SP, p * 8 + 4);
5435 if (!IS_2_WORD_TYPE(t)) {
5436 i386_flds_membase(cd, REG_SP,
5437 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5438 i386_fstps_membase(cd, REG_SP, p * 8);
5439 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
5440 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5443 i386_fldl_membase(cd, REG_SP,
5444 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5445 i386_fstpl_membase(cd, REG_SP, p * 8);
5448 disp += (IS_2_WORD_TYPE(t)) ? 8 : 4;
5452 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
5453 M_IST(REG_ITMP1, REG_SP, p * 8);
5454 M_IST(REG_ITMP1, REG_SP, p * 8 + 4);
5457 M_AST_IMM(m, REG_SP, TRACE_ARGS_NUM * 8);
5459 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
5462 M_AADD_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5464 #endif /* !defined(NDEBUG) */
5466 /* get function address (this must happen before the stackframeinfo) */
5468 #if !defined(WITH_STATIC_CLASSPATH)
5470 codegen_addpatchref(cd, PATCHER_resolve_native, m, 0);
5472 if (opt_showdisassemble) {
5473 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5478 M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
5480 /* Mark the whole fpu stack as free for native functions (only for saved */
5481 /* register count == 0). */
5483 i386_ffree_reg(cd, 0);
5484 i386_ffree_reg(cd, 1);
5485 i386_ffree_reg(cd, 2);
5486 i386_ffree_reg(cd, 3);
5487 i386_ffree_reg(cd, 4);
5488 i386_ffree_reg(cd, 5);
5489 i386_ffree_reg(cd, 6);
5490 i386_ffree_reg(cd, 7);
5492 /* prepare data structures for native function call */
5494 M_MOV(REG_SP, REG_ITMP1);
5495 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5497 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5498 M_IST_IMM(0, REG_SP, 1 * 4);
5501 M_MOV(REG_SP, REG_ITMP2);
5502 M_AADD_IMM(stackframesize * 4 + SIZEOF_VOID_P, REG_ITMP2);
5504 M_AST(REG_ITMP2, REG_SP, 2 * 4);
5505 M_ALD(REG_ITMP3, REG_SP, stackframesize * 4);
5506 M_AST(REG_ITMP3, REG_SP, 3 * 4);
5507 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
5510 M_ALD(REG_ITMP3, REG_SP, 4 * 4);
5512 /* copy arguments into new stackframe */
5514 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
5515 t = md->paramtypes[i].type;
5517 if (!md->params[i].inmemory) {
5518 /* no integer argument registers */
5519 } else { /* float/double in memory can be copied like int/longs */
5520 s1 = (md->params[i].regoff + stackframesize + 1) * 4;
5521 s2 = nmd->params[j].regoff * 4;
5523 M_ILD(REG_ITMP1, REG_SP, s1);
5524 M_IST(REG_ITMP1, REG_SP, s2);
5525 if (IS_2_WORD_TYPE(t)) {
5526 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
5527 M_IST(REG_ITMP1, REG_SP, s2 + 4);
5532 /* if function is static, put class into second argument */
5534 if (m->flags & ACC_STATIC)
5535 M_AST_IMM((ptrint) m->class, REG_SP, 1 * 4);
5537 /* put env into first argument */
5539 M_AST_IMM((ptrint) _Jv_env, REG_SP, 0 * 4);
5541 /* call the native function */
5545 /* save return value */
5547 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5548 if (IS_2_WORD_TYPE(md->returntype.type))
5549 M_IST(REG_RESULT2, REG_SP, 2 * 4);
5550 M_IST(REG_RESULT, REG_SP, 1 * 4);
5553 if (IS_2_WORD_TYPE(md->returntype.type))
5554 i386_fstl_membase(cd, REG_SP, 1 * 4);
5556 i386_fsts_membase(cd, REG_SP, 1 * 4);
5559 /* remove data structures for native function call */
5561 M_MOV(REG_SP, REG_ITMP1);
5562 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5564 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5565 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
5568 #if !defined(NDEBUG)
5569 if (opt_verbosecall) {
5570 /* restore return value */
5572 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5573 if (IS_2_WORD_TYPE(md->returntype.type))
5574 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5575 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5578 if (IS_2_WORD_TYPE(md->returntype.type))
5579 i386_fldl_membase(cd, REG_SP, 1 * 4);
5581 i386_flds_membase(cd, REG_SP, 1 * 4);
5584 M_ASUB_IMM(4 + 8 + 8 + 4, REG_SP);
5586 M_AST_IMM((ptrint) m, REG_SP, 0);
5588 M_IST(REG_RESULT, REG_SP, 4);
5589 M_IST(REG_RESULT2, REG_SP, 4 + 4);
5591 i386_fstl_membase(cd, REG_SP, 4 + 8);
5592 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5594 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
5597 M_AADD_IMM(4 + 8 + 8 + 4, REG_SP);
5599 #endif /* !defined(NDEBUG) */
5601 /* check for exception */
5603 #if defined(ENABLE_THREADS)
5604 /* i386_call_mem(cd, (ptrint) builtin_get_exceptionptrptr); */
5605 i386_call_mem(cd, (ptrint) &callgetexceptionptrptr);
5607 M_MOV_IMM(&_no_threads_exceptionptr, REG_RESULT);
5609 /* we can't use REG_ITMP3 == REG_RESULT2 */
5610 M_ALD(REG_ITMP2, REG_RESULT, 0);
5612 /* restore return value */
5614 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5615 if (IS_2_WORD_TYPE(md->returntype.type))
5616 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5617 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5620 if (IS_2_WORD_TYPE(md->returntype.type))
5621 i386_fldl_membase(cd, REG_SP, 1 * 4);
5623 i386_flds_membase(cd, REG_SP, 1 * 4);
5626 M_AADD_IMM(stackframesize * 4, REG_SP);
5633 /* handle exception */
5635 #if defined(ENABLE_THREADS)
5636 i386_push_reg(cd, REG_ITMP2);
5637 /* i386_call_mem(cd, (ptrint) builtin_get_exceptionptrptr); */
5638 i386_call_mem(cd, (ptrint) &callgetexceptionptrptr);
5639 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5640 i386_pop_reg(cd, REG_ITMP1_XPTR);
5642 M_MOV(REG_ITMP2, REG_ITMP1_XPTR);
5643 M_MOV_IMM(&_no_threads_exceptionptr, REG_ITMP2);
5644 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5646 M_ALD(REG_ITMP2_XPC, REG_SP, 0);
5647 M_ASUB_IMM(2, REG_ITMP2_XPC);
5649 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
5653 /* process patcher calls **************************************************/
5661 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5662 /* Get machine code which is patched back in later. A
5663 `call rel32' is 5 bytes long. */
5665 xcodeptr = cd->mcodebase + pref->branchpos;
5666 mcode = *((u8 *) xcodeptr);
5668 /* patch in `call rel32' to call the following code */
5670 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
5671 cd->mcodeptr = xcodeptr; /* set mcodeptr to patch position */
5673 M_CALL_IMM(tmpmcodeptr - (xcodeptr + PATCHER_CALL_SIZE));
5675 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
5677 /* save REG_ITMP3 */
5681 /* move pointer to java_objectheader onto stack */
5683 #if defined(ENABLE_THREADS)
5684 /* create a virtual java_objectheader */
5686 (void) dseg_addaddress(cd, NULL); /* flcword */
5687 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
5688 disp = dseg_addaddress(cd, NULL); /* vftbl */
5690 M_MOV_IMM(0, REG_ITMP3);
5692 M_AADD_IMM(disp, REG_ITMP3);
5698 /* move machine code bytes and classinfo pointer onto stack */
5700 M_PUSH_IMM((mcode >> 32));
5702 M_PUSH_IMM(pref->ref);
5703 M_PUSH_IMM(pref->patcher);
5705 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
5712 return jd->code->entrypoint;
5717 * These are local overrides for various environment variables in Emacs.
5718 * Please do not remove this and leave it at the end of the file, where
5719 * Emacs will automagically detect them.
5720 * ---------------------------------------------------------------------
5723 * indent-tabs-mode: t
5727 * vim:noexpandtab:sw=4:ts=4: