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 5089 2006-07-08 20:32:30Z 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 (!code->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, code->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 */
196 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
197 /* count frequency */
199 M_MOV_IMM(code, REG_ITMP3);
200 M_IADD_IMM_MEMBASE(1, REG_ITMP3, OFFSET(codeinfo, 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 */
471 /* generate basic block profiling code */
473 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
474 /* count frequency */
476 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
477 M_IADD_IMM_MEMBASE(1, REG_ITMP3, bptr->debug_nr * 4);
481 #if defined(ENABLE_LSRA)
483 while (src != NULL) {
485 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
486 if (!IS_2_WORD_TYPE(src->type)) {
487 if (bptr->type == BBTYPE_SBR) {
488 /* d = reg_of_var(m, src, REG_ITMP1); */
489 if (!(src->flags & INMEMORY))
495 emit_store(jd, NULL, src, d);
497 } else if (bptr->type == BBTYPE_EXH) {
498 /* d = reg_of_var(m, src, REG_ITMP1); */
499 if (!(src->flags & INMEMORY))
503 M_INTMOVE(REG_ITMP1, d);
504 emit_store(jd, NULL, src, d);
508 log_text("copy interface registers(EXH, SBR): longs have to be in memory (begin 1)");
517 while (src != NULL) {
519 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
520 if (!IS_2_WORD_TYPE(src->type)) {
521 if (bptr->type == BBTYPE_SBR) {
522 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
524 emit_store(jd, NULL, src, d);
525 } else if (bptr->type == BBTYPE_EXH) {
526 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
527 M_INTMOVE(REG_ITMP1, d);
528 emit_store(jd, NULL, src, d);
532 log_text("copy interface registers: longs have to be in memory (begin 1)");
537 if (IS_LNG_TYPE(src->type))
538 d = codegen_reg_of_var(rd, 0, src, PACK_REGS(REG_ITMP1, REG_ITMP2));
540 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
541 /* d = codegen_reg_of_var(rd, 0, src, REG_IFTMP); */
543 if ((src->varkind != STACKVAR)) {
545 s1 = rd->interfaces[len][s2].regoff;
547 if (IS_FLT_DBL_TYPE(s2)) {
548 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
552 if (IS_2_WORD_TYPE(s2))
553 M_DLD(d, REG_SP, s1 * 4);
555 M_FLD(d, REG_SP, s1 * 4);
559 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
560 if (IS_2_WORD_TYPE(s2))
566 if (IS_2_WORD_TYPE(s2))
567 M_LLD(d, REG_SP, s1 * 4);
569 M_ILD(d, REG_SP, s1 * 4);
573 emit_store(jd, NULL, src, d);
578 #if defined(ENABLE_LSRA)
582 /* walk through all instructions */
587 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
588 if (iptr->line != currentline) {
589 dseg_addlinenumber(cd, iptr->line);
590 currentline = iptr->line;
593 MCODECHECK(1024); /* 1kB should be enough */
596 case ICMD_INLINE_START:
598 insinfo_inline *insinfo = (insinfo_inline *) iptr->target;
599 #if defined(ENABLE_THREADS)
600 if (insinfo->synchronize) {
601 /* add monitor enter code */
602 if (insinfo->method->flags & ACC_STATIC) {
603 M_MOV_IMM(insinfo->method->class, REG_ITMP1);
604 M_AST(REG_ITMP1, REG_SP, 0 * 4);
605 M_MOV_IMM(BUILTIN_staticmonitorenter, REG_ITMP1);
609 /* nullpointer check must have been performed before */
610 /* (XXX not done, yet) */
611 var = &(rd->locals[insinfo->synclocal][TYPE_ADR]);
612 if (var->flags & INMEMORY) {
613 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP1);
614 M_AST(REG_ITMP1, REG_SP, 0 * 4);
617 M_AST(var->regoff, REG_SP, 0 * 4);
619 M_MOV_IMM(BUILTIN_monitorenter, REG_ITMP1);
624 dseg_addlinenumber_inline_start(cd, iptr);
628 case ICMD_INLINE_END:
630 insinfo_inline *insinfo = (insinfo_inline *) iptr->target;
632 dseg_addlinenumber_inline_end(cd, iptr);
633 dseg_addlinenumber(cd, iptr->line);
635 #if defined(ENABLE_THREADS)
636 if (insinfo->synchronize) {
637 /* add monitor exit code */
638 if (insinfo->method->flags & ACC_STATIC) {
639 M_MOV_IMM(insinfo->method->class, REG_ITMP1);
640 M_AST(REG_ITMP1, REG_SP, 0 * 4);
641 M_MOV_IMM(BUILTIN_monitorexit, REG_ITMP1);
645 var = &(rd->locals[insinfo->synclocal][TYPE_ADR]);
646 if (var->flags & INMEMORY) {
647 M_ALD(REG_ITMP1, REG_SP, var->regoff * 4);
648 M_AST(REG_ITMP1, REG_SP, 0 * 4);
651 M_AST(var->regoff, REG_SP, 0 * 4);
653 M_MOV_IMM(BUILTIN_monitorexit, REG_ITMP1);
661 case ICMD_NOP: /* ... ==> ... */
662 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
663 /* EAX: NO ECX: NO EDX: NO */
666 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
667 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
668 /* EAX: NO ECX: NO EDX: NO */
670 if (src->flags & INMEMORY)
671 M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 4);
675 codegen_add_nullpointerexception_ref(cd);
678 /* constant operations ************************************************/
680 case ICMD_ICONST: /* ... ==> ..., constant */
681 /* op1 = 0, val.i = constant */
683 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
684 /* EAX: NO ECX: NO EDX: NO */
686 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
687 if (iptr->dst->flags & INMEMORY) {
688 M_IST_IMM(iptr->val.i, REG_SP, iptr->dst->regoff * 4);
690 if (iptr->val.i == 0) {
693 M_MOV_IMM(iptr->val.i, d);
698 case ICMD_LCONST: /* ... ==> ..., constant */
699 /* op1 = 0, val.l = constant */
701 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
702 /* EAX: NO ECX: NO EDX: NO */
704 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
705 if (iptr->dst->flags & INMEMORY) {
706 M_IST_IMM(iptr->val.l, REG_SP, iptr->dst->regoff * 4);
707 M_IST_IMM(iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
709 log_text("LCONST: longs have to be in memory");
714 case ICMD_FCONST: /* ... ==> ..., constant */
715 /* op1 = 0, val.f = constant */
717 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
718 /* EAX: YES ECX: NO EDX: NO */
720 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
721 if (iptr->val.f == 0.0) {
726 if (iptr->val.i == 0x80000000) {
730 } else if (iptr->val.f == 1.0) {
734 } else if (iptr->val.f == 2.0) {
741 disp = dseg_addfloat(cd, iptr->val.f);
742 i386_mov_imm_reg(cd, 0, REG_ITMP1);
744 i386_flds_membase(cd, REG_ITMP1, disp);
747 emit_store(jd, iptr, iptr->dst, d);
750 case ICMD_DCONST: /* ... ==> ..., constant */
751 /* op1 = 0, val.d = constant */
753 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
754 /* EAX: YES ECX: NO EDX: NO */
756 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
757 if (iptr->val.d == 0.0) {
762 if (iptr->val.l == 0x8000000000000000LL) {
766 } else if (iptr->val.d == 1.0) {
770 } else if (iptr->val.d == 2.0) {
777 disp = dseg_adddouble(cd, iptr->val.d);
778 i386_mov_imm_reg(cd, 0, REG_ITMP1);
780 i386_fldl_membase(cd, REG_ITMP1, disp);
783 emit_store(jd, iptr, iptr->dst, d);
786 case ICMD_ACONST: /* ... ==> ..., constant */
787 /* op1 = 0, val.a = constant */
789 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
790 /* EAX: YES ECX: NO EDX: NO */
792 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
794 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
795 codegen_addpatchref(cd, PATCHER_aconst,
796 ICMD_ACONST_UNRESOLVED_CLASSREF(iptr), 0);
798 if (opt_showdisassemble) {
799 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
803 emit_store(jd, iptr, iptr->dst, d);
806 if (iptr->dst->flags & INMEMORY) {
807 M_AST_IMM((ptrint) iptr->val.a, REG_SP, iptr->dst->regoff * 4);
810 if ((ptrint) iptr->val.a == 0) {
813 M_MOV_IMM(iptr->val.a, d);
820 /* load/store operations **********************************************/
822 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
823 case ICMD_ALOAD: /* op1 = local variable */
824 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
825 /* EAX: YES ECX: NO EDX: NO */
827 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
828 if ((iptr->dst->varkind == LOCALVAR) &&
829 (iptr->dst->varnum == iptr->op1))
831 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
832 if (var->flags & INMEMORY)
833 M_ILD(d, REG_SP, var->regoff * 4);
835 M_INTMOVE(var->regoff, d);
836 emit_store(jd, iptr, iptr->dst, d);
839 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
840 /* op1 = local variable */
841 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
842 /* EAX: NO ECX: NO EDX: NO */
844 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP1, REG_ITMP2));
845 if ((iptr->dst->varkind == LOCALVAR) &&
846 (iptr->dst->varnum == iptr->op1))
848 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
849 if (var->flags & INMEMORY)
850 M_LLD(d, REG_SP, var->regoff * 4);
852 M_LNGMOVE(var->regoff, d);
853 emit_store(jd, iptr, iptr->dst, d);
856 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
857 /* op1 = local variable */
858 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
859 /* EAX: NO ECX: NO EDX: NO */
861 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
862 if ((iptr->dst->varkind == LOCALVAR) &&
863 (iptr->dst->varnum == iptr->op1))
865 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
866 if (var->flags & INMEMORY)
867 M_FLD(d, REG_SP, var->regoff * 4);
869 M_FLTMOVE(var->regoff, d);
870 emit_store(jd, iptr, iptr->dst, d);
873 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
874 /* op1 = local variable */
875 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
876 /* EAX: NO ECX: NO EDX: NO */
878 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
879 if ((iptr->dst->varkind == LOCALVAR) &&
880 (iptr->dst->varnum == iptr->op1))
882 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
883 if (var->flags & INMEMORY)
884 M_DLD(d, REG_SP, var->regoff * 4);
886 M_FLTMOVE(var->regoff, d);
887 emit_store(jd, iptr, iptr->dst, d);
890 case ICMD_ISTORE: /* ..., value ==> ... */
891 case ICMD_ASTORE: /* op1 = local variable */
892 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
893 /* EAX: YES ECX: NO EDX: NO */
895 if ((src->varkind == LOCALVAR) &&
896 (src->varnum == iptr->op1))
898 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
899 if (var->flags & INMEMORY) {
900 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
901 M_IST(s1, REG_SP, var->regoff * 4);
903 s1 = emit_load_s1(jd, iptr, src, var->regoff);
904 M_INTMOVE(s1, var->regoff);
908 case ICMD_LSTORE: /* ..., value ==> ... */
909 /* op1 = local variable */
910 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
911 /* EAX: NO ECX: NO EDX: NO */
913 if ((src->varkind == LOCALVAR) &&
914 (src->varnum == iptr->op1))
916 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
917 if (var->flags & INMEMORY) {
918 s1 = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP1, REG_ITMP2));
919 M_LST(s1, REG_SP, var->regoff * 4);
921 s1 = emit_load_s1(jd, iptr, src, var->regoff);
922 M_LNGMOVE(s1, var->regoff);
926 case ICMD_FSTORE: /* ..., value ==> ... */
927 /* op1 = local variable */
928 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
929 /* EAX: NO ECX: NO EDX: NO */
931 if ((src->varkind == LOCALVAR) &&
932 (src->varnum == iptr->op1))
934 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
935 if (var->flags & INMEMORY) {
936 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
937 M_FST(s1, REG_SP, var->regoff * 4);
939 s1 = emit_load_s1(jd, iptr, src, var->regoff);
940 M_FLTMOVE(s1, var->regoff);
944 case ICMD_DSTORE: /* ..., value ==> ... */
945 /* op1 = local variable */
946 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
947 /* EAX: NO ECX: NO EDX: NO */
949 if ((src->varkind == LOCALVAR) &&
950 (src->varnum == iptr->op1))
952 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
953 if (var->flags & INMEMORY) {
954 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
955 M_DST(s1, REG_SP, var->regoff * 4);
957 s1 = emit_load_s1(jd, iptr, src, var->regoff);
958 M_FLTMOVE(s1, var->regoff);
963 /* pop/dup/swap operations ********************************************/
965 /* attention: double and longs are only one entry in CACAO ICMDs */
967 case ICMD_POP: /* ..., value ==> ... */
968 case ICMD_POP2: /* ..., value, value ==> ... */
969 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
970 /* EAX: NO ECX: NO EDX: NO */
973 case ICMD_DUP: /* ..., a ==> ..., a, a */
974 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
975 /* EAX: YES ECX: NO EDX: NO */
976 M_COPY(src, iptr->dst);
979 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
980 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
981 /* EAX: YES ECX: NO EDX: NO */
983 M_COPY(src, iptr->dst);
984 M_COPY(src->prev, iptr->dst->prev);
987 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
988 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
989 /* EAX: YES ECX: NO EDX: NO */
991 M_COPY(src, iptr->dst);
992 M_COPY(src->prev, iptr->dst->prev);
993 M_COPY(iptr->dst, iptr->dst->prev->prev);
996 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
998 M_COPY(src, iptr->dst);
999 M_COPY(src->prev, iptr->dst->prev);
1000 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1001 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
1004 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
1005 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1006 /* EAX: YES ECX: NO EDX: NO */
1008 M_COPY(src, iptr->dst);
1009 M_COPY(src->prev, iptr->dst->prev);
1010 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1011 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
1012 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
1015 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
1016 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1017 /* EAX: YES ECX: NO EDX: NO */
1019 M_COPY(src, iptr->dst);
1020 M_COPY(src->prev, iptr->dst->prev);
1021 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1022 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
1023 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
1024 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
1027 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1028 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1029 /* EAX: YES ECX: NO EDX: NO */
1031 M_COPY(src, iptr->dst->prev);
1032 M_COPY(src->prev, iptr->dst);
1036 /* integer operations *************************************************/
1038 case ICMD_INEG: /* ..., value ==> ..., - value */
1039 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1040 /* EAX: YES ECX: NO EDX: NO */
1042 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1043 if (iptr->dst->flags & INMEMORY) {
1044 if (src->flags & INMEMORY) {
1045 if (src->regoff == iptr->dst->regoff) {
1046 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1049 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1050 i386_neg_reg(cd, REG_ITMP1);
1051 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1055 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1056 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1060 if (src->flags & INMEMORY) {
1061 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1062 i386_neg_reg(cd, iptr->dst->regoff);
1065 M_INTMOVE(src->regoff, iptr->dst->regoff);
1066 i386_neg_reg(cd, iptr->dst->regoff);
1071 case ICMD_LNEG: /* ..., value ==> ..., - value */
1072 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1073 /* EAX: YES ECX: NO EDX: NO */
1075 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1076 if (iptr->dst->flags & INMEMORY) {
1077 if (src->flags & INMEMORY) {
1078 if (src->regoff == iptr->dst->regoff) {
1079 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1080 i386_alu_imm_membase(cd, ALU_ADC, 0, REG_SP, iptr->dst->regoff * 4 + 4);
1081 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4 + 4);
1084 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1085 i386_neg_reg(cd, REG_ITMP1);
1086 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1087 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1088 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP1);
1089 i386_neg_reg(cd, REG_ITMP1);
1090 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1096 case ICMD_I2L: /* ..., value ==> ..., value */
1097 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1098 /* EAX: YES ECX: NO EDX: YES */
1100 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1101 if (iptr->dst->flags & INMEMORY) {
1102 if (src->flags & INMEMORY) {
1103 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, EAX);
1105 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1106 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1109 M_INTMOVE(src->regoff, EAX);
1111 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1112 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1117 case ICMD_L2I: /* ..., value ==> ..., value */
1118 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1119 /* EAX: YES ECX: NO EDX: NO */
1121 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1122 if (iptr->dst->flags & INMEMORY) {
1123 if (src->flags & INMEMORY) {
1124 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1125 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1129 if (src->flags & INMEMORY) {
1130 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1135 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1136 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1137 /* EAX: YES ECX: NO EDX: NO */
1139 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1140 if (iptr->dst->flags & INMEMORY) {
1141 if (src->flags & INMEMORY) {
1142 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1143 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1144 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1145 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1148 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1149 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 4);
1150 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 4);
1154 if (src->flags & INMEMORY) {
1155 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1156 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1157 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1160 M_INTMOVE(src->regoff, iptr->dst->regoff);
1161 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1162 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1167 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1168 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1169 /* EAX: YES ECX: NO EDX: NO */
1171 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1172 if (iptr->dst->flags & INMEMORY) {
1173 if (src->flags & INMEMORY) {
1174 if (src->regoff == iptr->dst->regoff) {
1175 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1178 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1179 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, REG_ITMP1);
1180 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1184 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1185 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1189 if (src->flags & INMEMORY) {
1190 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1191 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1194 M_INTMOVE(src->regoff, iptr->dst->regoff);
1195 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1200 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1201 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1202 /* EAX: YES ECX: NO EDX: NO */
1204 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1205 if (iptr->dst->flags & INMEMORY) {
1206 if (src->flags & INMEMORY) {
1207 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1208 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1209 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1210 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1213 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1214 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 4);
1215 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 4);
1219 if (src->flags & INMEMORY) {
1220 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1221 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1222 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1225 M_INTMOVE(src->regoff, iptr->dst->regoff);
1226 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1227 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1233 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1234 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1235 /* EAX: S|YES ECX: NO EDX: NO */
1237 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1238 i386_emit_ialu(cd, ALU_ADD, src, iptr);
1241 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1242 /* val.i = constant */
1243 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1244 /* EAX: NO ECX: NO EDX: NO */
1246 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1247 i386_emit_ialuconst(cd, ALU_ADD, src, iptr);
1250 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1251 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1252 /* EAX: S|YES ECX: NO EDX: NO */
1254 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1255 if (iptr->dst->flags & INMEMORY) {
1256 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1257 if (src->regoff == iptr->dst->regoff) {
1258 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1259 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1260 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1261 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1263 } else if (src->prev->regoff == iptr->dst->regoff) {
1264 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1265 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1266 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1267 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1270 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1271 i386_alu_membase_reg(cd, ALU_ADD, REG_SP, src->regoff * 4, REG_ITMP1);
1272 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1273 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1274 i386_alu_membase_reg(cd, ALU_ADC, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1275 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1282 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1283 /* val.l = constant */
1284 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1285 /* EAX: NO ECX: NO EDX: NO */
1286 /* else path can never happen? longs stay in memory! */
1288 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1289 if (iptr->dst->flags & INMEMORY) {
1290 if (src->flags & INMEMORY) {
1291 if (src->regoff == iptr->dst->regoff) {
1292 i386_alu_imm_membase(cd, ALU_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1293 i386_alu_imm_membase(cd, ALU_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1296 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1297 i386_alu_imm_reg(cd, ALU_ADD, iptr->val.l, REG_ITMP1);
1298 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1299 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1300 i386_alu_imm_reg(cd, ALU_ADC, iptr->val.l >> 32, REG_ITMP1);
1301 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1307 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1308 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1309 /* EAX: S|YES ECX: NO EDX: NO */
1311 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1312 if (iptr->dst->flags & INMEMORY) {
1313 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1314 if (src->prev->regoff == iptr->dst->regoff) {
1315 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1316 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1319 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1320 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1321 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1324 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1325 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1326 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1327 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1329 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1330 if (src->prev->regoff == iptr->dst->regoff) {
1331 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1334 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1335 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1336 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1340 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 4);
1341 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1345 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1346 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1347 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1349 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1350 M_INTMOVE(src->prev->regoff, d);
1351 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1353 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1354 /* workaround for reg alloc */
1355 if (src->regoff == iptr->dst->regoff) {
1356 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1357 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1358 M_INTMOVE(REG_ITMP1, d);
1361 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1362 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1366 /* workaround for reg alloc */
1367 if (src->regoff == iptr->dst->regoff) {
1368 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1369 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1370 M_INTMOVE(REG_ITMP1, d);
1373 M_INTMOVE(src->prev->regoff, d);
1374 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1380 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1381 /* val.i = constant */
1382 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1383 /* EAX: NO ECX: NO EDX: NO */
1385 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1386 i386_emit_ialuconst(cd, ALU_SUB, src, iptr);
1389 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1390 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1391 /* EAX: S|YES ECX: NO EDX: NO */
1393 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1394 if (iptr->dst->flags & INMEMORY) {
1395 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1396 if (src->prev->regoff == iptr->dst->regoff) {
1397 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1398 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1399 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1400 i386_alu_reg_membase(cd, ALU_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1403 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1404 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1405 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1406 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1407 i386_alu_membase_reg(cd, ALU_SBB, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1408 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1414 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1415 /* val.l = constant */
1416 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1417 /* EAX: NO ECX: NO EDX: NO */
1418 /* else path can never happen? longs stay in memory! */
1420 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1421 if (iptr->dst->flags & INMEMORY) {
1422 if (src->flags & INMEMORY) {
1423 if (src->regoff == iptr->dst->regoff) {
1424 i386_alu_imm_membase(cd, ALU_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1425 i386_alu_imm_membase(cd, ALU_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1428 /* TODO: could be size optimized with lea -- see gcc output */
1429 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1430 i386_alu_imm_reg(cd, ALU_SUB, iptr->val.l, REG_ITMP1);
1431 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1432 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1433 i386_alu_imm_reg(cd, ALU_SBB, iptr->val.l >> 32, REG_ITMP1);
1434 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1440 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1441 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1442 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1444 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1445 if (iptr->dst->flags & INMEMORY) {
1446 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1447 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1448 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1449 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1451 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1452 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1453 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1454 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1456 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1457 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1458 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1459 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1462 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1463 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1464 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1468 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1469 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1470 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1472 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1473 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1474 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1476 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1477 M_INTMOVE(src->regoff, iptr->dst->regoff);
1478 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1481 if (src->regoff == iptr->dst->regoff) {
1482 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1485 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1486 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1492 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1493 /* val.i = constant */
1494 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1495 /* EAX: YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1497 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1498 if (iptr->dst->flags & INMEMORY) {
1499 if (src->flags & INMEMORY) {
1500 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, REG_ITMP1);
1501 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1504 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1505 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1509 if (src->flags & INMEMORY) {
1510 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, iptr->dst->regoff);
1513 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1518 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1519 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1520 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1522 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1523 if (iptr->dst->flags & INMEMORY) {
1524 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1525 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX); /* mem -> EAX */
1526 /* optimize move EAX -> REG_ITMP3 is slower??? */
1527 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1528 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1530 /* TODO: optimize move EAX -> REG_ITMP3 */
1531 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); /* mem -> ITMP3 */
1532 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1533 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1535 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP2); /* mem -> ITMP3 */
1536 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1538 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1539 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1540 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1545 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1546 /* val.l = constant */
1547 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1548 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1550 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1551 if (iptr->dst->flags & INMEMORY) {
1552 if (src->flags & INMEMORY) {
1553 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1554 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1555 /* TODO: optimize move EAX -> REG_ITMP3 */
1556 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1557 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1559 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1560 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1561 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1563 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1564 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1565 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1570 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1571 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1572 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX */
1574 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1575 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
1577 if (src->prev->flags & INMEMORY) {
1578 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1581 M_INTMOVE(src->prev->regoff, EAX);
1584 /* check as described in jvm spec */
1586 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1587 i386_jcc(cd, I386_CC_NE, 3 + 6);
1588 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1589 i386_jcc(cd, I386_CC_E, 1 + 2);
1592 i386_idiv_reg(cd, s1);
1594 if (iptr->dst->flags & INMEMORY) {
1595 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1598 M_INTMOVE(EAX, iptr->dst->regoff);
1602 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1603 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1604 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EDX */
1607 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1608 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
1610 if (src->prev->flags & INMEMORY) {
1611 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1614 M_INTMOVE(src->prev->regoff, EAX);
1617 /* check as described in jvm spec */
1619 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1620 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1621 i386_alu_reg_reg(cd, ALU_XOR, EDX, EDX);
1622 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1623 i386_jcc(cd, I386_CC_E, 1 + 2);
1626 i386_idiv_reg(cd, s1);
1628 if (iptr->dst->flags & INMEMORY) {
1629 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4);
1632 M_INTMOVE(EDX, iptr->dst->regoff);
1636 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1637 /* val.i = constant */
1638 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1639 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL */
1641 /* TODO: optimize for `/ 2' */
1642 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1643 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1646 i386_test_reg_reg(cd, d, d);
1648 CALCIMMEDIATEBYTES(disp, (1 << iptr->val.i) - 1);
1649 i386_jcc(cd, I386_CC_NS, disp);
1650 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, d);
1652 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1653 emit_store(jd, iptr, iptr->dst, d);
1656 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1657 /* val.i = constant */
1658 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1659 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1661 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1662 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1664 M_INTMOVE(s1, REG_ITMP1);
1671 CALCIMMEDIATEBYTES(disp, iptr->val.i);
1674 /* TODO: optimize */
1676 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1677 i386_test_reg_reg(cd, s1, s1);
1678 i386_jcc(cd, I386_CC_GE, disp);
1679 i386_mov_reg_reg(cd, s1, d);
1680 i386_neg_reg(cd, d);
1681 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1682 i386_neg_reg(cd, d);
1684 /* M_INTMOVE(s1, EAX); */
1685 /* i386_cltd(cd); */
1686 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1687 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1688 /* i386_alu_reg_reg(cd, ALU_AND, iptr->val.i, EAX); */
1689 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1690 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1691 /* M_INTMOVE(EAX, d); */
1693 /* i386_alu_reg_reg(cd, ALU_XOR, d, d); */
1694 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1695 /* i386_shrd_reg_reg(cd, s1, d); */
1696 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1698 emit_store(jd, iptr, iptr->dst, d);
1701 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1702 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1704 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1705 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4);
1706 M_OR_MEMBASE(REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1709 codegen_add_arithmeticexception_ref(cd);
1714 M_ILD(REG_ITMP1, REG_SP, src->prev->regoff * 4);
1715 M_ILD(REG_ITMP2, REG_SP, src->prev->regoff * 4 + 4);
1716 M_IST(REG_ITMP1, REG_SP, 0 * 4);
1717 M_IST(REG_ITMP2, REG_SP, 0 * 4 + 4);
1719 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
1720 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4 + 4);
1721 M_IST(REG_ITMP1, REG_SP, 2 * 4);
1722 M_IST(REG_ITMP2, REG_SP, 2 * 4 + 4);
1724 M_MOV_IMM(bte->fp, REG_ITMP3);
1727 M_IST(REG_RESULT, REG_SP, iptr->dst->regoff * 4);
1728 M_IST(REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
1731 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1732 /* val.i = constant */
1733 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1734 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1736 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1737 if (iptr->dst->flags & INMEMORY) {
1738 if (src->flags & INMEMORY) {
1740 CALCIMMEDIATEBYTES(disp, (1 << iptr->val.i) - 1);
1742 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1743 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1745 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1746 i386_jcc(cd, I386_CC_NS, disp);
1747 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1748 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1749 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1750 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1752 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1753 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1758 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1759 /* val.l = constant */
1760 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1761 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1763 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1764 if (iptr->dst->flags & INMEMORY) {
1765 if (src->flags & INMEMORY) {
1766 /* Intel algorithm -- does not work, because constant is wrong */
1767 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1); */
1768 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3); */
1770 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1771 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1772 /* i386_jcc(cd, I386_CC_NS, offset); */
1773 /* i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1774 /* i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP3); */
1776 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1777 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1778 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1780 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1782 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1); */
1783 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); */
1784 /* i386_alu_reg_reg(cd, ALU_SBB, REG_ITMP3, REG_ITMP2); */
1786 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1787 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1789 /* Alpha algorithm */
1791 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1793 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4 + 4);
1799 /* TODO: hmm, don't know if this is always correct */
1801 CALCIMMEDIATEBYTES(disp, iptr->val.l & 0x00000000ffffffff);
1803 CALCIMMEDIATEBYTES(disp, iptr->val.l >> 32);
1809 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1810 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1812 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1813 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1814 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4 + 4);
1815 i386_jcc(cd, I386_CC_GE, disp);
1817 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1818 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1820 i386_neg_reg(cd, REG_ITMP1);
1821 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1822 i386_neg_reg(cd, REG_ITMP2);
1824 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1825 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1827 i386_neg_reg(cd, REG_ITMP1);
1828 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1829 i386_neg_reg(cd, REG_ITMP2);
1831 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1832 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1837 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1838 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1839 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1841 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1842 i386_emit_ishift(cd, I386_SHL, src, iptr);
1845 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1846 /* val.i = constant */
1847 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1848 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1850 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1851 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1854 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1855 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1856 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1858 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1859 i386_emit_ishift(cd, I386_SAR, src, iptr);
1862 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1863 /* val.i = constant */
1864 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1865 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1867 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1868 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1871 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1872 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1873 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1875 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1876 i386_emit_ishift(cd, I386_SHR, src, iptr);
1879 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1880 /* val.i = constant */
1881 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1882 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1884 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1885 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1888 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1889 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1890 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
1892 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1893 if (iptr->dst->flags & INMEMORY ){
1894 if (src->prev->flags & INMEMORY) {
1895 /* if (src->prev->regoff == iptr->dst->regoff) { */
1896 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1898 /* if (src->flags & INMEMORY) { */
1899 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1901 /* M_INTMOVE(src->regoff, ECX); */
1904 /* i386_test_imm_reg(cd, 32, ECX); */
1905 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1906 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1907 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1); */
1909 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 4 + 4); */
1910 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 4); */
1913 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1914 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1916 if (src->flags & INMEMORY) {
1917 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1919 M_INTMOVE(src->regoff, ECX);
1922 i386_test_imm_reg(cd, 32, ECX);
1923 i386_jcc(cd, I386_CC_E, 2 + 2);
1924 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1925 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1927 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1928 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1929 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1930 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
1936 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1937 /* val.i = constant */
1938 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1939 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1941 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1942 if (iptr->dst->flags & INMEMORY ) {
1943 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1944 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1946 if (iptr->val.i & 0x20) {
1947 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1948 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1949 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1952 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1953 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1956 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1957 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1961 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1962 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1963 /* EAX: S|YES ECX: YES S|EDX: YES OUTPUT: REG_NULL*/
1965 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1966 if (iptr->dst->flags & INMEMORY ){
1967 if (src->prev->flags & INMEMORY) {
1968 /* if (src->prev->regoff == iptr->dst->regoff) { */
1969 /* TODO: optimize */
1970 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1971 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
1973 /* if (src->flags & INMEMORY) { */
1974 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1976 /* M_INTMOVE(src->regoff, ECX); */
1979 /* i386_test_imm_reg(cd, 32, ECX); */
1980 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1981 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1982 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1984 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1985 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1986 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1987 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1990 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1991 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1993 if (src->flags & INMEMORY) {
1994 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1996 M_INTMOVE(src->regoff, ECX);
1999 i386_test_imm_reg(cd, 32, ECX);
2000 i386_jcc(cd, I386_CC_E, 2 + 3);
2001 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2002 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
2004 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2005 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
2006 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2007 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2013 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
2014 /* val.i = constant */
2015 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2016 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
2018 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2019 if (iptr->dst->flags & INMEMORY ) {
2020 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
2021 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
2023 if (iptr->val.i & 0x20) {
2024 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2025 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
2026 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2029 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2030 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
2033 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2034 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
2038 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
2039 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2040 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
2042 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2043 if (iptr->dst->flags & INMEMORY ){
2044 if (src->prev->flags & INMEMORY) {
2045 /* if (src->prev->regoff == iptr->dst->regoff) { */
2046 /* TODO: optimize */
2047 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
2048 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
2050 /* if (src->flags & INMEMORY) { */
2051 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
2053 /* M_INTMOVE(src->regoff, ECX); */
2056 /* i386_test_imm_reg(cd, 32, ECX); */
2057 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
2058 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2059 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2); */
2061 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
2062 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
2063 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
2064 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
2067 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
2068 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
2070 if (src->flags & INMEMORY) {
2071 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
2073 M_INTMOVE(src->regoff, ECX);
2076 i386_test_imm_reg(cd, 32, ECX);
2077 i386_jcc(cd, I386_CC_E, 2 + 2);
2078 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2079 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP3, REG_ITMP3);
2081 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2082 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
2083 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2084 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2090 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
2091 /* val.l = constant */
2092 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2093 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
2095 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2096 if (iptr->dst->flags & INMEMORY ) {
2097 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
2098 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
2100 if (iptr->val.i & 0x20) {
2101 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2102 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
2103 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2106 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2107 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
2110 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2111 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
2115 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2116 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2117 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2119 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2120 i386_emit_ialu(cd, ALU_AND, src, iptr);
2123 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
2124 /* val.i = constant */
2125 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2126 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2128 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2129 i386_emit_ialuconst(cd, ALU_AND, src, iptr);
2132 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2133 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2134 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2136 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2137 i386_emit_lalu(cd, ALU_AND, src, iptr);
2140 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
2141 /* val.l = constant */
2142 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2143 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2145 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2146 i386_emit_laluconst(cd, ALU_AND, src, iptr);
2149 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2150 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2151 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2153 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2154 i386_emit_ialu(cd, ALU_OR, src, iptr);
2157 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2158 /* val.i = constant */
2159 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2160 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2162 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2163 i386_emit_ialuconst(cd, ALU_OR, src, iptr);
2166 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2167 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2168 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2170 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2171 i386_emit_lalu(cd, ALU_OR, src, iptr);
2174 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2175 /* val.l = constant */
2176 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2177 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2179 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2180 i386_emit_laluconst(cd, ALU_OR, src, iptr);
2183 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2184 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2185 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2187 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2188 i386_emit_ialu(cd, ALU_XOR, src, iptr);
2191 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2192 /* val.i = constant */
2193 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2194 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2196 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2197 i386_emit_ialuconst(cd, ALU_XOR, src, iptr);
2200 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2201 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2202 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2204 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2205 i386_emit_lalu(cd, ALU_XOR, src, iptr);
2208 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2209 /* val.l = constant */
2210 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2211 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2213 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2214 i386_emit_laluconst(cd, ALU_XOR, src, iptr);
2217 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2218 /* op1 = variable, val.i = constant */
2219 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2220 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL */
2222 var = &(rd->locals[iptr->op1][TYPE_INT]);
2223 if (var->flags & INMEMORY)
2224 M_IADD_IMM_MEMBASE(iptr->val.i, REG_SP, var->regoff * 4);
2226 /* `inc reg' is slower on p4's (regarding to ia32
2227 optimization reference manual and benchmarks) and
2228 as fast on athlon's. */
2229 M_IADD_IMM(iptr->val.i, var->regoff);
2234 /* floating operations ************************************************/
2236 #define ROUND_TO_SINGLE \
2237 i386_fstps_membase(cd, REG_SP, -8); \
2238 i386_flds_membase(cd, REG_SP, -8);
2240 #define ROUND_TO_DOUBLE \
2241 i386_fstpl_membase(cd, REG_SP, -8); \
2242 i386_fldl_membase(cd, REG_SP, -8);
2244 #define FPU_SET_24BIT_MODE \
2245 if (!fpu_in_24bit_mode) { \
2246 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2247 fpu_in_24bit_mode = 1; \
2250 #define FPU_SET_53BIT_MODE \
2251 if (fpu_in_24bit_mode) { \
2252 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2253 fpu_in_24bit_mode = 0; \
2256 #define ROUND_TO_SINGLE
2257 #define ROUND_TO_DOUBLE
2258 #define FPU_SET_24BIT_MODE
2259 #define FPU_SET_53BIT_MODE
2261 case ICMD_FNEG: /* ..., value ==> ..., - value */
2262 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2263 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2266 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2267 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2269 emit_store(jd, iptr, iptr->dst, d);
2272 case ICMD_DNEG: /* ..., value ==> ..., - value */
2273 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2274 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2277 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2278 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2280 emit_store(jd, iptr, iptr->dst, d);
2283 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2284 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2285 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2288 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2289 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2290 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2293 emit_store(jd, iptr, iptr->dst, d);
2296 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2297 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2298 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2301 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2302 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2303 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2306 emit_store(jd, iptr, iptr->dst, d);
2309 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2310 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2311 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2314 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2315 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2316 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2319 emit_store(jd, iptr, iptr->dst, d);
2322 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2323 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2324 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2327 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2328 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2329 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2332 emit_store(jd, iptr, iptr->dst, d);
2335 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2336 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2337 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2340 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2341 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2342 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2346 emit_store(jd, iptr, iptr->dst, d);
2349 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2350 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2351 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2354 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2355 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2357 /* i386_fldt_mem(cd, subnormal_bias1); */
2358 /* i386_fmulp(cd); */
2360 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2365 /* i386_fldt_mem(cd, subnormal_bias2); */
2366 /* i386_fmulp(cd); */
2368 emit_store(jd, iptr, iptr->dst, d);
2371 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2372 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2373 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2376 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2377 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2378 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2382 emit_store(jd, iptr, iptr->dst, d);
2385 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2386 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2387 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2390 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2391 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2393 /* i386_fldt_mem(cd, subnormal_bias1); */
2394 /* i386_fmulp(cd); */
2396 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2401 /* i386_fldt_mem(cd, subnormal_bias2); */
2402 /* i386_fmulp(cd); */
2404 emit_store(jd, iptr, iptr->dst, d);
2407 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2408 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2409 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2412 /* exchanged to skip fxch */
2413 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2414 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2415 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2416 /* i386_fxch(cd); */
2421 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2422 emit_store(jd, iptr, iptr->dst, d);
2423 i386_ffree_reg(cd, 0);
2428 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2429 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2430 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2433 /* exchanged to skip fxch */
2434 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2435 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
2436 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2437 /* i386_fxch(cd); */
2442 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2443 emit_store(jd, iptr, iptr->dst, d);
2444 i386_ffree_reg(cd, 0);
2449 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2450 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2451 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2452 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2454 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2455 if (src->flags & INMEMORY) {
2456 i386_fildl_membase(cd, REG_SP, src->regoff * 4);
2460 disp = dseg_adds4(cd, 0);
2461 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2463 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, disp);
2464 i386_fildl_membase(cd, REG_ITMP1, disp);
2467 emit_store(jd, iptr, iptr->dst, d);
2470 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2471 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2472 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2473 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2475 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2476 if (src->flags & INMEMORY) {
2477 i386_fildll_membase(cd, REG_SP, src->regoff * 4);
2481 log_text("L2F: longs have to be in memory");
2484 emit_store(jd, iptr, iptr->dst, d);
2487 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2488 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2489 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2491 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2492 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2494 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2497 /* Round to zero, 53-bit mode, exception masked */
2498 disp = dseg_adds4(cd, 0x0e7f);
2499 i386_fldcw_membase(cd, REG_ITMP1, disp);
2501 if (iptr->dst->flags & INMEMORY) {
2502 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2505 /* Round to nearest, 53-bit mode, exceptions masked */
2506 disp = dseg_adds4(cd, 0x027f);
2507 i386_fldcw_membase(cd, REG_ITMP1, disp);
2509 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2512 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2514 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2517 disp = dseg_adds4(cd, 0);
2518 i386_fistpl_membase(cd, REG_ITMP1, disp);
2520 i386_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2522 /* Round to nearest, 53-bit mode, exceptions masked */
2523 disp = dseg_adds4(cd, 0x027f);
2524 i386_fldcw_membase(cd, REG_ITMP1, disp);
2526 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2529 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2530 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2533 i386_jcc(cd, I386_CC_NE, disp);
2535 /* XXX: change this when we use registers */
2536 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2537 i386_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP1);
2538 i386_call_reg(cd, REG_ITMP1);
2540 if (iptr->dst->flags & INMEMORY) {
2541 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2544 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2548 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2549 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2550 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2552 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2553 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2555 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2558 /* Round to zero, 53-bit mode, exception masked */
2559 disp = dseg_adds4(cd, 0x0e7f);
2560 i386_fldcw_membase(cd, REG_ITMP1, disp);
2562 if (iptr->dst->flags & INMEMORY) {
2563 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2566 /* Round to nearest, 53-bit mode, exceptions masked */
2567 disp = dseg_adds4(cd, 0x027f);
2568 i386_fldcw_membase(cd, REG_ITMP1, disp);
2570 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2573 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2575 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2578 disp = dseg_adds4(cd, 0);
2579 i386_fistpl_membase(cd, REG_ITMP1, disp);
2581 i386_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2583 /* Round to nearest, 53-bit mode, exceptions masked */
2584 disp = dseg_adds4(cd, 0x027f);
2585 i386_fldcw_membase(cd, REG_ITMP1, disp);
2587 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2590 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2591 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2594 i386_jcc(cd, I386_CC_NE, disp);
2596 /* XXX: change this when we use registers */
2597 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2598 i386_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP1);
2599 i386_call_reg(cd, REG_ITMP1);
2601 if (iptr->dst->flags & INMEMORY) {
2602 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2604 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2608 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2609 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2610 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2612 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2613 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2615 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2618 /* Round to zero, 53-bit mode, exception masked */
2619 disp = dseg_adds4(cd, 0x0e7f);
2620 i386_fldcw_membase(cd, REG_ITMP1, disp);
2622 if (iptr->dst->flags & INMEMORY) {
2623 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2626 /* Round to nearest, 53-bit mode, exceptions masked */
2627 disp = dseg_adds4(cd, 0x027f);
2628 i386_fldcw_membase(cd, REG_ITMP1, disp);
2630 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2633 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2635 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2638 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2640 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2642 i386_jcc(cd, I386_CC_NE, disp);
2644 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2647 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2649 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2651 i386_jcc(cd, I386_CC_NE, disp);
2653 /* XXX: change this when we use registers */
2654 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2655 i386_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP1);
2656 i386_call_reg(cd, REG_ITMP1);
2657 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2658 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2661 log_text("F2L: longs have to be in memory");
2666 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2667 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2668 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2670 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2671 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2673 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2676 /* Round to zero, 53-bit mode, exception masked */
2677 disp = dseg_adds4(cd, 0x0e7f);
2678 i386_fldcw_membase(cd, REG_ITMP1, disp);
2680 if (iptr->dst->flags & INMEMORY) {
2681 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2684 /* Round to nearest, 53-bit mode, exceptions masked */
2685 disp = dseg_adds4(cd, 0x027f);
2686 i386_fldcw_membase(cd, REG_ITMP1, disp);
2688 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2691 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2693 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2696 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2698 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2700 i386_jcc(cd, I386_CC_NE, disp);
2702 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2705 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2707 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2709 i386_jcc(cd, I386_CC_NE, disp);
2711 /* XXX: change this when we use registers */
2712 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2713 i386_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP1);
2714 i386_call_reg(cd, REG_ITMP1);
2715 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2716 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2719 log_text("D2L: longs have to be in memory");
2724 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2725 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2726 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2728 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2729 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2731 emit_store(jd, iptr, iptr->dst, d);
2734 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2735 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2736 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2738 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2739 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2741 emit_store(jd, iptr, iptr->dst, d);
2744 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2746 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2747 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2749 /* exchanged to skip fxch */
2750 s2 = emit_load_s2(jd, iptr, src->prev, REG_FTMP1);
2751 s1 = emit_load_s1(jd, iptr, src, REG_FTMP2);
2752 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2753 /* i386_fxch(cd); */
2757 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2758 i386_jcc(cd, I386_CC_E, 6);
2759 i386_alu_imm_reg(cd, ALU_AND, 0x000000ff, EAX);
2761 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2762 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2763 i386_jcc(cd, I386_CC_B, 3 + 5);
2764 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2765 i386_jmp_imm(cd, 3);
2766 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2767 emit_store(jd, iptr, iptr->dst, d);
2770 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2772 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2773 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2775 /* exchanged to skip fxch */
2776 s2 = emit_load_s2(jd, iptr, src->prev, REG_FTMP1);
2777 s1 = emit_load_s1(jd, iptr, src, REG_FTMP2);
2778 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2779 /* i386_fxch(cd); */
2783 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2784 i386_jcc(cd, I386_CC_E, 3);
2785 i386_movb_imm_reg(cd, 1, REG_AH);
2787 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2788 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2789 i386_jcc(cd, I386_CC_B, 3 + 5);
2790 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2791 i386_jmp_imm(cd, 3);
2792 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2793 emit_store(jd, iptr, iptr->dst, d);
2797 /* memory operations **************************************************/
2799 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2800 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2801 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2803 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2804 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2805 gen_nullptr_check(s1);
2806 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2807 emit_store(jd, iptr, iptr->dst, d);
2810 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2811 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2812 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2814 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2815 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2816 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2817 if (iptr->op1 == 0) {
2818 gen_nullptr_check(s1);
2821 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2822 emit_store(jd, iptr, iptr->dst, d);
2825 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2826 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2827 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2829 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2830 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2831 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2832 if (iptr->op1 == 0) {
2833 gen_nullptr_check(s1);
2837 if (iptr->dst->flags & INMEMORY) {
2838 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2839 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4);
2840 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2841 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2845 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2846 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2847 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2849 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2850 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2851 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2852 if (iptr->op1 == 0) {
2853 gen_nullptr_check(s1);
2856 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2857 emit_store(jd, iptr, iptr->dst, d);
2860 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2861 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2862 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2864 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2865 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2866 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2867 if (iptr->op1 == 0) {
2868 gen_nullptr_check(s1);
2871 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2873 emit_store(jd, iptr, iptr->dst, d);
2876 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2877 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2878 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2880 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2881 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2882 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2883 if (iptr->op1 == 0) {
2884 gen_nullptr_check(s1);
2887 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2889 emit_store(jd, iptr, iptr->dst, d);
2892 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2893 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2894 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2896 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2897 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2898 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2899 if (iptr->op1 == 0) {
2900 gen_nullptr_check(s1);
2903 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2904 emit_store(jd, iptr, iptr->dst, d);
2907 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2908 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2909 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2911 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2912 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2913 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2914 if (iptr->op1 == 0) {
2915 gen_nullptr_check(s1);
2918 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2919 emit_store(jd, iptr, iptr->dst, d);
2922 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2923 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2924 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2926 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2927 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2928 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2929 if (iptr->op1 == 0) {
2930 gen_nullptr_check(s1);
2933 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2934 emit_store(jd, iptr, iptr->dst, d);
2938 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2939 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2940 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
2942 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2943 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2944 if (iptr->op1 == 0) {
2945 gen_nullptr_check(s1);
2949 if (src->flags & INMEMORY) {
2950 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP3);
2951 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2952 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
2953 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2957 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2958 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2959 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2961 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2962 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2963 if (iptr->op1 == 0) {
2964 gen_nullptr_check(s1);
2967 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2968 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2971 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2972 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2973 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2975 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2976 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2977 if (iptr->op1 == 0) {
2978 gen_nullptr_check(s1);
2981 s3 = emit_load_s3(jd, iptr, src, REG_FTMP1);
2982 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2986 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2987 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2988 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2990 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2991 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2992 if (iptr->op1 == 0) {
2993 gen_nullptr_check(s1);
2996 s3 = emit_load_s3(jd, iptr, src, REG_FTMP1);
2997 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
3001 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
3002 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3003 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3005 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
3006 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
3007 if (iptr->op1 == 0) {
3008 gen_nullptr_check(s1);
3011 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
3012 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
3015 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
3016 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3017 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3019 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
3020 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
3021 if (iptr->op1 == 0) {
3022 gen_nullptr_check(s1);
3025 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
3026 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3029 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
3030 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3031 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3033 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
3034 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
3035 if (iptr->op1 == 0) {
3036 gen_nullptr_check(s1);
3039 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
3040 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
3041 M_INTMOVE(s3, REG_ITMP3);
3044 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3047 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
3049 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3050 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
3052 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
3053 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
3054 if (iptr->op1 == 0) {
3055 gen_nullptr_check(s1);
3058 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
3060 M_AST(s1, REG_SP, 0 * 4);
3061 M_AST(s3, REG_SP, 1 * 4);
3062 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
3066 codegen_add_arraystoreexception_ref(cd);
3068 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
3069 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
3070 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
3071 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3074 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
3075 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3076 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3078 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3079 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3080 if (iptr->op1 == 0) {
3081 gen_nullptr_check(s1);
3084 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
3087 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
3088 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3089 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3091 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3092 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3093 if (iptr->op1 == 0) {
3094 gen_nullptr_check(s1);
3098 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
3099 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
3102 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
3103 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3104 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3106 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3107 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3108 if (iptr->op1 == 0) {
3109 gen_nullptr_check(s1);
3112 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3115 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
3116 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3117 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3119 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3120 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3121 if (iptr->op1 == 0) {
3122 gen_nullptr_check(s1);
3125 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3128 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
3129 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3130 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3132 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3133 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3134 if (iptr->op1 == 0) {
3135 gen_nullptr_check(s1);
3138 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
3141 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
3142 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3143 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3145 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3146 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3147 if (iptr->op1 == 0) {
3148 gen_nullptr_check(s1);
3151 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3155 case ICMD_GETSTATIC: /* ... ==> ..., value */
3156 /* op1 = type, val.a = field address */
3157 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3158 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX*/
3160 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3161 codegen_addpatchref(cd, PATCHER_get_putstatic,
3162 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
3164 if (opt_showdisassemble) {
3165 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3171 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
3173 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3174 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
3176 if (opt_showdisassemble) {
3177 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3181 disp = (ptrint) &(fi->value);
3184 M_MOV_IMM(disp, REG_ITMP1);
3185 switch (iptr->op1) {
3188 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3189 M_ILD(d, REG_ITMP1, 0);
3192 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
3193 M_LLD(d, REG_ITMP1, 0);
3196 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
3197 M_FLD(d, REG_ITMP1, 0);
3200 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
3201 M_DLD(d, REG_ITMP1, 0);
3204 emit_store(jd, iptr, iptr->dst, d);
3207 case ICMD_PUTSTATIC: /* ..., value ==> ... */
3208 /* op1 = type, val.a = field address */
3209 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3210 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3212 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3213 codegen_addpatchref(cd, PATCHER_get_putstatic,
3214 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
3216 if (opt_showdisassemble) {
3217 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3223 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
3225 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3226 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
3228 if (opt_showdisassemble) {
3229 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3233 disp = (ptrint) &(fi->value);
3236 M_MOV_IMM(disp, REG_ITMP1);
3237 switch (iptr->op1) {
3240 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3241 M_IST(s2, REG_ITMP1, 0);
3244 if (src->flags & INMEMORY) {
3245 /* Using both REG_ITMP2 and REG_ITMP3 is faster
3246 than only using REG_ITMP2 alternating. */
3249 i386_mov_membase_reg(cd, REG_SP, s2 * 4, REG_ITMP2);
3250 i386_mov_membase_reg(cd, REG_SP, s2 * 4 + 4, REG_ITMP3);
3251 i386_mov_reg_membase(cd, REG_ITMP2, REG_ITMP1, 0);
3252 i386_mov_reg_membase(cd, REG_ITMP3, REG_ITMP1, 4);
3254 log_text("PUTSTATIC: longs have to be in memory");
3259 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
3260 i386_fstps_membase(cd, REG_ITMP1, 0);
3264 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
3265 i386_fstpl_membase(cd, REG_ITMP1, 0);
3271 case ICMD_PUTSTATICCONST: /* ... ==> ... */
3272 /* val = value (in current instruction) */
3273 /* op1 = type, val.a = field address (in */
3274 /* following NOP) */
3275 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3276 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3278 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
3279 codegen_addpatchref(cd, PATCHER_get_putstatic,
3280 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
3282 if (opt_showdisassemble) {
3283 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3289 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1);
3291 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
3292 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
3294 if (opt_showdisassemble) {
3295 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3299 disp = (ptrint) &(fi->value);
3302 M_MOV_IMM(disp, REG_ITMP1);
3303 switch (iptr[1].op1) {
3307 i386_mov_imm_membase(cd, iptr->val.i, REG_ITMP1, 0);
3311 i386_mov_imm_membase(cd, iptr->val.l, REG_ITMP1, 0);
3312 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_ITMP1, 4);
3317 case ICMD_GETFIELD: /* .., objectref. ==> ..., value */
3318 /* op1 = type, val.i = field offset */
3319 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3320 /* EAX: YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
3322 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3323 gen_nullptr_check(s1);
3325 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3326 codegen_addpatchref(cd, PATCHER_getfield,
3327 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
3329 if (opt_showdisassemble) {
3330 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3336 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
3339 switch (iptr->op1) {
3342 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3343 M_ILD32(d, s1, disp);
3346 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
3347 M_LLD32(d, s1, disp);
3350 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
3351 M_FLD32(d, s1, disp);
3354 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
3355 M_DLD32(d, s1, disp);
3358 emit_store(jd, iptr, iptr->dst, d);
3361 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
3362 /* op1 = type, val.a = field address */
3363 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3364 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3366 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3367 gen_nullptr_check(s1);
3369 /* must be done here because of code patching */
3371 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
3372 if (IS_2_WORD_TYPE(iptr->op1))
3373 s2 = emit_load_s2(jd, iptr, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
3375 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3377 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
3379 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3380 codegen_addpatchref(cd, PATCHER_putfield,
3381 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
3383 if (opt_showdisassemble) {
3384 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3390 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
3393 switch (iptr->op1) {
3396 M_IST32(s2, s1, disp);
3399 M_LST32(s2, s1, disp);
3402 i386_fstps_membase32(cd, s1, disp);
3406 i386_fstpl_membase32(cd, s1, disp);
3412 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
3413 /* val = value (in current instruction) */
3414 /* op1 = type, val.a = field address (in */
3415 /* following NOP) */
3416 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3417 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3419 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3420 gen_nullptr_check(s1);
3422 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
3423 codegen_addpatchref(cd, PATCHER_putfieldconst,
3424 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
3426 if (opt_showdisassemble) {
3427 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3433 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1)->offset;
3436 switch (iptr[1].op1) {
3440 M_IST32_IMM(iptr->val.i, s1, disp);
3444 M_LST32_IMM(iptr->val.l, s1, disp);
3450 /* branch operations **************************************************/
3452 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3453 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3454 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
3456 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3457 M_INTMOVE(s1, REG_ITMP1_XPTR);
3459 #ifdef ENABLE_VERIFIER
3461 codegen_addpatchref(cd, PATCHER_athrow_areturn,
3462 (unresolved_class *) iptr->val.a, 0);
3464 if (opt_showdisassemble) {
3465 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3468 #endif /* ENABLE_VERIFIER */
3470 M_CALL_IMM(0); /* passing exception pc */
3471 M_POP(REG_ITMP2_XPC);
3473 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
3477 case ICMD_INLINE_GOTO:
3479 M_COPY(src,iptr->dst);
3482 case ICMD_GOTO: /* ... ==> ... */
3483 /* op1 = target JavaVM pc */
3484 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3485 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3488 codegen_addreference(cd, (basicblock *) iptr->target);
3492 case ICMD_JSR: /* ... ==> ... */
3493 /* op1 = target JavaVM pc */
3494 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3495 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3498 codegen_addreference(cd, (basicblock *) iptr->target);
3501 case ICMD_RET: /* ... ==> ... */
3502 /* op1 = local variable */
3503 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3504 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3506 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3507 if (var->flags & INMEMORY) {
3508 M_ALD(REG_ITMP1, REG_SP, var->regoff * 4);
3514 case ICMD_IFNULL: /* ..., value ==> ... */
3515 /* op1 = target JavaVM pc */
3516 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3517 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3519 if (src->flags & INMEMORY) {
3520 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3523 i386_test_reg_reg(cd, src->regoff, src->regoff);
3525 i386_jcc(cd, I386_CC_E, 0);
3526 codegen_addreference(cd, (basicblock *) iptr->target);
3529 case ICMD_IFNONNULL: /* ..., value ==> ... */
3530 /* op1 = target JavaVM pc */
3531 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3532 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3534 if (src->flags & INMEMORY) {
3535 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3538 i386_test_reg_reg(cd, src->regoff, src->regoff);
3540 i386_jcc(cd, I386_CC_NE, 0);
3541 codegen_addreference(cd, (basicblock *) iptr->target);
3544 case ICMD_IFEQ: /* ..., value ==> ... */
3545 /* op1 = target JavaVM pc, val.i = constant */
3546 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3547 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3549 if (src->flags & INMEMORY) {
3550 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3553 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3555 i386_jcc(cd, I386_CC_E, 0);
3556 codegen_addreference(cd, (basicblock *) iptr->target);
3559 case ICMD_IFLT: /* ..., value ==> ... */
3560 /* op1 = target JavaVM pc, val.i = constant */
3561 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3562 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3564 if (src->flags & INMEMORY) {
3565 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3568 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3570 i386_jcc(cd, I386_CC_L, 0);
3571 codegen_addreference(cd, (basicblock *) iptr->target);
3574 case ICMD_IFLE: /* ..., value ==> ... */
3575 /* op1 = target JavaVM pc, val.i = constant */
3576 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3577 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3579 if (src->flags & INMEMORY) {
3580 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3583 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3585 i386_jcc(cd, I386_CC_LE, 0);
3586 codegen_addreference(cd, (basicblock *) iptr->target);
3589 case ICMD_IFNE: /* ..., value ==> ... */
3590 /* op1 = target JavaVM pc, val.i = constant */
3591 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3592 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3594 if (src->flags & INMEMORY) {
3595 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3598 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3600 i386_jcc(cd, I386_CC_NE, 0);
3601 codegen_addreference(cd, (basicblock *) iptr->target);
3604 case ICMD_IFGT: /* ..., value ==> ... */
3605 /* op1 = target JavaVM pc, val.i = constant */
3606 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3607 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3609 if (src->flags & INMEMORY) {
3610 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3613 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3615 i386_jcc(cd, I386_CC_G, 0);
3616 codegen_addreference(cd, (basicblock *) iptr->target);
3619 case ICMD_IFGE: /* ..., value ==> ... */
3620 /* op1 = target JavaVM pc, val.i = constant */
3621 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3622 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3624 if (src->flags & INMEMORY) {
3625 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3628 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3630 i386_jcc(cd, I386_CC_GE, 0);
3631 codegen_addreference(cd, (basicblock *) iptr->target);
3634 case ICMD_IF_LEQ: /* ..., value ==> ... */
3635 /* op1 = target JavaVM pc, val.l = constant */
3636 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3637 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3639 if (src->flags & INMEMORY) {
3640 if (iptr->val.l == 0) {
3641 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3642 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3645 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3646 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l >> 32, REG_ITMP2);
3647 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3648 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l, REG_ITMP1);
3649 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3652 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3653 i386_jcc(cd, I386_CC_E, 0);
3654 codegen_addreference(cd, (basicblock *) iptr->target);
3657 case ICMD_IF_LLT: /* ..., value ==> ... */
3658 /* op1 = target JavaVM pc, val.l = constant */
3659 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3660 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3662 if (src->flags & INMEMORY) {
3663 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3664 i386_jcc(cd, I386_CC_L, 0);
3665 codegen_addreference(cd, (basicblock *) iptr->target);
3668 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3669 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3671 i386_jcc(cd, I386_CC_G, disp);
3673 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3674 i386_jcc(cd, I386_CC_B, 0);
3675 codegen_addreference(cd, (basicblock *) iptr->target);
3679 case ICMD_IF_LLE: /* ..., value ==> ... */
3680 /* op1 = target JavaVM pc, val.l = constant */
3681 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3682 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3684 if (src->flags & INMEMORY) {
3685 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3686 i386_jcc(cd, I386_CC_L, 0);
3687 codegen_addreference(cd, (basicblock *) iptr->target);
3690 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3691 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3693 i386_jcc(cd, I386_CC_G, disp);
3695 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3696 i386_jcc(cd, I386_CC_BE, 0);
3697 codegen_addreference(cd, (basicblock *) iptr->target);
3701 case ICMD_IF_LNE: /* ..., value ==> ... */
3702 /* op1 = target JavaVM pc, val.l = constant */
3703 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3704 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3706 if (src->flags & INMEMORY) {
3707 if (iptr->val.l == 0) {
3708 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3709 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3712 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3713 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3714 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3715 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3716 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3719 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3720 i386_jcc(cd, I386_CC_NE, 0);
3721 codegen_addreference(cd, (basicblock *) iptr->target);
3724 case ICMD_IF_LGT: /* ..., value ==> ... */
3725 /* op1 = target JavaVM pc, val.l = constant */
3726 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3727 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3729 if (src->flags & INMEMORY) {
3730 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3731 i386_jcc(cd, I386_CC_G, 0);
3732 codegen_addreference(cd, (basicblock *) iptr->target);
3735 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3736 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3738 i386_jcc(cd, I386_CC_L, disp);
3740 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3741 i386_jcc(cd, I386_CC_A, 0);
3742 codegen_addreference(cd, (basicblock *) iptr->target);
3746 case ICMD_IF_LGE: /* ..., value ==> ... */
3747 /* op1 = target JavaVM pc, val.l = constant */
3748 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3749 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3751 if (src->flags & INMEMORY) {
3752 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3753 i386_jcc(cd, I386_CC_G, 0);
3754 codegen_addreference(cd, (basicblock *) iptr->target);
3757 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3758 CALCIMMEDIATEBYTES(disp, iptr->val.l);
3760 i386_jcc(cd, I386_CC_L, disp);
3762 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3763 i386_jcc(cd, I386_CC_AE, 0);
3764 codegen_addreference(cd, (basicblock *) iptr->target);
3768 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3769 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3770 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3771 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3773 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3774 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3775 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3777 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3778 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3780 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3781 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3784 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3786 i386_jcc(cd, I386_CC_E, 0);
3787 codegen_addreference(cd, (basicblock *) iptr->target);
3790 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3791 /* op1 = target JavaVM pc */
3792 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3793 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3795 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3796 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3797 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3798 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3799 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3800 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3801 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3803 i386_jcc(cd, I386_CC_E, 0);
3804 codegen_addreference(cd, (basicblock *) iptr->target);
3807 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3808 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3809 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3810 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3812 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3813 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3814 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3816 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3817 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3819 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3820 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3823 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3825 i386_jcc(cd, I386_CC_NE, 0);
3826 codegen_addreference(cd, (basicblock *) iptr->target);
3829 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3830 /* op1 = target JavaVM pc */
3831 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3832 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3834 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3835 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3836 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3837 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3838 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3839 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3840 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3842 i386_jcc(cd, I386_CC_NE, 0);
3843 codegen_addreference(cd, (basicblock *) iptr->target);
3846 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3847 /* op1 = target JavaVM pc */
3848 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3849 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3851 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3852 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3853 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3855 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3856 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3858 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3859 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3862 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3864 i386_jcc(cd, I386_CC_L, 0);
3865 codegen_addreference(cd, (basicblock *) iptr->target);
3868 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3869 /* op1 = target JavaVM pc */
3870 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3871 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3873 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3874 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3875 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3877 codegen_addreference(cd, (basicblock *) iptr->target);
3880 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3881 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3885 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3886 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3887 i386_jcc(cd, I386_CC_B, 0);
3888 codegen_addreference(cd, (basicblock *) iptr->target);
3892 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3893 /* op1 = target JavaVM pc */
3894 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3895 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3897 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3898 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3899 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3901 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3902 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3904 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3905 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3908 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3911 codegen_addreference(cd, (basicblock *) iptr->target);
3914 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3915 /* op1 = target JavaVM pc */
3916 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3917 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3919 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3920 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3921 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3923 codegen_addreference(cd, (basicblock *) iptr->target);
3926 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3927 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3931 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3932 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3933 i386_jcc(cd, I386_CC_A, 0);
3934 codegen_addreference(cd, (basicblock *) iptr->target);
3938 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3939 /* op1 = target JavaVM pc */
3940 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3941 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3943 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3944 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3945 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3947 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3948 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3950 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3951 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3954 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3957 codegen_addreference(cd, (basicblock *) iptr->target);
3960 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3961 /* op1 = target JavaVM pc */
3962 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3963 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3965 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3966 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3967 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3969 codegen_addreference(cd, (basicblock *) iptr->target);
3972 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
3973 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
3977 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3978 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3980 codegen_addreference(cd, (basicblock *) iptr->target);
3984 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3985 /* op1 = target JavaVM pc */
3986 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3987 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3989 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3990 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3991 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3993 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3994 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3996 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3997 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
4000 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
4003 codegen_addreference(cd, (basicblock *) iptr->target);
4006 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
4007 /* op1 = target JavaVM pc */
4008 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4009 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4011 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
4012 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
4013 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
4015 codegen_addreference(cd, (basicblock *) iptr->target);
4018 CALCOFFSETBYTES(disp, REG_SP, src->prev->regoff * 4);
4019 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
4023 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
4024 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
4026 codegen_addreference(cd, (basicblock *) iptr->target);
4030 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
4032 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
4033 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4034 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4037 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
4038 /* val.i = constant */
4039 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4040 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4042 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4043 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
4046 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
4047 /* val.i = constant */
4048 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4049 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4051 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4052 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
4055 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
4056 /* val.i = constant */
4057 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4058 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4060 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4061 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
4064 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
4065 /* val.i = constant */
4066 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4067 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4069 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4070 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
4073 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
4074 /* val.i = constant */
4075 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4076 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4078 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4079 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
4082 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
4083 /* val.i = constant */
4084 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4085 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4087 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4088 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
4092 case ICMD_IRETURN: /* ..., retvalue ==> ... */
4093 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4094 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4096 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
4097 M_INTMOVE(s1, REG_RESULT);
4098 goto nowperformreturn;
4100 case ICMD_LRETURN: /* ..., retvalue ==> ... */
4101 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4102 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4104 if (src->flags & INMEMORY) {
4105 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_RESULT);
4106 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_RESULT2);
4109 log_text("LRETURN: longs have to be in memory");
4112 goto nowperformreturn;
4114 case ICMD_ARETURN: /* ..., retvalue ==> ... */
4115 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4116 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4118 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
4119 M_INTMOVE(s1, REG_RESULT);
4121 #ifdef ENABLE_VERIFIER
4123 codegen_addpatchref(cd, PATCHER_athrow_areturn,
4124 (unresolved_class *) iptr->val.a, 0);
4126 if (opt_showdisassemble) {
4127 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4130 #endif /* ENABLE_VERIFIER */
4131 goto nowperformreturn;
4133 case ICMD_FRETURN: /* ..., retvalue ==> ... */
4135 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4136 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4138 s1 = emit_load_s1(jd, iptr, src, REG_FRESULT);
4139 /* this may be an early return -- keep the offset correct for the
4142 goto nowperformreturn;
4144 case ICMD_RETURN: /* ... ==> ... */
4145 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4146 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4154 #if !defined(NDEBUG)
4155 /* call trace function */
4156 if (opt_verbosecall) {
4157 i386_alu_imm_reg(cd, ALU_SUB, 4 + 8 + 8 + 4, REG_SP);
4159 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
4161 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
4162 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
4164 i386_fstl_membase(cd, REG_SP, 4 + 8);
4165 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
4167 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
4168 i386_call_reg(cd, REG_ITMP1);
4170 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
4171 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
4173 i386_alu_imm_reg(cd, ALU_ADD, 4 + 8 + 8 + 4, REG_SP);
4175 #endif /* !defined(NDEBUG) */
4177 #if defined(ENABLE_THREADS)
4178 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
4179 M_ALD(REG_ITMP2, REG_SP, rd->memuse * 4);
4181 /* we need to save the proper return value */
4182 switch (iptr->opc) {
4185 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4189 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4190 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4194 i386_fstps_membase(cd, REG_SP, rd->memuse * 4);
4198 i386_fstpl_membase(cd, REG_SP, rd->memuse * 4);
4202 M_AST(REG_ITMP2, REG_SP, 0);
4203 M_MOV_IMM(BUILTIN_monitorexit, REG_ITMP1);
4206 /* and now restore the proper return value */
4207 switch (iptr->opc) {
4210 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4214 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4215 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4219 i386_flds_membase(cd, REG_SP, rd->memuse * 4);
4223 i386_fldl_membase(cd, REG_SP, rd->memuse * 4);
4229 /* restore saved registers */
4231 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
4232 p--; M_ALD(rd->savintregs[i], REG_SP, p * 4);
4235 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
4237 i386_fldl_membase(cd, REG_SP, p * 4);
4239 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
4240 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
4242 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
4247 /* deallocate stack */
4250 M_AADD_IMM(stackframesize * 4, REG_SP);
4257 case ICMD_TABLESWITCH: /* ..., index ==> ... */
4258 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4259 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4264 tptr = (void **) iptr->target;
4266 s4ptr = iptr->val.a;
4267 l = s4ptr[1]; /* low */
4268 i = s4ptr[2]; /* high */
4270 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4271 M_INTMOVE(s1, REG_ITMP1);
4273 i386_alu_imm_reg(cd, ALU_SUB, l, REG_ITMP1);
4279 i386_alu_imm_reg(cd, ALU_CMP, i - 1, REG_ITMP1);
4280 i386_jcc(cd, I386_CC_A, 0);
4282 codegen_addreference(cd, (basicblock *) tptr[0]);
4284 /* build jump table top down and use address of lowest entry */
4289 dseg_addtarget(cd, (basicblock *) tptr[0]);
4293 /* length of dataseg after last dseg_addtarget is used by load */
4295 i386_mov_imm_reg(cd, 0, REG_ITMP2);
4297 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
4298 i386_jmp_reg(cd, REG_ITMP1);
4303 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
4304 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4305 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4307 s4 i, l, val, *s4ptr;
4310 tptr = (void **) iptr->target;
4312 s4ptr = iptr->val.a;
4313 l = s4ptr[0]; /* default */
4314 i = s4ptr[1]; /* count */
4316 MCODECHECK((i<<2)+8);
4317 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1); /* reg compare should always be faster */
4323 i386_alu_imm_reg(cd, ALU_CMP, val, s1);
4324 i386_jcc(cd, I386_CC_E, 0);
4325 codegen_addreference(cd, (basicblock *) tptr[0]);
4328 i386_jmp_imm(cd, 0);
4330 tptr = (void **) iptr->target;
4331 codegen_addreference(cd, (basicblock *) tptr[0]);
4335 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
4336 /* op1 = arg count val.a = builtintable entry */
4337 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4338 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4344 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
4345 /* op1 = arg count, val.a = method pointer */
4347 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
4348 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
4349 case ICMD_INVOKEINTERFACE:
4351 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4352 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
4354 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
4355 md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
4359 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
4360 md = lm->parseddesc;
4364 s3 = md->paramcount;
4366 MCODECHECK((s3 << 1) + 64);
4368 /* copy arguments to registers or stack location */
4370 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
4371 if (src->varkind == ARGVAR)
4373 if (IS_INT_LNG_TYPE(src->type)) {
4374 if (!md->params[s3].inmemory) {
4375 log_text("No integer argument registers available!");
4379 if (IS_2_WORD_TYPE(src->type)) {
4380 d = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP1, REG_ITMP2));
4381 M_LST(d, REG_SP, md->params[s3].regoff * 4);
4383 d = emit_load_s1(jd, iptr, src, REG_ITMP1);
4384 M_IST(d, REG_SP, md->params[s3].regoff * 4);
4389 if (!md->params[s3].inmemory) {
4390 s1 = rd->argfltregs[md->params[s3].regoff];
4391 d = emit_load_s1(jd, iptr, src, s1);
4395 d = emit_load_s1(jd, iptr, src, REG_FTMP1);
4396 if (IS_2_WORD_TYPE(src->type))
4397 M_DST(d, REG_SP, md->params[s3].regoff * 4);
4399 M_FST(d, REG_SP, md->params[s3].regoff * 4);
4404 switch (iptr->opc) {
4406 disp = (ptrint) bte->fp;
4407 d = md->returntype.type;
4409 M_MOV_IMM(disp, REG_ITMP1);
4412 /* if op1 == true, we need to check for an exception */
4414 if (iptr->op1 == true) {
4417 codegen_add_fillinstacktrace_ref(cd);
4421 case ICMD_INVOKESPECIAL:
4422 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
4423 gen_nullptr_check(REG_ITMP1);
4425 /* access memory for hardware nullptr */
4426 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1);
4430 case ICMD_INVOKESTATIC:
4432 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
4434 codegen_addpatchref(cd, PATCHER_invokestatic_special,
4437 if (opt_showdisassemble) {
4438 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4442 d = md->returntype.type;
4445 disp = (ptrint) lm->stubroutine;
4446 d = lm->parseddesc->returntype.type;
4449 M_MOV_IMM(disp, REG_ITMP2);
4453 case ICMD_INVOKEVIRTUAL:
4454 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4455 gen_nullptr_check(REG_ITMP1);
4458 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
4460 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
4462 if (opt_showdisassemble) {
4463 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4467 d = md->returntype.type;
4470 s1 = OFFSET(vftbl_t, table[0]) +
4471 sizeof(methodptr) * lm->vftblindex;
4472 d = md->returntype.type;
4475 M_ALD(REG_ITMP2, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4476 i386_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP1);
4480 case ICMD_INVOKEINTERFACE:
4481 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4482 gen_nullptr_check(REG_ITMP1);
4485 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
4487 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
4489 if (opt_showdisassemble) {
4490 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4495 d = md->returntype.type;
4498 s1 = OFFSET(vftbl_t, interfacetable[0]) -
4499 sizeof(methodptr) * lm->class->index;
4501 s2 = sizeof(methodptr) * (lm - lm->class->methods);
4503 d = md->returntype.type;
4506 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4507 i386_mov_membase32_reg(cd, REG_ITMP1, s1, REG_ITMP2);
4508 i386_mov_membase32_reg(cd, REG_ITMP2, s2, REG_ITMP1);
4513 /* d contains return type */
4515 if (d != TYPE_VOID) {
4516 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
4518 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
4519 if (IS_2_WORD_TYPE(iptr->dst->type)) {
4520 if (iptr->dst->flags & INMEMORY) {
4521 i386_mov_reg_membase(
4522 cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4523 i386_mov_reg_membase(
4524 cd, REG_RESULT2, REG_SP,
4525 iptr->dst->regoff * 4 + 4);
4527 log_text("RETURN: longs have to be in memory");
4532 if (iptr->dst->flags & INMEMORY) {
4533 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4536 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
4541 /* fld from called function -- has other fpu_st_offset counter */
4543 emit_store(jd, iptr, iptr->dst, d);
4549 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4550 /* op1: 0 == array, 1 == class */
4551 /* val.a: (classinfo*) superclass */
4553 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4554 /* EAX: YES ECX: I|YES EDX: I|YES OUTPUT: REG_NULL */
4556 /* superclass is an interface:
4558 * OK if ((sub == NULL) ||
4559 * (sub->vftbl->interfacetablelength > super->index) &&
4560 * (sub->vftbl->interfacetable[-super->index] != NULL));
4562 * superclass is a class:
4564 * OK if ((sub == NULL) || (0
4565 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4566 * super->vftbl->diffval));
4569 if (iptr->op1 == 1) {
4570 /* object type cast-check */
4573 vftbl_t *supervftbl;
4576 super = (classinfo *) iptr->val.a;
4583 superindex = super->index;
4584 supervftbl = super->vftbl;
4587 #if defined(ENABLE_THREADS)
4588 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4590 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4592 /* calculate interface checkcast code size */
4594 s2 = 2; /* mov_membase_reg */
4595 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4597 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ +
4598 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4599 2 /* test */ + 6 /* jcc */);
4602 s2 += (opt_showdisassemble ? 5 : 0);
4604 /* calculate class checkcast code size */
4606 s3 = 2; /* mov_membase_reg */
4607 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4609 s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */;
4612 if (s1 != REG_ITMP1) {
4614 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
4617 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
4624 s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ +
4625 5 /* mov_imm_reg */ + 2 /* mov_membase_reg */);
4626 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
4629 s3 += 2 /* cmp */ + 6 /* jcc */;
4632 s3 += (opt_showdisassemble ? 5 : 0);
4634 /* if class is not resolved, check which code to call */
4636 if (super == NULL) {
4637 i386_test_reg_reg(cd, s1, s1);
4638 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4640 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
4641 (constant_classref *) iptr->target, 0);
4643 if (opt_showdisassemble) {
4644 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4647 i386_mov_imm_reg(cd, 0, REG_ITMP2); /* super->flags */
4648 i386_alu_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP2);
4649 i386_jcc(cd, I386_CC_Z, s2 + 5);
4652 /* interface checkcast code */
4654 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
4655 if (super != NULL) {
4656 i386_test_reg_reg(cd, s1, s1);
4657 i386_jcc(cd, I386_CC_Z, s2);
4660 i386_mov_membase_reg(cd, s1,
4661 OFFSET(java_objectheader, vftbl),
4664 if (super == NULL) {
4665 codegen_addpatchref(cd,
4666 PATCHER_checkcast_instanceof_interface,
4667 (constant_classref *) iptr->target,
4670 if (opt_showdisassemble) {
4671 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4675 i386_mov_membase32_reg(cd, REG_ITMP2,
4676 OFFSET(vftbl_t, interfacetablelength),
4678 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4679 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4680 i386_jcc(cd, I386_CC_LE, 0);
4681 codegen_add_classcastexception_ref(cd, s1);
4682 i386_mov_membase32_reg(cd, REG_ITMP2,
4683 OFFSET(vftbl_t, interfacetable[0]) -
4684 superindex * sizeof(methodptr*),
4688 codegen_add_classcastexception_ref(cd, s1);
4694 /* class checkcast code */
4696 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
4697 if (super != NULL) {
4702 i386_mov_membase_reg(cd, s1,
4703 OFFSET(java_objectheader, vftbl),
4706 if (super == NULL) {
4707 codegen_addpatchref(cd, PATCHER_checkcast_class,
4708 (constant_classref *) iptr->target,
4711 if (opt_showdisassemble) {
4712 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4716 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4717 #if defined(ENABLE_THREADS)
4718 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4720 i386_mov_membase32_reg(cd, REG_ITMP2,
4721 OFFSET(vftbl_t, baseval),
4724 /* if (s1 != REG_ITMP1) { */
4725 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
4726 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
4727 /* #if defined(ENABLE_THREADS) */
4728 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
4730 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
4733 i386_mov_membase32_reg(cd, REG_ITMP3,
4734 OFFSET(vftbl_t, baseval),
4736 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP3, REG_ITMP2);
4737 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4738 i386_mov_membase_reg(cd, REG_ITMP3,
4739 OFFSET(vftbl_t, diffval),
4741 #if defined(ENABLE_THREADS)
4742 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4746 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP2);
4747 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
4748 codegen_add_classcastexception_ref(cd, s1);
4751 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
4754 /* array type cast-check */
4756 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4757 M_AST(s1, REG_SP, 0 * 4);
4759 if (iptr->val.a == NULL) {
4760 codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
4763 if (opt_showdisassemble) {
4764 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4768 M_AST_IMM(iptr->val.a, REG_SP, 1 * 4);
4769 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP3);
4773 codegen_add_classcastexception_ref(cd, s1);
4775 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4776 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
4780 emit_store(jd, iptr, iptr->dst, d);
4783 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
4785 /* op1: 0 == array, 1 == class */
4786 /* val.a: (classinfo*) superclass */
4787 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4788 /* EAX: S|D|YES ECX: YES S|D|EDX: S|D|YES OUTPUT: REG_NULL*/
4789 /* ????? Really necessary to block all ????? */
4791 /* superclass is an interface:
4793 * return (sub != NULL) &&
4794 * (sub->vftbl->interfacetablelength > super->index) &&
4795 * (sub->vftbl->interfacetable[-super->index] != NULL);
4797 * superclass is a class:
4799 * return ((sub != NULL) && (0
4800 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4801 * super->vftbl->diffvall));
4806 vftbl_t *supervftbl;
4809 super = (classinfo *) iptr->val.a;
4816 superindex = super->index;
4817 supervftbl = super->vftbl;
4820 #if defined(ENABLE_THREADS)
4821 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4824 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4825 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
4827 M_INTMOVE(s1, REG_ITMP1);
4831 /* calculate interface instanceof code size */
4833 s2 = 2; /* mov_membase_reg */
4834 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4836 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
4837 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4838 2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4841 s2 += (opt_showdisassemble ? 5 : 0);
4843 /* calculate class instanceof code size */
4845 s3 = 2; /* mov_membase_reg */
4846 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4847 s3 += 5; /* mov_imm_reg */
4849 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
4851 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
4853 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
4855 s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
4856 2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4859 s3 += (opt_showdisassemble ? 5 : 0);
4861 i386_alu_reg_reg(cd, ALU_XOR, d, d);
4863 /* if class is not resolved, check which code to call */
4866 i386_test_reg_reg(cd, s1, s1);
4867 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4869 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
4870 (constant_classref *) iptr->target, 0);
4872 if (opt_showdisassemble) {
4873 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4876 i386_mov_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
4877 i386_alu_imm32_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
4878 i386_jcc(cd, I386_CC_Z, s2 + 5);
4881 /* interface instanceof code */
4883 if (!super || (super->flags & ACC_INTERFACE)) {
4889 i386_mov_membase_reg(cd, s1,
4890 OFFSET(java_objectheader, vftbl),
4894 codegen_addpatchref(cd,
4895 PATCHER_checkcast_instanceof_interface,
4896 (constant_classref *) iptr->target, 0);
4898 if (opt_showdisassemble) {
4899 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4903 i386_mov_membase32_reg(cd, REG_ITMP1,
4904 OFFSET(vftbl_t, interfacetablelength),
4906 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4907 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4909 disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
4910 6 /* jcc */ + 5 /* mov_imm_reg */);
4913 i386_mov_membase32_reg(cd, REG_ITMP1,
4914 OFFSET(vftbl_t, interfacetable[0]) -
4915 superindex * sizeof(methodptr*),
4918 /* i386_setcc_reg(cd, I386_CC_A, d); */
4919 /* i386_jcc(cd, I386_CC_BE, 5); */
4927 /* class instanceof code */
4929 if (!super || !(super->flags & ACC_INTERFACE)) {
4935 i386_mov_membase_reg(cd, s1,
4936 OFFSET(java_objectheader, vftbl),
4940 codegen_addpatchref(cd, PATCHER_instanceof_class,
4941 (constant_classref *) iptr->target, 0);
4943 if (opt_showdisassemble) {
4944 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4948 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
4949 #if defined(ENABLE_THREADS)
4950 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4952 i386_mov_membase_reg(cd, REG_ITMP1,
4953 OFFSET(vftbl_t, baseval),
4955 i386_mov_membase_reg(cd, REG_ITMP2,
4956 OFFSET(vftbl_t, diffval),
4958 i386_mov_membase_reg(cd, REG_ITMP2,
4959 OFFSET(vftbl_t, baseval),
4961 #if defined(ENABLE_THREADS)
4962 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4964 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
4965 i386_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
4966 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
4967 i386_jcc(cd, I386_CC_A, 5);
4968 i386_mov_imm_reg(cd, 1, d);
4970 emit_store(jd, iptr, iptr->dst, d);
4976 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4977 /* op1 = dimension, val.a = class */
4978 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4979 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX */
4981 /* check for negative sizes and copy sizes to stack if necessary */
4983 MCODECHECK((iptr->op1 << 1) + 64);
4985 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4986 /* copy SAVEDVAR sizes to stack */
4988 if (src->varkind != ARGVAR) {
4989 if (src->flags & INMEMORY) {
4990 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
4991 M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4);
4994 M_IST(src->regoff, REG_SP, (s1 + 3) * 4);
4999 /* is a patcher function set? */
5001 if (iptr->val.a == NULL) {
5002 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
5003 (constant_classref *) iptr->target, 0);
5005 if (opt_showdisassemble) {
5006 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5012 disp = (ptrint) iptr->val.a;
5015 /* a0 = dimension count */
5017 M_IST_IMM(iptr->op1, REG_SP, 0 * 4);
5019 /* a1 = arraydescriptor */
5021 M_IST_IMM(disp, REG_SP, 1 * 4);
5023 /* a2 = pointer to dimensions = stack pointer */
5025 M_MOV(REG_SP, REG_ITMP1);
5026 M_AADD_IMM(3 * 4, REG_ITMP1);
5027 M_AST(REG_ITMP1, REG_SP, 2 * 4);
5029 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
5032 /* check for exception before result assignment */
5036 codegen_add_fillinstacktrace_ref(cd);
5038 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
5039 M_INTMOVE(REG_RESULT, s1);
5040 emit_store(jd, iptr, iptr->dst, s1);
5045 new_internalerror("Unknown ICMD %d", iptr->opc);
5049 } /* for instruction */
5051 /* copy values to interface registers */
5053 src = bptr->outstack;
5054 len = bptr->outdepth;
5056 #if defined(ENABLE_LSRA)
5061 if ((src->varkind != STACKVAR)) {
5063 if (IS_FLT_DBL_TYPE(s2)) {
5064 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
5065 if (!(rd->interfaces[len][s2].flags & INMEMORY))
5066 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
5068 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5071 if (IS_2_WORD_TYPE(s2))
5073 /* s1 = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP1, REG_ITMP2)); */
5075 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
5077 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5078 if (IS_2_WORD_TYPE(s2))
5079 M_LNGMOVE(s1, rd->interfaces[len][s2].regoff);
5081 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
5084 if (IS_2_WORD_TYPE(s2))
5085 M_LST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5087 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5094 /* At the end of a basic block we may have to append some nops,
5095 because the patcher stub calling code might be longer than the
5096 actual instruction. So codepatching does not change the
5097 following block unintentionally. */
5099 if (cd->mcodeptr < cd->lastmcodeptr) {
5100 while (cd->mcodeptr < cd->lastmcodeptr) {
5105 } /* if (bptr -> flags >= BBREACHED) */
5106 } /* for basic block */
5108 dseg_createlinenumbertable(cd);
5111 /* generate exception and patcher stubs */
5120 savedmcodeptr = NULL;
5122 /* generate exception stubs */
5124 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
5125 gen_resolvebranch(cd->mcodebase + eref->branchpos,
5127 cd->mcodeptr - cd->mcodebase);
5131 /* Check if the exception is an
5132 ArrayIndexOutOfBoundsException. If so, move index register
5135 if (eref->reg != -1)
5136 M_INTMOVE(eref->reg, REG_ITMP1);
5138 /* calcuate exception address */
5140 M_MOV_IMM(0, REG_ITMP2_XPC);
5142 M_AADD_IMM32(eref->branchpos - 6, REG_ITMP2_XPC);
5144 /* move function to call into REG_ITMP3 */
5146 M_MOV_IMM(eref->function, REG_ITMP3);
5148 if (savedmcodeptr != NULL) {
5149 M_JMP_IMM((savedmcodeptr - cd->mcodeptr) - 5);
5152 savedmcodeptr = cd->mcodeptr;
5154 M_ASUB_IMM(5 * 4, REG_SP);
5156 /* first save REG_ITMP1 so we can use it */
5158 M_AST(REG_ITMP1, REG_SP, 4 * 4); /* for AIOOBE */
5160 M_AST_IMM(0, REG_SP, 0 * 4);
5162 M_MOV(REG_SP, REG_ITMP1);
5163 M_AADD_IMM(5 * 4, REG_ITMP1);
5164 M_AST(REG_ITMP1, REG_SP, 1 * 4);
5165 M_ALD(REG_ITMP1, REG_SP, (5 + stackframesize) * 4);
5166 M_AST(REG_ITMP1, REG_SP, 2 * 4);
5167 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5171 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5172 M_AADD_IMM(5 * 4, REG_SP);
5174 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
5180 /* generate code patching stub call code */
5182 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5183 /* check code segment size */
5187 /* Get machine code which is patched back in later. A
5188 `call rel32' is 5 bytes long. */
5190 savedmcodeptr = cd->mcodebase + pref->branchpos;
5191 mcode = *((u8 *) savedmcodeptr);
5193 /* patch in `call rel32' to call the following code */
5195 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
5196 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
5198 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
5200 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
5202 /* save REG_ITMP3 */
5206 /* move pointer to java_objectheader onto stack */
5208 #if defined(ENABLE_THREADS)
5209 (void) dseg_addaddress(cd, NULL); /* flcword */
5210 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
5211 off = dseg_addaddress(cd, NULL); /* vftbl */
5213 M_MOV_IMM(0, REG_ITMP3);
5215 M_AADD_IMM(off, REG_ITMP3);
5221 /* move machine code bytes and classinfo pointer into registers */
5223 M_PUSH_IMM(mcode >> 32);
5225 M_PUSH_IMM(pref->ref);
5226 M_PUSH_IMM(pref->patcher);
5228 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
5233 /* generate replacement-out stubs */
5238 replacementpoint = jd->code->rplpoints;
5240 for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
5241 /* check code segment size */
5245 /* note start of stub code */
5247 replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
5249 /* make machine code for patching */
5251 disp = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
5252 replacementpoint->mcode = 0xe9 | ((u8)disp << 8);
5254 /* push address of `rplpoint` struct */
5256 M_PUSH_IMM(replacementpoint);
5258 /* jump to replacement function */
5260 M_PUSH_IMM(asm_replacement_out);
5267 /* everything's ok */
5273 /* createcompilerstub **********************************************************
5275 Creates a stub routine which calls the compiler.
5277 *******************************************************************************/
5279 #define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P
5280 #define COMPILERSTUB_CODESIZE 12
5282 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
5285 u1 *createcompilerstub(methodinfo *m)
5287 u1 *s; /* memory to hold the stub */
5293 s = CNEW(u1, COMPILERSTUB_SIZE);
5295 /* set data pointer and code pointer */
5298 s = s + COMPILERSTUB_DATASIZE;
5300 /* mark start of dump memory area */
5302 dumpsize = dump_size();
5304 cd = DNEW(codegendata);
5307 /* Store the codeinfo pointer in the same place as in the
5308 methodheader for compiled methods. */
5310 code = code_codeinfo_new(m);
5312 d[0] = (ptrint) asm_call_jit_compiler;
5314 d[2] = (ptrint) code;
5316 M_MOV_IMM(m, REG_ITMP1);
5318 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
5319 M_MOV_IMM(asm_call_jit_compiler, REG_ITMP3);
5322 #if defined(ENABLE_STATISTICS)
5324 count_cstub_len += COMPILERSTUB_SIZE;
5327 /* release dump area */
5329 dump_release(dumpsize);
5335 /* createnativestub ************************************************************
5337 Creates a stub routine which calls a native method.
5339 *******************************************************************************/
5341 #if defined(ENABLE_THREADS)
5342 /* this way we can call the function directly with a memory call */
5344 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
5347 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
5356 s4 i, j; /* count variables */
5360 /* get required compiler data */
5367 /* set some variables */
5370 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
5372 /* calculate stackframe size */
5375 sizeof(stackframeinfo) / SIZEOF_VOID_P +
5376 sizeof(localref_table) / SIZEOF_VOID_P +
5377 1 + /* function pointer */
5378 4 * 4 + /* 4 arguments (start_native_call) */
5381 /* create method header */
5383 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
5384 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
5385 (void) dseg_adds4(cd, 0); /* IsSync */
5386 (void) dseg_adds4(cd, 0); /* IsLeaf */
5387 (void) dseg_adds4(cd, 0); /* IntSave */
5388 (void) dseg_adds4(cd, 0); /* FltSave */
5389 (void) dseg_addlinenumbertablesize(cd);
5390 (void) dseg_adds4(cd, 0); /* ExTableSize */
5392 /* generate native method profiling code */
5394 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
5395 /* count frequency */
5397 M_MOV_IMM(code, REG_ITMP1);
5398 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(codeinfo, frequency));
5401 /* calculate stackframe size for native function */
5403 M_ASUB_IMM(stackframesize * 4, REG_SP);
5405 #if !defined(NDEBUG)
5406 if (opt_verbosecall) {
5409 disp = stackframesize * 4;
5411 M_ASUB_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5413 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
5414 t = md->paramtypes[p].type;
5415 if (IS_INT_LNG_TYPE(t)) {
5416 if (IS_2_WORD_TYPE(t)) {
5417 M_ILD(REG_ITMP1, REG_SP,
5418 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5419 M_ILD(REG_ITMP2, REG_SP,
5420 4 + TRACE_ARGS_NUM * 8 + 4 + disp + 4);
5421 M_IST(REG_ITMP1, REG_SP, p * 8);
5422 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5424 } else if (t == TYPE_ADR) {
5425 M_ALD(REG_ITMP1, REG_SP,
5426 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5428 M_AST(REG_ITMP1, REG_SP, p * 8);
5429 M_AST(REG_ITMP2, REG_SP, p * 8 + 4);
5432 M_ILD(EAX, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5434 M_IST(EAX, REG_SP, p * 8);
5435 M_IST(EDX, REG_SP, p * 8 + 4);
5439 if (!IS_2_WORD_TYPE(t)) {
5440 i386_flds_membase(cd, REG_SP,
5441 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5442 i386_fstps_membase(cd, REG_SP, p * 8);
5443 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
5444 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
5447 i386_fldl_membase(cd, REG_SP,
5448 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
5449 i386_fstpl_membase(cd, REG_SP, p * 8);
5452 disp += (IS_2_WORD_TYPE(t)) ? 8 : 4;
5456 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
5457 M_IST(REG_ITMP1, REG_SP, p * 8);
5458 M_IST(REG_ITMP1, REG_SP, p * 8 + 4);
5461 M_AST_IMM(m, REG_SP, TRACE_ARGS_NUM * 8);
5463 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
5466 M_AADD_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
5468 #endif /* !defined(NDEBUG) */
5470 /* get function address (this must happen before the stackframeinfo) */
5472 #if !defined(WITH_STATIC_CLASSPATH)
5474 codegen_addpatchref(cd, PATCHER_resolve_native, m, 0);
5476 if (opt_showdisassemble) {
5477 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5482 M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
5484 /* Mark the whole fpu stack as free for native functions (only for saved */
5485 /* register count == 0). */
5487 i386_ffree_reg(cd, 0);
5488 i386_ffree_reg(cd, 1);
5489 i386_ffree_reg(cd, 2);
5490 i386_ffree_reg(cd, 3);
5491 i386_ffree_reg(cd, 4);
5492 i386_ffree_reg(cd, 5);
5493 i386_ffree_reg(cd, 6);
5494 i386_ffree_reg(cd, 7);
5496 /* prepare data structures for native function call */
5498 M_MOV(REG_SP, REG_ITMP1);
5499 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5501 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5502 M_IST_IMM(0, REG_SP, 1 * 4);
5505 M_MOV(REG_SP, REG_ITMP2);
5506 M_AADD_IMM(stackframesize * 4 + SIZEOF_VOID_P, REG_ITMP2);
5508 M_AST(REG_ITMP2, REG_SP, 2 * 4);
5509 M_ALD(REG_ITMP3, REG_SP, stackframesize * 4);
5510 M_AST(REG_ITMP3, REG_SP, 3 * 4);
5511 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
5514 M_ALD(REG_ITMP3, REG_SP, 4 * 4);
5516 /* copy arguments into new stackframe */
5518 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
5519 t = md->paramtypes[i].type;
5521 if (!md->params[i].inmemory) {
5522 /* no integer argument registers */
5523 } else { /* float/double in memory can be copied like int/longs */
5524 s1 = (md->params[i].regoff + stackframesize + 1) * 4;
5525 s2 = nmd->params[j].regoff * 4;
5527 M_ILD(REG_ITMP1, REG_SP, s1);
5528 M_IST(REG_ITMP1, REG_SP, s2);
5529 if (IS_2_WORD_TYPE(t)) {
5530 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
5531 M_IST(REG_ITMP1, REG_SP, s2 + 4);
5536 /* if function is static, put class into second argument */
5538 if (m->flags & ACC_STATIC)
5539 M_AST_IMM((ptrint) m->class, REG_SP, 1 * 4);
5541 /* put env into first argument */
5543 M_AST_IMM((ptrint) _Jv_env, REG_SP, 0 * 4);
5545 /* call the native function */
5549 /* save return value */
5551 if (md->returntype.type != TYPE_VOID) {
5552 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5553 if (IS_2_WORD_TYPE(md->returntype.type))
5554 M_IST(REG_RESULT2, REG_SP, 2 * 4);
5555 M_IST(REG_RESULT, REG_SP, 1 * 4);
5558 if (IS_2_WORD_TYPE(md->returntype.type))
5559 i386_fstl_membase(cd, REG_SP, 1 * 4);
5561 i386_fsts_membase(cd, REG_SP, 1 * 4);
5565 #if !defined(NDEBUG)
5566 if (opt_verbosecall) {
5567 /* restore return value */
5569 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5570 if (IS_2_WORD_TYPE(md->returntype.type))
5571 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5572 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5575 if (IS_2_WORD_TYPE(md->returntype.type))
5576 i386_fldl_membase(cd, REG_SP, 1 * 4);
5578 i386_flds_membase(cd, REG_SP, 1 * 4);
5581 M_ASUB_IMM(4 + 8 + 8 + 4, REG_SP);
5583 M_AST_IMM((ptrint) m, REG_SP, 0);
5585 M_IST(REG_RESULT, REG_SP, 4);
5586 M_IST(REG_RESULT2, REG_SP, 4 + 4);
5588 i386_fstl_membase(cd, REG_SP, 4 + 8);
5589 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5591 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
5594 M_AADD_IMM(4 + 8 + 8 + 4, REG_SP);
5596 #endif /* !defined(NDEBUG) */
5598 /* remove native stackframe info */
5600 M_MOV(REG_SP, REG_ITMP1);
5601 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5603 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5604 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
5606 M_MOV(REG_RESULT, REG_ITMP2); /* REG_ITMP3 == REG_RESULT2 */
5608 /* restore return value */
5610 if (md->returntype.type != TYPE_VOID) {
5611 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5612 if (IS_2_WORD_TYPE(md->returntype.type))
5613 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5614 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5617 if (IS_2_WORD_TYPE(md->returntype.type))
5618 i386_fldl_membase(cd, REG_SP, 1 * 4);
5620 i386_flds_membase(cd, REG_SP, 1 * 4);
5624 M_AADD_IMM(stackframesize * 4, REG_SP);
5626 /* check for exception */
5633 /* handle exception */
5635 M_MOV(REG_ITMP2, REG_ITMP1_XPTR);
5636 M_ALD(REG_ITMP2_XPC, REG_SP, 0);
5637 M_ASUB_IMM(2, REG_ITMP2_XPC);
5639 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
5643 /* process patcher calls **************************************************/
5651 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5652 /* Get machine code which is patched back in later. A
5653 `call rel32' is 5 bytes long. */
5655 xcodeptr = cd->mcodebase + pref->branchpos;
5656 mcode = *((u8 *) xcodeptr);
5658 /* patch in `call rel32' to call the following code */
5660 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
5661 cd->mcodeptr = xcodeptr; /* set mcodeptr to patch position */
5663 M_CALL_IMM(tmpmcodeptr - (xcodeptr + PATCHER_CALL_SIZE));
5665 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
5667 /* save REG_ITMP3 */
5671 /* move pointer to java_objectheader onto stack */
5673 #if defined(ENABLE_THREADS)
5674 /* create a virtual java_objectheader */
5676 (void) dseg_addaddress(cd, NULL); /* flcword */
5677 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
5678 disp = dseg_addaddress(cd, NULL); /* vftbl */
5680 M_MOV_IMM(0, REG_ITMP3);
5682 M_AADD_IMM(disp, REG_ITMP3);
5688 /* move machine code bytes and classinfo pointer onto stack */
5690 M_PUSH_IMM((mcode >> 32));
5692 M_PUSH_IMM(pref->ref);
5693 M_PUSH_IMM(pref->patcher);
5695 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
5702 return jd->code->entrypoint;
5707 * These are local overrides for various environment variables in Emacs.
5708 * Please do not remove this and leave it at the end of the file, where
5709 * Emacs will automagically detect them.
5710 * ---------------------------------------------------------------------
5713 * indent-tabs-mode: t
5717 * vim:noexpandtab:sw=4:ts=4: