1 /* src/vm/jit/i386/codegen.c - machine code generator for i386
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Andreas Krall
30 Changes: Joseph Wenninger
34 $Id: codegen.c 5275 2006-08-24 18:42:48Z twisti $
46 #include "vm/jit/i386/md-abi.h"
48 #include "vm/jit/i386/codegen.h"
49 #include "vm/jit/i386/md-emit.h"
51 #include "mm/memory.h"
52 #include "native/jni.h"
53 #include "native/native.h"
55 #if defined(ENABLE_THREADS)
56 # include "threads/native/lock.h"
59 #include "vm/builtin.h"
60 #include "vm/exceptions.h"
61 #include "vm/global.h"
62 #include "vm/loader.h"
63 #include "vm/options.h"
64 #include "vm/stringlocal.h"
67 #include "vm/jit/asmpart.h"
68 #include "vm/jit/codegen-common.h"
69 #include "vm/jit/dseg.h"
70 #include "vm/jit/emit.h"
71 #include "vm/jit/jit.h"
72 #include "vm/jit/parse.h"
73 #include "vm/jit/patcher.h"
74 #include "vm/jit/reg.h"
75 #include "vm/jit/replace.h"
77 #if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
78 # include "vm/jit/allocator/lsra.h"
80 #if defined(ENABLE_SSA)
81 # include "vm/jit/optimizing/lsra.h"
82 # include "vm/jit/optimizing/ssa.h"
86 /* codegen *********************************************************************
88 Generates machine code.
90 *******************************************************************************/
92 #if defined(ENABLE_SSA)
93 void cg_move(codegendata *cd, s4 type, s4 src_regoff, s4 src_flags,
94 s4 dst_regoff, s4 dst_flags);
95 void codegen_insert_phi_moves(codegendata *cd, registerdata *rd, lsradata *ls,
99 bool codegen(jitdata *jd)
105 s4 len, s1, s2, s3, d, disp;
112 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
113 builtintable_entry *bte;
115 rplpoint *replacementpoint;
116 #if defined(ENABLE_SSA)
118 bool last_cmd_was_goto;
120 last_cmd_was_goto = false;
124 /* get required compiler data */
131 /* prevent compiler warnings */
141 s4 savedregs_num = 0;
144 /* space to save used callee saved registers */
146 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
148 /* float register are saved on 2 4-byte stackslots */
149 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
151 cd->stackframesize = rd->memuse + savedregs_num;
154 #if defined(ENABLE_THREADS)
155 /* space to save argument of monitor_enter */
157 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
158 /* reserve 2 slots for long/double return values for monitorexit */
160 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
161 cd->stackframesize += 2;
163 cd->stackframesize++;
167 /* create method header */
169 /* Keep stack of non-leaf functions 16-byte aligned. */
171 if (!jd->isleafmethod)
172 cd->stackframesize |= 0x3;
174 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
175 (void) dseg_adds4(cd, cd->stackframesize * 4); /* FrameSize */
177 #if defined(ENABLE_THREADS)
178 /* IsSync contains the offset relative to the stack pointer for the
179 argument of monitor_exit used in the exception handler. Since the
180 offset could be zero and give a wrong meaning of the flag it is
184 if (checksync && (m->flags & ACC_SYNCHRONIZED))
185 (void) dseg_adds4(cd, (rd->memuse + 1) * 4); /* IsSync */
188 (void) dseg_adds4(cd, 0); /* IsSync */
190 (void) dseg_adds4(cd, jd->isleafmethod); /* IsLeaf */
191 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
192 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
194 /* adds a reference for the length of the line number counter. We don't
195 know the size yet, since we evaluate the information during code
196 generation, to save one additional iteration over the whole
197 instructions. During code optimization the position could have changed
198 to the information gotten from the class file */
199 (void) dseg_addlinenumbertablesize(cd);
201 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
203 /* create exception table */
205 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
206 dseg_addtarget(cd, ex->start);
207 dseg_addtarget(cd, ex->end);
208 dseg_addtarget(cd, ex->handler);
209 (void) dseg_addaddress(cd, ex->catchtype.cls);
212 /* generate method profiling code */
214 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
215 /* count frequency */
217 M_MOV_IMM(code, REG_ITMP3);
218 M_IADD_IMM_MEMBASE(1, REG_ITMP3, OFFSET(codeinfo, frequency));
221 /* create stack frame (if necessary) */
223 if (cd->stackframesize)
224 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
226 /* save return address and used callee saved registers */
228 p = cd->stackframesize;
229 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
230 p--; M_AST(rd->savintregs[i], REG_SP, p * 4);
232 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
233 p-=2; emit_fld_reg(cd, rd->savfltregs[i]); emit_fstpl_membase(cd, REG_SP, p * 4);
236 /* take arguments out of register or stack frame */
241 for (p = 0, l = 0; p < md->paramcount; p++) {
242 t = md->paramtypes[p].type;
243 #if defined(ENABLE_SSA)
248 var = &(rd->locals[l][t]);
250 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
254 s1 = md->params[p].regoff;
256 if (IS_INT_LNG_TYPE(t)) { /* integer args */
257 if (!md->params[p].inmemory) { /* register arguments */
258 log_text("integer register argument");
260 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
261 /* rd->argintregs[md->params[p].regoff -> var->regoff */
263 else { /* reg arg -> spilled */
264 /* rd->argintregs[md->params[p].regoff -> var->regoff * 4 */
267 else { /* stack arguments */
268 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
269 emit_mov_membase_reg( /* + 4 for return address */
270 cd, REG_SP, (cd->stackframesize + s1) * 4 + 4, var->regoff);
271 /* + 4 for return address */
273 else { /* stack arg -> spilled */
274 if (!IS_2_WORD_TYPE(t)) {
275 #if defined(ENABLE_SSA)
276 /* no copy avoiding by now possible with SSA */
278 emit_mov_membase_reg( /* + 4 for return address */
279 cd, REG_SP, (cd->stackframesize + s1) * 4 + 4,
281 emit_mov_reg_membase(
282 cd, REG_ITMP1, REG_SP, var->regoff * 4);
285 #endif /*defined(ENABLE_SSA)*/
286 /* reuse Stackslotand avoid copying */
287 var->regoff = cd->stackframesize + s1 + 1;
291 #if defined(ENABLE_SSA)
292 /* no copy avoiding by now possible with SSA */
294 emit_mov_membase_reg( /* + 4 for return address */
295 cd, REG_SP, (cd->stackframesize + s1) * 4 + 4,
297 emit_mov_reg_membase(
298 cd, REG_ITMP1, REG_SP, var->regoff * 4);
299 emit_mov_membase_reg( /* + 4 for return address */
300 cd, REG_SP, (cd->stackframesize + s1) * 4 + 4 + 4,
302 emit_mov_reg_membase(
303 cd, REG_ITMP1, REG_SP, var->regoff * 4 + 4);
306 #endif /*defined(ENABLE_SSA)*/
307 /* reuse Stackslotand avoid copying */
308 var->regoff = cd->stackframesize + s1 + 1;
313 else { /* floating args */
314 if (!md->params[p].inmemory) { /* register arguments */
315 log_text("There are no float argument registers!");
317 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
318 /* rd->argfltregs[md->params[p].regoff -> var->regoff */
319 } else { /* reg arg -> spilled */
320 /* rd->argfltregs[md->params[p].regoff -> var->regoff * 4 */
324 else { /* stack arguments */
325 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
328 cd, REG_SP, (cd->stackframesize + s1) * 4 + 4);
330 /* emit_fstp_reg(cd, var->regoff + fpu_st_offset); */
335 cd, REG_SP, (cd->stackframesize + s1) * 4 + 4);
337 /* emit_fstp_reg(cd, var->regoff + fpu_st_offset); */
340 } else { /* stack-arg -> spilled */
341 #if defined(ENABLE_SSA)
342 /* no copy avoiding by now possible with SSA */
344 emit_mov_membase_reg(
345 cd, REG_SP, (cd->stackframesize + s1) * 4 + 4, REG_ITMP1);
346 emit_mov_reg_membase(
347 cd, REG_ITMP1, REG_SP, var->regoff * 4);
350 cd, REG_SP, (cd->stackframesize + s1) * 4 + 4);
351 emit_fstps_membase(cd, REG_SP, var->regoff * 4);
355 cd, REG_SP, (cd->stackframesize + s1) * 4 + 4);
356 emit_fstpl_membase(cd, REG_SP, var->regoff * 4);
360 #endif /*defined(ENABLE_SSA)*/
361 /* reuse Stackslotand avoid copying */
362 var->regoff = cd->stackframesize + s1 + 1;
368 /* call monitorenter function */
370 #if defined(ENABLE_THREADS)
371 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
374 if (m->flags & ACC_STATIC) {
375 M_MOV_IMM(&m->class->object.header, REG_ITMP1);
378 M_ALD(REG_ITMP1, REG_SP, cd->stackframesize * 4 + 4);
381 codegen_add_nullpointerexception_ref(cd);
384 M_AST(REG_ITMP1, REG_SP, s1 * 4);
385 M_AST(REG_ITMP1, REG_SP, 0 * 4);
386 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP3);
391 /* copy argument registers to stack and call trace function with pointer
392 to arguments on stack.
396 if (opt_verbosecall) {
398 s1 = INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4 + 4 + cd->stackframesize * 4;
400 M_ISUB_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
402 /* save temporary registers for leaf methods */
404 for (p = 0; p < INT_TMP_CNT; p++)
405 M_IST(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
407 for (p = 0, l = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
408 t = md->paramtypes[p].type;
410 if (IS_INT_LNG_TYPE(t)) {
411 if (IS_2_WORD_TYPE(t)) {
412 emit_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
413 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
414 emit_mov_membase_reg(cd, REG_SP, s1 + stack_off + 4, REG_ITMP1);
415 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
417 } else if (t == TYPE_ADR) {
419 emit_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
420 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
421 emit_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
422 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
425 emit_mov_membase_reg(cd, REG_SP, s1 + stack_off, EAX);
427 emit_mov_reg_membase(cd, EAX, REG_SP, p * 8);
428 emit_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
432 if (!IS_2_WORD_TYPE(t)) {
433 emit_flds_membase(cd, REG_SP, s1 + stack_off);
434 emit_fstps_membase(cd, REG_SP, p * 8);
435 emit_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
436 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
439 emit_fldl_membase(cd, REG_SP, s1 + stack_off);
440 emit_fstpl_membase(cd, REG_SP, p * 8);
443 stack_off += (IS_2_WORD_TYPE(t)) ? 8 : 4;
446 /* fill up the remaining arguments */
447 emit_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
448 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
449 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
450 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
453 emit_mov_imm_membase(cd, (ptrint) m, REG_SP, TRACE_ARGS_NUM * 8);
454 emit_mov_imm_reg(cd, (ptrint) builtin_trace_args, REG_ITMP1);
455 emit_call_reg(cd, REG_ITMP1);
457 /* restore temporary registers for leaf methods */
459 for (p = 0; p < INT_TMP_CNT; p++)
460 M_ILD(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
462 M_IADD_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
464 #endif /* !defined(NDEBUG) */
468 #if defined(ENABLE_SSA)
469 /* with SSA Header is Basic Block 0 - insert phi Moves if necessary */
471 codegen_insert_phi_moves(cd, rd, ls, ls->basicblocks[0]);
474 /* end of header generation */
476 replacementpoint = jd->code->rplpoints;
478 /* walk through all basic blocks */
479 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
481 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
483 if (bptr->flags >= BBREACHED) {
485 /* branch resolving */
488 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
489 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
494 /* handle replacement points */
496 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
497 replacementpoint->pc = (u1*)bptr->mpc; /* will be resolved later */
501 assert(cd->lastmcodeptr <= cd->mcodeptr);
502 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
505 /* copy interface registers to their destination */
512 /* generate basic block profiling code */
514 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
515 /* count frequency */
517 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
518 M_IADD_IMM_MEMBASE(1, REG_ITMP3, bptr->nr * 4);
522 #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
523 # if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
526 # if defined(ENABLE_SSA)
528 last_cmd_was_goto = false;
532 if (bptr->type != BBTYPE_STD) {
533 if (!IS_2_WORD_TYPE(src->type)) {
534 if (bptr->type == BBTYPE_SBR) {
535 if (!(src->flags & INMEMORY))
540 emit_store(jd, NULL, src, d);
541 } else if (bptr->type == BBTYPE_EXH) {
542 if (!(src->flags & INMEMORY))
546 M_INTMOVE(REG_ITMP1, d);
547 emit_store(jd, NULL, src, d);
551 log_text("copy interface registers(EXH, SBR): longs have to be in memory (begin 1)");
559 #endif /* defined(ENABLE_LSRA) || defined(ENABLE_SSA) */
561 while (src != NULL) {
563 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
564 if (!IS_2_WORD_TYPE(src->type)) {
565 if (bptr->type == BBTYPE_SBR) {
566 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
568 emit_store(jd, NULL, src, d);
570 } else if (bptr->type == BBTYPE_EXH) {
571 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
572 M_INTMOVE(REG_ITMP1, d);
573 emit_store(jd, NULL, src, d);
576 log_text("copy interface registers: longs have to be in memory (begin 1)");
581 if (IS_LNG_TYPE(src->type))
582 d = codegen_reg_of_var(rd, 0, src, PACK_REGS(REG_ITMP1, REG_ITMP2));
584 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
585 /* d = codegen_reg_of_var(rd, 0, src, REG_IFTMP); */
587 if ((src->varkind != STACKVAR)) {
589 s1 = rd->interfaces[len][s2].regoff;
591 if (IS_FLT_DBL_TYPE(s2)) {
592 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
596 if (IS_2_WORD_TYPE(s2))
597 M_DLD(d, REG_SP, s1 * 4);
599 M_FLD(d, REG_SP, s1 * 4);
603 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
604 if (IS_2_WORD_TYPE(s2))
610 if (IS_2_WORD_TYPE(s2))
611 M_LLD(d, REG_SP, s1 * 4);
613 M_ILD(d, REG_SP, s1 * 4);
617 emit_store(jd, NULL, src, d);
624 /* walk through all instructions */
629 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
630 if (iptr->line != currentline) {
631 dseg_addlinenumber(cd, iptr->line);
632 currentline = iptr->line;
635 MCODECHECK(1024); /* 1kB should be enough */
638 case ICMD_INLINE_START:
640 insinfo_inline *insinfo = (insinfo_inline *) iptr->target;
641 #if defined(ENABLE_THREADS)
642 if (insinfo->synchronize) {
643 /* add monitor enter code */
644 if (insinfo->method->flags & ACC_STATIC) {
645 M_MOV_IMM(&insinfo->method->class->object.header, REG_ITMP1);
646 M_AST(REG_ITMP1, REG_SP, 0 * 4);
649 /* nullpointer check must have been performed before */
650 /* (XXX not done, yet) */
651 var = &(rd->locals[insinfo->synclocal][TYPE_ADR]);
652 if (var->flags & INMEMORY) {
653 emit_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP1);
654 M_AST(REG_ITMP1, REG_SP, 0 * 4);
657 M_AST(var->regoff, REG_SP, 0 * 4);
661 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP3);
665 dseg_addlinenumber_inline_start(cd, iptr);
669 case ICMD_INLINE_END:
671 insinfo_inline *insinfo = (insinfo_inline *) iptr->target;
673 dseg_addlinenumber_inline_end(cd, iptr);
674 dseg_addlinenumber(cd, iptr->line);
676 #if defined(ENABLE_THREADS)
677 if (insinfo->synchronize) {
678 /* add monitor exit code */
679 if (insinfo->method->flags & ACC_STATIC) {
680 M_MOV_IMM(&insinfo->method->class->object.header, REG_ITMP1);
681 M_AST(REG_ITMP1, REG_SP, 0 * 4);
684 var = &(rd->locals[insinfo->synclocal][TYPE_ADR]);
685 if (var->flags & INMEMORY) {
686 M_ALD(REG_ITMP1, REG_SP, var->regoff * 4);
687 M_AST(REG_ITMP1, REG_SP, 0 * 4);
690 M_AST(var->regoff, REG_SP, 0 * 4);
694 M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3);
701 case ICMD_NOP: /* ... ==> ... */
704 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
706 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
709 codegen_add_nullpointerexception_ref(cd);
712 /* constant operations ************************************************/
714 case ICMD_ICONST: /* ... ==> ..., constant */
715 /* op1 = 0, val.i = constant */
717 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
718 ICONST(d, iptr->val.i);
719 emit_store(jd, iptr, iptr->dst, d);
722 case ICMD_LCONST: /* ... ==> ..., constant */
723 /* op1 = 0, val.l = constant */
725 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
726 LCONST(d, iptr->val.l);
727 emit_store(jd, iptr, iptr->dst, d);
730 case ICMD_FCONST: /* ... ==> ..., constant */
731 /* op1 = 0, val.f = constant */
733 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
734 if (iptr->val.f == 0.0) {
738 if (iptr->val.i == 0x80000000) {
742 } else if (iptr->val.f == 1.0) {
745 } else if (iptr->val.f == 2.0) {
751 disp = dseg_addfloat(cd, iptr->val.f);
752 emit_mov_imm_reg(cd, 0, REG_ITMP1);
754 emit_flds_membase(cd, REG_ITMP1, disp);
756 emit_store(jd, iptr, iptr->dst, d);
759 case ICMD_DCONST: /* ... ==> ..., constant */
760 /* op1 = 0, val.d = constant */
762 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
763 if (iptr->val.d == 0.0) {
767 if (iptr->val.l == 0x8000000000000000LL) {
771 } else if (iptr->val.d == 1.0) {
774 } else if (iptr->val.d == 2.0) {
780 disp = dseg_adddouble(cd, iptr->val.d);
781 emit_mov_imm_reg(cd, 0, REG_ITMP1);
783 emit_fldl_membase(cd, REG_ITMP1, disp);
785 emit_store(jd, iptr, iptr->dst, d);
788 case ICMD_ACONST: /* ... ==> ..., constant */
789 /* op1 = 0, val.a = constant */
791 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
793 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
794 codegen_addpatchref(cd, PATCHER_aconst,
795 ICMD_ACONST_UNRESOLVED_CLASSREF(iptr), 0);
797 if (opt_showdisassemble) {
798 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
804 if (iptr->val.a == NULL)
807 M_MOV_IMM(iptr->val.a, d);
809 emit_store(jd, iptr, iptr->dst, d);
813 /* load/store operations **********************************************/
815 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
816 case ICMD_ALOAD: /* op1 = local variable */
818 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
819 if ((iptr->dst->varkind == LOCALVAR) &&
820 (iptr->dst->varnum == iptr->op1))
822 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
823 if (var->flags & INMEMORY)
824 M_ILD(d, REG_SP, var->regoff * 4);
826 M_INTMOVE(var->regoff, d);
827 emit_store(jd, iptr, iptr->dst, d);
830 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
831 /* op1 = local variable */
833 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
834 if ((iptr->dst->varkind == LOCALVAR) &&
835 (iptr->dst->varnum == iptr->op1))
837 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
838 if (var->flags & INMEMORY)
839 M_LLD(d, REG_SP, var->regoff * 4);
841 M_LNGMOVE(var->regoff, d);
842 emit_store(jd, iptr, iptr->dst, d);
845 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
846 /* op1 = local variable */
848 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
849 if ((iptr->dst->varkind == LOCALVAR) &&
850 (iptr->dst->varnum == iptr->op1))
852 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
853 if (var->flags & INMEMORY)
854 M_FLD(d, REG_SP, var->regoff * 4);
856 M_FLTMOVE(var->regoff, d);
857 emit_store(jd, iptr, iptr->dst, d);
860 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
861 /* op1 = local variable */
863 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
864 if ((iptr->dst->varkind == LOCALVAR) &&
865 (iptr->dst->varnum == iptr->op1))
867 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
868 if (var->flags & INMEMORY)
869 M_DLD(d, REG_SP, var->regoff * 4);
871 M_FLTMOVE(var->regoff, d);
872 emit_store(jd, iptr, iptr->dst, d);
875 case ICMD_ISTORE: /* ..., value ==> ... */
876 case ICMD_ASTORE: /* op1 = local variable */
878 if ((src->varkind == LOCALVAR) &&
879 (src->varnum == iptr->op1))
881 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
882 if (var->flags & INMEMORY) {
883 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
884 M_IST(s1, REG_SP, var->regoff * 4);
887 s1 = emit_load_s1(jd, iptr, src, var->regoff);
888 M_INTMOVE(s1, var->regoff);
892 case ICMD_LSTORE: /* ..., value ==> ... */
893 /* op1 = local variable */
895 if ((src->varkind == LOCALVAR) &&
896 (src->varnum == iptr->op1))
898 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
899 if (var->flags & INMEMORY) {
900 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
901 M_LST(s1, REG_SP, var->regoff * 4);
904 s1 = emit_load_s1(jd, iptr, src, var->regoff);
905 M_LNGMOVE(s1, var->regoff);
909 case ICMD_FSTORE: /* ..., value ==> ... */
910 /* op1 = local variable */
912 if ((src->varkind == LOCALVAR) &&
913 (src->varnum == iptr->op1))
915 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
916 if (var->flags & INMEMORY) {
917 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
918 M_FST(s1, REG_SP, var->regoff * 4);
921 s1 = emit_load_s1(jd, iptr, src, var->regoff);
922 M_FLTMOVE(s1, var->regoff);
926 case ICMD_DSTORE: /* ..., value ==> ... */
927 /* op1 = local variable */
929 if ((src->varkind == LOCALVAR) &&
930 (src->varnum == iptr->op1))
932 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
933 if (var->flags & INMEMORY) {
934 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
935 M_DST(s1, REG_SP, var->regoff * 4);
938 s1 = emit_load_s1(jd, iptr, src, var->regoff);
939 M_FLTMOVE(s1, var->regoff);
944 /* pop/dup/swap operations ********************************************/
946 /* attention: double and longs are only one entry in CACAO ICMDs */
948 case ICMD_POP: /* ..., value ==> ... */
949 case ICMD_POP2: /* ..., value, value ==> ... */
952 case ICMD_DUP: /* ..., a ==> ..., a, a */
954 M_COPY(src, iptr->dst);
957 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
959 M_COPY(src, iptr->dst);
960 M_COPY(src->prev, iptr->dst->prev);
963 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
965 M_COPY(src, iptr->dst);
966 M_COPY(src->prev, iptr->dst->prev);
967 #if defined(ENABLE_SSA)
968 if ((ls==NULL) || (iptr->dst->varkind != TEMPVAR) ||
969 (ls->lifetime[-iptr->dst->varnum-1].type != -1)) {
971 M_COPY(iptr->dst, iptr->dst->prev->prev);
972 #if defined(ENABLE_SSA)
974 M_COPY(src, iptr->dst->prev->prev);
979 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
981 M_COPY(src, iptr->dst);
982 M_COPY(src->prev, iptr->dst->prev);
983 M_COPY(src->prev->prev, iptr->dst->prev->prev);
984 #if defined(ENABLE_SSA)
985 if ((ls==NULL) || (iptr->dst->varkind != TEMPVAR) ||
986 (ls->lifetime[-iptr->dst->varnum-1].type != -1)) {
988 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
989 #if defined(ENABLE_SSA)
991 M_COPY(src, iptr->dst->prev->prev->prev);
996 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
998 M_COPY(src, iptr->dst);
999 M_COPY(src->prev, iptr->dst->prev);
1000 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1001 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
1002 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
1005 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
1007 M_COPY(src, iptr->dst);
1008 M_COPY(src->prev, iptr->dst->prev);
1009 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1010 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
1011 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
1012 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
1015 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1017 M_COPY(src, iptr->dst->prev);
1018 M_COPY(src->prev, iptr->dst);
1022 /* integer operations *************************************************/
1024 case ICMD_INEG: /* ..., value ==> ..., - value */
1026 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1027 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1030 emit_store(jd, iptr, iptr->dst, d);
1033 case ICMD_LNEG: /* ..., value ==> ..., - value */
1035 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1036 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1038 M_NEG(GET_LOW_REG(d));
1039 M_IADDC_IMM(0, GET_HIGH_REG(d));
1040 M_NEG(GET_HIGH_REG(d));
1041 emit_store(jd, iptr, iptr->dst, d);
1044 case ICMD_I2L: /* ..., value ==> ..., value */
1046 s1 = emit_load_s1(jd, iptr, src, EAX);
1047 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EAX_EDX_PACKED);
1050 M_LNGMOVE(EAX_EDX_PACKED, d);
1051 emit_store(jd, iptr, iptr->dst, d);
1054 case ICMD_L2I: /* ..., value ==> ..., value */
1056 s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP2);
1057 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1059 emit_store(jd, iptr, iptr->dst, d);
1062 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1064 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1065 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1069 emit_store(jd, iptr, iptr->dst, d);
1072 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1074 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1075 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1077 emit_store(jd, iptr, iptr->dst, d);
1080 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1082 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1083 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1085 emit_store(jd, iptr, iptr->dst, d);
1089 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1091 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1092 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1093 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1100 emit_store(jd, iptr, iptr->dst, d);
1103 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1104 /* val.i = constant */
1106 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1107 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1109 M_IADD_IMM(iptr->val.i, d);
1110 emit_store(jd, iptr, iptr->dst, d);
1113 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1115 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1116 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1117 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1118 M_INTMOVE(s1, GET_LOW_REG(d));
1119 M_IADD(s2, GET_LOW_REG(d));
1120 /* don't use REG_ITMP1 */
1121 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1122 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1123 M_INTMOVE(s1, GET_HIGH_REG(d));
1124 M_IADDC(s2, GET_HIGH_REG(d));
1125 emit_store(jd, iptr, iptr->dst, d);
1128 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1129 /* val.l = constant */
1131 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1132 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1134 M_IADD_IMM(iptr->val.l, GET_LOW_REG(d));
1135 M_IADDC_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1136 emit_store(jd, iptr, iptr->dst, d);
1139 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1141 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1142 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1143 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1145 M_INTMOVE(s1, REG_ITMP1);
1146 M_ISUB(s2, REG_ITMP1);
1147 M_INTMOVE(REG_ITMP1, d);
1153 emit_store(jd, iptr, iptr->dst, d);
1156 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1157 /* val.i = constant */
1159 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1160 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1162 M_ISUB_IMM(iptr->val.i, d);
1163 emit_store(jd, iptr, iptr->dst, d);
1166 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1168 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1169 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1170 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1171 if (s2 == GET_LOW_REG(d)) {
1172 M_INTMOVE(s1, REG_ITMP1);
1173 M_ISUB(s2, REG_ITMP1);
1174 M_INTMOVE(REG_ITMP1, GET_LOW_REG(d));
1177 M_INTMOVE(s1, GET_LOW_REG(d));
1178 M_ISUB(s2, GET_LOW_REG(d));
1180 /* don't use REG_ITMP1 */
1181 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1182 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1183 if (s2 == GET_HIGH_REG(d)) {
1184 M_INTMOVE(s1, REG_ITMP2);
1185 M_ISUBB(s2, REG_ITMP2);
1186 M_INTMOVE(REG_ITMP2, GET_HIGH_REG(d));
1189 M_INTMOVE(s1, GET_HIGH_REG(d));
1190 M_ISUBB(s2, GET_HIGH_REG(d));
1192 emit_store(jd, iptr, iptr->dst, d);
1195 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1196 /* val.l = constant */
1198 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1199 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1201 M_ISUB_IMM(iptr->val.l, GET_LOW_REG(d));
1202 M_ISUBB_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1203 emit_store(jd, iptr, iptr->dst, d);
1206 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1208 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1209 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1210 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1217 emit_store(jd, iptr, iptr->dst, d);
1220 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1221 /* val.i = constant */
1223 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1224 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1225 M_IMUL_IMM(s1, iptr->val.i, d);
1226 emit_store(jd, iptr, iptr->dst, d);
1229 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1231 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1232 s2 = emit_load_s2_low(jd, iptr, src, EDX);
1233 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EAX_EDX_PACKED);
1235 M_INTMOVE(s1, REG_ITMP2);
1236 M_IMUL(s2, REG_ITMP2);
1238 s1 = emit_load_s1_low(jd, iptr, src->prev, EAX);
1239 s2 = emit_load_s2_high(jd, iptr, src, EDX);
1242 M_IADD(EDX, REG_ITMP2);
1244 s1 = emit_load_s1_low(jd, iptr, src->prev, EAX);
1245 s2 = emit_load_s2_low(jd, iptr, src, EDX);
1248 M_INTMOVE(EAX, GET_LOW_REG(d));
1249 M_IADD(REG_ITMP2, GET_HIGH_REG(d));
1251 emit_store(jd, iptr, iptr->dst, d);
1254 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1255 /* val.l = constant */
1257 s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP2);
1258 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EAX_EDX_PACKED);
1259 ICONST(EAX, iptr->val.l);
1261 M_IMUL_IMM(s1, iptr->val.l >> 32, REG_ITMP2);
1262 M_IADD(REG_ITMP2, EDX);
1263 s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP2);
1264 M_IMUL_IMM(s1, iptr->val.l, REG_ITMP2);
1265 M_IADD(REG_ITMP2, EDX);
1266 M_LNGMOVE(EAX_EDX_PACKED, d);
1267 emit_store(jd, iptr, iptr->dst, d);
1270 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1272 s1 = emit_load_s1(jd, iptr, src->prev, EAX);
1273 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1274 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EAX);
1279 codegen_add_arithmeticexception_ref(cd);
1282 M_INTMOVE(s1, EAX); /* we need the first operand in EAX */
1284 /* check as described in jvm spec */
1286 M_CMP_IMM(0x80000000, EAX);
1293 M_INTMOVE(EAX, d); /* if INMEMORY then d is already EAX */
1294 emit_store(jd, iptr, iptr->dst, d);
1297 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1299 s1 = emit_load_s1(jd, iptr, src->prev, EAX);
1300 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1301 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EDX);
1306 codegen_add_arithmeticexception_ref(cd);
1309 M_INTMOVE(s1, EAX); /* we need the first operand in EAX */
1311 /* check as described in jvm spec */
1313 M_CMP_IMM(0x80000000, EAX);
1321 M_INTMOVE(EDX, d); /* if INMEMORY then d is already EDX */
1322 emit_store(jd, iptr, iptr->dst, d);
1325 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1326 /* val.i = constant */
1328 /* TODO: optimize for `/ 2' */
1329 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1330 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1334 M_IADD_IMM32((1 << iptr->val.i) - 1, d); /* 32-bit for jump off. */
1335 M_SRA_IMM(iptr->val.i, d);
1336 emit_store(jd, iptr, iptr->dst, d);
1339 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1340 /* val.i = constant */
1342 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1343 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1345 M_MOV(s1, REG_ITMP1);
1349 M_AND_IMM(iptr->val.i, d);
1351 M_BGE(2 + 2 + 6 + 2);
1352 M_MOV(s1, d); /* don't use M_INTMOVE, so we know the jump offset */
1354 M_AND_IMM32(iptr->val.i, d); /* use 32-bit for jump offset */
1356 emit_store(jd, iptr, iptr->dst, d);
1359 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1360 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1362 s2 = emit_load_s2(jd, iptr, src, REG_ITMP12_PACKED);
1363 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
1365 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
1366 M_OR(GET_HIGH_REG(s2), REG_ITMP3);
1368 codegen_add_arithmeticexception_ref(cd);
1373 M_LST(s2, REG_SP, 2 * 4);
1375 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP12_PACKED);
1376 M_LST(s1, REG_SP, 0 * 4);
1378 M_MOV_IMM(bte->fp, REG_ITMP3);
1380 emit_store(jd, iptr, iptr->dst, d);
1383 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1384 /* val.i = constant */
1386 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1387 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
1389 M_TEST(GET_HIGH_REG(d));
1391 M_IADD_IMM32((1 << iptr->val.i) - 1, GET_LOW_REG(d));
1392 M_IADDC_IMM(0, GET_HIGH_REG(d));
1393 M_SRLD_IMM(iptr->val.i, GET_HIGH_REG(d), GET_LOW_REG(d));
1394 M_SRA_IMM(iptr->val.i, GET_HIGH_REG(d));
1395 emit_store(jd, iptr, iptr->dst, d);
1399 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1400 /* val.l = constant */
1402 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1403 if (iptr->dst->flags & INMEMORY) {
1404 if (src->flags & INMEMORY) {
1405 /* Alpha algorithm */
1407 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1409 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4 + 4);
1415 /* TODO: hmm, don't know if this is always correct */
1417 CALCIMMEDIATEBYTES(disp, iptr->val.l & 0x00000000ffffffff);
1419 CALCIMMEDIATEBYTES(disp, iptr->val.l >> 32);
1425 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1426 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1428 emit_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1429 emit_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1430 emit_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4 + 4);
1431 emit_jcc(cd, CC_GE, disp);
1433 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1434 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1436 emit_neg_reg(cd, REG_ITMP1);
1437 emit_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1438 emit_neg_reg(cd, REG_ITMP2);
1440 emit_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1441 emit_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1443 emit_neg_reg(cd, REG_ITMP1);
1444 emit_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1445 emit_neg_reg(cd, REG_ITMP2);
1447 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1448 emit_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1452 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1453 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
1455 M_AND_IMM(iptr->val.l, GET_LOW_REG(d));
1456 M_AND_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1457 M_TEST(GET_LOW_REG(s1));
1463 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1465 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1466 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1467 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1468 M_INTMOVE(s2, ECX); /* s2 may be equal to d */
1471 emit_store(jd, iptr, iptr->dst, d);
1474 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1475 /* val.i = constant */
1477 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1478 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1480 M_SLL_IMM(iptr->val.i, d);
1481 emit_store(jd, iptr, iptr->dst, d);
1484 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1486 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1487 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1488 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1489 M_INTMOVE(s2, ECX); /* s2 may be equal to d */
1492 emit_store(jd, iptr, iptr->dst, d);
1495 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1496 /* val.i = constant */
1498 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1499 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1501 M_SRA_IMM(iptr->val.i, d);
1502 emit_store(jd, iptr, iptr->dst, d);
1505 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1507 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1508 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1509 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1510 M_INTMOVE(s2, ECX); /* s2 may be equal to d */
1513 emit_store(jd, iptr, iptr->dst, d);
1516 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1517 /* val.i = constant */
1519 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1520 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1522 M_SRL_IMM(iptr->val.i, d);
1523 emit_store(jd, iptr, iptr->dst, d);
1526 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1528 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP13_PACKED);
1529 s2 = emit_load_s2(jd, iptr, src, ECX);
1530 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP13_PACKED);
1533 M_TEST_IMM(32, ECX);
1535 M_MOV(GET_LOW_REG(d), GET_HIGH_REG(d));
1536 M_CLR(GET_LOW_REG(d));
1537 M_SLLD(GET_LOW_REG(d), GET_HIGH_REG(d));
1538 M_SLL(GET_LOW_REG(d));
1539 emit_store(jd, iptr, iptr->dst, d);
1542 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1543 /* val.i = constant */
1545 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1546 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1548 if (iptr->val.i & 0x20) {
1549 M_MOV(GET_LOW_REG(d), GET_HIGH_REG(d));
1550 M_CLR(GET_LOW_REG(d));
1551 M_SLLD_IMM(iptr->val.i & 0x3f, GET_LOW_REG(d), GET_HIGH_REG(d));
1554 M_SLLD_IMM(iptr->val.i & 0x3f, GET_LOW_REG(d), GET_HIGH_REG(d));
1555 M_SLL_IMM(iptr->val.i & 0x3f, GET_LOW_REG(d));
1557 emit_store(jd, iptr, iptr->dst, d);
1560 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1562 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP13_PACKED);
1563 s2 = emit_load_s2(jd, iptr, src, ECX);
1564 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP13_PACKED);
1567 M_TEST_IMM(32, ECX);
1569 M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d));
1570 M_SRA_IMM(31, GET_HIGH_REG(d));
1571 M_SRLD(GET_HIGH_REG(d), GET_LOW_REG(d));
1572 M_SRA(GET_HIGH_REG(d));
1573 emit_store(jd, iptr, iptr->dst, d);
1576 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1577 /* val.i = constant */
1579 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1580 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1582 if (iptr->val.i & 0x20) {
1583 M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d));
1584 M_SRA_IMM(31, GET_HIGH_REG(d));
1585 M_SRLD_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d), GET_LOW_REG(d));
1588 M_SRLD_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d), GET_LOW_REG(d));
1589 M_SRA_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d));
1591 emit_store(jd, iptr, iptr->dst, d);
1594 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1596 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP13_PACKED);
1597 s2 = emit_load_s2(jd, iptr, src, ECX);
1598 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP13_PACKED);
1601 M_TEST_IMM(32, ECX);
1603 M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d));
1604 M_CLR(GET_HIGH_REG(d));
1605 M_SRLD(GET_HIGH_REG(d), GET_LOW_REG(d));
1606 M_SRL(GET_HIGH_REG(d));
1607 emit_store(jd, iptr, iptr->dst, d);
1610 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1611 /* val.l = constant */
1613 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1614 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1616 if (iptr->val.i & 0x20) {
1617 M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d));
1618 M_CLR(GET_HIGH_REG(d));
1619 M_SRLD_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d), GET_LOW_REG(d));
1622 M_SRLD_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d), GET_LOW_REG(d));
1623 M_SRL_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d));
1625 emit_store(jd, iptr, iptr->dst, d);
1628 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1630 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1631 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1632 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1639 emit_store(jd, iptr, iptr->dst, d);
1642 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1643 /* val.i = constant */
1645 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1646 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1648 M_AND_IMM(iptr->val.i, d);
1649 emit_store(jd, iptr, iptr->dst, d);
1652 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1654 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1655 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1656 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1657 if (s2 == GET_LOW_REG(d))
1658 M_AND(s1, GET_LOW_REG(d));
1660 M_INTMOVE(s1, GET_LOW_REG(d));
1661 M_AND(s2, GET_LOW_REG(d));
1663 /* REG_ITMP1 probably contains low 32-bit of destination */
1664 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1665 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1666 if (s2 == GET_HIGH_REG(d))
1667 M_AND(s1, GET_HIGH_REG(d));
1669 M_INTMOVE(s1, GET_HIGH_REG(d));
1670 M_AND(s2, GET_HIGH_REG(d));
1672 emit_store(jd, iptr, iptr->dst, d);
1675 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1676 /* val.l = constant */
1678 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1679 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1681 M_AND_IMM(iptr->val.l, GET_LOW_REG(d));
1682 M_AND_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1683 emit_store(jd, iptr, iptr->dst, d);
1686 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1688 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1689 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1690 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1697 emit_store(jd, iptr, iptr->dst, d);
1700 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1701 /* val.i = constant */
1703 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1704 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1706 M_OR_IMM(iptr->val.i, d);
1707 emit_store(jd, iptr, iptr->dst, d);
1710 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1712 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1713 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1714 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1715 if (s2 == GET_LOW_REG(d))
1716 M_OR(s1, GET_LOW_REG(d));
1718 M_INTMOVE(s1, GET_LOW_REG(d));
1719 M_OR(s2, GET_LOW_REG(d));
1721 /* REG_ITMP1 probably contains low 32-bit of destination */
1722 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1723 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1724 if (s2 == GET_HIGH_REG(d))
1725 M_OR(s1, GET_HIGH_REG(d));
1727 M_INTMOVE(s1, GET_HIGH_REG(d));
1728 M_OR(s2, GET_HIGH_REG(d));
1730 emit_store(jd, iptr, iptr->dst, d);
1733 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1734 /* val.l = constant */
1736 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1737 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1739 M_OR_IMM(iptr->val.l, GET_LOW_REG(d));
1740 M_OR_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1741 emit_store(jd, iptr, iptr->dst, d);
1744 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1746 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1747 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1748 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1755 emit_store(jd, iptr, iptr->dst, d);
1758 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1759 /* val.i = constant */
1761 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1762 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1764 M_XOR_IMM(iptr->val.i, d);
1765 emit_store(jd, iptr, iptr->dst, d);
1768 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1770 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1771 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1772 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1773 if (s2 == GET_LOW_REG(d))
1774 M_XOR(s1, GET_LOW_REG(d));
1776 M_INTMOVE(s1, GET_LOW_REG(d));
1777 M_XOR(s2, GET_LOW_REG(d));
1779 /* REG_ITMP1 probably contains low 32-bit of destination */
1780 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1781 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1782 if (s2 == GET_HIGH_REG(d))
1783 M_XOR(s1, GET_HIGH_REG(d));
1785 M_INTMOVE(s1, GET_HIGH_REG(d));
1786 M_XOR(s2, GET_HIGH_REG(d));
1788 emit_store(jd, iptr, iptr->dst, d);
1791 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1792 /* val.l = constant */
1794 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1795 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1797 M_XOR_IMM(iptr->val.l, GET_LOW_REG(d));
1798 M_XOR_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1799 emit_store(jd, iptr, iptr->dst, d);
1802 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1803 /* op1 = variable, val.i = constant */
1805 #if defined(ENABLE_SSA)
1808 /* with SSA in op1 is the source Local Var, in val._i.op1_t */
1809 /* the target Local Var, in val._i.i the constant */
1810 /* val._i.op1_t <- op1 + val._i.i */
1813 var = &(rd->locals[iptr->op1][TYPE_INT]);
1814 var_t = &(rd->locals[iptr->val._i.op1_t][TYPE_INT]);
1816 /* set s1 to reg of destination or REG_ITMP1 */
1817 if (var_t->flags & INMEMORY)
1822 /* move source value to s1 */
1823 if (var->flags & INMEMORY)
1824 M_ILD( s1, REG_SP, var->regoff * 4);
1826 M_INTMOVE(var->regoff, s1);
1828 /* `inc reg' is slower on p4's (regarding to ia32
1829 optimization reference manual and benchmarks) and as
1830 fast on athlon's. */
1832 M_IADD_IMM(iptr->val._i.i, s1);
1834 if (var_t->flags & INMEMORY)
1835 M_IST(s1, REG_SP, var_t->regoff * 4);
1838 #endif /* defined(ENABLE_SSA) */
1840 var = &(rd->locals[iptr->op1][TYPE_INT]);
1841 if (var->flags & INMEMORY) {
1843 M_ILD(s1, REG_SP, var->regoff * 4);
1848 /* `inc reg' is slower on p4's (regarding to ia32
1849 optimization reference manual and benchmarks) and as
1850 fast on athlon's. */
1852 M_IADD_IMM(iptr->val.i, s1);
1854 if (var->flags & INMEMORY)
1855 M_IST(s1, REG_SP, var->regoff * 4);
1860 /* floating operations ************************************************/
1862 case ICMD_FNEG: /* ..., value ==> ..., - value */
1864 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1865 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1867 emit_store(jd, iptr, iptr->dst, d);
1870 case ICMD_DNEG: /* ..., value ==> ..., - value */
1872 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1873 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1875 emit_store(jd, iptr, iptr->dst, d);
1878 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1880 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1881 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1882 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1884 emit_store(jd, iptr, iptr->dst, d);
1887 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1889 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1890 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1891 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1893 emit_store(jd, iptr, iptr->dst, d);
1896 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1898 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1899 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1900 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1902 emit_store(jd, iptr, iptr->dst, d);
1905 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1907 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1908 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1909 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1911 emit_store(jd, iptr, iptr->dst, d);
1914 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1916 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1917 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1918 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1920 emit_store(jd, iptr, iptr->dst, d);
1923 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1925 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1926 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1927 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1929 emit_store(jd, iptr, iptr->dst, d);
1932 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1934 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1935 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1936 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1938 emit_store(jd, iptr, iptr->dst, d);
1941 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1943 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1944 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1945 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1947 emit_store(jd, iptr, iptr->dst, d);
1950 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1952 /* exchanged to skip fxch */
1953 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1954 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1955 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1956 /* emit_fxch(cd); */
1961 emit_jcc(cd, CC_P, -(2 + 1 + 2 + 1 + 6));
1962 emit_store(jd, iptr, iptr->dst, d);
1963 emit_ffree_reg(cd, 0);
1967 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1969 /* exchanged to skip fxch */
1970 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1971 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1972 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1973 /* emit_fxch(cd); */
1978 emit_jcc(cd, CC_P, -(2 + 1 + 2 + 1 + 6));
1979 emit_store(jd, iptr, iptr->dst, d);
1980 emit_ffree_reg(cd, 0);
1984 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1985 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1987 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1988 if (src->flags & INMEMORY) {
1989 emit_fildl_membase(cd, REG_SP, src->regoff * 4);
1992 disp = dseg_adds4(cd, 0);
1993 emit_mov_imm_reg(cd, 0, REG_ITMP1);
1995 emit_mov_reg_membase(cd, src->regoff, REG_ITMP1, disp);
1996 emit_fildl_membase(cd, REG_ITMP1, disp);
1998 emit_store(jd, iptr, iptr->dst, d);
2001 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2002 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2004 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2005 if (src->flags & INMEMORY) {
2006 emit_fildll_membase(cd, REG_SP, src->regoff * 4);
2009 log_text("L2F: longs have to be in memory");
2012 emit_store(jd, iptr, iptr->dst, d);
2015 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2017 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2018 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2020 emit_mov_imm_reg(cd, 0, REG_ITMP1);
2023 /* Round to zero, 53-bit mode, exception masked */
2024 disp = dseg_adds4(cd, 0x0e7f);
2025 emit_fldcw_membase(cd, REG_ITMP1, disp);
2027 if (iptr->dst->flags & INMEMORY) {
2028 emit_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2030 /* Round to nearest, 53-bit mode, exceptions masked */
2031 disp = dseg_adds4(cd, 0x027f);
2032 emit_fldcw_membase(cd, REG_ITMP1, disp);
2034 emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2037 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2039 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2042 disp = dseg_adds4(cd, 0);
2043 emit_fistpl_membase(cd, REG_ITMP1, disp);
2044 emit_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2046 /* Round to nearest, 53-bit mode, exceptions masked */
2047 disp = dseg_adds4(cd, 0x027f);
2048 emit_fldcw_membase(cd, REG_ITMP1, disp);
2050 emit_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2053 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2054 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2057 emit_jcc(cd, CC_NE, disp);
2059 /* XXX: change this when we use registers */
2060 emit_flds_membase(cd, REG_SP, src->regoff * 4);
2061 emit_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP1);
2062 emit_call_reg(cd, REG_ITMP1);
2064 if (iptr->dst->flags & INMEMORY) {
2065 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2068 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2072 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2074 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2075 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2077 emit_mov_imm_reg(cd, 0, REG_ITMP1);
2080 /* Round to zero, 53-bit mode, exception masked */
2081 disp = dseg_adds4(cd, 0x0e7f);
2082 emit_fldcw_membase(cd, REG_ITMP1, disp);
2084 if (iptr->dst->flags & INMEMORY) {
2085 emit_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
2087 /* Round to nearest, 53-bit mode, exceptions masked */
2088 disp = dseg_adds4(cd, 0x027f);
2089 emit_fldcw_membase(cd, REG_ITMP1, disp);
2091 emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
2094 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2096 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2099 disp = dseg_adds4(cd, 0);
2100 emit_fistpl_membase(cd, REG_ITMP1, disp);
2101 emit_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2103 /* Round to nearest, 53-bit mode, exceptions masked */
2104 disp = dseg_adds4(cd, 0x027f);
2105 emit_fldcw_membase(cd, REG_ITMP1, disp);
2107 emit_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2110 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2111 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2114 emit_jcc(cd, CC_NE, disp);
2116 /* XXX: change this when we use registers */
2117 emit_fldl_membase(cd, REG_SP, src->regoff * 4);
2118 emit_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP1);
2119 emit_call_reg(cd, REG_ITMP1);
2121 if (iptr->dst->flags & INMEMORY) {
2122 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2124 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2128 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2130 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2131 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2133 emit_mov_imm_reg(cd, 0, REG_ITMP1);
2136 /* Round to zero, 53-bit mode, exception masked */
2137 disp = dseg_adds4(cd, 0x0e7f);
2138 emit_fldcw_membase(cd, REG_ITMP1, disp);
2140 if (iptr->dst->flags & INMEMORY) {
2141 emit_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2143 /* Round to nearest, 53-bit mode, exceptions masked */
2144 disp = dseg_adds4(cd, 0x027f);
2145 emit_fldcw_membase(cd, REG_ITMP1, disp);
2147 emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2150 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2152 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2155 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2157 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2159 emit_jcc(cd, CC_NE, disp);
2161 emit_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2164 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2166 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2168 emit_jcc(cd, CC_NE, disp);
2170 /* XXX: change this when we use registers */
2171 emit_flds_membase(cd, REG_SP, src->regoff * 4);
2172 emit_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP1);
2173 emit_call_reg(cd, REG_ITMP1);
2174 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2175 emit_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2178 log_text("F2L: longs have to be in memory");
2183 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2185 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2186 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2188 emit_mov_imm_reg(cd, 0, REG_ITMP1);
2191 /* Round to zero, 53-bit mode, exception masked */
2192 disp = dseg_adds4(cd, 0x0e7f);
2193 emit_fldcw_membase(cd, REG_ITMP1, disp);
2195 if (iptr->dst->flags & INMEMORY) {
2196 emit_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2198 /* Round to nearest, 53-bit mode, exceptions masked */
2199 disp = dseg_adds4(cd, 0x027f);
2200 emit_fldcw_membase(cd, REG_ITMP1, disp);
2202 emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2205 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2207 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2210 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2212 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2214 emit_jcc(cd, CC_NE, disp);
2216 emit_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2219 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2221 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2223 emit_jcc(cd, CC_NE, disp);
2225 /* XXX: change this when we use registers */
2226 emit_fldl_membase(cd, REG_SP, src->regoff * 4);
2227 emit_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP1);
2228 emit_call_reg(cd, REG_ITMP1);
2229 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2230 emit_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2233 log_text("D2L: longs have to be in memory");
2238 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2240 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2241 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2243 emit_store(jd, iptr, iptr->dst, d);
2246 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2248 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2249 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2251 emit_store(jd, iptr, iptr->dst, d);
2254 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2257 /* exchanged to skip fxch */
2258 s2 = emit_load_s2(jd, iptr, src->prev, REG_FTMP1);
2259 s1 = emit_load_s1(jd, iptr, src, REG_FTMP2);
2260 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2261 /* emit_fxch(cd); */
2264 emit_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2265 emit_jcc(cd, CC_E, 6);
2266 emit_alu_imm_reg(cd, ALU_AND, 0x000000ff, EAX);
2268 emit_mov_imm_reg(cd, 0, d); /* does not affect flags */
2269 emit_jcc(cd, CC_E, 6 + 3 + 5 + 3);
2270 emit_jcc(cd, CC_B, 3 + 5);
2271 emit_alu_imm_reg(cd, ALU_SUB, 1, d);
2272 emit_jmp_imm(cd, 3);
2273 emit_alu_imm_reg(cd, ALU_ADD, 1, d);
2274 emit_store(jd, iptr, iptr->dst, d);
2277 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2280 /* exchanged to skip fxch */
2281 s2 = emit_load_s2(jd, iptr, src->prev, REG_FTMP1);
2282 s1 = emit_load_s1(jd, iptr, src, REG_FTMP2);
2283 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2284 /* emit_fxch(cd); */
2287 emit_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2288 emit_jcc(cd, CC_E, 3);
2289 emit_movb_imm_reg(cd, 1, REG_AH);
2291 emit_mov_imm_reg(cd, 0, d); /* does not affect flags */
2292 emit_jcc(cd, CC_E, 6 + 3 + 5 + 3);
2293 emit_jcc(cd, CC_B, 3 + 5);
2294 emit_alu_imm_reg(cd, ALU_SUB, 1, d);
2295 emit_jmp_imm(cd, 3);
2296 emit_alu_imm_reg(cd, ALU_ADD, 1, d);
2297 emit_store(jd, iptr, iptr->dst, d);
2301 /* memory operations **************************************************/
2303 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2305 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2306 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2307 gen_nullptr_check(s1);
2308 M_ILD(d, s1, OFFSET(java_arrayheader, size));
2309 emit_store(jd, iptr, iptr->dst, d);
2312 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2314 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2315 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2316 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2317 if (iptr->op1 == 0) {
2318 gen_nullptr_check(s1);
2321 emit_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2322 emit_store(jd, iptr, iptr->dst, d);
2325 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2327 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2328 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2329 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2330 if (iptr->op1 == 0) {
2331 gen_nullptr_check(s1);
2334 emit_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2335 emit_store(jd, iptr, iptr->dst, d);
2338 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2340 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2341 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2342 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2343 if (iptr->op1 == 0) {
2344 gen_nullptr_check(s1);
2347 emit_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2348 emit_store(jd, iptr, iptr->dst, d);
2351 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2353 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2354 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2355 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2356 if (iptr->op1 == 0) {
2357 gen_nullptr_check(s1);
2360 emit_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2361 emit_store(jd, iptr, iptr->dst, d);
2364 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2366 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2367 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2368 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2369 if (iptr->op1 == 0) {
2370 gen_nullptr_check(s1);
2373 assert(iptr->dst->flags & INMEMORY);
2374 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2375 emit_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4);
2376 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2377 emit_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2380 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2382 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2383 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2384 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2385 if (iptr->op1 == 0) {
2386 gen_nullptr_check(s1);
2389 emit_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2390 emit_store(jd, iptr, iptr->dst, d);
2393 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2395 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2396 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2397 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2398 if (iptr->op1 == 0) {
2399 gen_nullptr_check(s1);
2402 emit_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2403 emit_store(jd, iptr, iptr->dst, d);
2406 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2408 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2409 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2410 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2411 if (iptr->op1 == 0) {
2412 gen_nullptr_check(s1);
2415 emit_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2416 emit_store(jd, iptr, iptr->dst, d);
2420 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2422 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2423 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2424 if (iptr->op1 == 0) {
2425 gen_nullptr_check(s1);
2428 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2429 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2430 M_INTMOVE(s3, REG_ITMP3);
2433 emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2436 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2438 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2439 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2440 if (iptr->op1 == 0) {
2441 gen_nullptr_check(s1);
2444 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2445 emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2448 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2450 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2451 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2452 if (iptr->op1 == 0) {
2453 gen_nullptr_check(s1);
2456 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2457 emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2460 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2462 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2463 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2464 if (iptr->op1 == 0) {
2465 gen_nullptr_check(s1);
2468 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2469 emit_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2472 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2474 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2475 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2476 if (iptr->op1 == 0) {
2477 gen_nullptr_check(s1);
2480 assert(src->flags & INMEMORY);
2481 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP3);
2482 emit_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2483 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
2484 emit_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2487 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2489 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2490 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2491 if (iptr->op1 == 0) {
2492 gen_nullptr_check(s1);
2495 s3 = emit_load_s3(jd, iptr, src, REG_FTMP1);
2496 emit_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2499 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2501 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2502 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2503 if (iptr->op1 == 0) {
2504 gen_nullptr_check(s1);
2507 s3 = emit_load_s3(jd, iptr, src, REG_FTMP1);
2508 emit_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2511 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2513 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2514 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2515 if (iptr->op1 == 0) {
2516 gen_nullptr_check(s1);
2519 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2521 M_AST(s1, REG_SP, 0 * 4);
2522 M_AST(s3, REG_SP, 1 * 4);
2523 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
2527 codegen_add_arraystoreexception_ref(cd);
2529 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2530 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2531 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2532 emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2535 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2537 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2538 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2539 if (iptr->op1 == 0) {
2540 gen_nullptr_check(s1);
2543 emit_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2546 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2548 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2549 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2550 if (iptr->op1 == 0) {
2551 gen_nullptr_check(s1);
2554 emit_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2557 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2559 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2560 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2561 if (iptr->op1 == 0) {
2562 gen_nullptr_check(s1);
2565 emit_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2568 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2570 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2571 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2572 if (iptr->op1 == 0) {
2573 gen_nullptr_check(s1);
2576 emit_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2579 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2581 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2582 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2583 if (iptr->op1 == 0) {
2584 gen_nullptr_check(s1);
2587 emit_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2588 emit_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2591 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2593 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2594 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2595 if (iptr->op1 == 0) {
2596 gen_nullptr_check(s1);
2599 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2603 case ICMD_GETSTATIC: /* ... ==> ..., value */
2604 /* op1 = type, val.a = field address */
2606 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2607 codegen_addpatchref(cd, PATCHER_get_putstatic,
2608 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2610 if (opt_showdisassemble) {
2611 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2618 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2620 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2621 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2623 if (opt_showdisassemble) {
2624 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2628 disp = (ptrint) &(fi->value);
2631 M_MOV_IMM(disp, REG_ITMP1);
2632 switch (iptr->op1) {
2635 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
2636 M_ILD(d, REG_ITMP1, 0);
2639 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP23_PACKED);
2640 M_LLD(d, REG_ITMP1, 0);
2643 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2644 M_FLD(d, REG_ITMP1, 0);
2647 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2648 M_DLD(d, REG_ITMP1, 0);
2651 emit_store(jd, iptr, iptr->dst, d);
2654 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2655 /* op1 = type, val.a = field address */
2657 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2658 codegen_addpatchref(cd, PATCHER_get_putstatic,
2659 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2661 if (opt_showdisassemble) {
2662 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2669 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2671 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2672 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2674 if (opt_showdisassemble) {
2675 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2679 disp = (ptrint) &(fi->value);
2682 M_MOV_IMM(disp, REG_ITMP1);
2683 switch (iptr->op1) {
2686 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2687 M_IST(s2, REG_ITMP1, 0);
2690 s2 = emit_load_s2(jd, iptr, src, REG_ITMP23_PACKED);
2691 M_LST(s2, REG_ITMP1, 0);
2694 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
2695 emit_fstps_membase(cd, REG_ITMP1, 0);
2698 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
2699 emit_fstpl_membase(cd, REG_ITMP1, 0);
2704 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2705 /* val = value (in current instruction) */
2706 /* op1 = type, val.a = field address (in */
2707 /* following NOP) */
2709 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2710 codegen_addpatchref(cd, PATCHER_get_putstatic,
2711 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
2713 if (opt_showdisassemble) {
2714 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2721 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1);
2723 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2724 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2726 if (opt_showdisassemble) {
2727 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2731 disp = (ptrint) &(fi->value);
2734 M_MOV_IMM(disp, REG_ITMP1);
2735 switch (iptr[1].op1) {
2739 M_IST_IMM(iptr->val.i, REG_ITMP1, 0);
2743 M_LST_IMM(iptr->val.l, REG_ITMP1, 0);
2748 case ICMD_GETFIELD: /* .., objectref. ==> ..., value */
2749 /* op1 = type, val.i = field offset */
2751 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2752 gen_nullptr_check(s1);
2754 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2755 codegen_addpatchref(cd, PATCHER_getfield,
2756 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2758 if (opt_showdisassemble) {
2759 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2766 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2768 switch (iptr->op1) {
2771 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
2772 M_ILD32(d, s1, disp);
2775 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP23_PACKED);
2776 M_LLD32(d, s1, disp);
2779 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2780 M_FLD32(d, s1, disp);
2783 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2784 M_DLD32(d, s1, disp);
2787 emit_store(jd, iptr, iptr->dst, d);
2790 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2791 /* op1 = type, val.a = field address */
2793 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2794 gen_nullptr_check(s1);
2796 /* must be done here because of code patching */
2798 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2799 if (IS_2_WORD_TYPE(iptr->op1))
2800 s2 = emit_load_s2(jd, iptr, src, REG_ITMP23_PACKED);
2802 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2805 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2807 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2808 codegen_addpatchref(cd, PATCHER_putfield,
2809 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2811 if (opt_showdisassemble) {
2812 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2819 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2821 switch (iptr->op1) {
2824 M_IST32(s2, s1, disp);
2827 M_LST32(s2, s1, disp);
2830 emit_fstps_membase32(cd, s1, disp);
2833 emit_fstpl_membase32(cd, s1, disp);
2838 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2839 /* val = value (in current instruction) */
2840 /* op1 = type, val.a = field address (in */
2841 /* following NOP) */
2843 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2844 gen_nullptr_check(s1);
2846 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2847 codegen_addpatchref(cd, PATCHER_putfieldconst,
2848 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
2850 if (opt_showdisassemble) {
2851 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2858 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1)->offset;
2860 switch (iptr[1].op1) {
2864 M_IST32_IMM(iptr->val.i, s1, disp);
2868 M_LST32_IMM(iptr->val.l, s1, disp);
2874 /* branch operations **************************************************/
2876 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2878 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2879 M_INTMOVE(s1, REG_ITMP1_XPTR);
2881 #ifdef ENABLE_VERIFIER
2883 codegen_addpatchref(cd, PATCHER_athrow_areturn,
2884 (unresolved_class *) iptr->val.a, 0);
2886 if (opt_showdisassemble) {
2887 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2890 #endif /* ENABLE_VERIFIER */
2892 M_CALL_IMM(0); /* passing exception pc */
2893 M_POP(REG_ITMP2_XPC);
2895 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
2899 case ICMD_INLINE_GOTO:
2901 M_COPY(src, iptr->dst);
2904 case ICMD_GOTO: /* ... ==> ... */
2905 /* op1 = target JavaVM pc */
2907 #if defined(ENABLE_SSA)
2909 last_cmd_was_goto = true;
2910 /* In case of a Goto phimoves have to be inserted before the */
2912 codegen_insert_phi_moves(cd, rd, ls, bptr);
2916 codegen_addreference(cd, (basicblock *) iptr->target);
2920 case ICMD_JSR: /* ... ==> ... */
2921 /* op1 = target JavaVM pc */
2924 codegen_addreference(cd, (basicblock *) iptr->target);
2927 case ICMD_RET: /* ... ==> ... */
2928 /* op1 = local variable */
2930 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2931 if (var->flags & INMEMORY) {
2932 M_ALD(REG_ITMP1, REG_SP, var->regoff * 4);
2939 case ICMD_IFNULL: /* ..., value ==> ... */
2940 /* op1 = target JavaVM pc */
2942 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2945 codegen_addreference(cd, (basicblock *) iptr->target);
2948 case ICMD_IFNONNULL: /* ..., value ==> ... */
2949 /* op1 = target JavaVM pc */
2951 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2954 codegen_addreference(cd, (basicblock *) iptr->target);
2957 case ICMD_IFEQ: /* ..., value ==> ... */
2958 /* op1 = target JavaVM pc, val.i = constant */
2960 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2961 M_CMP_IMM(iptr->val.i, s1);
2963 codegen_addreference(cd, (basicblock *) iptr->target);
2966 case ICMD_IFLT: /* ..., value ==> ... */
2967 /* op1 = target JavaVM pc, val.i = constant */
2969 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2970 M_CMP_IMM(iptr->val.i, s1);
2972 codegen_addreference(cd, (basicblock *) iptr->target);
2975 case ICMD_IFLE: /* ..., value ==> ... */
2976 /* op1 = target JavaVM pc, val.i = constant */
2978 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2979 M_CMP_IMM(iptr->val.i, s1);
2981 codegen_addreference(cd, (basicblock *) iptr->target);
2984 case ICMD_IFNE: /* ..., value ==> ... */
2985 /* op1 = target JavaVM pc, val.i = constant */
2987 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2988 M_CMP_IMM(iptr->val.i, s1);
2990 codegen_addreference(cd, (basicblock *) iptr->target);
2993 case ICMD_IFGT: /* ..., value ==> ... */
2994 /* op1 = target JavaVM pc, val.i = constant */
2996 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2997 M_CMP_IMM(iptr->val.i, s1);
2999 codegen_addreference(cd, (basicblock *) iptr->target);
3002 case ICMD_IFGE: /* ..., value ==> ... */
3003 /* op1 = target JavaVM pc, val.i = constant */
3005 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3006 M_CMP_IMM(iptr->val.i, s1);
3008 codegen_addreference(cd, (basicblock *) iptr->target);
3011 case ICMD_IF_LEQ: /* ..., value ==> ... */
3012 /* op1 = target JavaVM pc, val.l = constant */
3014 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
3015 if (iptr->val.l == 0) {
3016 M_INTMOVE(GET_LOW_REG(s1), REG_ITMP1);
3017 M_OR(GET_HIGH_REG(s1), REG_ITMP1);
3020 M_LNGMOVE(s1, REG_ITMP12_PACKED);
3021 M_XOR_IMM(iptr->val.l, REG_ITMP1);
3022 M_XOR_IMM(iptr->val.l >> 32, REG_ITMP2);
3023 M_OR(REG_ITMP2, REG_ITMP1);
3026 codegen_addreference(cd, (basicblock *) iptr->target);
3029 case ICMD_IF_LLT: /* ..., value ==> ... */
3030 /* op1 = target JavaVM pc, val.l = constant */
3032 if (iptr->val.l == 0) {
3033 /* If high 32-bit are less than zero, then the 64-bits
3035 s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP2);
3040 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
3041 M_CMP_IMM(iptr->val.l >> 32, GET_HIGH_REG(s1));
3043 codegen_addreference(cd, (basicblock *) iptr->target);
3045 M_CMP_IMM32(iptr->val.l, GET_LOW_REG(s1));
3048 codegen_addreference(cd, (basicblock *) iptr->target);
3051 case ICMD_IF_LLE: /* ..., value ==> ... */
3052 /* op1 = target JavaVM pc, val.l = constant */
3054 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
3055 M_CMP_IMM(iptr->val.l >> 32, GET_HIGH_REG(s1));
3057 codegen_addreference(cd, (basicblock *) iptr->target);
3059 M_CMP_IMM32(iptr->val.l, GET_LOW_REG(s1));
3061 codegen_addreference(cd, (basicblock *) iptr->target);
3064 case ICMD_IF_LNE: /* ..., value ==> ... */
3065 /* op1 = target JavaVM pc, val.l = constant */
3067 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
3068 if (iptr->val.l == 0) {
3069 M_INTMOVE(GET_LOW_REG(s1), REG_ITMP1);
3070 M_OR(GET_HIGH_REG(s1), REG_ITMP1);
3073 M_LNGMOVE(s1, REG_ITMP12_PACKED);
3074 M_XOR_IMM(iptr->val.l, REG_ITMP1);
3075 M_XOR_IMM(iptr->val.l >> 32, REG_ITMP2);
3076 M_OR(REG_ITMP2, REG_ITMP1);
3079 codegen_addreference(cd, (basicblock *) iptr->target);
3082 case ICMD_IF_LGT: /* ..., value ==> ... */
3083 /* op1 = target JavaVM pc, val.l = constant */
3085 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
3086 M_CMP_IMM(iptr->val.l >> 32, GET_HIGH_REG(s1));
3088 codegen_addreference(cd, (basicblock *) iptr->target);
3090 M_CMP_IMM32(iptr->val.l, GET_LOW_REG(s1));
3092 codegen_addreference(cd, (basicblock *) iptr->target);
3095 case ICMD_IF_LGE: /* ..., value ==> ... */
3096 /* op1 = target JavaVM pc, val.l = constant */
3098 if (iptr->val.l == 0) {
3099 /* If high 32-bit are greater equal zero, then the
3101 s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP2);
3106 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
3107 M_CMP_IMM(iptr->val.l >> 32, GET_HIGH_REG(s1));
3109 codegen_addreference(cd, (basicblock *) iptr->target);
3111 M_CMP_IMM32(iptr->val.l, GET_LOW_REG(s1));
3114 codegen_addreference(cd, (basicblock *) iptr->target);
3117 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3118 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3120 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3121 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3124 codegen_addreference(cd, (basicblock *) iptr->target);
3127 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3128 /* op1 = target JavaVM pc */
3130 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3131 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3132 M_INTMOVE(s1, REG_ITMP1);
3133 M_XOR(s2, REG_ITMP1);
3134 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
3135 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
3136 M_INTMOVE(s1, REG_ITMP2);
3137 M_XOR(s2, REG_ITMP2);
3138 M_OR(REG_ITMP1, REG_ITMP2);
3140 codegen_addreference(cd, (basicblock *) iptr->target);
3143 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3144 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3146 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3147 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3150 codegen_addreference(cd, (basicblock *) iptr->target);
3153 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3154 /* op1 = target JavaVM pc */
3156 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3157 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3158 M_INTMOVE(s1, REG_ITMP1);
3159 M_XOR(s2, REG_ITMP1);
3160 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
3161 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
3162 M_INTMOVE(s1, REG_ITMP2);
3163 M_XOR(s2, REG_ITMP2);
3164 M_OR(REG_ITMP1, REG_ITMP2);
3166 codegen_addreference(cd, (basicblock *) iptr->target);
3169 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3170 /* op1 = target JavaVM pc */
3172 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3173 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3176 codegen_addreference(cd, (basicblock *) iptr->target);
3179 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3180 /* op1 = target JavaVM pc */
3182 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
3183 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
3186 codegen_addreference(cd, (basicblock *) iptr->target);
3187 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3188 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3192 codegen_addreference(cd, (basicblock *) iptr->target);
3195 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3196 /* op1 = target JavaVM pc */
3198 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3199 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3202 codegen_addreference(cd, (basicblock *) iptr->target);
3205 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3206 /* op1 = target JavaVM pc */
3208 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
3209 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
3212 codegen_addreference(cd, (basicblock *) iptr->target);
3213 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3214 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3218 codegen_addreference(cd, (basicblock *) iptr->target);
3221 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3222 /* op1 = target JavaVM pc */
3224 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3225 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3228 codegen_addreference(cd, (basicblock *) iptr->target);
3231 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3232 /* op1 = target JavaVM pc */
3234 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
3235 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
3238 codegen_addreference(cd, (basicblock *) iptr->target);
3239 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3240 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3244 codegen_addreference(cd, (basicblock *) iptr->target);
3247 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3248 /* op1 = target JavaVM pc */
3250 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3251 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3254 codegen_addreference(cd, (basicblock *) iptr->target);
3257 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3258 /* op1 = target JavaVM pc */
3260 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
3261 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
3264 codegen_addreference(cd, (basicblock *) iptr->target);
3265 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3266 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3270 codegen_addreference(cd, (basicblock *) iptr->target);
3274 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3276 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
3277 M_INTMOVE(s1, REG_RESULT);
3278 goto nowperformreturn;
3280 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3282 s1 = emit_load_s1(jd, iptr, src, REG_RESULT_PACKED);
3283 M_LNGMOVE(s1, REG_RESULT_PACKED);
3284 goto nowperformreturn;
3286 case ICMD_ARETURN: /* ..., retvalue ==> ... */
3288 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
3289 M_INTMOVE(s1, REG_RESULT);
3291 #ifdef ENABLE_VERIFIER
3293 codegen_addpatchref(cd, PATCHER_athrow_areturn,
3294 (unresolved_class *) iptr->val.a, 0);
3296 if (opt_showdisassemble) {
3297 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3300 #endif /* ENABLE_VERIFIER */
3301 goto nowperformreturn;
3303 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3306 s1 = emit_load_s1(jd, iptr, src, REG_FRESULT);
3307 goto nowperformreturn;
3309 case ICMD_RETURN: /* ... ==> ... */
3315 p = cd->stackframesize;
3317 #if !defined(NDEBUG)
3318 /* call trace function */
3320 if (opt_verbosecall) {
3321 M_ISUB_IMM(4 + 8 + 8 + 4, REG_SP);
3323 emit_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3325 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3326 emit_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3328 emit_fstl_membase(cd, REG_SP, 4 + 8);
3329 emit_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3331 emit_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3332 emit_call_reg(cd, REG_ITMP1);
3334 emit_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3335 emit_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3337 emit_alu_imm_reg(cd, ALU_ADD, 4 + 8 + 8 + 4, REG_SP);
3339 #endif /* !defined(NDEBUG) */
3341 #if defined(ENABLE_THREADS)
3342 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3343 M_ALD(REG_ITMP2, REG_SP, rd->memuse * 4);
3345 /* we need to save the proper return value */
3346 switch (iptr->opc) {
3349 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
3353 M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 4);
3357 emit_fstps_membase(cd, REG_SP, rd->memuse * 4);
3361 emit_fstpl_membase(cd, REG_SP, rd->memuse * 4);
3365 M_AST(REG_ITMP2, REG_SP, 0);
3366 M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3);
3369 /* and now restore the proper return value */
3370 switch (iptr->opc) {
3373 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
3377 M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 4);
3381 emit_flds_membase(cd, REG_SP, rd->memuse * 4);
3385 emit_fldl_membase(cd, REG_SP, rd->memuse * 4);
3391 /* restore saved registers */
3393 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
3394 p--; M_ALD(rd->savintregs[i], REG_SP, p * 4);
3397 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
3399 emit_fldl_membase(cd, REG_SP, p * 4);
3400 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3402 /* emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1); */
3405 /* emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset); */
3409 /* deallocate stack */
3411 if (cd->stackframesize)
3412 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
3419 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3424 tptr = (void **) iptr->target;
3426 s4ptr = iptr->val.a;
3427 l = s4ptr[1]; /* low */
3428 i = s4ptr[2]; /* high */
3430 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3431 M_INTMOVE(s1, REG_ITMP1);
3434 M_ISUB_IMM(l, REG_ITMP1);
3440 M_CMP_IMM(i - 1, REG_ITMP1);
3442 codegen_addreference(cd, (basicblock *) tptr[0]);
3444 /* build jump table top down and use address of lowest entry */
3449 dseg_addtarget(cd, (basicblock *) tptr[0]);
3453 /* length of dataseg after last dseg_addtarget is used
3456 M_MOV_IMM(0, REG_ITMP2);
3458 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3464 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3466 s4 i, l, val, *s4ptr;
3469 tptr = (void **) iptr->target;
3471 s4ptr = iptr->val.a;
3472 l = s4ptr[0]; /* default */
3473 i = s4ptr[1]; /* count */
3475 MCODECHECK((i<<2)+8);
3476 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3485 codegen_addreference(cd, (basicblock *) tptr[0]);
3490 tptr = (void **) iptr->target;
3491 codegen_addreference(cd, (basicblock *) tptr[0]);
3495 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
3496 /* op1 = arg count val.a = builtintable entry */
3502 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3503 /* op1 = arg count, val.a = method pointer */
3505 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3506 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
3507 case ICMD_INVOKEINTERFACE:
3509 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3510 md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
3514 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
3515 md = lm->parseddesc;
3519 s3 = md->paramcount;
3521 MCODECHECK((s3 << 1) + 64);
3523 /* copy arguments to registers or stack location */
3525 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
3526 if (src->varkind == ARGVAR)
3528 if (IS_INT_LNG_TYPE(src->type)) {
3529 if (!md->params[s3].inmemory) {
3530 log_text("No integer argument registers available!");
3534 if (IS_2_WORD_TYPE(src->type)) {
3535 d = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
3536 M_LST(d, REG_SP, md->params[s3].regoff * 4);
3538 d = emit_load_s1(jd, iptr, src, REG_ITMP1);
3539 M_IST(d, REG_SP, md->params[s3].regoff * 4);
3544 if (!md->params[s3].inmemory) {
3545 s1 = rd->argfltregs[md->params[s3].regoff];
3546 d = emit_load_s1(jd, iptr, src, s1);
3550 d = emit_load_s1(jd, iptr, src, REG_FTMP1);
3551 if (IS_2_WORD_TYPE(src->type))
3552 M_DST(d, REG_SP, md->params[s3].regoff * 4);
3554 M_FST(d, REG_SP, md->params[s3].regoff * 4);
3559 switch (iptr->opc) {
3561 disp = (ptrint) bte->fp;
3562 d = md->returntype.type;
3564 M_MOV_IMM(disp, REG_ITMP1);
3567 /* if op1 == true, we need to check for an exception */
3569 if (iptr->op1 == true) {
3572 codegen_add_fillinstacktrace_ref(cd);
3576 case ICMD_INVOKESPECIAL:
3577 M_ALD(REG_ITMP1, REG_SP, 0);
3580 codegen_add_nullpointerexception_ref(cd);
3584 case ICMD_INVOKESTATIC:
3586 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3588 codegen_addpatchref(cd, PATCHER_invokestatic_special,
3591 if (opt_showdisassemble) {
3592 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3596 d = md->returntype.type;
3599 disp = (ptrint) lm->stubroutine;
3600 d = lm->parseddesc->returntype.type;
3603 M_MOV_IMM(disp, REG_ITMP2);
3607 case ICMD_INVOKEVIRTUAL:
3608 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
3609 gen_nullptr_check(REG_ITMP1);
3612 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3614 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
3616 if (opt_showdisassemble) {
3617 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3621 d = md->returntype.type;
3624 s1 = OFFSET(vftbl_t, table[0]) +
3625 sizeof(methodptr) * lm->vftblindex;
3626 d = md->returntype.type;
3629 M_ALD(REG_METHODPTR, REG_ITMP1,
3630 OFFSET(java_objectheader, vftbl));
3631 M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
3635 case ICMD_INVOKEINTERFACE:
3636 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
3637 gen_nullptr_check(REG_ITMP1);
3640 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3642 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
3644 if (opt_showdisassemble) {
3645 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3650 d = md->returntype.type;
3653 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3654 sizeof(methodptr) * lm->class->index;
3656 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3658 d = md->returntype.type;
3661 M_ALD(REG_METHODPTR, REG_ITMP1,
3662 OFFSET(java_objectheader, vftbl));
3663 M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
3664 M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
3669 /* d contains return type */
3671 if (d != TYPE_VOID) {
3672 #if defined(ENABLE_SSA)
3673 if ((ls == NULL) || (iptr->dst->varkind != TEMPVAR) ||
3674 (ls->lifetime[-iptr->dst->varnum-1].type != -1))
3675 /* a "living" stackslot */
3678 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3679 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3680 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
3681 M_LNGMOVE(REG_RESULT_PACKED, s1);
3684 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3685 M_INTMOVE(REG_RESULT, s1);
3689 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
3691 emit_store(jd, iptr, iptr->dst, s1);
3697 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3698 /* op1: 0 == array, 1 == class */
3699 /* val.a: (classinfo*) superclass */
3701 /* superclass is an interface:
3703 * OK if ((sub == NULL) ||
3704 * (sub->vftbl->interfacetablelength > super->index) &&
3705 * (sub->vftbl->interfacetable[-super->index] != NULL));
3707 * superclass is a class:
3709 * OK if ((sub == NULL) || (0
3710 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3711 * super->vftbl->diffval));
3714 if (iptr->op1 == 1) {
3715 /* object type cast-check */
3718 vftbl_t *supervftbl;
3721 super = (classinfo *) iptr->val.a;
3728 superindex = super->index;
3729 supervftbl = super->vftbl;
3732 #if defined(ENABLE_THREADS)
3733 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3735 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3737 /* calculate interface checkcast code size */
3739 s2 = 2; /* mov_membase_reg */
3740 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3742 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ +
3743 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
3744 2 /* test */ + 6 /* jcc */);
3747 s2 += (opt_showdisassemble ? 5 : 0);
3749 /* calculate class checkcast code size */
3751 s3 = 2; /* mov_membase_reg */
3752 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3754 s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */;
3757 if (s1 != REG_ITMP1) {
3759 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
3762 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
3769 s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ +
3770 5 /* mov_imm_reg */ + 2 /* mov_membase_reg */);
3771 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3774 s3 += 2 /* cmp */ + 6 /* jcc */;
3777 s3 += (opt_showdisassemble ? 5 : 0);
3779 /* if class is not resolved, check which code to call */
3781 if (super == NULL) {
3783 M_BEQ(5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
3785 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3786 (constant_classref *) iptr->target, 0);
3788 if (opt_showdisassemble) {
3789 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3792 M_MOV_IMM(0, REG_ITMP2); /* super->flags */
3793 M_AND_IMM32(ACC_INTERFACE, REG_ITMP2);
3797 /* interface checkcast code */
3799 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3800 if (super != NULL) {
3805 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3807 if (super == NULL) {
3808 codegen_addpatchref(cd,
3809 PATCHER_checkcast_instanceof_interface,
3810 (constant_classref *) iptr->target,
3813 if (opt_showdisassemble) {
3814 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3819 REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3820 M_ISUB_IMM32(superindex, REG_ITMP3);
3823 codegen_add_classcastexception_ref(cd, s1);
3824 M_ALD32(REG_ITMP3, REG_ITMP2,
3825 OFFSET(vftbl_t, interfacetable[0]) -
3826 superindex * sizeof(methodptr*));
3829 codegen_add_classcastexception_ref(cd, s1);
3835 /* class checkcast code */
3837 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3838 if (super != NULL) {
3843 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3845 if (super == NULL) {
3846 codegen_addpatchref(cd, PATCHER_checkcast_class,
3847 (constant_classref *) iptr->target,
3850 if (opt_showdisassemble) {
3851 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3855 M_MOV_IMM(supervftbl, REG_ITMP3);
3856 #if defined(ENABLE_THREADS)
3857 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3859 M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3861 /* if (s1 != REG_ITMP1) { */
3862 /* emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
3863 /* emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
3864 /* #if defined(ENABLE_THREADS) */
3865 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
3867 /* emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
3870 M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3871 M_ISUB(REG_ITMP3, REG_ITMP2);
3872 M_MOV_IMM(supervftbl, REG_ITMP3);
3873 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3874 #if defined(ENABLE_THREADS)
3875 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3879 M_CMP(REG_ITMP3, REG_ITMP2);
3880 M_BA(0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
3881 codegen_add_classcastexception_ref(cd, s1);
3884 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
3887 /* array type cast-check */
3889 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
3890 M_AST(s1, REG_SP, 0 * 4);
3892 if (iptr->val.a == NULL) {
3893 codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
3896 if (opt_showdisassemble) {
3897 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3901 M_AST_IMM(iptr->val.a, REG_SP, 1 * 4);
3902 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP3);
3905 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
3908 codegen_add_classcastexception_ref(cd, s1);
3910 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
3914 emit_store(jd, iptr, iptr->dst, d);
3917 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3918 /* op1: 0 == array, 1 == class */
3919 /* val.a: (classinfo*) superclass */
3921 /* superclass is an interface:
3923 * return (sub != NULL) &&
3924 * (sub->vftbl->interfacetablelength > super->index) &&
3925 * (sub->vftbl->interfacetable[-super->index] != NULL);
3927 * superclass is a class:
3929 * return ((sub != NULL) && (0
3930 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3931 * super->vftbl->diffvall));
3936 vftbl_t *supervftbl;
3939 super = (classinfo *) iptr->val.a;
3946 superindex = super->index;
3947 supervftbl = super->vftbl;
3950 #if defined(ENABLE_THREADS)
3951 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3954 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3955 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3957 M_INTMOVE(s1, REG_ITMP1);
3961 /* calculate interface instanceof code size */
3963 s2 = 2; /* mov_membase_reg */
3964 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3966 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
3967 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
3968 2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
3971 s2 += (opt_showdisassemble ? 5 : 0);
3973 /* calculate class instanceof code size */
3975 s3 = 2; /* mov_membase_reg */
3976 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3977 s3 += 5; /* mov_imm_reg */
3979 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
3981 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3983 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3985 s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
3986 2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
3989 s3 += (opt_showdisassemble ? 5 : 0);
3993 /* if class is not resolved, check which code to call */
3997 M_BEQ(5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
3999 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
4000 (constant_classref *) iptr->target, 0);
4002 if (opt_showdisassemble) {
4003 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4006 M_MOV_IMM(0, REG_ITMP3); /* super->flags */
4007 M_AND_IMM32(ACC_INTERFACE, REG_ITMP3);
4011 /* interface instanceof code */
4013 if (!super || (super->flags & ACC_INTERFACE)) {
4019 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
4022 codegen_addpatchref(cd,
4023 PATCHER_checkcast_instanceof_interface,
4024 (constant_classref *) iptr->target, 0);
4026 if (opt_showdisassemble) {
4027 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4032 REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4033 M_ISUB_IMM32(superindex, REG_ITMP3);
4036 disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
4037 6 /* jcc */ + 5 /* mov_imm_reg */);
4040 M_ALD32(REG_ITMP1, REG_ITMP1,
4041 OFFSET(vftbl_t, interfacetable[0]) -
4042 superindex * sizeof(methodptr*));
4044 /* emit_setcc_reg(cd, CC_A, d); */
4045 /* emit_jcc(cd, CC_BE, 5); */
4053 /* class instanceof code */
4055 if (!super || !(super->flags & ACC_INTERFACE)) {
4061 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
4064 codegen_addpatchref(cd, PATCHER_instanceof_class,
4065 (constant_classref *) iptr->target, 0);
4067 if (opt_showdisassemble) {
4068 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4072 M_MOV_IMM(supervftbl, REG_ITMP2);
4073 #if defined(ENABLE_THREADS)
4074 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4076 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
4077 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval));
4078 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
4079 #if defined(ENABLE_THREADS)
4080 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4082 M_ISUB(REG_ITMP2, REG_ITMP1);
4083 M_CLR(d); /* may be REG_ITMP2 */
4084 M_CMP(REG_ITMP3, REG_ITMP1);
4088 emit_store(jd, iptr, iptr->dst, d);
4094 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4095 /* op1 = dimension, val.a = class */
4097 /* check for negative sizes and copy sizes to stack if necessary */
4099 MCODECHECK((iptr->op1 << 1) + 64);
4101 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4102 /* copy SAVEDVAR sizes to stack */
4104 if (src->varkind != ARGVAR) {
4105 if (src->flags & INMEMORY) {
4106 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
4107 M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4);
4110 M_IST(src->regoff, REG_SP, (s1 + 3) * 4);
4114 /* is a patcher function set? */
4116 if (iptr->val.a == NULL) {
4117 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
4118 (constant_classref *) iptr->target, 0);
4120 if (opt_showdisassemble) {
4121 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4128 disp = (ptrint) iptr->val.a;
4130 /* a0 = dimension count */
4132 M_IST_IMM(iptr->op1, REG_SP, 0 * 4);
4134 /* a1 = arraydescriptor */
4136 M_IST_IMM(disp, REG_SP, 1 * 4);
4138 /* a2 = pointer to dimensions = stack pointer */
4140 M_MOV(REG_SP, REG_ITMP1);
4141 M_AADD_IMM(3 * 4, REG_ITMP1);
4142 M_AST(REG_ITMP1, REG_SP, 2 * 4);
4144 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
4147 /* check for exception before result assignment */
4151 codegen_add_fillinstacktrace_ref(cd);
4153 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
4154 M_INTMOVE(REG_RESULT, s1);
4155 emit_store(jd, iptr, iptr->dst, s1);
4160 new_internalerror("Unknown ICMD %d", iptr->opc);
4164 } /* for instruction */
4166 /* copy values to interface registers */
4168 src = bptr->outstack;
4169 len = bptr->outdepth;
4171 #if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
4174 #if defined(ENABLE_SSA)
4176 /* by edge splitting, in Blocks with phi moves there can only */
4177 /* be a goto as last command, no other Jump/Branch Command */
4178 if (!last_cmd_was_goto)
4179 codegen_insert_phi_moves(cd, rd, ls, bptr);
4184 if ((src->varkind != STACKVAR)) {
4186 if (IS_FLT_DBL_TYPE(s2)) {
4187 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
4188 if (!(rd->interfaces[len][s2].flags & INMEMORY))
4189 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
4191 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
4194 if (IS_2_WORD_TYPE(s2))
4196 /* s1 = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP1, REG_ITMP2)); */
4198 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4200 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4201 if (IS_2_WORD_TYPE(s2))
4202 M_LNGMOVE(s1, rd->interfaces[len][s2].regoff);
4204 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
4207 if (IS_2_WORD_TYPE(s2))
4208 M_LST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
4210 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
4217 /* At the end of a basic block we may have to append some nops,
4218 because the patcher stub calling code might be longer than the
4219 actual instruction. So codepatching does not change the
4220 following block unintentionally. */
4222 if (cd->mcodeptr < cd->lastmcodeptr) {
4223 while (cd->mcodeptr < cd->lastmcodeptr) {
4228 } /* if (bptr -> flags >= BBREACHED) */
4229 } /* for basic block */
4231 dseg_createlinenumbertable(cd);
4234 /* generate exception and patcher stubs */
4236 emit_exception_stubs(jd);
4237 emit_patcher_stubs(jd);
4238 emit_replacement_stubs(jd);
4242 /* everything's ok */
4247 #if defined(ENABLE_SSA)
4248 void codegen_insert_phi_moves(codegendata *cd, registerdata *rd, lsradata *ls, basicblock *bptr) {
4249 /* look for phi moves */
4250 int t_a,s_a,i, type;
4251 int t_lt, s_lt; /* lifetime indices of phi_moves */
4252 bool t_inmemory, s_inmemory;
4253 s4 t_regoff, s_regoff, s_flags, t_flags;
4256 /* Moves from phi functions with highest indices have to be */
4257 /* inserted first, since this is the order as is used for */
4258 /* conflict resolution */
4259 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
4260 t_a = ls->phi_moves[bptr->nr][i][0];
4261 s_a = ls->phi_moves[bptr->nr][i][1];
4262 #if defined(SSA_DEBUG_VERBOSE)
4264 printf("BB %3i Move %3i <- %3i ",bptr->nr,t_a,s_a);
4267 /* local var lifetimes */
4268 t_lt = ls->maxlifetimes + t_a;
4269 type = ls->lifetime[t_lt].type;
4272 type = ls->lifetime[t_lt].local_ss->s->type;
4273 /* stackslot lifetime */
4276 #if defined(SSA_DEBUG_VERBOSE)
4278 printf("...returning - phi lifetimes where joined\n");
4283 /* local var lifetimes */
4284 s_lt = ls->maxlifetimes + s_a;
4285 type = ls->lifetime[s_lt].type;
4288 type = ls->lifetime[s_lt].type;
4289 /* stackslot lifetime */
4292 #if defined(SSA_DEBUG_VERBOSE)
4294 printf("...returning - phi lifetimes where joined\n");
4300 t_inmemory = rd->locals[t_a][type].flags & INMEMORY;
4301 t_flags = rd->locals[t_a][type].flags;
4302 t_regoff = rd->locals[t_a][type].regoff;
4305 t_inmemory = ls->lifetime[t_lt].local_ss->s->flags & INMEMORY;
4306 t_flags = ls->lifetime[t_lt].local_ss->s->flags;
4307 t_regoff = ls->lifetime[t_lt].local_ss->s->regoff;
4311 /* local var move */
4313 s_inmemory = rd->locals[s_a][type].flags & INMEMORY;
4314 s_flags = rd->locals[s_a][type].flags;
4315 s_regoff = rd->locals[s_a][type].regoff;
4317 /* stackslot lifetime */
4318 s_inmemory = ls->lifetime[s_lt].local_ss->s->flags & INMEMORY;
4319 s_flags = ls->lifetime[s_lt].local_ss->s->flags;
4320 s_regoff = ls->lifetime[s_lt].local_ss->s->regoff;
4323 #if defined(SSA_DEBUG_VERBOSE)
4325 printf("...returning - phi lifetimes where joined\n");
4330 cg_move(cd, type, s_regoff, s_flags, t_regoff, t_flags);
4332 #if defined(SSA_DEBUG_VERBOSE)
4333 if (compileverbose) {
4334 if ((t_inmemory) && (s_inmemory)) {
4336 printf("M%3i <- M%3i",t_regoff,s_regoff);
4337 } else if (s_inmemory) {
4339 printf("R%3i <- M%3i",t_regoff,s_regoff);
4340 } else if (t_inmemory) {
4342 printf("M%3i <- R%3i",t_regoff,s_regoff);
4345 printf("R%3i <- R%3i",t_regoff,s_regoff);
4349 #endif /* defined(SSA_DEBUG_VERBOSE) */
4353 void cg_move(codegendata *cd, s4 type, s4 src_regoff, s4 src_flags,
4354 s4 dst_regoff, s4 dst_flags) {
4355 if ((dst_flags & INMEMORY) && (src_flags & INMEMORY)) {
4357 if (dst_regoff != src_regoff) {
4358 if (!IS_2_WORD_TYPE(type)) {
4359 if (IS_FLT_DBL_TYPE(type)) {
4360 emit_flds_membase(cd, REG_SP, src_regoff * 4);
4361 emit_fstps_membase(cd, REG_SP, dst_regoff * 4);
4363 emit_mov_membase_reg(cd, REG_SP, src_regoff * 4,
4365 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, dst_regoff * 4);
4367 } else { /* LONG OR DOUBLE */
4368 if (IS_FLT_DBL_TYPE(type)) {
4369 emit_fldl_membase( cd, REG_SP, src_regoff * 4);
4370 emit_fstpl_membase(cd, REG_SP, dst_regoff * 4);
4372 emit_mov_membase_reg(cd, REG_SP, src_regoff * 4,
4374 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, dst_regoff * 4);
4375 emit_mov_membase_reg(cd, REG_SP, src_regoff * 4 + 4,
4377 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP,
4378 dst_regoff * 4 + 4);
4383 if (IS_FLT_DBL_TYPE(type)) {
4384 log_text("cg_move: flt/dbl type have to be in memory\n");
4387 if (IS_2_WORD_TYPE(type)) {
4388 log_text("cg_move: longs have to be in memory\n");
4391 if (src_flags & INMEMORY) {
4393 emit_mov_membase_reg(cd, REG_SP, src_regoff * 4, dst_regoff);
4394 } else if (dst_flags & INMEMORY) {
4396 emit_mov_reg_membase(cd, src_regoff, REG_SP, dst_regoff * 4);
4399 /* only ints can be in regs on i386 */
4400 M_INTMOVE(src_regoff,dst_regoff);
4404 #endif /* defined(ENABLE_SSA) */
4406 /* createcompilerstub **********************************************************
4408 Creates a stub routine which calls the compiler.
4410 *******************************************************************************/
4412 #define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P
4413 #define COMPILERSTUB_CODESIZE 12
4415 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4418 u1 *createcompilerstub(methodinfo *m)
4420 u1 *s; /* memory to hold the stub */
4426 s = CNEW(u1, COMPILERSTUB_SIZE);
4428 /* set data pointer and code pointer */
4431 s = s + COMPILERSTUB_DATASIZE;
4433 /* mark start of dump memory area */
4435 dumpsize = dump_size();
4437 cd = DNEW(codegendata);
4440 /* Store the codeinfo pointer in the same place as in the
4441 methodheader for compiled methods. */
4443 code = code_codeinfo_new(m);
4445 d[0] = (ptrint) asm_call_jit_compiler;
4447 d[2] = (ptrint) code;
4449 /* code for the stub */
4451 M_MOV_IMM(m, REG_ITMP1); /* method info */
4452 M_MOV_IMM(asm_call_jit_compiler, REG_ITMP3);
4455 #if defined(ENABLE_STATISTICS)
4457 count_cstub_len += COMPILERSTUB_SIZE;
4460 /* release dump area */
4462 dump_release(dumpsize);
4468 /* createnativestub ************************************************************
4470 Creates a stub routine which calls a native method.
4472 *******************************************************************************/
4474 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
4482 s4 i, j; /* count variables */
4486 /* get required compiler data */
4493 /* set some variables */
4496 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4498 /* calculate stackframe size */
4500 cd->stackframesize =
4501 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4502 sizeof(localref_table) / SIZEOF_VOID_P +
4503 1 + /* function pointer */
4504 4 * 4 + /* 4 arguments (start_native_call) */
4507 /* keep stack 16-byte aligned */
4509 cd->stackframesize |= 0x3;
4511 /* create method header */
4513 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
4514 (void) dseg_adds4(cd, cd->stackframesize * 4); /* FrameSize */
4515 (void) dseg_adds4(cd, 0); /* IsSync */
4516 (void) dseg_adds4(cd, 0); /* IsLeaf */
4517 (void) dseg_adds4(cd, 0); /* IntSave */
4518 (void) dseg_adds4(cd, 0); /* FltSave */
4519 (void) dseg_addlinenumbertablesize(cd);
4520 (void) dseg_adds4(cd, 0); /* ExTableSize */
4522 /* generate native method profiling code */
4524 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
4525 /* count frequency */
4527 M_MOV_IMM(code, REG_ITMP1);
4528 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(codeinfo, frequency));
4531 /* calculate stackframe size for native function */
4533 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
4535 #if !defined(NDEBUG)
4536 if (opt_verbosecall) {
4539 disp = cd->stackframesize * 4;
4541 M_ASUB_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
4543 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
4544 t = md->paramtypes[p].type;
4545 if (IS_INT_LNG_TYPE(t)) {
4546 if (IS_2_WORD_TYPE(t)) {
4547 M_ILD(REG_ITMP1, REG_SP,
4548 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4549 M_ILD(REG_ITMP2, REG_SP,
4550 4 + TRACE_ARGS_NUM * 8 + 4 + disp + 4);
4551 M_IST(REG_ITMP1, REG_SP, p * 8);
4552 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
4554 } else if (t == TYPE_ADR) {
4555 M_ALD(REG_ITMP1, REG_SP,
4556 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4558 M_AST(REG_ITMP1, REG_SP, p * 8);
4559 M_AST(REG_ITMP2, REG_SP, p * 8 + 4);
4562 M_ILD(EAX, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4564 M_IST(EAX, REG_SP, p * 8);
4565 M_IST(EDX, REG_SP, p * 8 + 4);
4569 if (!IS_2_WORD_TYPE(t)) {
4570 emit_flds_membase(cd, REG_SP,
4571 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4572 emit_fstps_membase(cd, REG_SP, p * 8);
4573 emit_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
4574 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
4577 emit_fldl_membase(cd, REG_SP,
4578 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4579 emit_fstpl_membase(cd, REG_SP, p * 8);
4582 disp += (IS_2_WORD_TYPE(t)) ? 8 : 4;
4586 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
4587 M_IST(REG_ITMP1, REG_SP, p * 8);
4588 M_IST(REG_ITMP1, REG_SP, p * 8 + 4);
4591 M_AST_IMM(m, REG_SP, TRACE_ARGS_NUM * 8);
4593 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
4596 M_AADD_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
4598 #endif /* !defined(NDEBUG) */
4600 /* get function address (this must happen before the stackframeinfo) */
4602 #if !defined(WITH_STATIC_CLASSPATH)
4604 codegen_addpatchref(cd, PATCHER_resolve_native, m, 0);
4606 if (opt_showdisassemble) {
4607 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4612 M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
4614 /* Mark the whole fpu stack as free for native functions (only for saved */
4615 /* register count == 0). */
4617 emit_ffree_reg(cd, 0);
4618 emit_ffree_reg(cd, 1);
4619 emit_ffree_reg(cd, 2);
4620 emit_ffree_reg(cd, 3);
4621 emit_ffree_reg(cd, 4);
4622 emit_ffree_reg(cd, 5);
4623 emit_ffree_reg(cd, 6);
4624 emit_ffree_reg(cd, 7);
4626 /* prepare data structures for native function call */
4628 M_MOV(REG_SP, REG_ITMP1);
4629 M_AADD_IMM(cd->stackframesize * 4, REG_ITMP1);
4631 M_AST(REG_ITMP1, REG_SP, 0 * 4);
4632 M_IST_IMM(0, REG_SP, 1 * 4);
4635 M_MOV(REG_SP, REG_ITMP2);
4636 M_AADD_IMM(cd->stackframesize * 4 + SIZEOF_VOID_P, REG_ITMP2);
4638 M_AST(REG_ITMP2, REG_SP, 2 * 4);
4639 M_ALD(REG_ITMP3, REG_SP, cd->stackframesize * 4);
4640 M_AST(REG_ITMP3, REG_SP, 3 * 4);
4641 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
4644 M_ALD(REG_ITMP3, REG_SP, 4 * 4);
4646 /* copy arguments into new stackframe */
4648 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4649 t = md->paramtypes[i].type;
4651 if (!md->params[i].inmemory) {
4652 /* no integer argument registers */
4653 } else { /* float/double in memory can be copied like int/longs */
4654 s1 = (md->params[i].regoff + cd->stackframesize + 1) * 4;
4655 s2 = nmd->params[j].regoff * 4;
4657 M_ILD(REG_ITMP1, REG_SP, s1);
4658 M_IST(REG_ITMP1, REG_SP, s2);
4659 if (IS_2_WORD_TYPE(t)) {
4660 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
4661 M_IST(REG_ITMP1, REG_SP, s2 + 4);
4666 /* if function is static, put class into second argument */
4668 if (m->flags & ACC_STATIC)
4669 M_AST_IMM(m->class, REG_SP, 1 * 4);
4671 /* put env into first argument */
4673 M_AST_IMM(_Jv_env, REG_SP, 0 * 4);
4675 /* call the native function */
4679 /* save return value */
4681 if (md->returntype.type != TYPE_VOID) {
4682 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4683 if (IS_2_WORD_TYPE(md->returntype.type))
4684 M_IST(REG_RESULT2, REG_SP, 2 * 4);
4685 M_IST(REG_RESULT, REG_SP, 1 * 4);
4688 if (IS_2_WORD_TYPE(md->returntype.type))
4689 emit_fstl_membase(cd, REG_SP, 1 * 4);
4691 emit_fsts_membase(cd, REG_SP, 1 * 4);
4695 #if !defined(NDEBUG)
4696 if (opt_verbosecall) {
4697 /* restore return value */
4699 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4700 if (IS_2_WORD_TYPE(md->returntype.type))
4701 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
4702 M_ILD(REG_RESULT, REG_SP, 1 * 4);
4705 if (IS_2_WORD_TYPE(md->returntype.type))
4706 emit_fldl_membase(cd, REG_SP, 1 * 4);
4708 emit_flds_membase(cd, REG_SP, 1 * 4);
4711 M_ASUB_IMM(4 + 8 + 8 + 4, REG_SP);
4713 M_AST_IMM((ptrint) m, REG_SP, 0);
4715 M_IST(REG_RESULT, REG_SP, 4);
4716 M_IST(REG_RESULT2, REG_SP, 4 + 4);
4718 emit_fstl_membase(cd, REG_SP, 4 + 8);
4719 emit_fsts_membase(cd, REG_SP, 4 + 8 + 8);
4721 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
4724 M_AADD_IMM(4 + 8 + 8 + 4, REG_SP);
4726 #endif /* !defined(NDEBUG) */
4728 /* remove native stackframe info */
4730 M_MOV(REG_SP, REG_ITMP1);
4731 M_AADD_IMM(cd->stackframesize * 4, REG_ITMP1);
4733 M_AST(REG_ITMP1, REG_SP, 0 * 4);
4734 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
4736 M_MOV(REG_RESULT, REG_ITMP2); /* REG_ITMP3 == REG_RESULT2 */
4738 /* restore return value */
4740 if (md->returntype.type != TYPE_VOID) {
4741 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4742 if (IS_2_WORD_TYPE(md->returntype.type))
4743 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
4744 M_ILD(REG_RESULT, REG_SP, 1 * 4);
4747 if (IS_2_WORD_TYPE(md->returntype.type))
4748 emit_fldl_membase(cd, REG_SP, 1 * 4);
4750 emit_flds_membase(cd, REG_SP, 1 * 4);
4754 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
4756 /* check for exception */
4763 /* handle exception */
4765 M_MOV(REG_ITMP2, REG_ITMP1_XPTR);
4766 M_ALD(REG_ITMP2_XPC, REG_SP, 0);
4767 M_ASUB_IMM(2, REG_ITMP2_XPC);
4769 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
4773 /* generate patcher stubs */
4775 emit_patcher_stubs(jd);
4779 return code->entrypoint;
4784 * These are local overrides for various environment variables in Emacs.
4785 * Please do not remove this and leave it at the end of the file, where
4786 * Emacs will automagically detect them.
4787 * ---------------------------------------------------------------------
4790 * indent-tabs-mode: t
4794 * vim:noexpandtab:sw=4:ts=4: