1 /* src/vm/jit/i386/codegen.c - machine code generator for i386
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
30 Changes: Joseph Wenninger
33 $Id: codegen.c 3428 2005-10-13 09:50:19Z twisti $
44 #include "vm/jit/i386/md-abi.h"
45 #include "vm/jit/i386/md-abi.inc"
47 #include "vm/jit/i386/codegen.h"
48 #include "vm/jit/i386/emitfuncs.h"
50 #include "cacao/cacao.h"
51 #include "native/jni.h"
52 #include "native/native.h"
53 #include "vm/builtin.h"
54 #include "vm/exceptions.h"
55 #include "vm/global.h"
56 #include "vm/loader.h"
57 #include "vm/stringlocal.h"
58 #include "vm/tables.h"
60 #include "vm/jit/asmpart.h"
61 #include "vm/jit/jit.h"
62 #include "vm/jit/parse.h"
63 #include "vm/jit/patcher.h"
64 #include "vm/jit/reg.h"
67 #include "vm/jit/codegen.inc"
68 #include "vm/jit/reg.inc"
70 #ifdef LSRA_USES_REG_RES
71 #include "vm/jit/i386/icmd_uses_reg_res.inc"
73 #include "vm/jit/lsra.inc"
77 /* codegen *********************************************************************
79 Generates machine code.
81 *******************************************************************************/
83 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
85 s4 len, s1, s2, s3, d, off;
94 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
95 builtintable_entry *bte;
102 s4 savedregs_num = 0;
105 /* space to save used callee saved registers */
107 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
109 /* float register are saved on 2 4-byte stackslots */
110 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
112 parentargs_base = rd->memuse + savedregs_num;
115 #if defined(USE_THREADS)
116 /* space to save argument of monitor_enter */
118 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
119 /* reserve 2 slots for long/double return values for monitorexit */
121 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
122 parentargs_base += 2;
128 /* create method header */
130 (void) dseg_addaddress(cd, m); /* MethodPointer */
131 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
133 #if defined(USE_THREADS)
134 /* IsSync contains the offset relative to the stack pointer for the
135 argument of monitor_exit used in the exception handler. Since the
136 offset could be zero and give a wrong meaning of the flag it is
140 if (checksync && (m->flags & ACC_SYNCHRONIZED))
141 (void) dseg_adds4(cd, (rd->memuse + 1) * 4); /* IsSync */
144 (void) dseg_adds4(cd, 0); /* IsSync */
146 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
147 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
148 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
150 /* adds a reference for the length of the line number counter. We don't
151 know the size yet, since we evaluate the information during code
152 generation, to save one additional iteration over the whole
153 instructions. During code optimization the position could have changed
154 to the information gotten from the class file */
155 (void) dseg_addlinenumbertablesize(cd);
157 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
159 /* create exception table */
161 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
162 dseg_addtarget(cd, ex->start);
163 dseg_addtarget(cd, ex->end);
164 dseg_addtarget(cd, ex->handler);
165 (void) dseg_addaddress(cd, ex->catchtype.cls);
169 /* initialize mcode variables */
171 cd->mcodeptr = cd->mcodebase;
172 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
173 MCODECHECK(128 + m->paramcount);
175 /* create stack frame (if necessary) */
178 M_ASUB_IMM(parentargs_base * 4, REG_SP);
180 /* save return address and used callee saved registers */
183 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
184 p--; M_AST(rd->savintregs[i], REG_SP, p * 4);
186 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
187 p-=2; i386_fld_reg(cd, rd->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 4);
190 /* take arguments out of register or stack frame */
195 for (p = 0, l = 0; p < md->paramcount; p++) {
196 t = md->paramtypes[p].type;
197 var = &(rd->locals[l][t]);
199 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
203 s1 = md->params[p].regoff;
204 if (IS_INT_LNG_TYPE(t)) { /* integer args */
205 if (!md->params[p].inmemory) { /* register arguments */
206 log_text("integer register argument");
208 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
209 /* rd->argintregs[md->params[p].regoff -> var->regoff */
210 } else { /* reg arg -> spilled */
211 /* rd->argintregs[md->params[p].regoff -> var->regoff * 4 */
213 } else { /* stack arguments */
214 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
215 i386_mov_membase_reg( /* + 4 for return address */
216 cd, REG_SP, (parentargs_base + s1) * 4 + 4, var->regoff);
217 /* + 4 for return address */
218 } else { /* stack arg -> spilled */
219 if (!IS_2_WORD_TYPE(t)) {
221 i386_mov_membase_reg( /* + 4 for return address */
222 cd, REG_SP, (parentargs_base + s1) * 4 + 4,
224 i386_mov_reg_membase(
225 cd, REG_ITMP1, REG_SP, var->regoff * 4);
227 /* reuse Stackslotand avoid copying */
228 var->regoff = parentargs_base + s1 + 1;
233 i386_mov_membase_reg( /* + 4 for return address */
234 cd, REG_SP, (parentargs_base + s1) * 4 + 4,
236 i386_mov_reg_membase(
237 cd, REG_ITMP1, REG_SP, var->regoff * 4);
238 i386_mov_membase_reg( /* + 4 for return address */
239 cd, REG_SP, (parentargs_base + s1) * 4 + 4 + 4,
241 i386_mov_reg_membase(
242 cd, REG_ITMP1, REG_SP, var->regoff * 4 + 4);
244 /* reuse Stackslotand avoid copying */
245 var->regoff = parentargs_base + s1 + 1;
251 } else { /* floating args */
252 if (!md->params[p].inmemory) { /* register arguments */
253 log_text("There are no float argument registers!");
255 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
256 /* rd->argfltregs[md->params[p].regoff -> var->regoff */
257 } else { /* reg arg -> spilled */
258 /* rd->argfltregs[md->params[p].regoff -> var->regoff * 4 */
261 } else { /* stack arguments */
262 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
265 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
267 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
272 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
274 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
278 } else { /* stack-arg -> spilled */
280 i386_mov_membase_reg(
281 cd, REG_SP, (parentargs_base + s1) * 4 + 4, REG_ITMP1);
282 i386_mov_reg_membase(
283 cd, REG_ITMP1, REG_SP, var->regoff * 4);
286 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
287 i386_fstps_membase(cd, REG_SP, var->regoff * 4);
290 cd, REG_SP, (parentargs_base + s1) * 4 + 4);
291 i386_fstpl_membase(cd, REG_SP, var->regoff * 4);
294 /* reuse Stackslotand avoid copying */
295 var->regoff = parentargs_base + s1 + 1;
302 /* call monitorenter function */
304 #if defined(USE_THREADS)
305 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
308 if (m->flags & ACC_STATIC) {
309 i386_mov_imm_reg(cd, (ptrint) m->class, REG_ITMP1);
310 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s1 * 4);
311 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
312 i386_mov_imm_reg(cd, (ptrint) BUILTIN_staticmonitorenter, REG_ITMP1);
313 i386_call_reg(cd, REG_ITMP1);
316 i386_mov_membase_reg(cd, REG_SP, parentargs_base * 4 + 4, REG_ITMP1);
317 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
318 i386_jcc(cd, I386_CC_Z, 0);
319 codegen_addxnullrefs(cd, cd->mcodeptr);
320 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s1 * 4);
321 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
322 i386_mov_imm_reg(cd, (ptrint) BUILTIN_monitorenter, REG_ITMP1);
323 i386_call_reg(cd, REG_ITMP1);
328 /* copy argument registers to stack and call trace function with pointer
329 to arguments on stack.
334 s1 = INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4 + 4 + parentargs_base * 4;
336 M_ISUB_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
338 /* save temporary registers for leaf methods */
340 for (p = 0; p < INT_TMP_CNT; p++)
341 M_IST(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
343 for (p = 0, l = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
344 t = md->paramtypes[p].type;
346 if (IS_INT_LNG_TYPE(t)) {
347 if (IS_2_WORD_TYPE(t)) {
348 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
349 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
350 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off + 4, REG_ITMP1);
351 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
353 } else if (t == TYPE_ADR) {
355 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
356 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
357 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
358 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
361 i386_mov_membase_reg(cd, REG_SP, s1 + stack_off, EAX);
363 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
364 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
368 if (!IS_2_WORD_TYPE(t)) {
369 i386_flds_membase(cd, REG_SP, s1 + stack_off);
370 i386_fstps_membase(cd, REG_SP, p * 8);
371 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
372 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
375 i386_fldl_membase(cd, REG_SP, s1 + stack_off);
376 i386_fstpl_membase(cd, REG_SP, p * 8);
379 stack_off += (IS_2_WORD_TYPE(t)) ? 8 : 4;
382 /* fill up the remaining arguments */
383 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
384 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
385 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
386 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
389 i386_mov_imm_membase(cd, (ptrint) m, REG_SP, TRACE_ARGS_NUM * 8);
390 i386_mov_imm_reg(cd, (ptrint) builtin_trace_args, REG_ITMP1);
391 i386_call_reg(cd, REG_ITMP1);
393 /* restore temporary registers for leaf methods */
395 for (p = 0; p < INT_TMP_CNT; p++)
396 M_ILD(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
398 M_IADD_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
403 /* end of header generation */
405 /* walk through all basic blocks */
406 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
408 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
410 if (bptr->flags >= BBREACHED) {
412 /* branch resolving */
415 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
416 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
421 /* copy interface registers to their destination */
429 while (src != NULL) {
431 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
432 if (!IS_2_WORD_TYPE(src->type)) {
433 if (bptr->type == BBTYPE_SBR) {
434 /* d = reg_of_var(m, src, REG_ITMP1); */
435 if (!(src->flags & INMEMORY))
441 store_reg_to_var_int(src, d);
443 } else if (bptr->type == BBTYPE_EXH) {
444 /* d = reg_of_var(m, src, REG_ITMP1); */
445 if (!(src->flags & INMEMORY))
449 M_INTMOVE(REG_ITMP1, d);
450 store_reg_to_var_int(src, d);
454 log_text("copy interface registers(EXH, SBR): longs have to be in memory (begin 1)");
463 while (src != NULL) {
465 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
466 if (!IS_2_WORD_TYPE(src->type)) {
467 if (bptr->type == BBTYPE_SBR) {
468 d = reg_of_var(rd, src, REG_ITMP1);
470 store_reg_to_var_int(src, d);
471 } else if (bptr->type == BBTYPE_EXH) {
472 d = reg_of_var(rd, src, REG_ITMP1);
473 M_INTMOVE(REG_ITMP1, d);
474 store_reg_to_var_int(src, d);
478 log_text("copy interface registers: longs have to be in memory (begin 1)");
483 d = reg_of_var(rd, src, REG_ITMP1);
484 if ((src->varkind != STACKVAR)) {
486 if (IS_FLT_DBL_TYPE(s2)) {
487 s1 = rd->interfaces[len][s2].regoff;
488 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
492 if (s2 == TYPE_FLT) {
493 i386_flds_membase(cd, REG_SP, s1 * 4);
496 i386_fldl_membase(cd, REG_SP, s1 * 4);
499 store_reg_to_var_flt(src, d);
502 s1 = rd->interfaces[len][s2].regoff;
503 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
504 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
508 i386_mov_membase_reg(cd, REG_SP, s1 * 4, d);
510 store_reg_to_var_int(src, d);
513 if (rd->interfaces[len][s2].flags & INMEMORY) {
514 M_LNGMEMMOVE(s1, src->regoff);
517 log_text("copy interface registers: longs have to be in memory (begin 2)");
530 /* walk through all instructions */
535 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
536 if (iptr->line != currentline) {
537 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
538 currentline = iptr->line;
541 MCODECHECK(100); /* XXX are 100 bytes enough? */
544 case ICMD_INLINE_START:
545 case ICMD_INLINE_END:
546 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
547 /* EAX: NO ECX: NO EDX: NO */
550 case ICMD_NOP: /* ... ==> ... */
551 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
552 /* EAX: NO ECX: NO EDX: NO */
555 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
556 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
557 /* EAX: NO ECX: NO EDX: NO */
558 if (src->flags & INMEMORY) {
559 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
562 i386_test_reg_reg(cd, src->regoff, src->regoff);
564 i386_jcc(cd, I386_CC_Z, 0);
565 codegen_addxnullrefs(cd, cd->mcodeptr);
568 /* constant operations ************************************************/
570 case ICMD_ICONST: /* ... ==> ..., constant */
571 /* op1 = 0, val.i = constant */
573 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
574 /* EAX: NO ECX: NO EDX: NO */
575 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
576 if (iptr->dst->flags & INMEMORY) {
577 i386_mov_imm_membase(cd, iptr->val.i, REG_SP, iptr->dst->regoff * 4);
580 if (iptr->val.i == 0) {
581 i386_alu_reg_reg(cd, ALU_XOR, d, d);
584 i386_mov_imm_reg(cd, iptr->val.i, d);
589 case ICMD_LCONST: /* ... ==> ..., constant */
590 /* op1 = 0, val.l = constant */
592 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
593 /* EAX: NO ECX: NO EDX: NO */
594 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
595 if (iptr->dst->flags & INMEMORY) {
596 i386_mov_imm_membase(cd, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
597 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
600 log_text("LCONST: longs have to be in memory");
605 case ICMD_FCONST: /* ... ==> ..., constant */
606 /* op1 = 0, val.f = constant */
607 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
608 /* EAX: YES ECX: NO EDX: NO */
610 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
611 if (iptr->val.f == 0.0) {
616 if (iptr->val.i == 0x80000000) {
620 } else if (iptr->val.f == 1.0) {
624 } else if (iptr->val.f == 2.0) {
631 a = dseg_addfloat(cd, iptr->val.f);
632 i386_mov_imm_reg(cd, 0, REG_ITMP1);
633 dseg_adddata(cd, cd->mcodeptr);
634 i386_flds_membase(cd, REG_ITMP1, a);
637 store_reg_to_var_flt(iptr->dst, d);
640 case ICMD_DCONST: /* ... ==> ..., constant */
641 /* op1 = 0, val.d = constant */
642 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
643 /* EAX: YES ECX: NO EDX: NO */
645 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
646 if (iptr->val.d == 0.0) {
651 if (iptr->val.l == 0x8000000000000000LL) {
655 } else if (iptr->val.d == 1.0) {
659 } else if (iptr->val.d == 2.0) {
666 a = dseg_adddouble(cd, iptr->val.d);
667 i386_mov_imm_reg(cd, 0, REG_ITMP1);
668 dseg_adddata(cd, cd->mcodeptr);
669 i386_fldl_membase(cd, REG_ITMP1, a);
672 store_reg_to_var_flt(iptr->dst, d);
675 case ICMD_ACONST: /* ... ==> ..., constant */
676 /* op1 = 0, val.a = constant */
677 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
678 /* EAX: YES ECX: NO EDX: NO */
680 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
681 if (iptr->dst->flags & INMEMORY) {
682 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, iptr->dst->regoff * 4);
685 if ((s4) iptr->val.a == 0) {
686 i386_alu_reg_reg(cd, ALU_XOR, d, d);
689 i386_mov_imm_reg(cd, (s4) iptr->val.a, d);
695 /* load/store operations **********************************************/
697 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
698 case ICMD_ALOAD: /* op1 = local variable */
699 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
700 /* EAX: YES ECX: NO EDX: NO */
702 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
703 if ((iptr->dst->varkind == LOCALVAR) &&
704 (iptr->dst->varnum == iptr->op1)) {
707 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
708 if (iptr->dst->flags & INMEMORY) {
709 if (var->flags & INMEMORY) {
710 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP1);
711 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
714 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 4);
718 if (var->flags & INMEMORY) {
719 i386_mov_membase_reg(cd, REG_SP, var->regoff * 4, iptr->dst->regoff);
722 M_INTMOVE(var->regoff, iptr->dst->regoff);
727 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
728 /* op1 = local variable */
729 /* REG_RES Register usage: see lsra.inc icmd_uses_tmp */
730 /* EAX: NO ECX: NO EDX: NO */
732 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
733 if ((iptr->dst->varkind == LOCALVAR) &&
734 (iptr->dst->varnum == iptr->op1)) {
737 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
738 if (iptr->dst->flags & INMEMORY) {
739 if (var->flags & INMEMORY) {
740 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
743 log_text("LLOAD: longs have to be in memory");
748 log_text("LLOAD: longs have to be in memory");
753 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
754 /* op1 = local variable */
755 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
756 /* EAX: NO ECX: NO EDX: NO */
758 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
759 if ((iptr->dst->varkind == LOCALVAR) &&
760 (iptr->dst->varnum == iptr->op1)) {
763 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
764 if (var->flags & INMEMORY) {
765 i386_flds_membase(cd, REG_SP, var->regoff * 4);
768 i386_fld_reg(cd, var->regoff + fpu_st_offset);
771 store_reg_to_var_flt(iptr->dst, d);
774 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
775 /* op1 = local variable */
776 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
777 /* EAX: NO ECX: NO EDX: NO */
779 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
780 if ((iptr->dst->varkind == LOCALVAR) &&
781 (iptr->dst->varnum == iptr->op1)) {
784 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
785 if (var->flags & INMEMORY) {
786 i386_fldl_membase(cd, REG_SP, var->regoff * 4);
789 i386_fld_reg(cd, var->regoff + fpu_st_offset);
792 store_reg_to_var_flt(iptr->dst, d);
795 case ICMD_ISTORE: /* ..., value ==> ... */
796 case ICMD_ASTORE: /* op1 = local variable */
797 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
798 /* EAX: YES ECX: NO EDX: NO */
800 if ((src->varkind == LOCALVAR) &&
801 (src->varnum == iptr->op1)) {
804 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
805 if (var->flags & INMEMORY) {
806 if (src->flags & INMEMORY) {
807 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
808 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 4);
811 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 4);
815 var_to_reg_int(s1, src, var->regoff);
816 M_INTMOVE(s1, var->regoff);
820 case ICMD_LSTORE: /* ..., value ==> ... */
821 /* op1 = local variable */
822 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
823 /* EAX: NO ECX: NO EDX: NO */
825 if ((src->varkind == LOCALVAR) &&
826 (src->varnum == iptr->op1)) {
829 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
830 if (var->flags & INMEMORY) {
831 if (src->flags & INMEMORY) {
832 M_LNGMEMMOVE(src->regoff, var->regoff);
835 log_text("LSTORE: longs have to be in memory");
840 log_text("LSTORE: longs have to be in memory");
845 case ICMD_FSTORE: /* ..., value ==> ... */
846 /* op1 = local variable */
847 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
848 /* EAX: NO ECX: NO EDX: NO */
850 if ((src->varkind == LOCALVAR) &&
851 (src->varnum == iptr->op1)) {
854 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
855 if (var->flags & INMEMORY) {
856 var_to_reg_flt(s1, src, REG_FTMP1);
857 i386_fstps_membase(cd, REG_SP, var->regoff * 4);
860 var_to_reg_flt(s1, src, var->regoff);
861 /* M_FLTMOVE(s1, var->regoff); */
862 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
867 case ICMD_DSTORE: /* ..., value ==> ... */
868 /* op1 = local variable */
869 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
870 /* EAX: NO ECX: NO EDX: NO */
872 if ((src->varkind == LOCALVAR) &&
873 (src->varnum == iptr->op1)) {
876 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
877 if (var->flags & INMEMORY) {
878 var_to_reg_flt(s1, src, REG_FTMP1);
879 i386_fstpl_membase(cd, REG_SP, var->regoff * 4);
882 var_to_reg_flt(s1, src, var->regoff);
883 /* M_FLTMOVE(s1, var->regoff); */
884 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
890 /* pop/dup/swap operations ********************************************/
892 /* attention: double and longs are only one entry in CACAO ICMDs */
894 case ICMD_POP: /* ..., value ==> ... */
895 case ICMD_POP2: /* ..., value, value ==> ... */
896 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
897 /* EAX: NO ECX: NO EDX: NO */
900 case ICMD_DUP: /* ..., a ==> ..., a, a */
901 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
902 /* EAX: YES ECX: NO EDX: NO */
903 M_COPY(src, iptr->dst);
906 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
907 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
908 /* EAX: YES ECX: NO EDX: NO */
910 M_COPY(src, iptr->dst);
911 M_COPY(src->prev, iptr->dst->prev);
914 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
915 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
916 /* EAX: YES ECX: NO EDX: NO */
918 M_COPY(src, iptr->dst);
919 M_COPY(src->prev, iptr->dst->prev);
920 M_COPY(iptr->dst, iptr->dst->prev->prev);
923 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
925 M_COPY(src, iptr->dst);
926 M_COPY(src->prev, iptr->dst->prev);
927 M_COPY(src->prev->prev, iptr->dst->prev->prev);
928 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
931 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
932 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
933 /* EAX: YES ECX: NO EDX: NO */
935 M_COPY(src, iptr->dst);
936 M_COPY(src->prev, iptr->dst->prev);
937 M_COPY(src->prev->prev, iptr->dst->prev->prev);
938 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
939 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev);
942 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
943 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
944 /* EAX: YES ECX: NO EDX: NO */
946 M_COPY(src, iptr->dst);
947 M_COPY(src->prev, iptr->dst->prev);
948 M_COPY(src->prev->prev, iptr->dst->prev->prev);
949 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
950 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
951 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
954 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
955 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
956 /* EAX: YES ECX: NO EDX: NO */
958 M_COPY(src, iptr->dst->prev);
959 M_COPY(src->prev, iptr->dst);
963 /* integer operations *************************************************/
965 case ICMD_INEG: /* ..., value ==> ..., - value */
966 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
967 /* EAX: YES ECX: NO EDX: NO */
969 d = reg_of_var(rd, iptr->dst, REG_NULL);
970 if (iptr->dst->flags & INMEMORY) {
971 if (src->flags & INMEMORY) {
972 if (src->regoff == iptr->dst->regoff) {
973 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
976 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
977 i386_neg_reg(cd, REG_ITMP1);
978 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
982 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
983 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
987 if (src->flags & INMEMORY) {
988 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
989 i386_neg_reg(cd, iptr->dst->regoff);
992 M_INTMOVE(src->regoff, iptr->dst->regoff);
993 i386_neg_reg(cd, iptr->dst->regoff);
998 case ICMD_LNEG: /* ..., value ==> ..., - value */
999 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1000 /* EAX: YES ECX: NO EDX: NO */
1002 d = reg_of_var(rd, iptr->dst, REG_NULL);
1003 if (iptr->dst->flags & INMEMORY) {
1004 if (src->flags & INMEMORY) {
1005 if (src->regoff == iptr->dst->regoff) {
1006 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4);
1007 i386_alu_imm_membase(cd, ALU_ADC, 0, REG_SP, iptr->dst->regoff * 4 + 4);
1008 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 4 + 4);
1011 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1012 i386_neg_reg(cd, REG_ITMP1);
1013 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1014 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1015 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP1);
1016 i386_neg_reg(cd, REG_ITMP1);
1017 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1023 case ICMD_I2L: /* ..., value ==> ..., value */
1024 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1025 /* EAX: YES ECX: NO EDX: YES */
1027 d = reg_of_var(rd, iptr->dst, REG_NULL);
1028 if (iptr->dst->flags & INMEMORY) {
1029 if (src->flags & INMEMORY) {
1030 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, EAX);
1032 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1033 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1036 M_INTMOVE(src->regoff, EAX);
1038 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1039 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1044 case ICMD_L2I: /* ..., value ==> ..., value */
1045 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1046 /* EAX: YES ECX: NO EDX: NO */
1048 d = reg_of_var(rd, iptr->dst, REG_NULL);
1049 if (iptr->dst->flags & INMEMORY) {
1050 if (src->flags & INMEMORY) {
1051 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1052 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1056 if (src->flags & INMEMORY) {
1057 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1062 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1063 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1064 /* EAX: YES ECX: NO EDX: NO */
1066 d = reg_of_var(rd, iptr->dst, REG_NULL);
1067 if (iptr->dst->flags & INMEMORY) {
1068 if (src->flags & INMEMORY) {
1069 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1070 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1071 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1072 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1075 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1076 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 4);
1077 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 4);
1081 if (src->flags & INMEMORY) {
1082 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1083 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1084 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1087 M_INTMOVE(src->regoff, iptr->dst->regoff);
1088 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1089 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1094 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1095 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1096 /* EAX: YES ECX: NO EDX: NO */
1098 d = reg_of_var(rd, iptr->dst, REG_NULL);
1099 if (iptr->dst->flags & INMEMORY) {
1100 if (src->flags & INMEMORY) {
1101 if (src->regoff == iptr->dst->regoff) {
1102 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1105 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1106 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, REG_ITMP1);
1107 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1111 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1112 i386_alu_imm_membase(cd, ALU_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 4);
1116 if (src->flags & INMEMORY) {
1117 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1118 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1121 M_INTMOVE(src->regoff, iptr->dst->regoff);
1122 i386_alu_imm_reg(cd, ALU_AND, 0x0000ffff, iptr->dst->regoff);
1127 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1128 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1129 /* EAX: YES ECX: NO EDX: NO */
1131 d = reg_of_var(rd, iptr->dst, REG_NULL);
1132 if (iptr->dst->flags & INMEMORY) {
1133 if (src->flags & INMEMORY) {
1134 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1135 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1136 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1137 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1140 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 4);
1141 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 4);
1142 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 4);
1146 if (src->flags & INMEMORY) {
1147 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1148 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1149 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1152 M_INTMOVE(src->regoff, iptr->dst->regoff);
1153 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1154 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1160 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1161 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1162 /* EAX: S|YES ECX: NO EDX: NO */
1164 d = reg_of_var(rd, iptr->dst, REG_NULL);
1165 i386_emit_ialu(cd, ALU_ADD, src, iptr);
1168 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1169 /* val.i = constant */
1170 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1171 /* EAX: NO ECX: NO EDX: NO */
1173 d = reg_of_var(rd, iptr->dst, REG_NULL);
1174 i386_emit_ialuconst(cd, ALU_ADD, src, iptr);
1177 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1178 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1179 /* EAX: S|YES ECX: NO EDX: NO */
1181 d = reg_of_var(rd, iptr->dst, REG_NULL);
1182 if (iptr->dst->flags & INMEMORY) {
1183 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1184 if (src->regoff == iptr->dst->regoff) {
1185 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1186 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1187 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1188 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1190 } else if (src->prev->regoff == iptr->dst->regoff) {
1191 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1192 i386_alu_reg_membase(cd, ALU_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1193 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1194 i386_alu_reg_membase(cd, ALU_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1197 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1198 i386_alu_membase_reg(cd, ALU_ADD, REG_SP, src->regoff * 4, REG_ITMP1);
1199 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1200 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1201 i386_alu_membase_reg(cd, ALU_ADC, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1202 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1209 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1210 /* val.l = constant */
1211 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1212 /* EAX: NO ECX: NO EDX: NO */
1213 /* else path can never happen? longs stay in memory! */
1215 d = reg_of_var(rd, iptr->dst, REG_NULL);
1216 if (iptr->dst->flags & INMEMORY) {
1217 if (src->flags & INMEMORY) {
1218 if (src->regoff == iptr->dst->regoff) {
1219 i386_alu_imm_membase(cd, ALU_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1220 i386_alu_imm_membase(cd, ALU_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1223 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1224 i386_alu_imm_reg(cd, ALU_ADD, iptr->val.l, REG_ITMP1);
1225 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1226 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1227 i386_alu_imm_reg(cd, ALU_ADC, iptr->val.l >> 32, REG_ITMP1);
1228 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1234 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1235 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1236 /* EAX: S|YES ECX: NO EDX: NO */
1238 d = reg_of_var(rd, iptr->dst, REG_NULL);
1239 if (iptr->dst->flags & INMEMORY) {
1240 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1241 if (src->prev->regoff == iptr->dst->regoff) {
1242 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1243 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1246 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1247 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1248 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1251 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1252 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1253 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1254 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1256 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1257 if (src->prev->regoff == iptr->dst->regoff) {
1258 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1261 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1262 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1263 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1267 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 4);
1268 i386_alu_reg_membase(cd, ALU_SUB, src->regoff, REG_SP, iptr->dst->regoff * 4);
1272 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1273 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1274 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1276 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1277 M_INTMOVE(src->prev->regoff, d);
1278 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, d);
1280 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1281 /* workaround for reg alloc */
1282 if (src->regoff == iptr->dst->regoff) {
1283 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1284 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1285 M_INTMOVE(REG_ITMP1, d);
1288 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, d);
1289 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1293 /* workaround for reg alloc */
1294 if (src->regoff == iptr->dst->regoff) {
1295 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1296 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, REG_ITMP1);
1297 M_INTMOVE(REG_ITMP1, d);
1300 M_INTMOVE(src->prev->regoff, d);
1301 i386_alu_reg_reg(cd, ALU_SUB, src->regoff, d);
1307 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1308 /* val.i = constant */
1309 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1310 /* EAX: NO ECX: NO EDX: NO */
1312 d = reg_of_var(rd, iptr->dst, REG_NULL);
1313 i386_emit_ialuconst(cd, ALU_SUB, src, iptr);
1316 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1317 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1318 /* EAX: S|YES ECX: NO EDX: NO */
1320 d = reg_of_var(rd, iptr->dst, REG_NULL);
1321 if (iptr->dst->flags & INMEMORY) {
1322 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1323 if (src->prev->regoff == iptr->dst->regoff) {
1324 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1325 i386_alu_reg_membase(cd, ALU_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1326 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1327 i386_alu_reg_membase(cd, ALU_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1330 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1331 i386_alu_membase_reg(cd, ALU_SUB, REG_SP, src->regoff * 4, REG_ITMP1);
1332 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1333 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
1334 i386_alu_membase_reg(cd, ALU_SBB, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1335 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1341 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1342 /* val.l = constant */
1343 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1344 /* EAX: NO ECX: NO EDX: NO */
1345 /* else path can never happen? longs stay in memory! */
1347 d = reg_of_var(rd, iptr->dst, REG_NULL);
1348 if (iptr->dst->flags & INMEMORY) {
1349 if (src->flags & INMEMORY) {
1350 if (src->regoff == iptr->dst->regoff) {
1351 i386_alu_imm_membase(cd, ALU_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 4);
1352 i386_alu_imm_membase(cd, ALU_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 4 + 4);
1355 /* TODO: could be size optimized with lea -- see gcc output */
1356 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1357 i386_alu_imm_reg(cd, ALU_SUB, iptr->val.l, REG_ITMP1);
1358 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1359 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
1360 i386_alu_imm_reg(cd, ALU_SBB, iptr->val.l >> 32, REG_ITMP1);
1361 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4 + 4);
1367 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1368 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1369 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1371 d = reg_of_var(rd, iptr->dst, REG_NULL);
1372 if (iptr->dst->flags & INMEMORY) {
1373 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1374 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1375 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1376 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1378 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1379 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1380 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1381 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1383 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1384 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1385 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1386 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1389 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1390 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1391 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1395 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1396 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1397 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1399 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1400 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1401 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, iptr->dst->regoff);
1403 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1404 M_INTMOVE(src->regoff, iptr->dst->regoff);
1405 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 4, iptr->dst->regoff);
1408 if (src->regoff == iptr->dst->regoff) {
1409 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1412 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1413 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1419 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1420 /* val.i = constant */
1421 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1422 /* EAX: YES ECX: NO EDX: NO OUTPUT: EAX*/ /* EDX really not destroyed by IMUL? */
1424 d = reg_of_var(rd, iptr->dst, REG_NULL);
1425 if (iptr->dst->flags & INMEMORY) {
1426 if (src->flags & INMEMORY) {
1427 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, REG_ITMP1);
1428 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1431 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1432 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1436 if (src->flags & INMEMORY) {
1437 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 4, iptr->dst->regoff);
1440 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1445 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1446 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1447 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1449 d = reg_of_var(rd, iptr->dst, REG_NULL);
1450 if (iptr->dst->flags & INMEMORY) {
1451 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1452 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX); /* mem -> EAX */
1453 /* optimize move EAX -> REG_ITMP3 is slower??? */
1454 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1455 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1457 /* TODO: optimize move EAX -> REG_ITMP3 */
1458 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); /* mem -> ITMP3 */
1459 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1460 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1462 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP2); /* mem -> ITMP3 */
1463 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1465 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1466 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1467 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1472 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1473 /* val.l = constant */
1474 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1475 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
1477 d = reg_of_var(rd, iptr->dst, REG_NULL);
1478 if (iptr->dst->flags & INMEMORY) {
1479 if (src->flags & INMEMORY) {
1480 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1481 i386_mul_membase(cd, REG_SP, src->regoff * 4); /* mem * EAX -> EDX:EAX */
1482 /* TODO: optimize move EAX -> REG_ITMP3 */
1483 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1484 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1486 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1487 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1488 i386_imul_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1490 i386_alu_reg_reg(cd, ALU_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1491 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1492 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4 + 4);
1497 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1498 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1499 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX */
1501 d = reg_of_var(rd, iptr->dst, REG_NULL);
1502 var_to_reg_int(s1, src, REG_ITMP2);
1504 if (src->prev->flags & INMEMORY) {
1505 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1508 M_INTMOVE(src->prev->regoff, EAX);
1511 /* check as described in jvm spec */
1513 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1514 i386_jcc(cd, I386_CC_NE, 3 + 6);
1515 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1516 i386_jcc(cd, I386_CC_E, 1 + 2);
1519 i386_idiv_reg(cd, s1);
1521 if (iptr->dst->flags & INMEMORY) {
1522 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 4);
1525 M_INTMOVE(EAX, iptr->dst->regoff);
1529 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1530 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1531 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EDX */
1534 d = reg_of_var(rd, iptr->dst, REG_NULL);
1535 var_to_reg_int(s1, src, REG_ITMP2);
1537 if (src->prev->flags & INMEMORY) {
1538 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, EAX);
1541 M_INTMOVE(src->prev->regoff, EAX);
1544 /* check as described in jvm spec */
1546 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, EAX);
1547 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1548 i386_alu_reg_reg(cd, ALU_XOR, EDX, EDX);
1549 i386_alu_imm_reg(cd, ALU_CMP, -1, s1);
1550 i386_jcc(cd, I386_CC_E, 1 + 2);
1553 i386_idiv_reg(cd, s1);
1555 if (iptr->dst->flags & INMEMORY) {
1556 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 4);
1559 M_INTMOVE(EDX, iptr->dst->regoff);
1563 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1564 /* val.i = constant */
1565 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1566 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL */
1568 /* TODO: optimize for `/ 2' */
1569 var_to_reg_int(s1, src, REG_ITMP1);
1570 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1573 i386_test_reg_reg(cd, d, d);
1575 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1576 i386_jcc(cd, I386_CC_NS, a);
1577 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, d);
1579 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1580 store_reg_to_var_int(iptr->dst, d);
1583 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1584 /* val.i = constant */
1585 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1586 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1588 var_to_reg_int(s1, src, REG_ITMP1);
1589 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1591 M_INTMOVE(s1, REG_ITMP1);
1598 CALCIMMEDIATEBYTES(a, iptr->val.i);
1601 /* TODO: optimize */
1603 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1604 i386_test_reg_reg(cd, s1, s1);
1605 i386_jcc(cd, I386_CC_GE, a);
1606 i386_mov_reg_reg(cd, s1, d);
1607 i386_neg_reg(cd, d);
1608 i386_alu_imm_reg(cd, ALU_AND, iptr->val.i, d);
1609 i386_neg_reg(cd, d);
1611 /* M_INTMOVE(s1, EAX); */
1612 /* i386_cltd(cd); */
1613 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1614 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1615 /* i386_alu_reg_reg(cd, ALU_AND, iptr->val.i, EAX); */
1616 /* i386_alu_reg_reg(cd, ALU_XOR, EDX, EAX); */
1617 /* i386_alu_reg_reg(cd, ALU_SUB, EDX, EAX); */
1618 /* M_INTMOVE(EAX, d); */
1620 /* i386_alu_reg_reg(cd, ALU_XOR, d, d); */
1621 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1622 /* i386_shrd_reg_reg(cd, s1, d); */
1623 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1625 store_reg_to_var_int(iptr->dst, d);
1628 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1629 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1631 d = reg_of_var(rd, iptr->dst, REG_NULL);
1632 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4);
1633 M_OR_MEMBASE(REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1636 codegen_addxdivrefs(cd, cd->mcodeptr);
1641 M_ILD(REG_ITMP1, REG_SP, src->prev->regoff * 4);
1642 M_ILD(REG_ITMP2, REG_SP, src->prev->regoff * 4 + 4);
1643 M_IST(REG_ITMP1, REG_SP, 0 * 4);
1644 M_IST(REG_ITMP2, REG_SP, 0 * 4 + 4);
1646 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
1647 M_ILD(REG_ITMP2, REG_SP, src->regoff * 4 + 4);
1648 M_IST(REG_ITMP1, REG_SP, 2 * 4);
1649 M_IST(REG_ITMP2, REG_SP, 2 * 4 + 4);
1651 M_MOV_IMM((ptrint) bte->fp, REG_ITMP3);
1654 M_IST(REG_RESULT, REG_SP, iptr->dst->regoff * 4);
1655 M_IST(REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
1658 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1659 /* val.i = constant */
1660 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1661 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1663 d = reg_of_var(rd, iptr->dst, REG_NULL);
1664 if (iptr->dst->flags & INMEMORY) {
1665 if (src->flags & INMEMORY) {
1667 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1669 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1670 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1672 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1673 i386_jcc(cd, I386_CC_NS, a);
1674 i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1675 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1676 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1677 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1679 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1680 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1685 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1686 /* val.l = constant */
1687 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1688 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL */
1690 d = reg_of_var(rd, iptr->dst, REG_NULL);
1691 if (iptr->dst->flags & INMEMORY) {
1692 if (src->flags & INMEMORY) {
1693 /* Intel algorithm -- does not work, because constant is wrong */
1694 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1); */
1695 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3); */
1697 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1698 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1699 /* i386_jcc(cd, I386_CC_NS, offset); */
1700 /* i386_alu_imm_reg(cd, ALU_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1701 /* i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP3); */
1703 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1704 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1705 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1707 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1709 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1); */
1710 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2); */
1711 /* i386_alu_reg_reg(cd, ALU_SBB, REG_ITMP3, REG_ITMP2); */
1713 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1714 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1716 /* Alpha algorithm */
1718 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
1720 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4 + 4);
1726 /* TODO: hmm, don't know if this is always correct */
1728 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1730 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1736 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1737 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1739 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1740 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1741 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4 + 4);
1742 i386_jcc(cd, I386_CC_GE, a);
1744 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1745 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1747 i386_neg_reg(cd, REG_ITMP1);
1748 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1749 i386_neg_reg(cd, REG_ITMP2);
1751 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1752 i386_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1754 i386_neg_reg(cd, REG_ITMP1);
1755 i386_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1756 i386_neg_reg(cd, REG_ITMP2);
1758 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1759 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1764 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1765 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1766 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1768 d = reg_of_var(rd, iptr->dst, REG_NULL);
1769 i386_emit_ishift(cd, I386_SHL, src, iptr);
1772 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1773 /* val.i = constant */
1774 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1775 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1777 d = reg_of_var(rd, iptr->dst, REG_NULL);
1778 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1781 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1782 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1783 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1785 d = reg_of_var(rd, iptr->dst, REG_NULL);
1786 i386_emit_ishift(cd, I386_SAR, src, iptr);
1789 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1790 /* val.i = constant */
1791 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1792 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1794 d = reg_of_var(rd, iptr->dst, REG_NULL);
1795 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1798 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1799 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1800 /* EAX: YES ECX: D|S|YES EDX: NO OUTPUT: REG_NULL*/
1802 d = reg_of_var(rd, iptr->dst, REG_NULL);
1803 i386_emit_ishift(cd, I386_SHR, src, iptr);
1806 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1807 /* val.i = constant */
1808 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1809 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
1811 d = reg_of_var(rd, iptr->dst, REG_NULL);
1812 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1815 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1816 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1817 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
1819 d = reg_of_var(rd, iptr->dst, REG_NULL);
1820 if (iptr->dst->flags & INMEMORY ){
1821 if (src->prev->flags & INMEMORY) {
1822 /* if (src->prev->regoff == iptr->dst->regoff) { */
1823 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1825 /* if (src->flags & INMEMORY) { */
1826 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1828 /* M_INTMOVE(src->regoff, ECX); */
1831 /* i386_test_imm_reg(cd, 32, ECX); */
1832 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1833 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1834 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1); */
1836 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 4 + 4); */
1837 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 4); */
1840 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1841 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1843 if (src->flags & INMEMORY) {
1844 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1846 M_INTMOVE(src->regoff, ECX);
1849 i386_test_imm_reg(cd, 32, ECX);
1850 i386_jcc(cd, I386_CC_E, 2 + 2);
1851 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1852 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1854 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1855 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1856 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1857 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
1863 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1864 /* val.i = constant */
1865 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1866 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1868 d = reg_of_var(rd, iptr->dst, REG_NULL);
1869 if (iptr->dst->flags & INMEMORY ) {
1870 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1871 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1873 if (iptr->val.i & 0x20) {
1874 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1875 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
1876 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1879 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1880 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1883 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1884 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1888 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1889 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1890 /* EAX: S|YES ECX: YES S|EDX: YES OUTPUT: REG_NULL*/
1892 d = reg_of_var(rd, 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 /* TODO: optimize */
1897 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1898 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
1900 /* if (src->flags & INMEMORY) { */
1901 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1903 /* M_INTMOVE(src->regoff, ECX); */
1906 /* i386_test_imm_reg(cd, 32, ECX); */
1907 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1908 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1909 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1911 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1912 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1913 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1914 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1917 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1918 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1920 if (src->flags & INMEMORY) {
1921 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
1923 M_INTMOVE(src->regoff, ECX);
1926 i386_test_imm_reg(cd, 32, ECX);
1927 i386_jcc(cd, I386_CC_E, 2 + 3);
1928 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1929 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1931 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1932 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1933 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1934 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
1940 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1941 /* val.i = constant */
1942 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1943 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
1945 d = reg_of_var(rd, iptr->dst, REG_NULL);
1946 if (iptr->dst->flags & INMEMORY ) {
1947 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1948 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1950 if (iptr->val.i & 0x20) {
1951 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1952 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
1953 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1956 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1957 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1960 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1961 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1965 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1966 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
1967 /* EAX: S|YES ECX: YES EDX: S|YES OUTPUT: REG_NULL*/
1969 d = reg_of_var(rd, iptr->dst, REG_NULL);
1970 if (iptr->dst->flags & INMEMORY ){
1971 if (src->prev->flags & INMEMORY) {
1972 /* if (src->prev->regoff == iptr->dst->regoff) { */
1973 /* TODO: optimize */
1974 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1); */
1975 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2); */
1977 /* if (src->flags & INMEMORY) { */
1978 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX); */
1980 /* M_INTMOVE(src->regoff, ECX); */
1983 /* i386_test_imm_reg(cd, 32, ECX); */
1984 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1985 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1986 /* i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2); */
1988 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1989 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
1990 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4); */
1991 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4); */
1994 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
1995 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP3);
1997 if (src->flags & INMEMORY) {
1998 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, ECX);
2000 M_INTMOVE(src->regoff, ECX);
2003 i386_test_imm_reg(cd, 32, ECX);
2004 i386_jcc(cd, I386_CC_E, 2 + 2);
2005 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2006 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP3, REG_ITMP3);
2008 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
2009 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
2010 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2011 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2017 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
2018 /* val.l = constant */
2019 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2020 /* EAX: YES ECX: YES EDX: NO OUTPUT: REG_NULL*/
2022 d = reg_of_var(rd, iptr->dst, REG_NULL);
2023 if (iptr->dst->flags & INMEMORY ) {
2024 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
2025 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
2027 if (iptr->val.i & 0x20) {
2028 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
2029 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
2030 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2033 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2034 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
2037 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
2038 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
2042 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2043 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2044 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2046 d = reg_of_var(rd, iptr->dst, REG_NULL);
2047 i386_emit_ialu(cd, ALU_AND, src, iptr);
2050 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
2051 /* val.i = constant */
2052 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2053 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2055 d = reg_of_var(rd, iptr->dst, REG_NULL);
2056 i386_emit_ialuconst(cd, ALU_AND, src, iptr);
2059 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2060 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2061 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2063 d = reg_of_var(rd, iptr->dst, REG_NULL);
2064 i386_emit_lalu(cd, ALU_AND, src, iptr);
2067 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
2068 /* val.l = constant */
2069 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2070 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2072 d = reg_of_var(rd, iptr->dst, REG_NULL);
2073 i386_emit_laluconst(cd, ALU_AND, src, iptr);
2076 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2077 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2078 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2080 d = reg_of_var(rd, iptr->dst, REG_NULL);
2081 i386_emit_ialu(cd, ALU_OR, src, iptr);
2084 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2085 /* val.i = constant */
2086 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2087 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2089 d = reg_of_var(rd, iptr->dst, REG_NULL);
2090 i386_emit_ialuconst(cd, ALU_OR, src, iptr);
2093 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2094 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2095 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2097 d = reg_of_var(rd, iptr->dst, REG_NULL);
2098 i386_emit_lalu(cd, ALU_OR, src, iptr);
2101 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2102 /* val.l = constant */
2103 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2104 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2106 d = reg_of_var(rd, iptr->dst, REG_NULL);
2107 i386_emit_laluconst(cd, ALU_OR, src, iptr);
2110 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2111 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2112 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2114 d = reg_of_var(rd, iptr->dst, REG_NULL);
2115 i386_emit_ialu(cd, ALU_XOR, src, iptr);
2118 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2119 /* val.i = constant */
2120 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2121 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2123 d = reg_of_var(rd, iptr->dst, REG_NULL);
2124 i386_emit_ialuconst(cd, ALU_XOR, src, iptr);
2127 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2128 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2129 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2131 d = reg_of_var(rd, iptr->dst, REG_NULL);
2132 i386_emit_lalu(cd, ALU_XOR, src, iptr);
2135 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2136 /* val.l = constant */
2137 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2138 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2140 d = reg_of_var(rd, iptr->dst, REG_NULL);
2141 i386_emit_laluconst(cd, ALU_XOR, src, iptr);
2144 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2145 /* op1 = variable, val.i = constant */
2146 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2147 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2149 var = &(rd->locals[iptr->op1][TYPE_INT]);
2150 if (var->flags & INMEMORY) {
2151 i386_alu_imm_membase(cd, ALU_ADD, iptr->val.i, REG_SP, var->regoff * 4);
2154 /* `inc reg' is slower on p4's (regarding to ia32 */
2155 /* optimization reference manual and benchmarks) and as fast */
2157 i386_alu_imm_reg(cd, ALU_ADD, iptr->val.i, var->regoff);
2162 /* floating operations ************************************************/
2164 #define ROUND_TO_SINGLE \
2165 i386_fstps_membase(cd, REG_SP, -8); \
2166 i386_flds_membase(cd, REG_SP, -8);
2168 #define ROUND_TO_DOUBLE \
2169 i386_fstpl_membase(cd, REG_SP, -8); \
2170 i386_fldl_membase(cd, REG_SP, -8);
2172 #define FPU_SET_24BIT_MODE \
2173 if (!fpu_in_24bit_mode) { \
2174 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2175 fpu_in_24bit_mode = 1; \
2178 #define FPU_SET_53BIT_MODE \
2179 if (fpu_in_24bit_mode) { \
2180 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2181 fpu_in_24bit_mode = 0; \
2184 #define ROUND_TO_SINGLE
2185 #define ROUND_TO_DOUBLE
2186 #define FPU_SET_24BIT_MODE
2187 #define FPU_SET_53BIT_MODE
2189 case ICMD_FNEG: /* ..., value ==> ..., - value */
2190 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2191 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2194 var_to_reg_flt(s1, src, REG_FTMP1);
2195 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2197 store_reg_to_var_flt(iptr->dst, d);
2200 case ICMD_DNEG: /* ..., value ==> ..., - value */
2201 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2202 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2205 var_to_reg_flt(s1, src, REG_FTMP1);
2206 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2208 store_reg_to_var_flt(iptr->dst, d);
2211 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2212 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2213 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2216 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2217 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2218 var_to_reg_flt(s2, src, REG_FTMP2);
2221 store_reg_to_var_flt(iptr->dst, d);
2224 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2225 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2226 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2229 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2230 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2231 var_to_reg_flt(s2, src, REG_FTMP2);
2234 store_reg_to_var_flt(iptr->dst, d);
2237 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2238 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2239 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2242 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2243 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2244 var_to_reg_flt(s2, src, REG_FTMP2);
2247 store_reg_to_var_flt(iptr->dst, d);
2250 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2251 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2252 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2255 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2256 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2257 var_to_reg_flt(s2, src, REG_FTMP2);
2260 store_reg_to_var_flt(iptr->dst, d);
2263 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2264 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2265 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2268 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2269 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2270 var_to_reg_flt(s2, src, REG_FTMP2);
2274 store_reg_to_var_flt(iptr->dst, d);
2277 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2278 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2279 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2282 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2283 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2285 /* i386_fldt_mem(cd, subnormal_bias1); */
2286 /* i386_fmulp(cd); */
2288 var_to_reg_flt(s2, src, REG_FTMP2);
2293 /* i386_fldt_mem(cd, subnormal_bias2); */
2294 /* i386_fmulp(cd); */
2296 store_reg_to_var_flt(iptr->dst, d);
2299 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2300 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2301 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2304 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2305 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2306 var_to_reg_flt(s2, src, REG_FTMP2);
2310 store_reg_to_var_flt(iptr->dst, d);
2313 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2314 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2315 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2318 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2319 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2321 /* i386_fldt_mem(cd, subnormal_bias1); */
2322 /* i386_fmulp(cd); */
2324 var_to_reg_flt(s2, src, REG_FTMP2);
2329 /* i386_fldt_mem(cd, subnormal_bias2); */
2330 /* i386_fmulp(cd); */
2332 store_reg_to_var_flt(iptr->dst, d);
2335 case ICMD_FREM: /* ..., 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 /* exchanged to skip fxch */
2341 var_to_reg_flt(s2, src, REG_FTMP2);
2342 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2343 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2344 /* i386_fxch(cd); */
2349 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2350 store_reg_to_var_flt(iptr->dst, d);
2351 i386_ffree_reg(cd, 0);
2356 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2357 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2358 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2361 /* exchanged to skip fxch */
2362 var_to_reg_flt(s2, src, REG_FTMP2);
2363 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2364 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2365 /* i386_fxch(cd); */
2370 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2371 store_reg_to_var_flt(iptr->dst, d);
2372 i386_ffree_reg(cd, 0);
2377 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2378 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2379 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2380 /* EAX: S|YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2382 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2383 if (src->flags & INMEMORY) {
2384 i386_fildl_membase(cd, REG_SP, src->regoff * 4);
2388 a = dseg_adds4(cd, 0);
2389 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2390 dseg_adddata(cd, cd->mcodeptr);
2391 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, a);
2392 i386_fildl_membase(cd, REG_ITMP1, a);
2395 store_reg_to_var_flt(iptr->dst, d);
2398 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2399 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2400 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2401 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2403 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2404 if (src->flags & INMEMORY) {
2405 i386_fildll_membase(cd, REG_SP, src->regoff * 4);
2409 log_text("L2F: longs have to be in memory");
2412 store_reg_to_var_flt(iptr->dst, d);
2415 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2416 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2417 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2419 var_to_reg_flt(s1, src, REG_FTMP1);
2420 d = reg_of_var(rd, iptr->dst, REG_NULL);
2422 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2423 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2424 dseg_adddata(cd, cd->mcodeptr);
2425 i386_fldcw_membase(cd, REG_ITMP1, a);
2427 if (iptr->dst->flags & INMEMORY) {
2428 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2431 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2432 i386_fldcw_membase(cd, REG_ITMP1, a);
2434 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2437 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2439 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2442 a = dseg_adds4(cd, 0);
2443 i386_fistpl_membase(cd, REG_ITMP1, a);
2445 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2447 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2448 i386_fldcw_membase(cd, REG_ITMP1, a);
2450 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2453 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2454 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2457 i386_jcc(cd, I386_CC_NE, a);
2459 /* XXX: change this when we use registers */
2460 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2461 i386_mov_imm_reg(cd, (s4) asm_builtin_f2i, REG_ITMP1);
2462 i386_call_reg(cd, REG_ITMP1);
2464 if (iptr->dst->flags & INMEMORY) {
2465 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2468 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2472 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2473 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2474 /* EAX: D|YES ECX: NO EDX: NO OUTPUT: EAX*/
2476 var_to_reg_flt(s1, src, REG_FTMP1);
2477 d = reg_of_var(rd, iptr->dst, REG_NULL);
2479 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2480 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2481 dseg_adddata(cd, cd->mcodeptr);
2482 i386_fldcw_membase(cd, REG_ITMP1, a);
2484 if (iptr->dst->flags & INMEMORY) {
2485 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2488 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2489 i386_fldcw_membase(cd, REG_ITMP1, a);
2491 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2494 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2496 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2499 a = dseg_adds4(cd, 0);
2500 i386_fistpl_membase(cd, REG_ITMP1, a);
2502 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2504 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2505 i386_fldcw_membase(cd, REG_ITMP1, a);
2507 i386_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2510 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2511 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2514 i386_jcc(cd, I386_CC_NE, a);
2516 /* XXX: change this when we use registers */
2517 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2518 i386_mov_imm_reg(cd, (s4) asm_builtin_d2i, REG_ITMP1);
2519 i386_call_reg(cd, REG_ITMP1);
2521 if (iptr->dst->flags & INMEMORY) {
2522 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2524 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2528 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2529 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2530 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2532 var_to_reg_flt(s1, src, REG_FTMP1);
2533 d = reg_of_var(rd, iptr->dst, REG_NULL);
2535 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2536 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2537 dseg_adddata(cd, cd->mcodeptr);
2538 i386_fldcw_membase(cd, REG_ITMP1, a);
2540 if (iptr->dst->flags & INMEMORY) {
2541 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2544 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2545 i386_fldcw_membase(cd, REG_ITMP1, a);
2547 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2550 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2552 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2555 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2557 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4 + 4);
2559 i386_jcc(cd, I386_CC_NE, a);
2561 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2564 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2566 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2568 i386_jcc(cd, I386_CC_NE, a);
2570 /* XXX: change this when we use registers */
2571 i386_flds_membase(cd, REG_SP, src->regoff * 4);
2572 i386_mov_imm_reg(cd, (s4) asm_builtin_f2l, REG_ITMP1);
2573 i386_call_reg(cd, REG_ITMP1);
2574 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2575 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2578 log_text("F2L: longs have to be in memory");
2583 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2584 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2585 /* EAX: YES ECX: NO EDX: YES OUTPUT: REG_NULL*/
2587 var_to_reg_flt(s1, src, REG_FTMP1);
2588 d = reg_of_var(rd, iptr->dst, REG_NULL);
2590 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2591 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2592 dseg_adddata(cd, cd->mcodeptr);
2593 i386_fldcw_membase(cd, REG_ITMP1, a);
2595 if (iptr->dst->flags & INMEMORY) {
2596 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2599 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2600 i386_fldcw_membase(cd, REG_ITMP1, a);
2602 i386_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2605 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2607 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2610 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2612 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4 + 4);
2614 i386_jcc(cd, I386_CC_NE, a);
2616 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2619 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
2621 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 4);
2623 i386_jcc(cd, I386_CC_NE, a);
2625 /* XXX: change this when we use registers */
2626 i386_fldl_membase(cd, REG_SP, src->regoff * 4);
2627 i386_mov_imm_reg(cd, (s4) asm_builtin_d2l, REG_ITMP1);
2628 i386_call_reg(cd, REG_ITMP1);
2629 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2630 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2633 log_text("D2L: longs have to be in memory");
2638 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2639 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2640 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2642 var_to_reg_flt(s1, src, REG_FTMP1);
2643 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2645 store_reg_to_var_flt(iptr->dst, d);
2648 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2649 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2650 /* EAX: NO ECX: NO EDX: NO OUTPUT: REG_NULL*/
2652 var_to_reg_flt(s1, src, REG_FTMP1);
2653 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2655 store_reg_to_var_flt(iptr->dst, d);
2658 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2660 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2661 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2663 /* exchanged to skip fxch */
2664 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2665 var_to_reg_flt(s1, src, REG_FTMP2);
2666 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2667 /* i386_fxch(cd); */
2671 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2672 i386_jcc(cd, I386_CC_E, 6);
2673 i386_alu_imm_reg(cd, ALU_AND, 0x000000ff, EAX);
2675 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2676 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2677 i386_jcc(cd, I386_CC_B, 3 + 5);
2678 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2679 i386_jmp_imm(cd, 3);
2680 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2681 store_reg_to_var_int(iptr->dst, d);
2684 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2686 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2687 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2689 /* exchanged to skip fxch */
2690 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2691 var_to_reg_flt(s1, src, REG_FTMP2);
2692 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2693 /* i386_fxch(cd); */
2697 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2698 i386_jcc(cd, I386_CC_E, 3);
2699 i386_movb_imm_reg(cd, 1, REG_AH);
2701 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2702 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2703 i386_jcc(cd, I386_CC_B, 3 + 5);
2704 i386_alu_imm_reg(cd, ALU_SUB, 1, d);
2705 i386_jmp_imm(cd, 3);
2706 i386_alu_imm_reg(cd, ALU_ADD, 1, d);
2707 store_reg_to_var_int(iptr->dst, d);
2711 /* memory operations **************************************************/
2713 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2714 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2715 /* EAX: YES ECX: NO EDX: NO OUTPUT: REG_NULL*/
2717 var_to_reg_int(s1, src, REG_ITMP1);
2718 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2719 gen_nullptr_check(s1);
2720 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2721 store_reg_to_var_int(iptr->dst, d);
2724 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2725 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2726 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2728 var_to_reg_int(s1, src->prev, REG_ITMP1);
2729 var_to_reg_int(s2, src, REG_ITMP2);
2730 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2731 if (iptr->op1 == 0) {
2732 gen_nullptr_check(s1);
2735 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2736 store_reg_to_var_int(iptr->dst, d);
2739 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2740 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2741 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2743 var_to_reg_int(s1, src->prev, REG_ITMP1);
2744 var_to_reg_int(s2, src, REG_ITMP2);
2745 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2746 if (iptr->op1 == 0) {
2747 gen_nullptr_check(s1);
2751 if (iptr->dst->flags & INMEMORY) {
2752 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2753 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4);
2754 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2755 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2759 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2760 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2761 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2763 var_to_reg_int(s1, src->prev, REG_ITMP1);
2764 var_to_reg_int(s2, src, REG_ITMP2);
2765 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2766 if (iptr->op1 == 0) {
2767 gen_nullptr_check(s1);
2770 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2771 store_reg_to_var_int(iptr->dst, d);
2774 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2775 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2776 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2778 var_to_reg_int(s1, src->prev, REG_ITMP1);
2779 var_to_reg_int(s2, src, REG_ITMP2);
2780 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2781 if (iptr->op1 == 0) {
2782 gen_nullptr_check(s1);
2785 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2787 store_reg_to_var_flt(iptr->dst, d);
2790 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2791 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2792 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2794 var_to_reg_int(s1, src->prev, REG_ITMP1);
2795 var_to_reg_int(s2, src, REG_ITMP2);
2796 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2797 if (iptr->op1 == 0) {
2798 gen_nullptr_check(s1);
2801 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2803 store_reg_to_var_flt(iptr->dst, d);
2806 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2807 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2808 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2810 var_to_reg_int(s1, src->prev, REG_ITMP1);
2811 var_to_reg_int(s2, src, REG_ITMP2);
2812 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2813 if (iptr->op1 == 0) {
2814 gen_nullptr_check(s1);
2817 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2818 store_reg_to_var_int(iptr->dst, d);
2821 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2822 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2823 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2825 var_to_reg_int(s1, src->prev, REG_ITMP1);
2826 var_to_reg_int(s2, src, REG_ITMP2);
2827 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2828 if (iptr->op1 == 0) {
2829 gen_nullptr_check(s1);
2832 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2833 store_reg_to_var_int(iptr->dst, d);
2836 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2837 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2838 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2840 var_to_reg_int(s1, src->prev, REG_ITMP1);
2841 var_to_reg_int(s2, src, REG_ITMP2);
2842 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2843 if (iptr->op1 == 0) {
2844 gen_nullptr_check(s1);
2847 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2848 store_reg_to_var_int(iptr->dst, d);
2852 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2853 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2854 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
2856 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2857 var_to_reg_int(s2, src->prev, REG_ITMP2);
2858 if (iptr->op1 == 0) {
2859 gen_nullptr_check(s1);
2863 if (src->flags & INMEMORY) {
2864 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP3);
2865 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2866 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
2867 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2871 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2872 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2873 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2875 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2876 var_to_reg_int(s2, src->prev, REG_ITMP2);
2877 if (iptr->op1 == 0) {
2878 gen_nullptr_check(s1);
2881 var_to_reg_int(s3, src, REG_ITMP3);
2882 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2885 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2886 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2887 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2889 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2890 var_to_reg_int(s2, src->prev, REG_ITMP2);
2891 if (iptr->op1 == 0) {
2892 gen_nullptr_check(s1);
2895 var_to_reg_flt(s3, src, REG_FTMP1);
2896 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2900 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2901 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2902 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2904 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2905 var_to_reg_int(s2, src->prev, REG_ITMP2);
2906 if (iptr->op1 == 0) {
2907 gen_nullptr_check(s1);
2910 var_to_reg_flt(s3, src, REG_FTMP1);
2911 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2915 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2916 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2917 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2919 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2920 var_to_reg_int(s2, src->prev, REG_ITMP2);
2921 if (iptr->op1 == 0) {
2922 gen_nullptr_check(s1);
2925 var_to_reg_int(s3, src, REG_ITMP3);
2926 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2929 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2930 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2931 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2933 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2934 var_to_reg_int(s2, src->prev, REG_ITMP2);
2935 if (iptr->op1 == 0) {
2936 gen_nullptr_check(s1);
2939 var_to_reg_int(s3, src, REG_ITMP3);
2940 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2943 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2944 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2945 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
2947 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2948 var_to_reg_int(s2, src->prev, REG_ITMP2);
2949 if (iptr->op1 == 0) {
2950 gen_nullptr_check(s1);
2953 var_to_reg_int(s3, src, REG_ITMP3);
2954 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2955 M_INTMOVE(s3, REG_ITMP3);
2958 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2961 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2962 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2963 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
2965 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2966 var_to_reg_int(s2, src->prev, REG_ITMP2);
2967 /* if (iptr->op1 == 0) { */
2968 gen_nullptr_check(s1);
2971 var_to_reg_int(s3, src, REG_ITMP3);
2975 M_AST(s1, REG_SP, 0 * 4);
2976 M_AST(s3, REG_SP, 1 * 4);
2977 M_MOV_IMM((ptrint) bte->fp, REG_ITMP1);
2981 codegen_addxstorerefs(cd, cd->mcodeptr);
2983 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2984 var_to_reg_int(s2, src->prev, REG_ITMP2);
2985 var_to_reg_int(s3, src, REG_ITMP3);
2986 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2989 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2990 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
2991 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
2993 var_to_reg_int(s1, src->prev, REG_ITMP1);
2994 var_to_reg_int(s2, src, REG_ITMP2);
2995 if (iptr->op1 == 0) {
2996 gen_nullptr_check(s1);
2999 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
3002 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
3003 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3004 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3006 var_to_reg_int(s1, src->prev, REG_ITMP1);
3007 var_to_reg_int(s2, src, REG_ITMP2);
3008 if (iptr->op1 == 0) {
3009 gen_nullptr_check(s1);
3013 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
3014 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
3017 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
3018 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3019 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3021 var_to_reg_int(s1, src->prev, REG_ITMP1);
3022 var_to_reg_int(s2, src, REG_ITMP2);
3023 if (iptr->op1 == 0) {
3024 gen_nullptr_check(s1);
3027 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
3030 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
3031 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3032 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3034 var_to_reg_int(s1, src->prev, REG_ITMP1);
3035 var_to_reg_int(s2, src, REG_ITMP2);
3036 if (iptr->op1 == 0) {
3037 gen_nullptr_check(s1);
3040 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
3043 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
3044 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3045 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3047 var_to_reg_int(s1, src->prev, REG_ITMP1);
3048 var_to_reg_int(s2, src, REG_ITMP2);
3049 if (iptr->op1 == 0) {
3050 gen_nullptr_check(s1);
3053 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
3056 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
3057 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3058 /* EAX: S|YES ECX: S|YES EDX: NO OUTPUT: REG_NULL*/
3060 var_to_reg_int(s1, src->prev, REG_ITMP1);
3061 var_to_reg_int(s2, src, REG_ITMP2);
3062 if (iptr->op1 == 0) {
3063 gen_nullptr_check(s1);
3066 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
3070 case ICMD_GETSTATIC: /* ... ==> ..., value */
3071 /* op1 = type, val.a = field address */
3072 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3073 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: EAX*/
3076 codegen_addpatchref(cd, cd->mcodeptr,
3077 PATCHER_get_putstatic,
3078 (unresolved_field *) iptr->target, 0);
3080 if (opt_showdisassemble) {
3081 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3087 fieldinfo *fi = iptr->val.a;
3089 if (!fi->class->initialized) {
3090 codegen_addpatchref(cd, cd->mcodeptr,
3091 PATCHER_clinit, fi->class, 0);
3093 if (opt_showdisassemble) {
3094 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3098 a = (ptrint) &(fi->value);
3101 i386_mov_imm_reg(cd, a, REG_ITMP1);
3102 switch (iptr->op1) {
3105 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3106 i386_mov_membase_reg(cd, REG_ITMP1, 0, d);
3107 store_reg_to_var_int(iptr->dst, d);
3110 d = reg_of_var(rd, iptr->dst, REG_NULL);
3111 if (iptr->dst->flags & INMEMORY) {
3112 /* Using both REG_ITMP2 and REG_ITMP3 is faster than only */
3113 /* using REG_ITMP2 alternating. */
3114 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP2);
3115 i386_mov_membase_reg(cd, REG_ITMP1, 4, REG_ITMP3);
3116 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4);
3117 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
3119 log_text("GETSTATIC: longs have to be in memory");
3124 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3125 i386_flds_membase(cd, REG_ITMP1, 0);
3127 store_reg_to_var_flt(iptr->dst, d);
3130 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3131 i386_fldl_membase(cd, REG_ITMP1, 0);
3133 store_reg_to_var_flt(iptr->dst, d);
3138 case ICMD_PUTSTATIC: /* ..., value ==> ... */
3139 /* op1 = type, val.a = field address */
3140 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3141 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3144 codegen_addpatchref(cd, cd->mcodeptr,
3145 PATCHER_get_putstatic,
3146 (unresolved_field *) iptr->target, 0);
3148 if (opt_showdisassemble) {
3149 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3155 fieldinfo *fi = iptr->val.a;
3157 if (!fi->class->initialized) {
3158 codegen_addpatchref(cd, cd->mcodeptr,
3159 PATCHER_clinit, fi->class, 0);
3161 if (opt_showdisassemble) {
3162 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3166 a = (ptrint) &(fi->value);
3169 i386_mov_imm_reg(cd, a, REG_ITMP1);
3170 switch (iptr->op1) {
3173 var_to_reg_int(s2, src, REG_ITMP2);
3174 i386_mov_reg_membase(cd, s2, REG_ITMP1, 0);
3177 if (src->flags & INMEMORY) {
3178 /* Using both REG_ITMP2 and REG_ITMP3 is faster than only */
3179 /* using REG_ITMP2 alternating. */
3182 i386_mov_membase_reg(cd, REG_SP, s2 * 4, REG_ITMP2);
3183 i386_mov_membase_reg(cd, REG_SP, s2 * 4 + 4, REG_ITMP3);
3184 i386_mov_reg_membase(cd, REG_ITMP2, REG_ITMP1, 0);
3185 i386_mov_reg_membase(cd, REG_ITMP3, REG_ITMP1, 4);
3187 log_text("PUTSTATIC: longs have to be in memory");
3192 var_to_reg_flt(s2, src, REG_FTMP1);
3193 i386_fstps_membase(cd, REG_ITMP1, 0);
3197 var_to_reg_flt(s2, src, REG_FTMP1);
3198 i386_fstpl_membase(cd, REG_ITMP1, 0);
3204 case ICMD_PUTSTATICCONST: /* ... ==> ... */
3205 /* val = value (in current instruction) */
3206 /* op1 = type, val.a = field address (in */
3207 /* following NOP) */
3208 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3209 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3211 if (!iptr[1].val.a) {
3212 codegen_addpatchref(cd, cd->mcodeptr,
3213 PATCHER_get_putstatic,
3214 (unresolved_field *) iptr[1].target, 0);
3216 if (opt_showdisassemble) {
3217 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3223 fieldinfo *fi = iptr[1].val.a;
3225 if (!fi->class->initialized) {
3226 codegen_addpatchref(cd, cd->mcodeptr,
3227 PATCHER_clinit, fi->class, 0);
3229 if (opt_showdisassemble) {
3230 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3234 a = (ptrint) &(fi->value);
3237 i386_mov_imm_reg(cd, a, REG_ITMP1);
3238 switch (iptr[1].op1) {
3242 i386_mov_imm_membase(cd, iptr->val.i, REG_ITMP1, 0);
3246 i386_mov_imm_membase(cd, iptr->val.l, REG_ITMP1, 0);
3247 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_ITMP1, 4);
3252 case ICMD_GETFIELD: /* .., objectref. ==> ..., value */
3253 /* op1 = type, val.i = field offset */
3254 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3255 /* EAX: YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL */
3257 var_to_reg_int(s1, src, REG_ITMP1);
3258 gen_nullptr_check(s1);
3261 codegen_addpatchref(cd, cd->mcodeptr,
3263 (unresolved_field *) iptr->target, 0);
3265 if (opt_showdisassemble) {
3266 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3272 a = ((fieldinfo *) (iptr->val.a))->offset;
3275 switch (iptr->op1) {
3278 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3279 i386_mov_membase32_reg(cd, s1, a, d);
3280 store_reg_to_var_int(iptr->dst, d);
3283 d = reg_of_var(rd, iptr->dst, REG_NULL);
3284 i386_mov_membase32_reg(cd, s1, a, REG_ITMP2);
3285 i386_mov_membase32_reg(cd, s1, a + 4, REG_ITMP3);
3286 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4);
3287 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
3290 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3291 i386_flds_membase32(cd, s1, a);
3293 store_reg_to_var_flt(iptr->dst, d);
3296 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3297 i386_fldl_membase32(cd, s1, a);
3299 store_reg_to_var_flt(iptr->dst, d);
3304 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
3305 /* op1 = type, val.a = field address */
3306 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3307 /* EAX: S|YES ECX: S|YES EDX: S|YES OUTPUT: REG_NULL*/
3309 var_to_reg_int(s1, src->prev, REG_ITMP1);
3310 gen_nullptr_check(s1);
3311 if ((iptr->op1 == TYPE_INT) || IS_ADR_TYPE(iptr->op1)) {
3312 var_to_reg_int(s2, src, REG_ITMP2);
3313 } else if (IS_FLT_DBL_TYPE(iptr->op1)) {
3314 var_to_reg_flt(s2, src, REG_FTMP2);
3318 codegen_addpatchref(cd, cd->mcodeptr,
3320 (unresolved_field *) iptr->target, 0);
3322 if (opt_showdisassemble) {
3323 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3329 a = ((fieldinfo *) (iptr->val.a))->offset;
3332 switch (iptr->op1) {
3335 i386_mov_reg_membase32(cd, s2, s1, a);
3338 if (src->flags & INMEMORY) {
3339 i386_mov_membase32_reg(cd, REG_SP, src->regoff * 4, REG_ITMP2);
3340 i386_mov_membase32_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
3341 i386_mov_reg_membase32(cd, REG_ITMP2, s1, a);
3342 i386_mov_reg_membase32(cd, REG_ITMP3, s1, a + 4);
3344 log_text("PUTFIELD: longs have to be in memory");
3349 i386_fstps_membase32(cd, s1, a);
3353 i386_fstpl_membase32(cd, s1, a);
3359 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
3360 /* val = value (in current instruction) */
3361 /* op1 = type, val.a = field address (in */
3362 /* following NOP) */
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 var_to_reg_int(s1, src, REG_ITMP1);
3367 gen_nullptr_check(s1);
3369 if (!iptr[1].val.a) {
3370 codegen_addpatchref(cd, cd->mcodeptr,
3371 PATCHER_putfieldconst,
3372 (unresolved_field *) iptr[1].target, 0);
3374 if (opt_showdisassemble) {
3375 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3381 a = ((fieldinfo *) (iptr[1].val.a))->offset;
3384 switch (iptr[1].op1) {
3388 i386_mov_imm_membase32(cd, iptr->val.i, s1, a);
3392 i386_mov_imm_membase32(cd, iptr->val.l, s1, a);
3393 i386_mov_imm_membase32(cd, iptr->val.l >> 32, s1, a + 4);
3399 /* branch operations **************************************************/
3401 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3402 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3403 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
3405 var_to_reg_int(s1, src, REG_ITMP1);
3406 M_INTMOVE(s1, REG_ITMP1_XPTR);
3409 codegen_addpatchref(cd, cd->mcodeptr,
3410 PATCHER_athrow_areturn,
3411 (unresolved_class *) iptr->val.a, 0);
3413 if (opt_showdisassemble) {
3414 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3418 M_CALL_IMM(0); /* passing exception pc */
3419 M_POP(REG_ITMP2_XPC);
3421 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
3425 case ICMD_GOTO: /* ... ==> ... */
3426 /* op1 = target JavaVM pc */
3427 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3428 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3430 i386_jmp_imm(cd, 0);
3431 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3434 case ICMD_JSR: /* ... ==> ... */
3435 /* op1 = target JavaVM pc */
3436 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3437 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3439 i386_call_imm(cd, 0);
3440 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3443 case ICMD_RET: /* ... ==> ... */
3444 /* op1 = local variable */
3445 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3446 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3448 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3449 var_to_reg_int(s1, var, REG_ITMP1);
3450 i386_jmp_reg(cd, s1);
3453 case ICMD_IFNULL: /* ..., value ==> ... */
3454 /* op1 = target JavaVM pc */
3455 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3456 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3458 if (src->flags & INMEMORY) {
3459 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3462 i386_test_reg_reg(cd, src->regoff, src->regoff);
3464 i386_jcc(cd, I386_CC_E, 0);
3465 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3468 case ICMD_IFNONNULL: /* ..., value ==> ... */
3469 /* op1 = target JavaVM pc */
3470 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3471 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3473 if (src->flags & INMEMORY) {
3474 i386_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4);
3477 i386_test_reg_reg(cd, src->regoff, src->regoff);
3479 i386_jcc(cd, I386_CC_NE, 0);
3480 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3483 case ICMD_IFEQ: /* ..., value ==> ... */
3484 /* op1 = target JavaVM pc, val.i = constant */
3485 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3486 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3488 if (src->flags & INMEMORY) {
3489 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3492 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3494 i386_jcc(cd, I386_CC_E, 0);
3495 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3498 case ICMD_IFLT: /* ..., value ==> ... */
3499 /* op1 = target JavaVM pc, val.i = constant */
3500 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3501 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3503 if (src->flags & INMEMORY) {
3504 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3507 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3509 i386_jcc(cd, I386_CC_L, 0);
3510 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3513 case ICMD_IFLE: /* ..., value ==> ... */
3514 /* op1 = target JavaVM pc, val.i = constant */
3515 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3516 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3518 if (src->flags & INMEMORY) {
3519 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3522 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3524 i386_jcc(cd, I386_CC_LE, 0);
3525 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3528 case ICMD_IFNE: /* ..., value ==> ... */
3529 /* op1 = target JavaVM pc, val.i = constant */
3530 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3531 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3533 if (src->flags & INMEMORY) {
3534 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3537 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3539 i386_jcc(cd, I386_CC_NE, 0);
3540 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3543 case ICMD_IFGT: /* ..., value ==> ... */
3544 /* op1 = target JavaVM pc, val.i = constant */
3545 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3546 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3548 if (src->flags & INMEMORY) {
3549 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3552 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3554 i386_jcc(cd, I386_CC_G, 0);
3555 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3558 case ICMD_IFGE: /* ..., value ==> ... */
3559 /* op1 = target JavaVM pc, val.i = constant */
3560 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3561 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3563 if (src->flags & INMEMORY) {
3564 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.i, REG_SP, src->regoff * 4);
3567 i386_alu_imm_reg(cd, ALU_CMP, iptr->val.i, src->regoff);
3569 i386_jcc(cd, I386_CC_GE, 0);
3570 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3573 case ICMD_IF_LEQ: /* ..., value ==> ... */
3574 /* op1 = target JavaVM pc, val.l = constant */
3575 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3576 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3578 if (src->flags & INMEMORY) {
3579 if (iptr->val.l == 0) {
3580 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3581 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3584 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3585 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l >> 32, REG_ITMP2);
3586 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3587 i386_alu_imm_reg(cd, ALU_XOR, iptr->val.l, REG_ITMP1);
3588 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3591 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3592 i386_jcc(cd, I386_CC_E, 0);
3593 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3596 case ICMD_IF_LLT: /* ..., value ==> ... */
3597 /* op1 = target JavaVM pc, val.l = constant */
3598 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3599 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3601 if (src->flags & INMEMORY) {
3602 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3603 i386_jcc(cd, I386_CC_L, 0);
3604 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3607 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3608 CALCIMMEDIATEBYTES(a, iptr->val.l);
3610 i386_jcc(cd, I386_CC_G, a);
3612 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3613 i386_jcc(cd, I386_CC_B, 0);
3614 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3618 case ICMD_IF_LLE: /* ..., value ==> ... */
3619 /* op1 = target JavaVM pc, val.l = constant */
3620 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3621 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3623 if (src->flags & INMEMORY) {
3624 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3625 i386_jcc(cd, I386_CC_L, 0);
3626 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3629 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3630 CALCIMMEDIATEBYTES(a, iptr->val.l);
3632 i386_jcc(cd, I386_CC_G, a);
3634 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3635 i386_jcc(cd, I386_CC_BE, 0);
3636 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3640 case ICMD_IF_LNE: /* ..., value ==> ... */
3641 /* op1 = target JavaVM pc, val.l = constant */
3642 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3643 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3645 if (src->flags & INMEMORY) {
3646 if (iptr->val.l == 0) {
3647 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3648 i386_alu_membase_reg(cd, ALU_OR, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3651 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3652 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3653 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3654 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3655 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3658 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3659 i386_jcc(cd, I386_CC_NE, 0);
3660 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3663 case ICMD_IF_LGT: /* ..., value ==> ... */
3664 /* op1 = target JavaVM pc, val.l = constant */
3665 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3666 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3668 if (src->flags & INMEMORY) {
3669 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3670 i386_jcc(cd, I386_CC_G, 0);
3671 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3674 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3675 CALCIMMEDIATEBYTES(a, iptr->val.l);
3677 i386_jcc(cd, I386_CC_L, a);
3679 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3680 i386_jcc(cd, I386_CC_A, 0);
3681 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3685 case ICMD_IF_LGE: /* ..., value ==> ... */
3686 /* op1 = target JavaVM pc, val.l = constant */
3687 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3688 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3690 if (src->flags & INMEMORY) {
3691 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 4 + 4);
3692 i386_jcc(cd, I386_CC_G, 0);
3693 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3696 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3697 CALCIMMEDIATEBYTES(a, iptr->val.l);
3699 i386_jcc(cd, I386_CC_L, a);
3701 i386_alu_imm_membase(cd, ALU_CMP, iptr->val.l, REG_SP, src->regoff * 4);
3702 i386_jcc(cd, I386_CC_AE, 0);
3703 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3707 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3708 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3709 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3710 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3712 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3713 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3714 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3716 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3717 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3719 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3720 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3723 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3725 i386_jcc(cd, I386_CC_E, 0);
3726 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3729 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3730 /* op1 = target JavaVM pc */
3731 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3732 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3734 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3735 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3736 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3737 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3738 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3739 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3740 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3742 i386_jcc(cd, I386_CC_E, 0);
3743 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3746 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3747 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
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) && (src->prev->flags & INMEMORY)) {
3752 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3753 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3755 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3756 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3758 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3759 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3762 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3764 i386_jcc(cd, I386_CC_NE, 0);
3765 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3768 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3769 /* 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->prev->regoff * 4, REG_ITMP1);
3775 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP2);
3776 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4, REG_ITMP1);
3777 i386_alu_membase_reg(cd, ALU_XOR, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
3778 i386_alu_reg_reg(cd, ALU_OR, REG_ITMP2, REG_ITMP1);
3779 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3781 i386_jcc(cd, I386_CC_NE, 0);
3782 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3785 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3786 /* op1 = target JavaVM pc */
3787 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3788 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3790 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3791 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3792 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3794 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3795 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3797 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3798 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3801 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3803 i386_jcc(cd, I386_CC_L, 0);
3804 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3807 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3808 /* 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->prev->regoff * 4 + 4, REG_ITMP1);
3814 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3815 i386_jcc(cd, I386_CC_L, 0);
3816 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3819 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 4);
3820 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3822 i386_jcc(cd, I386_CC_G, a);
3824 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3825 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3826 i386_jcc(cd, I386_CC_B, 0);
3827 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3831 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3832 /* op1 = target JavaVM pc */
3833 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3834 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3836 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3837 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3838 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3840 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3841 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3843 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3844 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3847 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3849 i386_jcc(cd, I386_CC_G, 0);
3850 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3853 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3854 /* op1 = target JavaVM pc */
3855 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3856 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3858 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3859 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3860 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3861 i386_jcc(cd, I386_CC_G, 0);
3862 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3865 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 4);
3866 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3868 i386_jcc(cd, I386_CC_L, a);
3870 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3871 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3872 i386_jcc(cd, I386_CC_A, 0);
3873 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3877 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3878 /* op1 = target JavaVM pc */
3879 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3880 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3882 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3883 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3884 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3886 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3887 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3889 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3890 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3893 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3895 i386_jcc(cd, I386_CC_LE, 0);
3896 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3899 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3900 /* op1 = target JavaVM pc */
3901 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3902 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3904 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3905 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3906 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3907 i386_jcc(cd, I386_CC_L, 0);
3908 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3911 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 4);
3912 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3914 i386_jcc(cd, I386_CC_G, a);
3916 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3917 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3918 i386_jcc(cd, I386_CC_BE, 0);
3919 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3923 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3924 /* op1 = target JavaVM pc */
3925 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3926 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3928 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3929 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
3930 i386_alu_reg_membase(cd, ALU_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 4);
3932 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3933 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, src->prev->regoff);
3935 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3936 i386_alu_reg_membase(cd, ALU_CMP, src->regoff, REG_SP, src->prev->regoff * 4);
3939 i386_alu_reg_reg(cd, ALU_CMP, src->regoff, src->prev->regoff);
3941 i386_jcc(cd, I386_CC_GE, 0);
3942 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3945 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3946 /* op1 = target JavaVM pc */
3947 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3948 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3950 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3951 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4 + 4, REG_ITMP1);
3952 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4 + 4, REG_ITMP1);
3953 i386_jcc(cd, I386_CC_G, 0);
3954 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3957 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 4);
3958 CALCOFFSETBYTES(a, REG_SP, src->regoff * 4);
3960 i386_jcc(cd, I386_CC_L, a);
3962 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 4, REG_ITMP1);
3963 i386_alu_membase_reg(cd, ALU_CMP, REG_SP, src->regoff * 4, REG_ITMP1);
3964 i386_jcc(cd, I386_CC_AE, 0);
3965 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3969 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3971 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3972 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3973 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3976 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3977 /* val.i = constant */
3978 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3979 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3981 d = reg_of_var(rd, iptr->dst, REG_NULL);
3982 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
3985 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3986 /* val.i = constant */
3987 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3988 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3990 d = reg_of_var(rd, iptr->dst, REG_NULL);
3991 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
3994 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3995 /* val.i = constant */
3996 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
3997 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
3999 d = reg_of_var(rd, iptr->dst, REG_NULL);
4000 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
4003 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
4004 /* val.i = constant */
4005 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4006 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4008 d = reg_of_var(rd, iptr->dst, REG_NULL);
4009 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
4012 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
4013 /* val.i = constant */
4014 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4015 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4017 d = reg_of_var(rd, iptr->dst, REG_NULL);
4018 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
4021 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
4022 /* val.i = constant */
4023 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4024 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4026 d = reg_of_var(rd, iptr->dst, REG_NULL);
4027 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
4031 case ICMD_IRETURN: /* ..., retvalue ==> ... */
4032 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4033 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4035 var_to_reg_int(s1, src, REG_RESULT);
4036 M_INTMOVE(s1, REG_RESULT);
4037 goto nowperformreturn;
4039 case ICMD_LRETURN: /* ..., retvalue ==> ... */
4040 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4041 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4043 if (src->flags & INMEMORY) {
4044 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_RESULT);
4045 i386_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_RESULT2);
4048 log_text("LRETURN: longs have to be in memory");
4051 goto nowperformreturn;
4053 case ICMD_ARETURN: /* ..., retvalue ==> ... */
4054 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4055 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4057 var_to_reg_int(s1, src, REG_RESULT);
4058 M_INTMOVE(s1, REG_RESULT);
4061 codegen_addpatchref(cd, cd->mcodeptr,
4062 PATCHER_athrow_areturn,
4063 (unresolved_class *) iptr->val.a, 0);
4065 if (opt_showdisassemble) {
4066 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4069 goto nowperformreturn;
4071 case ICMD_FRETURN: /* ..., retvalue ==> ... */
4073 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4074 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL */
4076 var_to_reg_flt(s1, src, REG_FRESULT);
4077 /* this may be an early return -- keep the offset correct for the
4080 goto nowperformreturn;
4082 case ICMD_RETURN: /* ... ==> ... */
4083 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4084 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4090 p = parentargs_base;
4092 /* call trace function */
4094 i386_alu_imm_reg(cd, ALU_SUB, 4 + 8 + 8 + 4, REG_SP);
4096 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
4098 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
4099 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
4101 i386_fstl_membase(cd, REG_SP, 4 + 8);
4102 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
4104 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
4105 i386_call_reg(cd, REG_ITMP1);
4107 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
4108 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
4110 i386_alu_imm_reg(cd, ALU_ADD, 4 + 8 + 8 + 4, REG_SP);
4113 #if defined(USE_THREADS)
4114 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
4115 M_ALD(REG_ITMP2, REG_SP, rd->memuse * 4);
4117 /* we need to save the proper return value */
4118 switch (iptr->opc) {
4121 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4125 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
4126 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4130 i386_fsts_membase(cd, REG_SP, rd->memuse * 4);
4134 i386_fstl_membase(cd, REG_SP, rd->memuse * 4);
4138 M_AST(REG_ITMP2, REG_SP, 0);
4139 i386_mov_imm_reg(cd, (ptrint) BUILTIN_monitorexit, REG_ITMP1);
4140 i386_call_reg(cd, REG_ITMP1);
4142 /* and now restore the proper return value */
4143 switch (iptr->opc) {
4146 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4150 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
4151 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 4);
4155 i386_flds_membase(cd, REG_SP, rd->memuse * 4);
4159 i386_fldl_membase(cd, REG_SP, rd->memuse * 4);
4165 /* restore saved registers */
4167 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
4168 p--; M_ALD(rd->savintregs[i], REG_SP, p * 4);
4171 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
4173 i386_fldl_membase(cd, REG_SP, p * 4);
4175 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
4176 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
4178 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
4183 /* deallocate stack */
4185 if (parentargs_base)
4186 M_AADD_IMM(parentargs_base * 4, REG_SP);
4193 case ICMD_TABLESWITCH: /* ..., index ==> ... */
4194 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4195 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4200 tptr = (void **) iptr->target;
4202 s4ptr = iptr->val.a;
4203 l = s4ptr[1]; /* low */
4204 i = s4ptr[2]; /* high */
4206 var_to_reg_int(s1, src, REG_ITMP1);
4207 M_INTMOVE(s1, REG_ITMP1);
4209 i386_alu_imm_reg(cd, ALU_SUB, l, REG_ITMP1);
4215 i386_alu_imm_reg(cd, ALU_CMP, i - 1, REG_ITMP1);
4216 i386_jcc(cd, I386_CC_A, 0);
4218 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
4219 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4221 /* build jump table top down and use address of lowest entry */
4223 /* s4ptr += 3 + i; */
4227 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
4228 dseg_addtarget(cd, (basicblock *) tptr[0]);
4232 /* length of dataseg after last dseg_addtarget is used by load */
4234 i386_mov_imm_reg(cd, 0, REG_ITMP2);
4235 dseg_adddata(cd, cd->mcodeptr);
4236 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
4237 i386_jmp_reg(cd, REG_ITMP1);
4242 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
4243 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4244 /* EAX: YES ECX: YES EDX: YES OUTPUT: REG_NULL*/
4246 s4 i, l, val, *s4ptr;
4249 tptr = (void **) iptr->target;
4251 s4ptr = iptr->val.a;
4252 l = s4ptr[0]; /* default */
4253 i = s4ptr[1]; /* count */
4255 MCODECHECK((i<<2)+8);
4256 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
4262 i386_alu_imm_reg(cd, ALU_CMP, val, s1);
4263 i386_jcc(cd, I386_CC_E, 0);
4264 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), cd->mcodeptr); */
4265 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4268 i386_jmp_imm(cd, 0);
4269 /* codegen_addreference(cd, BlockPtrOfPC(l), cd->mcodeptr); */
4271 tptr = (void **) iptr->target;
4272 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
4276 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
4277 /* op1 = arg count val.a = builtintable entry */
4278 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4279 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4285 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
4286 /* op1 = arg count, val.a = method pointer */
4288 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
4289 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
4290 case ICMD_INVOKEINTERFACE:
4291 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4292 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4297 md = lm->parseddesc;
4299 unresolved_method *um = iptr->target;
4300 md = um->methodref->parseddesc.md;
4304 s3 = md->paramcount;
4306 MCODECHECK((s3 << 1) + 64);
4308 /* copy arguments to registers or stack location */
4310 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
4311 if (src->varkind == ARGVAR)
4313 if (IS_INT_LNG_TYPE(src->type)) {
4314 if (!md->params[s3].inmemory) {
4315 log_text("No integer argument registers available!");
4318 if (!IS_2_WORD_TYPE(src->type)) {
4319 if (src->flags & INMEMORY) {
4320 i386_mov_membase_reg(
4321 cd, REG_SP, src->regoff * 4, REG_ITMP1);
4322 i386_mov_reg_membase(
4323 cd, REG_ITMP1, REG_SP,
4324 md->params[s3].regoff * 4);
4326 i386_mov_reg_membase(
4327 cd, src->regoff, REG_SP,
4328 md->params[s3].regoff * 4);
4332 if (src->flags & INMEMORY) {
4334 src->regoff, md->params[s3].regoff);
4336 log_text("copy arguments: longs have to be in memory");
4342 if (!md->params[s3].inmemory) {
4343 log_text("No float argument registers available!");
4346 var_to_reg_flt(d, src, REG_FTMP1);
4347 if (src->type == TYPE_FLT) {
4349 cd, REG_SP, md->params[s3].regoff * 4);
4353 cd, REG_SP, md->params[s3].regoff * 4);
4359 switch (iptr->opc) {
4362 codegen_addpatchref(cd, cd->mcodeptr, bte->fp,
4365 if (opt_showdisassemble) {
4366 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4372 a = (ptrint) bte->fp;
4375 d = md->returntype.type;
4377 M_MOV_IMM(a, REG_ITMP1);
4380 /* if op1 == true, we need to check for an exception */
4382 if (iptr->op1 == true) {
4385 codegen_addxexceptionrefs(cd, cd->mcodeptr);
4389 case ICMD_INVOKESPECIAL:
4390 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
4391 gen_nullptr_check(REG_ITMP1);
4393 /* access memory for hardware nullptr */
4394 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1);
4398 case ICMD_INVOKESTATIC:
4400 unresolved_method *um = iptr->target;
4402 codegen_addpatchref(cd, cd->mcodeptr,
4403 PATCHER_invokestatic_special, um, 0);
4405 if (opt_showdisassemble) {
4406 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4410 d = md->returntype.type;
4413 a = (ptrint) lm->stubroutine;
4414 d = lm->parseddesc->returntype.type;
4417 M_MOV_IMM(a, REG_ITMP2);
4421 case ICMD_INVOKEVIRTUAL:
4422 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
4423 gen_nullptr_check(REG_ITMP1);
4426 unresolved_method *um = iptr->target;
4428 codegen_addpatchref(cd, cd->mcodeptr,
4429 PATCHER_invokevirtual, um, 0);
4431 if (opt_showdisassemble) {
4432 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4436 d = md->returntype.type;
4439 s1 = OFFSET(vftbl_t, table[0]) +
4440 sizeof(methodptr) * lm->vftblindex;
4441 d = md->returntype.type;
4444 M_ALD(REG_ITMP2, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4445 i386_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP1);
4449 case ICMD_INVOKEINTERFACE:
4450 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
4451 gen_nullptr_check(REG_ITMP1);
4454 unresolved_method *um = iptr->target;
4456 codegen_addpatchref(cd, cd->mcodeptr,
4457 PATCHER_invokeinterface, um, 0);
4459 if (opt_showdisassemble) {
4460 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4465 d = md->returntype.type;
4468 s1 = OFFSET(vftbl_t, interfacetable[0]) -
4469 sizeof(methodptr) * lm->class->index;
4471 s2 = sizeof(methodptr) * (lm - lm->class->methods);
4473 d = md->returntype.type;
4476 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(java_objectheader, vftbl));
4477 i386_mov_membase32_reg(cd, REG_ITMP1, s1, REG_ITMP2);
4478 i386_mov_membase32_reg(cd, REG_ITMP2, s2, REG_ITMP1);
4483 /* d contains return type */
4485 if (d != TYPE_VOID) {
4486 d = reg_of_var(rd, iptr->dst, REG_NULL);
4488 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
4489 if (IS_2_WORD_TYPE(iptr->dst->type)) {
4490 if (iptr->dst->flags & INMEMORY) {
4491 i386_mov_reg_membase(
4492 cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4493 i386_mov_reg_membase(
4494 cd, REG_RESULT2, REG_SP,
4495 iptr->dst->regoff * 4 + 4);
4497 log_text("RETURN: longs have to be in memory");
4502 if (iptr->dst->flags & INMEMORY) {
4503 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
4506 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
4511 /* fld from called function -- has other fpu_st_offset counter */
4513 store_reg_to_var_flt(iptr->dst, d);
4519 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4520 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4521 /* EAX: YES ECX: I|YES EDX: I|YES OUTPUT: REG_NULL*/
4523 /* op1: 0 == array, 1 == class */
4524 /* val.a: (classinfo*) superclass */
4526 /* superclass is an interface:
4528 * OK if ((sub == NULL) ||
4529 * (sub->vftbl->interfacetablelength > super->index) &&
4530 * (sub->vftbl->interfacetable[-super->index] != NULL));
4532 * superclass is a class:
4534 * OK if ((sub == NULL) || (0
4535 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4536 * super->vftbl->diffval));
4541 vftbl_t *supervftbl;
4544 super = (classinfo *) iptr->val.a;
4551 superindex = super->index;
4552 supervftbl = super->vftbl;
4555 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4556 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4558 var_to_reg_int(s1, src, REG_ITMP1);
4560 /* calculate interface checkcast code size */
4562 s2 = 2; /* mov_membase_reg */
4563 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4565 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ +
4566 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4567 2 /* test */ + 6 /* jcc */);
4570 s2 += (opt_showdisassemble ? 5 : 0);
4572 /* calculate class checkcast code size */
4574 s3 = 2; /* mov_membase_reg */
4575 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4577 s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */;
4580 if (s1 != REG_ITMP1) {
4582 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
4585 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
4592 s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ +
4593 5 /* mov_imm_reg */ + 2 /* mov_membase_reg */);
4594 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
4597 s3 += 2 /* cmp */ + 6 /* jcc */;
4600 s3 += (opt_showdisassemble ? 5 : 0);
4602 /* if class is not resolved, check which code to call */
4605 i386_test_reg_reg(cd, s1, s1);
4606 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4608 codegen_addpatchref(cd, cd->mcodeptr,
4609 PATCHER_checkcast_instanceof_flags,
4610 (constant_classref *) iptr->target, 0);
4612 if (opt_showdisassemble) {
4613 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4616 i386_mov_imm_reg(cd, 0, REG_ITMP2); /* super->flags */
4617 i386_alu_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP2);
4618 i386_jcc(cd, I386_CC_Z, s2 + 5);
4621 /* interface checkcast code */
4623 if (!super || (super->flags & ACC_INTERFACE)) {
4625 i386_test_reg_reg(cd, s1, s1);
4626 i386_jcc(cd, I386_CC_Z, s2);
4629 i386_mov_membase_reg(cd, s1,
4630 OFFSET(java_objectheader, vftbl),
4634 codegen_addpatchref(cd, cd->mcodeptr,
4635 PATCHER_checkcast_instanceof_interface,
4636 (constant_classref *) iptr->target, 0);
4638 if (opt_showdisassemble) {
4639 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4643 i386_mov_membase32_reg(cd, REG_ITMP2,
4644 OFFSET(vftbl_t, interfacetablelength),
4646 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4647 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4648 i386_jcc(cd, I386_CC_LE, 0);
4649 codegen_addxcastrefs(cd, cd->mcodeptr);
4650 i386_mov_membase32_reg(cd, REG_ITMP2,
4651 OFFSET(vftbl_t, interfacetable[0]) -
4652 superindex * sizeof(methodptr*),
4654 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4655 i386_jcc(cd, I386_CC_E, 0);
4656 codegen_addxcastrefs(cd, cd->mcodeptr);
4659 i386_jmp_imm(cd, s3);
4662 /* class checkcast code */
4664 if (!super || !(super->flags & ACC_INTERFACE)) {
4666 i386_test_reg_reg(cd, s1, s1);
4667 i386_jcc(cd, I386_CC_Z, s3);
4670 i386_mov_membase_reg(cd, s1,
4671 OFFSET(java_objectheader, vftbl),
4675 codegen_addpatchref(cd, cd->mcodeptr,
4676 PATCHER_checkcast_class,
4677 (constant_classref *) iptr->target, 0);
4679 if (opt_showdisassemble) {
4680 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4684 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4685 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4686 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4688 i386_mov_membase32_reg(cd, REG_ITMP2,
4689 OFFSET(vftbl_t, baseval),
4692 /* if (s1 != REG_ITMP1) { */
4693 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
4694 /* i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
4695 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
4696 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
4698 /* i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
4701 i386_mov_membase32_reg(cd, REG_ITMP3,
4702 OFFSET(vftbl_t, baseval),
4704 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP3, REG_ITMP2);
4705 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP3);
4706 i386_mov_membase_reg(cd, REG_ITMP3,
4707 OFFSET(vftbl_t, diffval),
4709 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4710 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4714 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP2);
4715 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
4716 codegen_addxcastrefs(cd, cd->mcodeptr);
4718 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4720 store_reg_to_var_int(iptr->dst, d);
4724 case ICMD_ARRAYCHECKCAST: /* ..., objectref ==> ..., objectref */
4725 /* op1: 1... resolved, 0... not resolved */
4727 var_to_reg_int(s1, src, REG_ITMP1);
4728 M_AST(s1, REG_SP, 0 * 4);
4733 codegen_addpatchref(cd, cd->mcodeptr, bte->fp, iptr->target, 0);
4735 if (opt_showdisassemble) {
4736 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4742 a = (ptrint) bte->fp;
4745 M_AST_IMM((ptrint) iptr->target, REG_SP, 1 * 4);
4746 M_MOV_IMM((ptrint) a, REG_ITMP3);
4750 codegen_addxcastrefs(cd, cd->mcodeptr);
4752 var_to_reg_int(s1, src, REG_ITMP1);
4753 d = reg_of_var(rd, iptr->dst, s1);
4755 store_reg_to_var_int(iptr->dst, d);
4758 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
4760 /* op1: 0 == array, 1 == class */
4761 /* val.a: (classinfo*) superclass */
4762 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4763 /* EAX: S|D|YES ECX: YES S|D|EDX: S|D|YES OUTPUT: REG_NULL*/
4764 /* ????? Really necessary to block all ????? */
4766 /* superclass is an interface:
4768 * return (sub != NULL) &&
4769 * (sub->vftbl->interfacetablelength > super->index) &&
4770 * (sub->vftbl->interfacetable[-super->index] != NULL);
4772 * superclass is a class:
4774 * return ((sub != NULL) && (0
4775 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4776 * super->vftbl->diffvall));
4781 vftbl_t *supervftbl;
4784 super = (classinfo *) iptr->val.a;
4791 superindex = super->index;
4792 supervftbl = super->vftbl;
4795 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4796 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4799 var_to_reg_int(s1, src, REG_ITMP1);
4800 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
4802 M_INTMOVE(s1, REG_ITMP1);
4806 /* calculate interface instanceof code size */
4808 s2 = 2; /* mov_membase_reg */
4809 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
4811 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
4812 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
4813 2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4816 s2 += (opt_showdisassemble ? 5 : 0);
4818 /* calculate class instanceof code size */
4820 s3 = 2; /* mov_membase_reg */
4821 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
4822 s3 += 5; /* mov_imm_reg */
4824 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
4826 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
4828 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
4830 s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
4831 2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
4834 s3 += (opt_showdisassemble ? 5 : 0);
4836 i386_alu_reg_reg(cd, ALU_XOR, d, d);
4838 /* if class is not resolved, check which code to call */
4841 i386_test_reg_reg(cd, s1, s1);
4842 i386_jcc(cd, I386_CC_Z, 5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
4844 codegen_addpatchref(cd, cd->mcodeptr,
4845 PATCHER_checkcast_instanceof_flags,
4846 (constant_classref *) iptr->target, 0);
4848 if (opt_showdisassemble) {
4849 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4852 i386_mov_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
4853 i386_alu_imm32_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
4854 i386_jcc(cd, I386_CC_Z, s2 + 5);
4857 /* interface instanceof code */
4859 if (!super || (super->flags & ACC_INTERFACE)) {
4861 i386_test_reg_reg(cd, s1, s1);
4862 i386_jcc(cd, I386_CC_Z, s2);
4865 i386_mov_membase_reg(cd, s1,
4866 OFFSET(java_objectheader, vftbl),
4870 codegen_addpatchref(cd, cd->mcodeptr,
4871 PATCHER_checkcast_instanceof_interface,
4872 (constant_classref *) iptr->target, 0);
4874 if (opt_showdisassemble) {
4875 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4879 i386_mov_membase32_reg(cd, REG_ITMP1,
4880 OFFSET(vftbl_t, interfacetablelength),
4882 i386_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
4883 i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4885 a = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
4886 6 /* jcc */ + 5 /* mov_imm_reg */);
4888 i386_jcc(cd, I386_CC_LE, a);
4889 i386_mov_membase32_reg(cd, REG_ITMP1,
4890 OFFSET(vftbl_t, interfacetable[0]) -
4891 superindex * sizeof(methodptr*),
4893 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
4894 /* i386_setcc_reg(cd, I386_CC_A, d); */
4895 /* i386_jcc(cd, I386_CC_BE, 5); */
4896 i386_jcc(cd, I386_CC_E, 5);
4897 i386_mov_imm_reg(cd, 1, d);
4900 i386_jmp_imm(cd, s3);
4903 /* class instanceof code */
4905 if (!super || !(super->flags & ACC_INTERFACE)) {
4907 i386_test_reg_reg(cd, s1, s1);
4908 i386_jcc(cd, I386_CC_Z, s3);
4911 i386_mov_membase_reg(cd, s1,
4912 OFFSET(java_objectheader, vftbl),
4916 codegen_addpatchref(cd, cd->mcodeptr,
4917 PATCHER_instanceof_class,
4918 (constant_classref *) iptr->target, 0);
4920 if (opt_showdisassemble) {
4921 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4925 i386_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
4926 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4927 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4929 i386_mov_membase_reg(cd, REG_ITMP1,
4930 OFFSET(vftbl_t, baseval),
4932 i386_mov_membase_reg(cd, REG_ITMP2,
4933 OFFSET(vftbl_t, diffval),
4935 i386_mov_membase_reg(cd, REG_ITMP2,
4936 OFFSET(vftbl_t, baseval),
4938 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4939 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4941 i386_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
4942 i386_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
4943 i386_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
4944 i386_jcc(cd, I386_CC_A, 5);
4945 i386_mov_imm_reg(cd, 1, d);
4947 store_reg_to_var_int(iptr->dst, d);
4953 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4954 /* op1 = dimension, val.a = array descriptor */
4955 /* REG_RES Register usage: see icmd_uses_reg_res.inc */
4956 /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/
4958 /* check for negative sizes and copy sizes to stack if necessary */
4960 MCODECHECK((iptr->op1 << 1) + 64);
4962 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4963 /* copy SAVEDVAR sizes to stack */
4965 if (src->varkind != ARGVAR) {
4966 if (src->flags & INMEMORY) {
4967 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
4968 M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4);
4971 M_IST(src->regoff, REG_SP, (s1 + 3) * 4);
4976 /* is a patcher function set? */
4979 codegen_addpatchref(cd, cd->mcodeptr,
4980 (functionptr) (ptrint) iptr->target,
4983 if (opt_showdisassemble) {
4984 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4990 a = (ptrint) iptr->val.a;
4993 /* a0 = dimension count */
4995 i386_mov_imm_membase(cd, iptr->op1, REG_SP, 0 * 4);
4997 /* a1 = arraydescriptor */
4999 i386_mov_imm_membase(cd, a, REG_SP, 1 * 4);
5001 /* a2 = pointer to dimensions = stack pointer */
5003 M_MOV(REG_SP, REG_ITMP1);
5004 M_AADD_IMM(3 * 4, REG_ITMP1);
5005 M_AST(REG_ITMP1, REG_SP, 2 * 4);
5007 M_MOV_IMM((ptrint) BUILTIN_multianewarray, REG_ITMP1);
5010 /* check for exception before result assignment */
5014 codegen_addxexceptionrefs(cd, cd->mcodeptr);
5016 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
5017 M_INTMOVE(REG_RESULT, s1);
5018 store_reg_to_var_int(iptr->dst, s1);
5022 throw_cacao_exception_exit(string_java_lang_InternalError,
5023 "Unknown ICMD %d", iptr->opc);
5026 } /* for instruction */
5028 /* copy values to interface registers */
5030 src = bptr->outstack;
5031 len = bptr->outdepth;
5038 if ((src->varkind != STACKVAR)) {
5040 if (IS_FLT_DBL_TYPE(s2)) {
5041 var_to_reg_flt(s1, src, REG_FTMP1);
5042 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5043 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
5046 log_text("double store");
5048 /* M_DST(s1, REG_SP, 4 * interfaces[len][s2].regoff); */
5052 var_to_reg_int(s1, src, REG_ITMP1);
5053 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
5054 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
5055 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
5058 i386_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
5062 if (rd->interfaces[len][s2].flags & INMEMORY) {
5063 M_LNGMEMMOVE(s1, rd->interfaces[len][s2].regoff);
5066 log_text("copy interface registers: longs have to be in memory (end)");
5074 } /* if (bptr -> flags >= BBREACHED) */
5075 } /* for basic block */
5077 codegen_createlinenumbertable(cd);
5084 /* generate ArithmeticException stubs */
5088 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
5089 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
5090 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5092 xcodeptr - cd->mcodebase - (5 + 6));
5096 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5098 cd->mcodeptr - cd->mcodebase);
5102 M_MOV_IMM(0, REG_ITMP2_XPC); /* 5 bytes */
5103 dseg_adddata(cd, cd->mcodeptr);
5104 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC); /* 6 bytes */
5106 if (xcodeptr != NULL) {
5107 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5110 xcodeptr = cd->mcodeptr;
5112 M_ASUB_IMM(4 * 4, REG_SP);
5114 M_AST_IMM(0, REG_SP, 0 * 4);
5115 dseg_adddata(cd, cd->mcodeptr);
5116 M_MOV(REG_SP, REG_ITMP3);
5117 M_AADD_IMM(4 * 4, REG_ITMP3);
5118 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5119 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5120 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5121 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5123 M_MOV_IMM((ptrint) stacktrace_inline_arithmeticexception,
5127 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5128 M_AADD_IMM(4 * 4, REG_SP);
5130 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5135 /* generate ArrayIndexOutOfBoundsException stubs */
5139 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
5140 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5142 cd->mcodeptr - cd->mcodebase);
5146 /* move index register into REG_ITMP1 */
5148 M_INTMOVE(bref->reg, REG_ITMP1); /* 2 bytes */
5150 M_MOV_IMM(0, REG_ITMP2_XPC); /* 5 bytes */
5151 dseg_adddata(cd, cd->mcodeptr);
5152 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC); /* 6 bytes */
5154 if (xcodeptr != NULL) {
5155 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5158 xcodeptr = cd->mcodeptr;
5160 M_ASUB_IMM(5 * 4, REG_SP);
5162 M_AST_IMM(0, REG_SP, 0 * 4);
5163 dseg_adddata(cd, cd->mcodeptr);
5164 M_MOV(REG_SP, REG_ITMP3);
5165 M_AADD_IMM(5 * 4, REG_ITMP3);
5166 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5167 M_ALD(REG_ITMP3, REG_SP, (5 + parentargs_base) * 4);
5168 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5169 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5170 M_AST(REG_ITMP1, REG_SP, 4 * 4); /* don't use REG_ITMP1 till here */
5172 M_MOV_IMM((ptrint) stacktrace_inline_arrayindexoutofboundsexception,
5176 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5177 M_AADD_IMM(5 * 4, REG_SP);
5179 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5184 /* generate ArrayStoreException stubs */
5188 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
5189 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
5190 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5192 xcodeptr - cd->mcodebase - (5 + 6));
5196 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5198 cd->mcodeptr - cd->mcodebase);
5202 M_MOV_IMM(0, REG_ITMP2_XPC); /* 5 bytes */
5203 dseg_adddata(cd, cd->mcodeptr);
5204 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC); /* 6 bytes */
5206 if (xcodeptr != NULL) {
5207 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5210 xcodeptr = cd->mcodeptr;
5212 M_ASUB_IMM(4 * 4, REG_SP);
5214 M_AST_IMM(0, REG_SP, 0 * 4);
5215 dseg_adddata(cd, cd->mcodeptr);
5216 M_MOV(REG_SP, REG_ITMP3);
5217 M_AADD_IMM(4 * 4, REG_ITMP3);
5218 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5219 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5220 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5221 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5223 M_MOV_IMM((ptrint) stacktrace_inline_arraystoreexception,
5227 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5228 M_AADD_IMM(4 * 4, REG_SP);
5230 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5235 /* generate ClassCastException stubs */
5239 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
5240 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
5241 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5243 xcodeptr - cd->mcodebase - (5 + 6));
5247 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5249 cd->mcodeptr - cd->mcodebase);
5253 M_MOV_IMM(0, REG_ITMP2_XPC); /* 5 bytes */
5254 dseg_adddata(cd, cd->mcodeptr);
5255 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC); /* 6 bytes */
5257 if (xcodeptr != NULL) {
5258 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5261 xcodeptr = cd->mcodeptr;
5263 M_ASUB_IMM(4 * 4, REG_SP);
5265 M_AST_IMM(0, REG_SP, 0 * 4);
5266 dseg_adddata(cd, cd->mcodeptr);
5267 M_MOV(REG_SP, REG_ITMP3);
5268 M_AADD_IMM(4 * 4, REG_ITMP3);
5269 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5270 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5271 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5272 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5274 M_MOV_IMM((ptrint) stacktrace_inline_classcastexception, REG_ITMP3);
5277 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5278 M_AADD_IMM(4 * 4, REG_SP);
5280 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5285 /* generate NullPointerException stubs */
5289 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
5290 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
5291 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5293 xcodeptr - cd->mcodebase - (5 + 6));
5297 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5299 cd->mcodeptr - cd->mcodebase);
5303 M_MOV_IMM(0, REG_ITMP2_XPC); /* 5 bytes */
5304 dseg_adddata(cd, cd->mcodeptr);
5305 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC); /* 6 bytes */
5307 if (xcodeptr != NULL) {
5308 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5311 xcodeptr = cd->mcodeptr;
5313 M_ASUB_IMM(4 * 4, REG_SP);
5315 M_AST_IMM(0, REG_SP, 0 * 4);
5316 dseg_adddata(cd, cd->mcodeptr);
5317 M_MOV(REG_SP, REG_ITMP3);
5318 M_AADD_IMM(4 * 4, REG_ITMP3);
5319 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5320 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5321 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5322 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5324 M_MOV_IMM((ptrint) stacktrace_inline_nullpointerexception,
5328 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5329 M_AADD_IMM(4 * 4, REG_SP);
5331 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5336 /* generate exception check stubs */
5340 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
5341 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
5342 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5344 xcodeptr - cd->mcodebase - (5 + 6));
5348 gen_resolvebranch(cd->mcodebase + bref->branchpos,
5350 cd->mcodeptr - cd->mcodebase);
5354 M_MOV_IMM(0, REG_ITMP2_XPC); /* 5 bytes */
5355 dseg_adddata(cd, cd->mcodeptr);
5356 M_AADD_IMM32(bref->branchpos - 6, REG_ITMP2_XPC); /* 6 bytes */
5358 if (xcodeptr != NULL) {
5359 M_JMP_IMM((xcodeptr - cd->mcodeptr) - 5);
5362 xcodeptr = cd->mcodeptr;
5364 M_ASUB_IMM(4 * 4, REG_SP);
5366 M_AST_IMM(0, REG_SP, 0 * 4);
5367 dseg_adddata(cd, cd->mcodeptr);
5368 M_MOV(REG_SP, REG_ITMP3);
5369 M_AADD_IMM(4 * 4, REG_ITMP3);
5370 M_AST(REG_ITMP3, REG_SP, 1 * 4);
5371 M_ALD(REG_ITMP3, REG_SP, (4 + parentargs_base) * 4);
5372 M_AST(REG_ITMP3, REG_SP, 2 * 4);
5373 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
5375 M_MOV_IMM((ptrint) stacktrace_inline_fillInStackTrace, REG_ITMP3);
5378 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
5379 M_AADD_IMM(4 * 4, REG_SP);
5381 M_MOV_IMM((ptrint) asm_handle_exception, REG_ITMP3);
5386 /* generate code patching stub call code */
5393 tmpcd = DNEW(codegendata);
5395 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5396 /* check code segment size */
5400 /* Get machine code which is patched back in later. A */
5401 /* `call rel32' is 5 bytes long. */
5403 xcodeptr = cd->mcodebase + pref->branchpos;
5404 mcode = *((u8 *) xcodeptr);
5406 /* patch in `call rel32' to call the following code */
5408 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5409 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5411 /* move pointer to java_objectheader onto stack */
5413 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5414 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
5415 off = dseg_addaddress(cd, NULL); /* vftbl */
5417 M_MOV_IMM(0, REG_ITMP3);
5418 dseg_adddata(cd, cd->mcodeptr);
5419 M_AADD_IMM(off, REG_ITMP3);
5425 /* move machine code bytes and classinfo pointer into registers */
5427 M_PUSH_IMM((ptrint) (mcode >> 32));
5428 M_PUSH_IMM((ptrint) mcode);
5429 M_PUSH_IMM((ptrint) pref->ref);
5430 M_PUSH_IMM((ptrint) pref->patcher);
5432 M_MOV_IMM((ptrint) asm_wrapper_patcher, REG_ITMP3);
5438 codegen_finish(m, cd, (ptrint) (cd->mcodeptr - cd->mcodebase));
5442 /* createcompilerstub **********************************************************
5444 Creates a stub routine which calls the compiler.
5446 *******************************************************************************/
5448 #define COMPILERSTUB_SIZE 12
5450 functionptr createcompilerstub(methodinfo *m)
5452 u1 *s; /* memory to hold the stub */
5456 s = CNEW(u1, COMPILERSTUB_SIZE);
5458 /* mark start of dump memory area */
5460 dumpsize = dump_size();
5462 cd = DNEW(codegendata);
5465 i386_mov_imm_reg(cd, (ptrint) m, REG_ITMP1);
5467 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
5468 i386_mov_imm_reg(cd, (ptrint) asm_call_jit_compiler, REG_ITMP3);
5469 i386_jmp_reg(cd, REG_ITMP3);
5471 #if defined(STATISTICS)
5473 count_cstub_len += COMPILERSTUB_SIZE;
5476 /* release dump area */
5478 dump_release(dumpsize);
5480 return (functionptr) (ptrint) s;
5484 /* createnativestub ************************************************************
5486 Creates a stub routine which calls a native method.
5488 *******************************************************************************/
5490 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5491 /* this way we can call the function directly with a memory call */
5493 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
5496 functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
5497 registerdata *rd, methoddesc *nmd)
5502 s4 i, j; /* count variables */
5506 /* set some variables */
5509 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
5511 /* calculate stackframe size */
5514 sizeof(stackframeinfo) / SIZEOF_VOID_P +
5515 sizeof(localref_table) / SIZEOF_VOID_P +
5516 1 + /* function pointer */
5517 4 * 4 + /* 4 arguments (start_native_call) */
5521 /* create method header */
5523 (void) dseg_addaddress(cd, m); /* MethodPointer */
5524 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
5525 (void) dseg_adds4(cd, 0); /* IsSync */
5526 (void) dseg_adds4(cd, 0); /* IsLeaf */
5527 (void) dseg_adds4(cd, 0); /* IntSave */
5528 (void) dseg_adds4(cd, 0); /* FltSave */
5529 (void) dseg_addlinenumbertablesize(cd);
5530 (void) dseg_adds4(cd, 0); /* ExTableSize */
5533 /* initialize mcode variables */
5535 cd->mcodeptr = (u1 *) cd->mcodebase;
5536 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
5539 /* calculate stackframe size for native function */
5541 M_ASUB_IMM(stackframesize * 4, REG_SP);
5548 i386_alu_imm_reg(cd, ALU_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
5550 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
5551 t = md->paramtypes[p].type;
5552 if (IS_INT_LNG_TYPE(t)) {
5553 if (IS_2_WORD_TYPE(t)) {
5554 i386_mov_membase_reg(cd, REG_SP,
5555 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off, REG_ITMP1);
5556 i386_mov_membase_reg(cd, REG_SP,
5557 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off + 4, REG_ITMP2);
5558 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5559 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5561 } else if (t == TYPE_ADR) {
5562 i386_mov_membase_reg(cd, REG_SP,
5563 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off, REG_ITMP1);
5564 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
5565 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5566 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5569 i386_mov_membase_reg(cd, REG_SP,
5570 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off, EAX);
5572 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
5573 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
5577 if (!IS_2_WORD_TYPE(t)) {
5578 i386_flds_membase(cd, REG_SP,
5579 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off);
5580 i386_fstps_membase(cd, REG_SP, p * 8);
5581 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
5582 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5585 i386_fldl_membase(cd, REG_SP,
5586 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off);
5587 i386_fstpl_membase(cd, REG_SP, p * 8);
5590 stack_off += (IS_2_WORD_TYPE(t)) ? 8 : 4;
5593 i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
5594 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
5595 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5596 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
5599 i386_mov_imm_membase(cd, (ptrint) m, REG_SP, TRACE_ARGS_NUM * 8);
5601 i386_mov_imm_reg(cd, (ptrint) builtin_trace_args, REG_ITMP1);
5602 i386_call_reg(cd, REG_ITMP1);
5604 i386_alu_imm_reg(cd, ALU_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
5607 /* get function address (this must happen before the stackframeinfo) */
5609 #if !defined(ENABLE_STATICVM)
5611 codegen_addpatchref(cd, cd->mcodeptr, PATCHER_resolve_native, m, 0);
5613 if (opt_showdisassemble) {
5614 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
5619 M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
5621 /* Mark the whole fpu stack as free for native functions (only for saved */
5622 /* register count == 0). */
5624 i386_ffree_reg(cd, 0);
5625 i386_ffree_reg(cd, 1);
5626 i386_ffree_reg(cd, 2);
5627 i386_ffree_reg(cd, 3);
5628 i386_ffree_reg(cd, 4);
5629 i386_ffree_reg(cd, 5);
5630 i386_ffree_reg(cd, 6);
5631 i386_ffree_reg(cd, 7);
5633 /* prepare data structures for native function call */
5635 M_MOV(REG_SP, REG_ITMP1);
5636 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5638 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5639 M_IST_IMM(0, REG_SP, 1 * 4);
5640 dseg_adddata(cd, cd->mcodeptr);
5642 M_MOV(REG_SP, REG_ITMP2);
5643 M_AADD_IMM(stackframesize * 4 + SIZEOF_VOID_P, REG_ITMP2);
5645 M_AST(REG_ITMP2, REG_SP, 2 * 4);
5646 M_ALD(REG_ITMP3, REG_SP, stackframesize * 4);
5647 M_AST(REG_ITMP3, REG_SP, 3 * 4);
5648 M_MOV_IMM((ptrint) codegen_start_native_call, REG_ITMP1);
5651 M_ALD(REG_ITMP3, REG_SP, 4 * 4);
5653 /* copy arguments into new stackframe */
5655 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
5656 t = md->paramtypes[i].type;
5658 if (!md->params[i].inmemory) {
5659 /* no integer argument registers */
5660 } else { /* float/double in memory can be copied like int/longs */
5661 s1 = (md->params[i].regoff + stackframesize + 1) * 4;
5662 s2 = nmd->params[j].regoff * 4;
5664 M_ILD(REG_ITMP1, REG_SP, s1);
5665 M_IST(REG_ITMP1, REG_SP, s2);
5666 if (IS_2_WORD_TYPE(t)) {
5667 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
5668 M_IST(REG_ITMP1, REG_SP, s2 + 4);
5673 /* if function is static, put class into second argument */
5675 if (m->flags & ACC_STATIC)
5676 M_AST_IMM((ptrint) m->class, REG_SP, 1 * 4);
5678 /* put env into first argument */
5680 M_AST_IMM((ptrint) &env, REG_SP, 0 * 4);
5682 /* call the native function */
5686 /* save return value */
5688 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5689 if (IS_2_WORD_TYPE(md->returntype.type))
5690 M_IST(REG_RESULT2, REG_SP, 2 * 4);
5691 M_IST(REG_RESULT, REG_SP, 1 * 4);
5694 if (IS_2_WORD_TYPE(md->returntype.type))
5695 i386_fstl_membase(cd, REG_SP, 1 * 4);
5697 i386_fsts_membase(cd, REG_SP, 1 * 4);
5700 /* remove data structures for native function call */
5702 M_MOV(REG_SP, REG_ITMP1);
5703 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
5705 M_AST(REG_ITMP1, REG_SP, 0 * 4);
5706 M_MOV_IMM((ptrint) codegen_finish_native_call, REG_ITMP1);
5710 M_ASUB_IMM(4 + 8 + 8 + 4, REG_SP);
5712 i386_mov_imm_membase(cd, (ptrint) m, REG_SP, 0);
5714 M_IST(REG_RESULT, REG_SP, 4);
5715 M_IST(REG_RESULT2, REG_SP, 4 + 4);
5717 i386_fstl_membase(cd, REG_SP, 4 + 8);
5718 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5720 M_MOV_IMM((ptrint) builtin_displaymethodstop, REG_ITMP1);
5723 M_AADD_IMM(4 + 8 + 8 + 4, REG_SP);
5726 /* check for exception */
5728 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5729 /* i386_call_mem(cd, (ptrint) builtin_get_exceptionptrptr); */
5730 i386_call_mem(cd, (ptrint) &callgetexceptionptrptr);
5732 M_MOV_IMM((ptrint) &_exceptionptr, REG_RESULT);
5734 /* we can't use REG_ITMP3 == REG_RESULT2 */
5735 M_ALD(REG_ITMP2, REG_RESULT, 0);
5737 /* restore return value */
5739 if (IS_INT_LNG_TYPE(md->returntype.type)) {
5740 if (IS_2_WORD_TYPE(md->returntype.type))
5741 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
5742 M_ILD(REG_RESULT, REG_SP, 1 * 4);
5745 if (IS_2_WORD_TYPE(md->returntype.type))
5746 i386_fldl_membase(cd, REG_SP, 1 * 4);
5748 i386_flds_membase(cd, REG_SP, 1 * 4);
5751 M_AADD_IMM(stackframesize * 4, REG_SP);
5758 /* handle exception */
5760 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5761 i386_push_reg(cd, REG_ITMP2);
5762 /* i386_call_mem(cd, (ptrint) builtin_get_exceptionptrptr); */
5763 i386_call_mem(cd, (ptrint) &callgetexceptionptrptr);
5764 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5765 i386_pop_reg(cd, REG_ITMP1_XPTR);
5767 M_MOV(REG_ITMP2, REG_ITMP1_XPTR);
5768 M_MOV_IMM((ptrint) &_exceptionptr, REG_ITMP2);
5769 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5771 M_ALD(REG_ITMP2_XPC, REG_SP, 0);
5772 M_ASUB_IMM(2, REG_ITMP2_XPC);
5774 M_MOV_IMM((ptrint) asm_handle_nat_exception, REG_ITMP3);
5778 /* process patcher calls **************************************************/
5786 tmpcd = DNEW(codegendata);
5788 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
5789 /* Get machine code which is patched back in later. A */
5790 /* `call rel32' is 5 bytes long. */
5792 xcodeptr = cd->mcodebase + pref->branchpos;
5793 mcode = *((u8 *) xcodeptr);
5795 /* patch in `call rel32' to call the following code */
5797 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5798 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5800 /* move pointer to java_objectheader onto stack */
5802 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5803 /* create a virtual java_objectheader */
5805 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
5806 disp = dseg_addaddress(cd, NULL); /* vftbl */
5808 M_MOV_IMM(0, REG_ITMP3);
5809 dseg_adddata(cd, cd->mcodeptr);
5810 M_AADD_IMM(disp, REG_ITMP3);
5816 /* move machine code bytes and classinfo pointer onto stack */
5818 M_PUSH_IMM((ptrint) (mcode >> 32));
5819 M_PUSH_IMM((ptrint) mcode);
5820 M_PUSH_IMM((ptrint) pref->ref);
5821 M_PUSH_IMM((ptrint) pref->patcher);
5823 M_MOV_IMM((ptrint) asm_wrapper_patcher, REG_ITMP3);
5828 codegen_finish(m, cd, (s4) ((u1 *) cd->mcodeptr - cd->mcodebase));
5830 return m->entrypoint;
5835 * These are local overrides for various environment variables in Emacs.
5836 * Please do not remove this and leave it at the end of the file, where
5837 * Emacs will automagically detect them.
5838 * ---------------------------------------------------------------------
5841 * indent-tabs-mode: t