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 5173 2006-07-25 15:57:11Z 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)
78 # ifdef LSRA_USES_REG_RES
79 # include "vm/jit/i386/icmd_uses_reg_res.inc"
81 # include "vm/jit/allocator/lsra.h"
85 /* codegen *********************************************************************
87 Generates machine code.
89 *******************************************************************************/
91 bool codegen(jitdata *jd)
97 s4 len, s1, s2, s3, d, off, disp;
105 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
106 builtintable_entry *bte;
108 rplpoint *replacementpoint;
110 /* get required compiler data */
117 /* prevent compiler warnings */
127 s4 savedregs_num = 0;
130 /* space to save used callee saved registers */
132 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
134 /* float register are saved on 2 4-byte stackslots */
135 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
137 stackframesize = rd->memuse + savedregs_num;
140 #if defined(ENABLE_THREADS)
141 /* space to save argument of monitor_enter */
143 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
144 /* reserve 2 slots for long/double return values for monitorexit */
146 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
153 /* create method header */
155 /* Keep stack of non-leaf functions 16-byte aligned. */
157 if (!jd->isleafmethod)
158 stackframesize |= 0x3;
160 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
161 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
163 #if defined(ENABLE_THREADS)
164 /* IsSync contains the offset relative to the stack pointer for the
165 argument of monitor_exit used in the exception handler. Since the
166 offset could be zero and give a wrong meaning of the flag it is
170 if (checksync && (m->flags & ACC_SYNCHRONIZED))
171 (void) dseg_adds4(cd, (rd->memuse + 1) * 4); /* IsSync */
174 (void) dseg_adds4(cd, 0); /* IsSync */
176 (void) dseg_adds4(cd, jd->isleafmethod); /* IsLeaf */
177 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
178 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
180 /* adds a reference for the length of the line number counter. We don't
181 know the size yet, since we evaluate the information during code
182 generation, to save one additional iteration over the whole
183 instructions. During code optimization the position could have changed
184 to the information gotten from the class file */
185 (void) dseg_addlinenumbertablesize(cd);
187 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
189 /* create exception table */
191 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
192 dseg_addtarget(cd, ex->start);
193 dseg_addtarget(cd, ex->end);
194 dseg_addtarget(cd, ex->handler);
195 (void) dseg_addaddress(cd, ex->catchtype.cls);
198 /* generate method profiling code */
200 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
201 /* count frequency */
203 M_MOV_IMM(code, REG_ITMP3);
204 M_IADD_IMM_MEMBASE(1, REG_ITMP3, OFFSET(codeinfo, frequency));
207 /* create stack frame (if necessary) */
210 M_ASUB_IMM(stackframesize * 4, REG_SP);
212 /* save return address and used callee saved registers */
215 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
216 p--; M_AST(rd->savintregs[i], REG_SP, p * 4);
218 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
219 p-=2; emit_fld_reg(cd, rd->savfltregs[i]); emit_fstpl_membase(cd, REG_SP, p * 4);
222 /* take arguments out of register or stack frame */
227 for (p = 0, l = 0; p < md->paramcount; p++) {
228 t = md->paramtypes[p].type;
229 var = &(rd->locals[l][t]);
231 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
235 s1 = md->params[p].regoff;
236 if (IS_INT_LNG_TYPE(t)) { /* integer args */
237 if (!md->params[p].inmemory) { /* register arguments */
238 log_text("integer register argument");
240 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
241 /* rd->argintregs[md->params[p].regoff -> var->regoff */
242 } else { /* reg arg -> spilled */
243 /* rd->argintregs[md->params[p].regoff -> var->regoff * 4 */
245 } else { /* stack arguments */
246 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
247 emit_mov_membase_reg( /* + 4 for return address */
248 cd, REG_SP, (stackframesize + s1) * 4 + 4, var->regoff);
249 /* + 4 for return address */
250 } else { /* stack arg -> spilled */
251 if (!IS_2_WORD_TYPE(t)) {
253 emit_mov_membase_reg( /* + 4 for return address */
254 cd, REG_SP, (stackframesize + s1) * 4 + 4,
256 emit_mov_reg_membase(
257 cd, REG_ITMP1, REG_SP, var->regoff * 4);
259 /* reuse Stackslotand avoid copying */
260 var->regoff = stackframesize + s1 + 1;
265 emit_mov_membase_reg( /* + 4 for return address */
266 cd, REG_SP, (stackframesize + s1) * 4 + 4,
268 emit_mov_reg_membase(
269 cd, REG_ITMP1, REG_SP, var->regoff * 4);
270 emit_mov_membase_reg( /* + 4 for return address */
271 cd, REG_SP, (stackframesize + s1) * 4 + 4 + 4,
273 emit_mov_reg_membase(
274 cd, REG_ITMP1, REG_SP, var->regoff * 4 + 4);
276 /* reuse Stackslotand avoid copying */
277 var->regoff = stackframesize + s1 + 1;
283 } else { /* floating args */
284 if (!md->params[p].inmemory) { /* register arguments */
285 log_text("There are no float argument registers!");
287 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
288 /* rd->argfltregs[md->params[p].regoff -> var->regoff */
289 } else { /* reg arg -> spilled */
290 /* rd->argfltregs[md->params[p].regoff -> var->regoff * 4 */
293 } else { /* stack arguments */
294 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
297 cd, REG_SP, (stackframesize + s1) * 4 + 4);
299 /* emit_fstp_reg(cd, var->regoff + fpu_st_offset); */
303 cd, REG_SP, (stackframesize + s1) * 4 + 4);
305 /* emit_fstp_reg(cd, var->regoff + fpu_st_offset); */
308 } else { /* stack-arg -> spilled */
310 emit_mov_membase_reg(
311 cd, REG_SP, (stackframesize + s1) * 4 + 4, REG_ITMP1);
312 emit_mov_reg_membase(
313 cd, REG_ITMP1, REG_SP, var->regoff * 4);
316 cd, REG_SP, (stackframesize + s1) * 4 + 4);
317 emit_fstps_membase(cd, REG_SP, var->regoff * 4);
320 cd, REG_SP, (stackframesize + s1) * 4 + 4);
321 emit_fstpl_membase(cd, REG_SP, var->regoff * 4);
324 /* reuse Stackslotand avoid copying */
325 var->regoff = stackframesize + s1 + 1;
332 /* call monitorenter function */
334 #if defined(ENABLE_THREADS)
335 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
338 if (m->flags & ACC_STATIC) {
339 M_MOV_IMM(&m->class->object.header, REG_ITMP1);
342 M_ALD(REG_ITMP1, REG_SP, stackframesize * 4 + 4);
345 codegen_add_nullpointerexception_ref(cd);
348 M_AST(REG_ITMP1, REG_SP, s1 * 4);
349 M_AST(REG_ITMP1, REG_SP, 0 * 4);
350 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP3);
355 /* copy argument registers to stack and call trace function with pointer
356 to arguments on stack.
360 if (opt_verbosecall) {
362 s1 = INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4 + 4 + stackframesize * 4;
364 M_ISUB_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
366 /* save temporary registers for leaf methods */
368 for (p = 0; p < INT_TMP_CNT; p++)
369 M_IST(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
371 for (p = 0, l = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
372 t = md->paramtypes[p].type;
374 if (IS_INT_LNG_TYPE(t)) {
375 if (IS_2_WORD_TYPE(t)) {
376 emit_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
377 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
378 emit_mov_membase_reg(cd, REG_SP, s1 + stack_off + 4, REG_ITMP1);
379 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
381 } else if (t == TYPE_ADR) {
383 emit_mov_membase_reg(cd, REG_SP, s1 + stack_off, REG_ITMP1);
384 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
385 emit_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
386 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
389 emit_mov_membase_reg(cd, REG_SP, s1 + stack_off, EAX);
391 emit_mov_reg_membase(cd, EAX, REG_SP, p * 8);
392 emit_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
396 if (!IS_2_WORD_TYPE(t)) {
397 emit_flds_membase(cd, REG_SP, s1 + stack_off);
398 emit_fstps_membase(cd, REG_SP, p * 8);
399 emit_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
400 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
403 emit_fldl_membase(cd, REG_SP, s1 + stack_off);
404 emit_fstpl_membase(cd, REG_SP, p * 8);
407 stack_off += (IS_2_WORD_TYPE(t)) ? 8 : 4;
410 /* fill up the remaining arguments */
411 emit_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1);
412 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
413 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
414 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
417 emit_mov_imm_membase(cd, (ptrint) m, REG_SP, TRACE_ARGS_NUM * 8);
418 emit_mov_imm_reg(cd, (ptrint) builtin_trace_args, REG_ITMP1);
419 emit_call_reg(cd, REG_ITMP1);
421 /* restore temporary registers for leaf methods */
423 for (p = 0; p < INT_TMP_CNT; p++)
424 M_ILD(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4);
426 M_IADD_IMM(INT_TMP_CNT * 4 + TRACE_ARGS_NUM * 8 + 4, REG_SP);
428 #endif /* !defined(NDEBUG) */
432 /* end of header generation */
434 replacementpoint = jd->code->rplpoints;
436 /* walk through all basic blocks */
437 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
439 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
441 if (bptr->flags >= BBREACHED) {
443 /* branch resolving */
446 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
447 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
452 /* handle replacement points */
454 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
455 replacementpoint->pc = (u1*)bptr->mpc; /* will be resolved later */
459 assert(cd->lastmcodeptr <= cd->mcodeptr);
460 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
463 /* copy interface registers to their destination */
470 /* generate basic block profiling code */
472 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
473 /* count frequency */
475 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
476 M_IADD_IMM_MEMBASE(1, REG_ITMP3, bptr->debug_nr * 4);
480 #if defined(ENABLE_LSRA)
482 while (src != NULL) {
484 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
485 if (!IS_2_WORD_TYPE(src->type)) {
486 if (bptr->type == BBTYPE_SBR) {
487 /* d = reg_of_var(m, src, REG_ITMP1); */
488 if (!(src->flags & INMEMORY))
494 emit_store(jd, NULL, src, d);
496 } else if (bptr->type == BBTYPE_EXH) {
497 /* d = reg_of_var(m, src, REG_ITMP1); */
498 if (!(src->flags & INMEMORY))
502 M_INTMOVE(REG_ITMP1, d);
503 emit_store(jd, NULL, src, d);
507 log_text("copy interface registers(EXH, SBR): longs have to be in memory (begin 1)");
516 while (src != NULL) {
518 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
519 if (!IS_2_WORD_TYPE(src->type)) {
520 if (bptr->type == BBTYPE_SBR) {
521 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
523 emit_store(jd, NULL, src, d);
524 } else if (bptr->type == BBTYPE_EXH) {
525 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
526 M_INTMOVE(REG_ITMP1, d);
527 emit_store(jd, NULL, src, d);
531 log_text("copy interface registers: longs have to be in memory (begin 1)");
536 if (IS_LNG_TYPE(src->type))
537 d = codegen_reg_of_var(rd, 0, src, PACK_REGS(REG_ITMP1, REG_ITMP2));
539 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
540 /* d = codegen_reg_of_var(rd, 0, src, REG_IFTMP); */
542 if ((src->varkind != STACKVAR)) {
544 s1 = rd->interfaces[len][s2].regoff;
546 if (IS_FLT_DBL_TYPE(s2)) {
547 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
551 if (IS_2_WORD_TYPE(s2))
552 M_DLD(d, REG_SP, s1 * 4);
554 M_FLD(d, REG_SP, s1 * 4);
558 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
559 if (IS_2_WORD_TYPE(s2))
565 if (IS_2_WORD_TYPE(s2))
566 M_LLD(d, REG_SP, s1 * 4);
568 M_ILD(d, REG_SP, s1 * 4);
572 emit_store(jd, NULL, src, d);
577 #if defined(ENABLE_LSRA)
581 /* walk through all instructions */
586 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
587 if (iptr->line != currentline) {
588 dseg_addlinenumber(cd, iptr->line);
589 currentline = iptr->line;
592 MCODECHECK(1024); /* 1kB should be enough */
595 case ICMD_INLINE_START:
597 insinfo_inline *insinfo = (insinfo_inline *) iptr->target;
598 #if defined(ENABLE_THREADS)
599 if (insinfo->synchronize) {
600 /* add monitor enter code */
601 if (insinfo->method->flags & ACC_STATIC) {
602 M_MOV_IMM(&insinfo->method->class->object.header, REG_ITMP1);
603 M_AST(REG_ITMP1, REG_SP, 0 * 4);
606 /* nullpointer check must have been performed before */
607 /* (XXX not done, yet) */
608 var = &(rd->locals[insinfo->synclocal][TYPE_ADR]);
609 if (var->flags & INMEMORY) {
610 emit_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP1);
611 M_AST(REG_ITMP1, REG_SP, 0 * 4);
614 M_AST(var->regoff, REG_SP, 0 * 4);
618 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP3);
622 dseg_addlinenumber_inline_start(cd, iptr);
626 case ICMD_INLINE_END:
628 insinfo_inline *insinfo = (insinfo_inline *) iptr->target;
630 dseg_addlinenumber_inline_end(cd, iptr);
631 dseg_addlinenumber(cd, iptr->line);
633 #if defined(ENABLE_THREADS)
634 if (insinfo->synchronize) {
635 /* add monitor exit code */
636 if (insinfo->method->flags & ACC_STATIC) {
637 M_MOV_IMM(&insinfo->method->class->object.header, REG_ITMP1);
638 M_AST(REG_ITMP1, REG_SP, 0 * 4);
641 var = &(rd->locals[insinfo->synclocal][TYPE_ADR]);
642 if (var->flags & INMEMORY) {
643 M_ALD(REG_ITMP1, REG_SP, var->regoff * 4);
644 M_AST(REG_ITMP1, REG_SP, 0 * 4);
647 M_AST(var->regoff, REG_SP, 0 * 4);
651 M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3);
658 case ICMD_NOP: /* ... ==> ... */
661 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
663 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
666 codegen_add_nullpointerexception_ref(cd);
669 /* constant operations ************************************************/
671 case ICMD_ICONST: /* ... ==> ..., constant */
672 /* op1 = 0, val.i = constant */
674 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
675 ICONST(d, iptr->val.i);
676 emit_store(jd, iptr, iptr->dst, d);
679 case ICMD_LCONST: /* ... ==> ..., constant */
680 /* op1 = 0, val.l = constant */
682 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
683 LCONST(d, iptr->val.l);
684 emit_store(jd, iptr, iptr->dst, d);
687 case ICMD_FCONST: /* ... ==> ..., constant */
688 /* op1 = 0, val.f = constant */
690 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
691 if (iptr->val.f == 0.0) {
695 if (iptr->val.i == 0x80000000) {
699 } else if (iptr->val.f == 1.0) {
702 } else if (iptr->val.f == 2.0) {
708 disp = dseg_addfloat(cd, iptr->val.f);
709 emit_mov_imm_reg(cd, 0, REG_ITMP1);
711 emit_flds_membase(cd, REG_ITMP1, disp);
713 emit_store(jd, iptr, iptr->dst, d);
716 case ICMD_DCONST: /* ... ==> ..., constant */
717 /* op1 = 0, val.d = constant */
719 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
720 if (iptr->val.d == 0.0) {
724 if (iptr->val.l == 0x8000000000000000LL) {
728 } else if (iptr->val.d == 1.0) {
731 } else if (iptr->val.d == 2.0) {
737 disp = dseg_adddouble(cd, iptr->val.d);
738 emit_mov_imm_reg(cd, 0, REG_ITMP1);
740 emit_fldl_membase(cd, REG_ITMP1, disp);
742 emit_store(jd, iptr, iptr->dst, d);
745 case ICMD_ACONST: /* ... ==> ..., constant */
746 /* op1 = 0, val.a = constant */
748 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
750 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
751 codegen_addpatchref(cd, PATCHER_aconst,
752 ICMD_ACONST_UNRESOLVED_CLASSREF(iptr), 0);
754 if (opt_showdisassemble) {
755 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
761 if (iptr->val.a == NULL)
764 M_MOV_IMM(iptr->val.a, d);
766 emit_store(jd, iptr, iptr->dst, d);
770 /* load/store operations **********************************************/
772 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
773 case ICMD_ALOAD: /* op1 = local variable */
775 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
776 if ((iptr->dst->varkind == LOCALVAR) &&
777 (iptr->dst->varnum == iptr->op1))
779 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
780 if (var->flags & INMEMORY)
781 M_ILD(d, REG_SP, var->regoff * 4);
783 M_INTMOVE(var->regoff, d);
784 emit_store(jd, iptr, iptr->dst, d);
787 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
788 /* op1 = local variable */
790 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
791 if ((iptr->dst->varkind == LOCALVAR) &&
792 (iptr->dst->varnum == iptr->op1))
794 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
795 if (var->flags & INMEMORY)
796 M_LLD(d, REG_SP, var->regoff * 4);
798 M_LNGMOVE(var->regoff, d);
799 emit_store(jd, iptr, iptr->dst, d);
802 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
803 /* op1 = local variable */
805 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
806 if ((iptr->dst->varkind == LOCALVAR) &&
807 (iptr->dst->varnum == iptr->op1))
809 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
810 if (var->flags & INMEMORY)
811 M_FLD(d, REG_SP, var->regoff * 4);
813 M_FLTMOVE(var->regoff, d);
814 emit_store(jd, iptr, iptr->dst, d);
817 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
818 /* op1 = local variable */
820 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
821 if ((iptr->dst->varkind == LOCALVAR) &&
822 (iptr->dst->varnum == iptr->op1))
824 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
825 if (var->flags & INMEMORY)
826 M_DLD(d, REG_SP, var->regoff * 4);
828 M_FLTMOVE(var->regoff, d);
829 emit_store(jd, iptr, iptr->dst, d);
832 case ICMD_ISTORE: /* ..., value ==> ... */
833 case ICMD_ASTORE: /* op1 = local variable */
835 if ((src->varkind == LOCALVAR) &&
836 (src->varnum == iptr->op1))
838 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
839 if (var->flags & INMEMORY) {
840 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
841 M_IST(s1, REG_SP, var->regoff * 4);
844 s1 = emit_load_s1(jd, iptr, src, var->regoff);
845 M_INTMOVE(s1, var->regoff);
849 case ICMD_LSTORE: /* ..., value ==> ... */
850 /* op1 = local variable */
852 if ((src->varkind == LOCALVAR) &&
853 (src->varnum == iptr->op1))
855 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
856 if (var->flags & INMEMORY) {
857 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
858 M_LST(s1, REG_SP, var->regoff * 4);
861 s1 = emit_load_s1(jd, iptr, src, var->regoff);
862 M_LNGMOVE(s1, var->regoff);
866 case ICMD_FSTORE: /* ..., value ==> ... */
867 /* op1 = local variable */
869 if ((src->varkind == LOCALVAR) &&
870 (src->varnum == iptr->op1))
872 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
873 if (var->flags & INMEMORY) {
874 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
875 M_FST(s1, REG_SP, var->regoff * 4);
878 s1 = emit_load_s1(jd, iptr, src, var->regoff);
879 M_FLTMOVE(s1, var->regoff);
883 case ICMD_DSTORE: /* ..., value ==> ... */
884 /* op1 = local variable */
886 if ((src->varkind == LOCALVAR) &&
887 (src->varnum == iptr->op1))
889 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
890 if (var->flags & INMEMORY) {
891 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
892 M_DST(s1, REG_SP, var->regoff * 4);
895 s1 = emit_load_s1(jd, iptr, src, var->regoff);
896 M_FLTMOVE(s1, var->regoff);
901 /* pop/dup/swap operations ********************************************/
903 /* attention: double and longs are only one entry in CACAO ICMDs */
905 case ICMD_POP: /* ..., value ==> ... */
906 case ICMD_POP2: /* ..., value, value ==> ... */
909 case ICMD_DUP: /* ..., a ==> ..., a, a */
911 M_COPY(src, iptr->dst);
914 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
916 M_COPY(src, iptr->dst);
917 M_COPY(src->prev, iptr->dst->prev);
920 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
922 M_COPY(src, iptr->dst);
923 M_COPY(src->prev, iptr->dst->prev);
924 M_COPY(iptr->dst, iptr->dst->prev->prev);
927 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
929 M_COPY(src, iptr->dst);
930 M_COPY(src->prev, iptr->dst->prev);
931 M_COPY(src->prev->prev, iptr->dst->prev->prev);
932 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
935 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
937 M_COPY(src, iptr->dst);
938 M_COPY(src->prev, iptr->dst->prev);
939 M_COPY(src->prev->prev, iptr->dst->prev->prev);
940 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
941 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
944 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
946 M_COPY(src, iptr->dst);
947 M_COPY(src->prev, iptr->dst->prev);
948 M_COPY(src->prev->prev, iptr->dst->prev->prev);
949 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
950 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
951 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
954 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
956 M_COPY(src, iptr->dst->prev);
957 M_COPY(src->prev, iptr->dst);
961 /* integer operations *************************************************/
963 case ICMD_INEG: /* ..., value ==> ..., - value */
965 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
966 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
969 emit_store(jd, iptr, iptr->dst, d);
972 case ICMD_LNEG: /* ..., value ==> ..., - value */
974 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
975 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
977 M_NEG(GET_LOW_REG(d));
978 M_IADDC_IMM(0, GET_HIGH_REG(d));
979 M_NEG(GET_HIGH_REG(d));
980 emit_store(jd, iptr, iptr->dst, d);
983 case ICMD_I2L: /* ..., value ==> ..., value */
985 s1 = emit_load_s1(jd, iptr, src, EAX);
986 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EAX_EDX_PACKED);
989 M_LNGMOVE(EAX_EDX_PACKED, d);
990 emit_store(jd, iptr, iptr->dst, d);
993 case ICMD_L2I: /* ..., value ==> ..., value */
995 s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP2);
996 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
998 emit_store(jd, iptr, iptr->dst, d);
1001 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1003 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1004 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1008 emit_store(jd, iptr, iptr->dst, d);
1011 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1013 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1014 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1016 emit_store(jd, iptr, iptr->dst, d);
1019 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1021 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1022 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1024 emit_store(jd, iptr, iptr->dst, d);
1028 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1030 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1031 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1032 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1039 emit_store(jd, iptr, iptr->dst, d);
1042 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1043 /* val.i = constant */
1045 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1046 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1048 M_IADD_IMM(iptr->val.i, d);
1049 emit_store(jd, iptr, iptr->dst, d);
1052 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1054 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1055 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1056 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1057 M_INTMOVE(s1, GET_LOW_REG(d));
1058 M_IADD(s2, GET_LOW_REG(d));
1059 /* don't use REG_ITMP1 */
1060 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1061 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1062 M_INTMOVE(s1, GET_HIGH_REG(d));
1063 M_IADDC(s2, GET_HIGH_REG(d));
1064 emit_store(jd, iptr, iptr->dst, d);
1067 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1068 /* val.l = constant */
1070 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1071 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1073 M_IADD_IMM(iptr->val.l, GET_LOW_REG(d));
1074 M_IADDC_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1075 emit_store(jd, iptr, iptr->dst, d);
1078 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1080 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1081 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1082 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1084 M_INTMOVE(s1, REG_ITMP1);
1085 M_ISUB(s2, REG_ITMP1);
1086 M_INTMOVE(REG_ITMP1, d);
1092 emit_store(jd, iptr, iptr->dst, d);
1095 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1096 /* val.i = constant */
1098 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1099 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1101 M_ISUB_IMM(iptr->val.i, d);
1102 emit_store(jd, iptr, iptr->dst, d);
1105 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1107 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1108 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1109 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1110 if (s2 == GET_LOW_REG(d)) {
1111 M_INTMOVE(s1, REG_ITMP1);
1112 M_ISUB(s2, REG_ITMP1);
1113 M_INTMOVE(REG_ITMP1, GET_LOW_REG(d));
1116 M_INTMOVE(s1, GET_LOW_REG(d));
1117 M_ISUB(s2, GET_LOW_REG(d));
1119 /* don't use REG_ITMP1 */
1120 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1121 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1122 if (s2 == GET_HIGH_REG(d)) {
1123 M_INTMOVE(s1, REG_ITMP2);
1124 M_ISUBB(s2, REG_ITMP2);
1125 M_INTMOVE(REG_ITMP2, GET_HIGH_REG(d));
1128 M_INTMOVE(s1, GET_HIGH_REG(d));
1129 M_ISUBB(s2, GET_HIGH_REG(d));
1131 emit_store(jd, iptr, iptr->dst, d);
1134 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1135 /* val.l = constant */
1137 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1138 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1140 M_ISUB_IMM(iptr->val.l, GET_LOW_REG(d));
1141 M_ISUBB_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1142 emit_store(jd, iptr, iptr->dst, d);
1145 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1147 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1148 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1149 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1156 emit_store(jd, iptr, iptr->dst, d);
1159 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1160 /* val.i = constant */
1162 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1163 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1164 M_IMUL_IMM(s1, iptr->val.i, d);
1165 emit_store(jd, iptr, iptr->dst, d);
1168 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1170 s1 = emit_load_s1_low(jd, iptr, src->prev, EAX);
1171 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1172 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EAX_EDX_PACKED);
1176 M_INTMOVE(EAX, GET_LOW_REG(d));
1177 emit_store_low(jd, iptr, iptr->dst, d); /* free REG_ITMP1 */
1179 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
1180 M_INTMOVE(s1, REG_ITMP1);
1181 M_IMUL(s2, REG_ITMP1);
1182 M_IADD(REG_ITMP1, EDX);
1184 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1185 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
1186 M_INTMOVE(s1, REG_ITMP1);
1187 M_IMUL(s2, REG_ITMP1);
1188 M_IADD(REG_ITMP1, EDX);
1189 M_INTMOVE(EDX, GET_HIGH_REG(d));
1191 emit_store_high(jd, iptr, iptr->dst, d);
1194 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1195 /* val.l = constant */
1197 s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP2);
1198 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EAX_EDX_PACKED);
1199 ICONST(EAX, iptr->val.l);
1201 M_IMUL_IMM(s1, iptr->val.l >> 32, REG_ITMP2);
1202 M_IADD(REG_ITMP2, EDX);
1203 s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP2);
1204 M_IMUL_IMM(s1, iptr->val.l, REG_ITMP2);
1205 M_IADD(REG_ITMP2, EDX);
1206 M_LNGMOVE(EAX_EDX_PACKED, d);
1207 emit_store(jd, iptr, iptr->dst, d);
1210 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1212 s1 = emit_load_s1(jd, iptr, src->prev, EAX);
1213 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1214 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EAX);
1219 codegen_add_arithmeticexception_ref(cd);
1222 M_INTMOVE(s1, EAX); /* we need the first operand in EAX */
1224 /* check as described in jvm spec */
1226 M_CMP_IMM(0x80000000, EAX);
1233 M_INTMOVE(EAX, d); /* if INMEMORY then d is already EAX */
1234 emit_store(jd, iptr, iptr->dst, d);
1237 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1239 s1 = emit_load_s1(jd, iptr, src->prev, EAX);
1240 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1241 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EDX);
1246 codegen_add_arithmeticexception_ref(cd);
1249 M_INTMOVE(s1, EAX); /* we need the first operand in EAX */
1251 /* check as described in jvm spec */
1253 M_CMP_IMM(0x80000000, EAX);
1261 M_INTMOVE(EDX, d); /* if INMEMORY then d is already EDX */
1262 emit_store(jd, iptr, iptr->dst, d);
1265 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1266 /* val.i = constant */
1268 /* TODO: optimize for `/ 2' */
1269 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1270 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1274 M_IADD_IMM32((1 << iptr->val.i) - 1, d); /* 32-bit for jump off. */
1275 M_SRA_IMM(iptr->val.i, d);
1276 emit_store(jd, iptr, iptr->dst, d);
1279 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1280 /* val.i = constant */
1282 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1283 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1285 M_MOV(s1, REG_ITMP1);
1289 M_AND_IMM(iptr->val.i, d);
1291 M_BGE(2 + 2 + 6 + 2);
1292 M_MOV(s1, d); /* don't use M_INTMOVE, so we know the jump offset */
1294 M_AND_IMM32(iptr->val.i, d); /* use 32-bit for jump offset */
1296 emit_store(jd, iptr, iptr->dst, d);
1299 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1300 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1302 s2 = emit_load_s2(jd, iptr, src, REG_ITMP12_PACKED);
1303 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
1305 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
1306 M_OR(GET_HIGH_REG(s2), REG_ITMP3);
1308 codegen_add_arithmeticexception_ref(cd);
1313 M_LST(s2, REG_SP, 2 * 4);
1315 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP12_PACKED);
1316 M_LST(s1, REG_SP, 0 * 4);
1318 M_MOV_IMM(bte->fp, REG_ITMP3);
1320 emit_store(jd, iptr, iptr->dst, d);
1323 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1324 /* val.i = constant */
1326 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1327 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
1329 M_TEST(GET_HIGH_REG(d));
1331 M_IADD_IMM32((1 << iptr->val.i) - 1, GET_LOW_REG(d));
1332 M_IADDC_IMM(0, GET_HIGH_REG(d));
1333 M_SRLD_IMM(iptr->val.i, GET_HIGH_REG(d), GET_LOW_REG(d));
1334 M_SRA_IMM(iptr->val.i, GET_HIGH_REG(d));
1335 emit_store(jd, iptr, iptr->dst, d);
1339 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1340 /* val.l = constant */
1342 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1343 if (iptr->dst->flags & INMEMORY) {
1344 if (src->flags & INMEMORY) {
1345 /* Alpha algorithm */
1347 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1349 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4 + 4);
1355 /* TODO: hmm, don't know if this is always correct */
1357 CALCIMMEDIATEBYTES(disp, iptr->val.l & 0x00000000ffffffff);
1359 CALCIMMEDIATEBYTES(disp, iptr->val.l >> 32);
1365 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1366 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1368 emit_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1369 emit_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1370 emit_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4 + 4);
1371 emit_jcc(cd, CC_GE, disp);
1373 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1374 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1376 emit_neg_reg(cd, REG_ITMP1);
1377 emit_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1378 emit_neg_reg(cd, REG_ITMP2);
1380 emit_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1381 emit_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1383 emit_neg_reg(cd, REG_ITMP1);
1384 emit_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1385 emit_neg_reg(cd, REG_ITMP2);
1387 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1388 emit_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1392 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1393 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
1395 M_AND_IMM(iptr->val.l, GET_LOW_REG(d));
1396 M_AND_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1397 M_TEST(GET_LOW_REG(s1));
1403 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1405 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1406 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1407 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1408 M_INTMOVE(s2, ECX); /* s2 may be equal to d */
1411 emit_store(jd, iptr, iptr->dst, d);
1414 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1415 /* val.i = constant */
1417 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1418 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1420 M_SLL_IMM(iptr->val.i, d);
1421 emit_store(jd, iptr, iptr->dst, d);
1424 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1426 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1427 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1428 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1429 M_INTMOVE(s2, ECX); /* s2 may be equal to d */
1432 emit_store(jd, iptr, iptr->dst, d);
1435 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1436 /* val.i = constant */
1438 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1439 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1441 M_SRA_IMM(iptr->val.i, d);
1442 emit_store(jd, iptr, iptr->dst, d);
1445 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1447 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1448 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1449 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1450 M_INTMOVE(s2, ECX); /* s2 may be equal to d */
1453 emit_store(jd, iptr, iptr->dst, d);
1456 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1457 /* val.i = constant */
1459 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1460 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1462 M_SRL_IMM(iptr->val.i, d);
1463 emit_store(jd, iptr, iptr->dst, d);
1466 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1468 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP13_PACKED);
1469 s2 = emit_load_s2(jd, iptr, src, ECX);
1470 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP13_PACKED);
1473 M_TEST_IMM(32, ECX);
1475 M_MOV(GET_LOW_REG(d), GET_HIGH_REG(d));
1476 M_CLR(GET_LOW_REG(d));
1477 M_SLLD(GET_LOW_REG(d), GET_HIGH_REG(d));
1478 M_SLL(GET_LOW_REG(d));
1479 emit_store(jd, iptr, iptr->dst, d);
1482 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1483 /* val.i = constant */
1485 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1486 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1488 if (iptr->val.i & 0x20) {
1489 M_MOV(GET_LOW_REG(d), GET_HIGH_REG(d));
1490 M_CLR(GET_LOW_REG(d));
1491 M_SLLD_IMM(iptr->val.i & 0x3f, GET_LOW_REG(d), GET_HIGH_REG(d));
1494 M_SLLD_IMM(iptr->val.i & 0x3f, GET_LOW_REG(d), GET_HIGH_REG(d));
1495 M_SLL_IMM(iptr->val.i & 0x3f, GET_LOW_REG(d));
1497 emit_store(jd, iptr, iptr->dst, d);
1500 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1502 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP13_PACKED);
1503 s2 = emit_load_s2(jd, iptr, src, ECX);
1504 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP13_PACKED);
1507 M_TEST_IMM(32, ECX);
1509 M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d));
1510 M_SRA_IMM(31, GET_HIGH_REG(d));
1511 M_SRLD(GET_HIGH_REG(d), GET_LOW_REG(d));
1512 M_SRA(GET_HIGH_REG(d));
1513 emit_store(jd, iptr, iptr->dst, d);
1516 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1517 /* val.i = constant */
1519 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1520 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1522 if (iptr->val.i & 0x20) {
1523 M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d));
1524 M_SRA_IMM(31, GET_HIGH_REG(d));
1525 M_SRLD_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d), GET_LOW_REG(d));
1528 M_SRLD_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d), GET_LOW_REG(d));
1529 M_SRA_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d));
1531 emit_store(jd, iptr, iptr->dst, d);
1534 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1536 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP13_PACKED);
1537 s2 = emit_load_s2(jd, iptr, src, ECX);
1538 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP13_PACKED);
1541 M_TEST_IMM(32, ECX);
1543 M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d));
1544 M_CLR(GET_HIGH_REG(d));
1545 M_SRLD(GET_HIGH_REG(d), GET_LOW_REG(d));
1546 M_SRL(GET_HIGH_REG(d));
1547 emit_store(jd, iptr, iptr->dst, d);
1550 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1551 /* val.l = constant */
1553 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1554 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1556 if (iptr->val.i & 0x20) {
1557 M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d));
1558 M_CLR(GET_HIGH_REG(d));
1559 M_SRLD_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d), GET_LOW_REG(d));
1562 M_SRLD_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d), GET_LOW_REG(d));
1563 M_SRL_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d));
1565 emit_store(jd, iptr, iptr->dst, d);
1568 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1570 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1571 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1572 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1579 emit_store(jd, iptr, iptr->dst, d);
1582 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1583 /* val.i = constant */
1585 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1586 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1588 M_AND_IMM(iptr->val.i, d);
1589 emit_store(jd, iptr, iptr->dst, d);
1592 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1594 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1595 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1596 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1597 if (s2 == GET_LOW_REG(d))
1598 M_AND(s1, GET_LOW_REG(d));
1600 M_INTMOVE(s1, GET_LOW_REG(d));
1601 M_AND(s2, GET_LOW_REG(d));
1603 /* REG_ITMP1 probably contains low 32-bit of destination */
1604 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1605 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1606 if (s2 == GET_HIGH_REG(d))
1607 M_AND(s1, GET_HIGH_REG(d));
1609 M_INTMOVE(s1, GET_HIGH_REG(d));
1610 M_AND(s2, GET_HIGH_REG(d));
1612 emit_store(jd, iptr, iptr->dst, d);
1615 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1616 /* val.l = constant */
1618 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1619 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1621 M_AND_IMM(iptr->val.l, GET_LOW_REG(d));
1622 M_AND_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1623 emit_store(jd, iptr, iptr->dst, d);
1626 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1628 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1629 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1630 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1637 emit_store(jd, iptr, iptr->dst, d);
1640 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1641 /* val.i = constant */
1643 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1644 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1646 M_OR_IMM(iptr->val.i, d);
1647 emit_store(jd, iptr, iptr->dst, d);
1650 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1652 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1653 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1654 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1655 if (s2 == GET_LOW_REG(d))
1656 M_OR(s1, GET_LOW_REG(d));
1658 M_INTMOVE(s1, GET_LOW_REG(d));
1659 M_OR(s2, GET_LOW_REG(d));
1661 /* REG_ITMP1 probably contains low 32-bit of destination */
1662 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1663 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1664 if (s2 == GET_HIGH_REG(d))
1665 M_OR(s1, GET_HIGH_REG(d));
1667 M_INTMOVE(s1, GET_HIGH_REG(d));
1668 M_OR(s2, GET_HIGH_REG(d));
1670 emit_store(jd, iptr, iptr->dst, d);
1673 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1674 /* val.l = constant */
1676 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1677 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1679 M_OR_IMM(iptr->val.l, GET_LOW_REG(d));
1680 M_OR_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1681 emit_store(jd, iptr, iptr->dst, d);
1684 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1686 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1687 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1688 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1695 emit_store(jd, iptr, iptr->dst, d);
1698 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1699 /* val.i = constant */
1701 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1702 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1704 M_XOR_IMM(iptr->val.i, d);
1705 emit_store(jd, iptr, iptr->dst, d);
1708 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1710 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1711 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1712 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1713 if (s2 == GET_LOW_REG(d))
1714 M_XOR(s1, GET_LOW_REG(d));
1716 M_INTMOVE(s1, GET_LOW_REG(d));
1717 M_XOR(s2, GET_LOW_REG(d));
1719 /* REG_ITMP1 probably contains low 32-bit of destination */
1720 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1721 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1722 if (s2 == GET_HIGH_REG(d))
1723 M_XOR(s1, GET_HIGH_REG(d));
1725 M_INTMOVE(s1, GET_HIGH_REG(d));
1726 M_XOR(s2, GET_HIGH_REG(d));
1728 emit_store(jd, iptr, iptr->dst, d);
1731 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1732 /* val.l = constant */
1734 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1735 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1737 M_XOR_IMM(iptr->val.l, GET_LOW_REG(d));
1738 M_XOR_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1739 emit_store(jd, iptr, iptr->dst, d);
1742 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1743 /* op1 = variable, val.i = constant */
1745 var = &(rd->locals[iptr->op1][TYPE_INT]);
1746 if (var->flags & INMEMORY) {
1748 M_ILD(s1, REG_SP, var->regoff * 4);
1753 /* `inc reg' is slower on p4's (regarding to ia32
1754 optimization reference manual and benchmarks) and as
1755 fast on athlon's. */
1757 M_IADD_IMM(iptr->val.i, s1);
1759 if (var->flags & INMEMORY)
1760 M_IST(s1, REG_SP, var->regoff * 4);
1764 /* floating operations ************************************************/
1766 case ICMD_FNEG: /* ..., value ==> ..., - value */
1768 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1769 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1771 emit_store(jd, iptr, iptr->dst, d);
1774 case ICMD_DNEG: /* ..., value ==> ..., - value */
1776 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1777 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1779 emit_store(jd, iptr, iptr->dst, d);
1782 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1784 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1785 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1786 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1788 emit_store(jd, iptr, iptr->dst, d);
1791 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1793 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1794 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1795 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1797 emit_store(jd, iptr, iptr->dst, d);
1800 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1802 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1803 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1804 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1806 emit_store(jd, iptr, iptr->dst, d);
1809 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1811 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1812 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1813 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1815 emit_store(jd, iptr, iptr->dst, d);
1818 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1820 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1821 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1822 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1824 emit_store(jd, iptr, iptr->dst, d);
1827 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1829 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1830 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1831 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1833 emit_store(jd, iptr, iptr->dst, d);
1836 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1838 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1839 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1840 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1842 emit_store(jd, iptr, iptr->dst, d);
1845 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1847 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1848 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1849 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1851 emit_store(jd, iptr, iptr->dst, d);
1854 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1856 /* exchanged to skip fxch */
1857 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1858 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1859 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1860 /* emit_fxch(cd); */
1865 emit_jcc(cd, CC_P, -(2 + 1 + 2 + 1 + 6));
1866 emit_store(jd, iptr, iptr->dst, d);
1867 emit_ffree_reg(cd, 0);
1871 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1873 /* exchanged to skip fxch */
1874 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1875 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1876 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1877 /* emit_fxch(cd); */
1882 emit_jcc(cd, CC_P, -(2 + 1 + 2 + 1 + 6));
1883 emit_store(jd, iptr, iptr->dst, d);
1884 emit_ffree_reg(cd, 0);
1888 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1889 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1891 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1892 if (src->flags & INMEMORY) {
1893 emit_fildl_membase(cd, REG_SP, src->regoff * 4);
1896 disp = dseg_adds4(cd, 0);
1897 emit_mov_imm_reg(cd, 0, REG_ITMP1);
1899 emit_mov_reg_membase(cd, src->regoff, REG_ITMP1, disp);
1900 emit_fildl_membase(cd, REG_ITMP1, disp);
1902 emit_store(jd, iptr, iptr->dst, d);
1905 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1906 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1908 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1909 if (src->flags & INMEMORY) {
1910 emit_fildll_membase(cd, REG_SP, src->regoff * 4);
1913 log_text("L2F: longs have to be in memory");
1916 emit_store(jd, iptr, iptr->dst, d);
1919 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1921 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1922 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1924 emit_mov_imm_reg(cd, 0, REG_ITMP1);
1927 /* Round to zero, 53-bit mode, exception masked */
1928 disp = dseg_adds4(cd, 0x0e7f);
1929 emit_fldcw_membase(cd, REG_ITMP1, disp);
1931 if (iptr->dst->flags & INMEMORY) {
1932 emit_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
1934 /* Round to nearest, 53-bit mode, exceptions masked */
1935 disp = dseg_adds4(cd, 0x027f);
1936 emit_fldcw_membase(cd, REG_ITMP1, disp);
1938 emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
1941 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1943 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
1946 disp = dseg_adds4(cd, 0);
1947 emit_fistpl_membase(cd, REG_ITMP1, disp);
1948 emit_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
1950 /* Round to nearest, 53-bit mode, exceptions masked */
1951 disp = dseg_adds4(cd, 0x027f);
1952 emit_fldcw_membase(cd, REG_ITMP1, disp);
1954 emit_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
1957 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1958 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
1961 emit_jcc(cd, CC_NE, disp);
1963 /* XXX: change this when we use registers */
1964 emit_flds_membase(cd, REG_SP, src->regoff * 4);
1965 emit_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP1);
1966 emit_call_reg(cd, REG_ITMP1);
1968 if (iptr->dst->flags & INMEMORY) {
1969 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
1972 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
1976 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1978 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1979 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1981 emit_mov_imm_reg(cd, 0, REG_ITMP1);
1984 /* Round to zero, 53-bit mode, exception masked */
1985 disp = dseg_adds4(cd, 0x0e7f);
1986 emit_fldcw_membase(cd, REG_ITMP1, disp);
1988 if (iptr->dst->flags & INMEMORY) {
1989 emit_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
1991 /* Round to nearest, 53-bit mode, exceptions masked */
1992 disp = dseg_adds4(cd, 0x027f);
1993 emit_fldcw_membase(cd, REG_ITMP1, disp);
1995 emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
1998 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2000 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2003 disp = dseg_adds4(cd, 0);
2004 emit_fistpl_membase(cd, REG_ITMP1, disp);
2005 emit_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2007 /* Round to nearest, 53-bit mode, exceptions masked */
2008 disp = dseg_adds4(cd, 0x027f);
2009 emit_fldcw_membase(cd, REG_ITMP1, disp);
2011 emit_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2014 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2015 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2018 emit_jcc(cd, CC_NE, disp);
2020 /* XXX: change this when we use registers */
2021 emit_fldl_membase(cd, REG_SP, src->regoff * 4);
2022 emit_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP1);
2023 emit_call_reg(cd, REG_ITMP1);
2025 if (iptr->dst->flags & INMEMORY) {
2026 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2028 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2032 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2034 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2035 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2037 emit_mov_imm_reg(cd, 0, REG_ITMP1);
2040 /* Round to zero, 53-bit mode, exception masked */
2041 disp = dseg_adds4(cd, 0x0e7f);
2042 emit_fldcw_membase(cd, REG_ITMP1, disp);
2044 if (iptr->dst->flags & INMEMORY) {
2045 emit_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2047 /* Round to nearest, 53-bit mode, exceptions masked */
2048 disp = dseg_adds4(cd, 0x027f);
2049 emit_fldcw_membase(cd, REG_ITMP1, disp);
2051 emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2054 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2056 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2059 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2061 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2063 emit_jcc(cd, CC_NE, disp);
2065 emit_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2068 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2070 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2072 emit_jcc(cd, CC_NE, disp);
2074 /* XXX: change this when we use registers */
2075 emit_flds_membase(cd, REG_SP, src->regoff * 4);
2076 emit_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP1);
2077 emit_call_reg(cd, REG_ITMP1);
2078 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2079 emit_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2082 log_text("F2L: longs have to be in memory");
2087 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2089 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2090 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2092 emit_mov_imm_reg(cd, 0, REG_ITMP1);
2095 /* Round to zero, 53-bit mode, exception masked */
2096 disp = dseg_adds4(cd, 0x0e7f);
2097 emit_fldcw_membase(cd, REG_ITMP1, disp);
2099 if (iptr->dst->flags & INMEMORY) {
2100 emit_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2102 /* Round to nearest, 53-bit mode, exceptions masked */
2103 disp = dseg_adds4(cd, 0x027f);
2104 emit_fldcw_membase(cd, REG_ITMP1, disp);
2106 emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2109 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2111 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2114 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2116 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2118 emit_jcc(cd, CC_NE, disp);
2120 emit_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2123 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2125 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2127 emit_jcc(cd, CC_NE, disp);
2129 /* XXX: change this when we use registers */
2130 emit_fldl_membase(cd, REG_SP, src->regoff * 4);
2131 emit_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP1);
2132 emit_call_reg(cd, REG_ITMP1);
2133 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2134 emit_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2137 log_text("D2L: longs have to be in memory");
2142 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2144 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2145 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2147 emit_store(jd, iptr, iptr->dst, d);
2150 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2152 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2153 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2155 emit_store(jd, iptr, iptr->dst, d);
2158 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2161 /* exchanged to skip fxch */
2162 s2 = emit_load_s2(jd, iptr, src->prev, REG_FTMP1);
2163 s1 = emit_load_s1(jd, iptr, src, REG_FTMP2);
2164 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2165 /* emit_fxch(cd); */
2168 emit_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2169 emit_jcc(cd, CC_E, 6);
2170 emit_alu_imm_reg(cd, ALU_AND, 0x000000ff, EAX);
2172 emit_mov_imm_reg(cd, 0, d); /* does not affect flags */
2173 emit_jcc(cd, CC_E, 6 + 3 + 5 + 3);
2174 emit_jcc(cd, CC_B, 3 + 5);
2175 emit_alu_imm_reg(cd, ALU_SUB, 1, d);
2176 emit_jmp_imm(cd, 3);
2177 emit_alu_imm_reg(cd, ALU_ADD, 1, d);
2178 emit_store(jd, iptr, iptr->dst, d);
2181 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2184 /* exchanged to skip fxch */
2185 s2 = emit_load_s2(jd, iptr, src->prev, REG_FTMP1);
2186 s1 = emit_load_s1(jd, iptr, src, REG_FTMP2);
2187 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2188 /* emit_fxch(cd); */
2191 emit_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2192 emit_jcc(cd, CC_E, 3);
2193 emit_movb_imm_reg(cd, 1, REG_AH);
2195 emit_mov_imm_reg(cd, 0, d); /* does not affect flags */
2196 emit_jcc(cd, CC_E, 6 + 3 + 5 + 3);
2197 emit_jcc(cd, CC_B, 3 + 5);
2198 emit_alu_imm_reg(cd, ALU_SUB, 1, d);
2199 emit_jmp_imm(cd, 3);
2200 emit_alu_imm_reg(cd, ALU_ADD, 1, d);
2201 emit_store(jd, iptr, iptr->dst, d);
2205 /* memory operations **************************************************/
2207 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2209 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2210 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2211 gen_nullptr_check(s1);
2212 M_ILD(d, s1, OFFSET(java_arrayheader, size));
2213 emit_store(jd, iptr, iptr->dst, d);
2216 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2218 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2219 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2220 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2221 if (iptr->op1 == 0) {
2222 gen_nullptr_check(s1);
2225 emit_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2226 emit_store(jd, iptr, iptr->dst, d);
2229 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2231 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2232 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2233 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2234 if (iptr->op1 == 0) {
2235 gen_nullptr_check(s1);
2238 emit_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2239 emit_store(jd, iptr, iptr->dst, d);
2242 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2244 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2245 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2246 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2247 if (iptr->op1 == 0) {
2248 gen_nullptr_check(s1);
2251 emit_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2252 emit_store(jd, iptr, iptr->dst, d);
2255 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2257 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2258 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2259 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2260 if (iptr->op1 == 0) {
2261 gen_nullptr_check(s1);
2264 emit_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2265 emit_store(jd, iptr, iptr->dst, d);
2268 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2270 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2271 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2272 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2273 if (iptr->op1 == 0) {
2274 gen_nullptr_check(s1);
2277 assert(iptr->dst->flags & INMEMORY);
2278 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2279 emit_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4);
2280 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2281 emit_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2284 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2286 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2287 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2288 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2289 if (iptr->op1 == 0) {
2290 gen_nullptr_check(s1);
2293 emit_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2294 emit_store(jd, iptr, iptr->dst, d);
2297 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2299 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2300 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2301 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2302 if (iptr->op1 == 0) {
2303 gen_nullptr_check(s1);
2306 emit_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2307 emit_store(jd, iptr, iptr->dst, d);
2310 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2312 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2313 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2314 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2315 if (iptr->op1 == 0) {
2316 gen_nullptr_check(s1);
2319 emit_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2320 emit_store(jd, iptr, iptr->dst, d);
2324 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2326 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2327 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2328 if (iptr->op1 == 0) {
2329 gen_nullptr_check(s1);
2332 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2333 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2334 M_INTMOVE(s3, REG_ITMP3);
2337 emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2340 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2342 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2343 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2344 if (iptr->op1 == 0) {
2345 gen_nullptr_check(s1);
2348 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2349 emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2352 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2354 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2355 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2356 if (iptr->op1 == 0) {
2357 gen_nullptr_check(s1);
2360 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2361 emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2364 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2366 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2367 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2368 if (iptr->op1 == 0) {
2369 gen_nullptr_check(s1);
2372 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2373 emit_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2376 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2378 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2379 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2380 if (iptr->op1 == 0) {
2381 gen_nullptr_check(s1);
2384 assert(src->flags & INMEMORY);
2385 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP3);
2386 emit_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2387 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
2388 emit_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2391 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2393 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2394 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2395 if (iptr->op1 == 0) {
2396 gen_nullptr_check(s1);
2399 s3 = emit_load_s3(jd, iptr, src, REG_FTMP1);
2400 emit_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2403 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2405 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2406 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2407 if (iptr->op1 == 0) {
2408 gen_nullptr_check(s1);
2411 s3 = emit_load_s3(jd, iptr, src, REG_FTMP1);
2412 emit_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2415 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2417 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2418 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2419 if (iptr->op1 == 0) {
2420 gen_nullptr_check(s1);
2423 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2425 M_AST(s1, REG_SP, 0 * 4);
2426 M_AST(s3, REG_SP, 1 * 4);
2427 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
2431 codegen_add_arraystoreexception_ref(cd);
2433 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2434 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2435 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2436 emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2439 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2441 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2442 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2443 if (iptr->op1 == 0) {
2444 gen_nullptr_check(s1);
2447 emit_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2450 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2452 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2453 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2454 if (iptr->op1 == 0) {
2455 gen_nullptr_check(s1);
2458 emit_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2461 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2463 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2464 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2465 if (iptr->op1 == 0) {
2466 gen_nullptr_check(s1);
2469 emit_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2472 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2474 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2475 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2476 if (iptr->op1 == 0) {
2477 gen_nullptr_check(s1);
2480 emit_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2483 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2485 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2486 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2487 if (iptr->op1 == 0) {
2488 gen_nullptr_check(s1);
2491 emit_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2492 emit_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2495 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2497 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2498 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2499 if (iptr->op1 == 0) {
2500 gen_nullptr_check(s1);
2503 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2507 case ICMD_GETSTATIC: /* ... ==> ..., value */
2508 /* op1 = type, val.a = field address */
2510 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2511 codegen_addpatchref(cd, PATCHER_get_putstatic,
2512 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2514 if (opt_showdisassemble) {
2515 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2522 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2524 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2525 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2527 if (opt_showdisassemble) {
2528 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2532 disp = (ptrint) &(fi->value);
2535 M_MOV_IMM(disp, REG_ITMP1);
2536 switch (iptr->op1) {
2539 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
2540 M_ILD(d, REG_ITMP1, 0);
2543 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP23_PACKED);
2544 M_LLD(d, REG_ITMP1, 0);
2547 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2548 M_FLD(d, REG_ITMP1, 0);
2551 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2552 M_DLD(d, REG_ITMP1, 0);
2555 emit_store(jd, iptr, iptr->dst, d);
2558 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2559 /* op1 = type, val.a = field address */
2561 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2562 codegen_addpatchref(cd, PATCHER_get_putstatic,
2563 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2565 if (opt_showdisassemble) {
2566 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2573 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2575 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2576 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2578 if (opt_showdisassemble) {
2579 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2583 disp = (ptrint) &(fi->value);
2586 M_MOV_IMM(disp, REG_ITMP1);
2587 switch (iptr->op1) {
2590 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2591 M_IST(s2, REG_ITMP1, 0);
2594 s2 = emit_load_s2(jd, iptr, src, REG_ITMP23_PACKED);
2595 M_LST(s2, REG_ITMP1, 0);
2598 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
2599 emit_fstps_membase(cd, REG_ITMP1, 0);
2602 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
2603 emit_fstpl_membase(cd, REG_ITMP1, 0);
2608 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2609 /* val = value (in current instruction) */
2610 /* op1 = type, val.a = field address (in */
2611 /* following NOP) */
2613 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2614 codegen_addpatchref(cd, PATCHER_get_putstatic,
2615 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
2617 if (opt_showdisassemble) {
2618 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2625 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1);
2627 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2628 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2630 if (opt_showdisassemble) {
2631 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2635 disp = (ptrint) &(fi->value);
2638 M_MOV_IMM(disp, REG_ITMP1);
2639 switch (iptr[1].op1) {
2643 M_IST_IMM(iptr->val.i, REG_ITMP1, 0);
2647 M_LST_IMM(iptr->val.l, REG_ITMP1, 0);
2652 case ICMD_GETFIELD: /* .., objectref. ==> ..., value */
2653 /* op1 = type, val.i = field offset */
2655 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2656 gen_nullptr_check(s1);
2658 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2659 codegen_addpatchref(cd, PATCHER_getfield,
2660 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2662 if (opt_showdisassemble) {
2663 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2670 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2672 switch (iptr->op1) {
2675 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
2676 M_ILD32(d, s1, disp);
2679 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP23_PACKED);
2680 M_LLD32(d, s1, disp);
2683 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2684 M_FLD32(d, s1, disp);
2687 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2688 M_DLD32(d, s1, disp);
2691 emit_store(jd, iptr, iptr->dst, d);
2694 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2695 /* op1 = type, val.a = field address */
2697 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2698 gen_nullptr_check(s1);
2700 /* must be done here because of code patching */
2702 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2703 if (IS_2_WORD_TYPE(iptr->op1))
2704 s2 = emit_load_s2(jd, iptr, src, REG_ITMP23_PACKED);
2706 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2709 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2711 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2712 codegen_addpatchref(cd, PATCHER_putfield,
2713 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2715 if (opt_showdisassemble) {
2716 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2723 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2725 switch (iptr->op1) {
2728 M_IST32(s2, s1, disp);
2731 M_LST32(s2, s1, disp);
2734 emit_fstps_membase32(cd, s1, disp);
2737 emit_fstpl_membase32(cd, s1, disp);
2742 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2743 /* val = value (in current instruction) */
2744 /* op1 = type, val.a = field address (in */
2745 /* following NOP) */
2747 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2748 gen_nullptr_check(s1);
2750 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2751 codegen_addpatchref(cd, PATCHER_putfieldconst,
2752 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
2754 if (opt_showdisassemble) {
2755 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2762 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1)->offset;
2764 switch (iptr[1].op1) {
2768 M_IST32_IMM(iptr->val.i, s1, disp);
2772 M_LST32_IMM(iptr->val.l, s1, disp);
2778 /* branch operations **************************************************/
2780 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2782 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2783 M_INTMOVE(s1, REG_ITMP1_XPTR);
2785 #ifdef ENABLE_VERIFIER
2787 codegen_addpatchref(cd, PATCHER_athrow_areturn,
2788 (unresolved_class *) iptr->val.a, 0);
2790 if (opt_showdisassemble) {
2791 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2794 #endif /* ENABLE_VERIFIER */
2796 M_CALL_IMM(0); /* passing exception pc */
2797 M_POP(REG_ITMP2_XPC);
2799 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
2803 case ICMD_INLINE_GOTO:
2805 M_COPY(src, iptr->dst);
2808 case ICMD_GOTO: /* ... ==> ... */
2809 /* op1 = target JavaVM pc */
2812 codegen_addreference(cd, (basicblock *) iptr->target);
2816 case ICMD_JSR: /* ... ==> ... */
2817 /* op1 = target JavaVM pc */
2820 codegen_addreference(cd, (basicblock *) iptr->target);
2823 case ICMD_RET: /* ... ==> ... */
2824 /* op1 = local variable */
2826 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2827 if (var->flags & INMEMORY) {
2828 M_ALD(REG_ITMP1, REG_SP, var->regoff * 4);
2835 case ICMD_IFNULL: /* ..., value ==> ... */
2836 /* op1 = target JavaVM pc */
2838 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2841 codegen_addreference(cd, (basicblock *) iptr->target);
2844 case ICMD_IFNONNULL: /* ..., value ==> ... */
2845 /* op1 = target JavaVM pc */
2847 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2850 codegen_addreference(cd, (basicblock *) iptr->target);
2853 case ICMD_IFEQ: /* ..., value ==> ... */
2854 /* op1 = target JavaVM pc, val.i = constant */
2856 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2857 M_CMP_IMM(iptr->val.i, s1);
2859 codegen_addreference(cd, (basicblock *) iptr->target);
2862 case ICMD_IFLT: /* ..., value ==> ... */
2863 /* op1 = target JavaVM pc, val.i = constant */
2865 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2866 M_CMP_IMM(iptr->val.i, s1);
2868 codegen_addreference(cd, (basicblock *) iptr->target);
2871 case ICMD_IFLE: /* ..., value ==> ... */
2872 /* op1 = target JavaVM pc, val.i = constant */
2874 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2875 M_CMP_IMM(iptr->val.i, s1);
2877 codegen_addreference(cd, (basicblock *) iptr->target);
2880 case ICMD_IFNE: /* ..., value ==> ... */
2881 /* op1 = target JavaVM pc, val.i = constant */
2883 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2884 M_CMP_IMM(iptr->val.i, s1);
2886 codegen_addreference(cd, (basicblock *) iptr->target);
2889 case ICMD_IFGT: /* ..., value ==> ... */
2890 /* op1 = target JavaVM pc, val.i = constant */
2892 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2893 M_CMP_IMM(iptr->val.i, s1);
2895 codegen_addreference(cd, (basicblock *) iptr->target);
2898 case ICMD_IFGE: /* ..., value ==> ... */
2899 /* op1 = target JavaVM pc, val.i = constant */
2901 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2902 M_CMP_IMM(iptr->val.i, s1);
2904 codegen_addreference(cd, (basicblock *) iptr->target);
2907 case ICMD_IF_LEQ: /* ..., value ==> ... */
2908 /* op1 = target JavaVM pc, val.l = constant */
2910 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
2911 if (iptr->val.l == 0) {
2912 M_INTMOVE(GET_LOW_REG(s1), REG_ITMP1);
2913 M_OR(GET_HIGH_REG(s1), REG_ITMP1);
2916 M_LNGMOVE(s1, REG_ITMP12_PACKED);
2917 M_XOR_IMM(iptr->val.l, REG_ITMP1);
2918 M_XOR_IMM(iptr->val.l >> 32, REG_ITMP2);
2919 M_OR(REG_ITMP2, REG_ITMP1);
2922 codegen_addreference(cd, (basicblock *) iptr->target);
2925 case ICMD_IF_LLT: /* ..., value ==> ... */
2926 /* op1 = target JavaVM pc, val.l = constant */
2928 if (iptr->val.l == 0) {
2929 /* If high 32-bit are less than zero, then the 64-bits
2931 s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP2);
2936 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
2937 M_CMP_IMM(iptr->val.l >> 32, GET_HIGH_REG(s1));
2939 codegen_addreference(cd, (basicblock *) iptr->target);
2941 M_CMP_IMM32(iptr->val.l, GET_LOW_REG(s1));
2944 codegen_addreference(cd, (basicblock *) iptr->target);
2947 case ICMD_IF_LLE: /* ..., value ==> ... */
2948 /* op1 = target JavaVM pc, val.l = constant */
2950 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
2951 M_CMP_IMM(iptr->val.l >> 32, GET_HIGH_REG(s1));
2953 codegen_addreference(cd, (basicblock *) iptr->target);
2955 M_CMP_IMM32(iptr->val.l, GET_LOW_REG(s1));
2957 codegen_addreference(cd, (basicblock *) iptr->target);
2960 case ICMD_IF_LNE: /* ..., value ==> ... */
2961 /* op1 = target JavaVM pc, val.l = constant */
2963 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
2964 if (iptr->val.l == 0) {
2965 M_INTMOVE(GET_LOW_REG(s1), REG_ITMP1);
2966 M_OR(GET_HIGH_REG(s1), REG_ITMP1);
2969 M_LNGMOVE(s1, REG_ITMP12_PACKED);
2970 M_XOR_IMM(iptr->val.l, REG_ITMP1);
2971 M_XOR_IMM(iptr->val.l >> 32, REG_ITMP2);
2972 M_OR(REG_ITMP2, REG_ITMP1);
2975 codegen_addreference(cd, (basicblock *) iptr->target);
2978 case ICMD_IF_LGT: /* ..., value ==> ... */
2979 /* op1 = target JavaVM pc, val.l = constant */
2981 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
2982 M_CMP_IMM(iptr->val.l >> 32, GET_HIGH_REG(s1));
2984 codegen_addreference(cd, (basicblock *) iptr->target);
2986 M_CMP_IMM32(iptr->val.l, GET_LOW_REG(s1));
2988 codegen_addreference(cd, (basicblock *) iptr->target);
2991 case ICMD_IF_LGE: /* ..., value ==> ... */
2992 /* op1 = target JavaVM pc, val.l = constant */
2994 if (iptr->val.l == 0) {
2995 /* If high 32-bit are greater equal zero, then the
2997 s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP2);
3002 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
3003 M_CMP_IMM(iptr->val.l >> 32, GET_HIGH_REG(s1));
3005 codegen_addreference(cd, (basicblock *) iptr->target);
3007 M_CMP_IMM32(iptr->val.l, GET_LOW_REG(s1));
3010 codegen_addreference(cd, (basicblock *) iptr->target);
3013 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3014 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3016 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3017 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3020 codegen_addreference(cd, (basicblock *) iptr->target);
3023 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3024 /* op1 = target JavaVM pc */
3026 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3027 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3028 M_INTMOVE(s1, REG_ITMP1);
3029 M_XOR(s2, REG_ITMP1);
3030 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
3031 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
3032 M_INTMOVE(s1, REG_ITMP2);
3033 M_XOR(s2, REG_ITMP2);
3034 M_OR(REG_ITMP1, REG_ITMP2);
3036 codegen_addreference(cd, (basicblock *) iptr->target);
3039 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3040 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3042 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3043 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3046 codegen_addreference(cd, (basicblock *) iptr->target);
3049 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3050 /* op1 = target JavaVM pc */
3052 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3053 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3054 M_INTMOVE(s1, REG_ITMP1);
3055 M_XOR(s2, REG_ITMP1);
3056 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
3057 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
3058 M_INTMOVE(s1, REG_ITMP2);
3059 M_XOR(s2, REG_ITMP2);
3060 M_OR(REG_ITMP1, REG_ITMP2);
3062 codegen_addreference(cd, (basicblock *) iptr->target);
3065 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3066 /* op1 = target JavaVM pc */
3068 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3069 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3072 codegen_addreference(cd, (basicblock *) iptr->target);
3075 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3076 /* op1 = target JavaVM pc */
3078 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
3079 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
3082 codegen_addreference(cd, (basicblock *) iptr->target);
3083 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3084 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3088 codegen_addreference(cd, (basicblock *) iptr->target);
3091 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3092 /* op1 = target JavaVM pc */
3094 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3095 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3098 codegen_addreference(cd, (basicblock *) iptr->target);
3101 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3102 /* op1 = target JavaVM pc */
3104 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
3105 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
3108 codegen_addreference(cd, (basicblock *) iptr->target);
3109 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3110 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3114 codegen_addreference(cd, (basicblock *) iptr->target);
3117 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3118 /* 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_LCMPLE: /* ..., value, value ==> ... */
3128 /* op1 = target JavaVM pc */
3130 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
3131 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
3134 codegen_addreference(cd, (basicblock *) iptr->target);
3135 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3136 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3140 codegen_addreference(cd, (basicblock *) iptr->target);
3143 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3144 /* 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_LCMPGE: /* ..., value, value ==> ... */
3154 /* op1 = target JavaVM pc */
3156 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
3157 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
3160 codegen_addreference(cd, (basicblock *) iptr->target);
3161 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3162 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3166 codegen_addreference(cd, (basicblock *) iptr->target);
3170 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3172 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
3173 M_INTMOVE(s1, REG_RESULT);
3174 goto nowperformreturn;
3176 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3178 s1 = emit_load_s1(jd, iptr, src, REG_RESULT_PACKED);
3179 M_LNGMOVE(s1, REG_RESULT_PACKED);
3180 goto nowperformreturn;
3182 case ICMD_ARETURN: /* ..., retvalue ==> ... */
3184 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
3185 M_INTMOVE(s1, REG_RESULT);
3187 #ifdef ENABLE_VERIFIER
3189 codegen_addpatchref(cd, PATCHER_athrow_areturn,
3190 (unresolved_class *) iptr->val.a, 0);
3192 if (opt_showdisassemble) {
3193 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3196 #endif /* ENABLE_VERIFIER */
3197 goto nowperformreturn;
3199 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3202 s1 = emit_load_s1(jd, iptr, src, REG_FRESULT);
3203 goto nowperformreturn;
3205 case ICMD_RETURN: /* ... ==> ... */
3213 #if !defined(NDEBUG)
3214 /* call trace function */
3216 if (opt_verbosecall) {
3217 M_ISUB_IMM(4 + 8 + 8 + 4, REG_SP);
3219 emit_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3221 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3222 emit_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3224 emit_fstl_membase(cd, REG_SP, 4 + 8);
3225 emit_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3227 emit_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3228 emit_call_reg(cd, REG_ITMP1);
3230 emit_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3231 emit_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3233 emit_alu_imm_reg(cd, ALU_ADD, 4 + 8 + 8 + 4, REG_SP);
3235 #endif /* !defined(NDEBUG) */
3237 #if defined(ENABLE_THREADS)
3238 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3239 M_ALD(REG_ITMP2, REG_SP, rd->memuse * 4);
3241 /* we need to save the proper return value */
3242 switch (iptr->opc) {
3245 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
3249 M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 4);
3253 emit_fstps_membase(cd, REG_SP, rd->memuse * 4);
3257 emit_fstpl_membase(cd, REG_SP, rd->memuse * 4);
3261 M_AST(REG_ITMP2, REG_SP, 0);
3262 M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3);
3265 /* and now restore the proper return value */
3266 switch (iptr->opc) {
3269 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
3273 M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 4);
3277 emit_flds_membase(cd, REG_SP, rd->memuse * 4);
3281 emit_fldl_membase(cd, REG_SP, rd->memuse * 4);
3287 /* restore saved registers */
3289 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
3290 p--; M_ALD(rd->savintregs[i], REG_SP, p * 4);
3293 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
3295 emit_fldl_membase(cd, REG_SP, p * 4);
3296 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3298 /* emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1); */
3301 /* emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset); */
3305 /* deallocate stack */
3308 M_AADD_IMM(stackframesize * 4, REG_SP);
3315 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3320 tptr = (void **) iptr->target;
3322 s4ptr = iptr->val.a;
3323 l = s4ptr[1]; /* low */
3324 i = s4ptr[2]; /* high */
3326 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3327 M_INTMOVE(s1, REG_ITMP1);
3330 M_ISUB_IMM(l, REG_ITMP1);
3336 M_CMP_IMM(i - 1, REG_ITMP1);
3338 codegen_addreference(cd, (basicblock *) tptr[0]);
3340 /* build jump table top down and use address of lowest entry */
3345 dseg_addtarget(cd, (basicblock *) tptr[0]);
3349 /* length of dataseg after last dseg_addtarget is used
3352 M_MOV_IMM(0, REG_ITMP2);
3354 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3360 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3362 s4 i, l, val, *s4ptr;
3365 tptr = (void **) iptr->target;
3367 s4ptr = iptr->val.a;
3368 l = s4ptr[0]; /* default */
3369 i = s4ptr[1]; /* count */
3371 MCODECHECK((i<<2)+8);
3372 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3381 codegen_addreference(cd, (basicblock *) tptr[0]);
3386 tptr = (void **) iptr->target;
3387 codegen_addreference(cd, (basicblock *) tptr[0]);
3391 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
3392 /* op1 = arg count val.a = builtintable entry */
3398 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3399 /* op1 = arg count, val.a = method pointer */
3401 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3402 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
3403 case ICMD_INVOKEINTERFACE:
3405 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3406 md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
3410 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
3411 md = lm->parseddesc;
3415 s3 = md->paramcount;
3417 MCODECHECK((s3 << 1) + 64);
3419 /* copy arguments to registers or stack location */
3421 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
3422 if (src->varkind == ARGVAR)
3424 if (IS_INT_LNG_TYPE(src->type)) {
3425 if (!md->params[s3].inmemory) {
3426 log_text("No integer argument registers available!");
3430 if (IS_2_WORD_TYPE(src->type)) {
3431 d = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
3432 M_LST(d, REG_SP, md->params[s3].regoff * 4);
3434 d = emit_load_s1(jd, iptr, src, REG_ITMP1);
3435 M_IST(d, REG_SP, md->params[s3].regoff * 4);
3440 if (!md->params[s3].inmemory) {
3441 s1 = rd->argfltregs[md->params[s3].regoff];
3442 d = emit_load_s1(jd, iptr, src, s1);
3446 d = emit_load_s1(jd, iptr, src, REG_FTMP1);
3447 if (IS_2_WORD_TYPE(src->type))
3448 M_DST(d, REG_SP, md->params[s3].regoff * 4);
3450 M_FST(d, REG_SP, md->params[s3].regoff * 4);
3455 switch (iptr->opc) {
3457 disp = (ptrint) bte->fp;
3458 d = md->returntype.type;
3460 M_MOV_IMM(disp, REG_ITMP1);
3463 /* if op1 == true, we need to check for an exception */
3465 if (iptr->op1 == true) {
3468 codegen_add_fillinstacktrace_ref(cd);
3472 case ICMD_INVOKESPECIAL:
3473 M_ALD(REG_ITMP1, REG_SP, 0);
3476 codegen_add_nullpointerexception_ref(cd);
3480 case ICMD_INVOKESTATIC:
3482 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3484 codegen_addpatchref(cd, PATCHER_invokestatic_special,
3487 if (opt_showdisassemble) {
3488 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3492 d = md->returntype.type;
3495 disp = (ptrint) lm->stubroutine;
3496 d = lm->parseddesc->returntype.type;
3499 M_MOV_IMM(disp, REG_ITMP2);
3503 case ICMD_INVOKEVIRTUAL:
3504 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
3505 gen_nullptr_check(REG_ITMP1);
3508 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3510 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
3512 if (opt_showdisassemble) {
3513 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3517 d = md->returntype.type;
3520 s1 = OFFSET(vftbl_t, table[0]) +
3521 sizeof(methodptr) * lm->vftblindex;
3522 d = md->returntype.type;
3525 M_ALD(REG_METHODPTR, REG_ITMP1,
3526 OFFSET(java_objectheader, vftbl));
3527 M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
3531 case ICMD_INVOKEINTERFACE:
3532 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
3533 gen_nullptr_check(REG_ITMP1);
3536 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3538 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
3540 if (opt_showdisassemble) {
3541 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3546 d = md->returntype.type;
3549 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3550 sizeof(methodptr) * lm->class->index;
3552 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3554 d = md->returntype.type;
3557 M_ALD(REG_METHODPTR, REG_ITMP1,
3558 OFFSET(java_objectheader, vftbl));
3559 M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
3560 M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
3565 /* d contains return type */
3567 if (d != TYPE_VOID) {
3568 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3569 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3570 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
3571 M_LNGMOVE(REG_RESULT_PACKED, s1);
3574 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3575 M_INTMOVE(REG_RESULT, s1);
3579 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
3581 emit_store(jd, iptr, iptr->dst, s1);
3586 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3587 /* op1: 0 == array, 1 == class */
3588 /* val.a: (classinfo*) superclass */
3590 /* superclass is an interface:
3592 * OK if ((sub == NULL) ||
3593 * (sub->vftbl->interfacetablelength > super->index) &&
3594 * (sub->vftbl->interfacetable[-super->index] != NULL));
3596 * superclass is a class:
3598 * OK if ((sub == NULL) || (0
3599 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3600 * super->vftbl->diffval));
3603 if (iptr->op1 == 1) {
3604 /* object type cast-check */
3607 vftbl_t *supervftbl;
3610 super = (classinfo *) iptr->val.a;
3617 superindex = super->index;
3618 supervftbl = super->vftbl;
3621 #if defined(ENABLE_THREADS)
3622 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3624 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3626 /* calculate interface checkcast code size */
3628 s2 = 2; /* mov_membase_reg */
3629 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3631 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ +
3632 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
3633 2 /* test */ + 6 /* jcc */);
3636 s2 += (opt_showdisassemble ? 5 : 0);
3638 /* calculate class checkcast code size */
3640 s3 = 2; /* mov_membase_reg */
3641 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3643 s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */;
3646 if (s1 != REG_ITMP1) {
3648 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
3651 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
3658 s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ +
3659 5 /* mov_imm_reg */ + 2 /* mov_membase_reg */);
3660 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3663 s3 += 2 /* cmp */ + 6 /* jcc */;
3666 s3 += (opt_showdisassemble ? 5 : 0);
3668 /* if class is not resolved, check which code to call */
3670 if (super == NULL) {
3672 M_BEQ(5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
3674 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3675 (constant_classref *) iptr->target, 0);
3677 if (opt_showdisassemble) {
3678 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3681 M_MOV_IMM(0, REG_ITMP2); /* super->flags */
3682 M_AND_IMM32(ACC_INTERFACE, REG_ITMP2);
3686 /* interface checkcast code */
3688 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3689 if (super != NULL) {
3694 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3696 if (super == NULL) {
3697 codegen_addpatchref(cd,
3698 PATCHER_checkcast_instanceof_interface,
3699 (constant_classref *) iptr->target,
3702 if (opt_showdisassemble) {
3703 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3708 REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3709 M_ISUB_IMM32(superindex, REG_ITMP3);
3712 codegen_add_classcastexception_ref(cd, s1);
3713 M_ALD32(REG_ITMP3, REG_ITMP2,
3714 OFFSET(vftbl_t, interfacetable[0]) -
3715 superindex * sizeof(methodptr*));
3718 codegen_add_classcastexception_ref(cd, s1);
3724 /* class checkcast code */
3726 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3727 if (super != NULL) {
3732 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3734 if (super == NULL) {
3735 codegen_addpatchref(cd, PATCHER_checkcast_class,
3736 (constant_classref *) iptr->target,
3739 if (opt_showdisassemble) {
3740 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3744 M_MOV_IMM(supervftbl, REG_ITMP3);
3745 #if defined(ENABLE_THREADS)
3746 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3748 M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3750 /* if (s1 != REG_ITMP1) { */
3751 /* emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
3752 /* emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
3753 /* #if defined(ENABLE_THREADS) */
3754 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
3756 /* emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
3759 M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3760 M_ISUB(REG_ITMP3, REG_ITMP2);
3761 M_MOV_IMM(supervftbl, REG_ITMP3);
3762 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3763 #if defined(ENABLE_THREADS)
3764 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3768 M_CMP(REG_ITMP3, REG_ITMP2);
3769 M_BA(0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
3770 codegen_add_classcastexception_ref(cd, s1);
3773 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
3776 /* array type cast-check */
3778 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
3779 M_AST(s1, REG_SP, 0 * 4);
3781 if (iptr->val.a == NULL) {
3782 codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
3785 if (opt_showdisassemble) {
3786 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3790 M_AST_IMM(iptr->val.a, REG_SP, 1 * 4);
3791 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP3);
3794 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
3797 codegen_add_classcastexception_ref(cd, s1);
3799 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
3803 emit_store(jd, iptr, iptr->dst, d);
3806 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3807 /* op1: 0 == array, 1 == class */
3808 /* val.a: (classinfo*) superclass */
3810 /* superclass is an interface:
3812 * return (sub != NULL) &&
3813 * (sub->vftbl->interfacetablelength > super->index) &&
3814 * (sub->vftbl->interfacetable[-super->index] != NULL);
3816 * superclass is a class:
3818 * return ((sub != NULL) && (0
3819 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3820 * super->vftbl->diffvall));
3825 vftbl_t *supervftbl;
3828 super = (classinfo *) iptr->val.a;
3835 superindex = super->index;
3836 supervftbl = super->vftbl;
3839 #if defined(ENABLE_THREADS)
3840 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3843 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3844 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3846 M_INTMOVE(s1, REG_ITMP1);
3850 /* calculate interface instanceof code size */
3852 s2 = 2; /* mov_membase_reg */
3853 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3855 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
3856 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
3857 2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
3860 s2 += (opt_showdisassemble ? 5 : 0);
3862 /* calculate class instanceof code size */
3864 s3 = 2; /* mov_membase_reg */
3865 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3866 s3 += 5; /* mov_imm_reg */
3868 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
3870 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3872 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3874 s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
3875 2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
3878 s3 += (opt_showdisassemble ? 5 : 0);
3882 /* if class is not resolved, check which code to call */
3886 M_BEQ(5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
3888 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3889 (constant_classref *) iptr->target, 0);
3891 if (opt_showdisassemble) {
3892 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3895 M_MOV_IMM(0, REG_ITMP3); /* super->flags */
3896 M_AND_IMM32(ACC_INTERFACE, REG_ITMP3);
3900 /* interface instanceof code */
3902 if (!super || (super->flags & ACC_INTERFACE)) {
3908 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3911 codegen_addpatchref(cd,
3912 PATCHER_checkcast_instanceof_interface,
3913 (constant_classref *) iptr->target, 0);
3915 if (opt_showdisassemble) {
3916 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3921 REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3922 M_ISUB_IMM32(superindex, REG_ITMP3);
3925 disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
3926 6 /* jcc */ + 5 /* mov_imm_reg */);
3929 M_ALD32(REG_ITMP1, REG_ITMP1,
3930 OFFSET(vftbl_t, interfacetable[0]) -
3931 superindex * sizeof(methodptr*));
3933 /* emit_setcc_reg(cd, CC_A, d); */
3934 /* emit_jcc(cd, CC_BE, 5); */
3942 /* class instanceof code */
3944 if (!super || !(super->flags & ACC_INTERFACE)) {
3950 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3953 codegen_addpatchref(cd, PATCHER_instanceof_class,
3954 (constant_classref *) iptr->target, 0);
3956 if (opt_showdisassemble) {
3957 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3961 M_MOV_IMM(supervftbl, REG_ITMP2);
3962 #if defined(ENABLE_THREADS)
3963 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3965 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3966 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3967 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3968 #if defined(ENABLE_THREADS)
3969 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3971 M_ISUB(REG_ITMP2, REG_ITMP1);
3972 M_CLR(d); /* may be REG_ITMP2 */
3973 M_CMP(REG_ITMP3, REG_ITMP1);
3977 emit_store(jd, iptr, iptr->dst, d);
3983 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3984 /* op1 = dimension, val.a = class */
3986 /* check for negative sizes and copy sizes to stack if necessary */
3988 MCODECHECK((iptr->op1 << 1) + 64);
3990 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3991 /* copy SAVEDVAR sizes to stack */
3993 if (src->varkind != ARGVAR) {
3994 if (src->flags & INMEMORY) {
3995 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
3996 M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4);
3999 M_IST(src->regoff, REG_SP, (s1 + 3) * 4);
4003 /* is a patcher function set? */
4005 if (iptr->val.a == NULL) {
4006 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
4007 (constant_classref *) iptr->target, 0);
4009 if (opt_showdisassemble) {
4010 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4017 disp = (ptrint) iptr->val.a;
4019 /* a0 = dimension count */
4021 M_IST_IMM(iptr->op1, REG_SP, 0 * 4);
4023 /* a1 = arraydescriptor */
4025 M_IST_IMM(disp, REG_SP, 1 * 4);
4027 /* a2 = pointer to dimensions = stack pointer */
4029 M_MOV(REG_SP, REG_ITMP1);
4030 M_AADD_IMM(3 * 4, REG_ITMP1);
4031 M_AST(REG_ITMP1, REG_SP, 2 * 4);
4033 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
4036 /* check for exception before result assignment */
4040 codegen_add_fillinstacktrace_ref(cd);
4042 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
4043 M_INTMOVE(REG_RESULT, s1);
4044 emit_store(jd, iptr, iptr->dst, s1);
4049 new_internalerror("Unknown ICMD %d", iptr->opc);
4053 } /* for instruction */
4055 /* copy values to interface registers */
4057 src = bptr->outstack;
4058 len = bptr->outdepth;
4060 #if defined(ENABLE_LSRA)
4065 if ((src->varkind != STACKVAR)) {
4067 if (IS_FLT_DBL_TYPE(s2)) {
4068 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
4069 if (!(rd->interfaces[len][s2].flags & INMEMORY))
4070 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
4072 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
4075 if (IS_2_WORD_TYPE(s2))
4077 /* s1 = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP1, REG_ITMP2)); */
4079 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4081 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4082 if (IS_2_WORD_TYPE(s2))
4083 M_LNGMOVE(s1, rd->interfaces[len][s2].regoff);
4085 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
4088 if (IS_2_WORD_TYPE(s2))
4089 M_LST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
4091 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
4098 /* At the end of a basic block we may have to append some nops,
4099 because the patcher stub calling code might be longer than the
4100 actual instruction. So codepatching does not change the
4101 following block unintentionally. */
4103 if (cd->mcodeptr < cd->lastmcodeptr) {
4104 while (cd->mcodeptr < cd->lastmcodeptr) {
4109 } /* if (bptr -> flags >= BBREACHED) */
4110 } /* for basic block */
4112 dseg_createlinenumbertable(cd);
4115 /* generate exception and patcher stubs */
4124 savedmcodeptr = NULL;
4126 /* generate exception stubs */
4128 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
4129 gen_resolvebranch(cd->mcodebase + eref->branchpos,
4131 cd->mcodeptr - cd->mcodebase);
4135 /* Check if the exception is an
4136 ArrayIndexOutOfBoundsException. If so, move index register
4139 if (eref->reg != -1)
4140 M_INTMOVE(eref->reg, REG_ITMP1);
4142 /* calcuate exception address */
4144 M_MOV_IMM(0, REG_ITMP2_XPC);
4146 M_AADD_IMM32(eref->branchpos - 6, REG_ITMP2_XPC);
4148 /* move function to call into REG_ITMP3 */
4150 M_MOV_IMM(eref->function, REG_ITMP3);
4152 if (savedmcodeptr != NULL) {
4153 M_JMP_IMM((savedmcodeptr - cd->mcodeptr) - 5);
4156 savedmcodeptr = cd->mcodeptr;
4158 M_ASUB_IMM(5 * 4, REG_SP);
4160 /* first save REG_ITMP1 so we can use it */
4162 M_AST(REG_ITMP1, REG_SP, 4 * 4); /* for AIOOBE */
4164 M_AST_IMM(0, REG_SP, 0 * 4);
4166 M_MOV(REG_SP, REG_ITMP1);
4167 M_AADD_IMM(5 * 4, REG_ITMP1);
4168 M_AST(REG_ITMP1, REG_SP, 1 * 4);
4169 M_ALD(REG_ITMP1, REG_SP, (5 + stackframesize) * 4);
4170 M_AST(REG_ITMP1, REG_SP, 2 * 4);
4171 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
4175 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
4176 M_AADD_IMM(5 * 4, REG_SP);
4178 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
4184 /* generate code patching stub call code */
4186 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4187 /* check code segment size */
4191 /* Get machine code which is patched back in later. A
4192 `call rel32' is 5 bytes long. */
4194 savedmcodeptr = cd->mcodebase + pref->branchpos;
4195 mcode = *((u8 *) savedmcodeptr);
4197 /* patch in `call rel32' to call the following code */
4199 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
4200 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
4202 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
4204 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4206 /* save REG_ITMP3 */
4210 /* move pointer to java_objectheader onto stack */
4212 #if defined(ENABLE_THREADS)
4213 (void) dseg_addaddress(cd, NULL); /* flcword */
4214 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
4215 off = dseg_addaddress(cd, NULL); /* vftbl */
4217 M_MOV_IMM(0, REG_ITMP3);
4219 M_AADD_IMM(off, REG_ITMP3);
4225 /* move machine code bytes and classinfo pointer into registers */
4227 M_PUSH_IMM(mcode >> 32);
4229 M_PUSH_IMM(pref->ref);
4230 M_PUSH_IMM(pref->patcher);
4232 M_MOV_IMM(asm_patcher_wrapper, REG_ITMP3);
4237 /* generate replacement-out stubs */
4242 replacementpoint = jd->code->rplpoints;
4244 for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
4245 /* check code segment size */
4249 /* note start of stub code */
4251 replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
4253 /* make machine code for patching */
4255 disp = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
4256 replacementpoint->mcode = 0xe9 | ((u8)disp << 8);
4258 /* push address of `rplpoint` struct */
4260 M_PUSH_IMM(replacementpoint);
4262 /* jump to replacement function */
4264 M_PUSH_IMM(asm_replacement_out);
4271 /* everything's ok */
4277 /* createcompilerstub **********************************************************
4279 Creates a stub routine which calls the compiler.
4281 *******************************************************************************/
4283 #define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P
4284 #define COMPILERSTUB_CODESIZE 12
4286 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4289 u1 *createcompilerstub(methodinfo *m)
4291 u1 *s; /* memory to hold the stub */
4297 s = CNEW(u1, COMPILERSTUB_SIZE);
4299 /* set data pointer and code pointer */
4302 s = s + COMPILERSTUB_DATASIZE;
4304 /* mark start of dump memory area */
4306 dumpsize = dump_size();
4308 cd = DNEW(codegendata);
4311 /* Store the codeinfo pointer in the same place as in the
4312 methodheader for compiled methods. */
4314 code = code_codeinfo_new(m);
4316 d[0] = (ptrint) asm_call_jit_compiler;
4318 d[2] = (ptrint) code;
4320 /* code for the stub */
4322 M_MOV_IMM(m, REG_ITMP1); /* method info */
4323 M_MOV_IMM(asm_call_jit_compiler, REG_ITMP3);
4326 #if defined(ENABLE_STATISTICS)
4328 count_cstub_len += COMPILERSTUB_SIZE;
4331 /* release dump area */
4333 dump_release(dumpsize);
4339 /* createnativestub ************************************************************
4341 Creates a stub routine which calls a native method.
4343 *******************************************************************************/
4345 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
4354 s4 i, j; /* count variables */
4358 /* get required compiler data */
4365 /* set some variables */
4368 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4370 /* calculate stackframe size */
4373 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4374 sizeof(localref_table) / SIZEOF_VOID_P +
4375 1 + /* function pointer */
4376 4 * 4 + /* 4 arguments (start_native_call) */
4379 /* create method header */
4381 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
4382 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
4383 (void) dseg_adds4(cd, 0); /* IsSync */
4384 (void) dseg_adds4(cd, 0); /* IsLeaf */
4385 (void) dseg_adds4(cd, 0); /* IntSave */
4386 (void) dseg_adds4(cd, 0); /* FltSave */
4387 (void) dseg_addlinenumbertablesize(cd);
4388 (void) dseg_adds4(cd, 0); /* ExTableSize */
4390 /* generate native method profiling code */
4392 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
4393 /* count frequency */
4395 M_MOV_IMM(code, REG_ITMP1);
4396 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(codeinfo, frequency));
4399 /* calculate stackframe size for native function */
4401 M_ASUB_IMM(stackframesize * 4, REG_SP);
4403 #if !defined(NDEBUG)
4404 if (opt_verbosecall) {
4407 disp = stackframesize * 4;
4409 M_ASUB_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
4411 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
4412 t = md->paramtypes[p].type;
4413 if (IS_INT_LNG_TYPE(t)) {
4414 if (IS_2_WORD_TYPE(t)) {
4415 M_ILD(REG_ITMP1, REG_SP,
4416 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4417 M_ILD(REG_ITMP2, REG_SP,
4418 4 + TRACE_ARGS_NUM * 8 + 4 + disp + 4);
4419 M_IST(REG_ITMP1, REG_SP, p * 8);
4420 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
4422 } else if (t == TYPE_ADR) {
4423 M_ALD(REG_ITMP1, REG_SP,
4424 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4426 M_AST(REG_ITMP1, REG_SP, p * 8);
4427 M_AST(REG_ITMP2, REG_SP, p * 8 + 4);
4430 M_ILD(EAX, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4432 M_IST(EAX, REG_SP, p * 8);
4433 M_IST(EDX, REG_SP, p * 8 + 4);
4437 if (!IS_2_WORD_TYPE(t)) {
4438 emit_flds_membase(cd, REG_SP,
4439 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4440 emit_fstps_membase(cd, REG_SP, p * 8);
4441 emit_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
4442 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
4445 emit_fldl_membase(cd, REG_SP,
4446 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4447 emit_fstpl_membase(cd, REG_SP, p * 8);
4450 disp += (IS_2_WORD_TYPE(t)) ? 8 : 4;
4454 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
4455 M_IST(REG_ITMP1, REG_SP, p * 8);
4456 M_IST(REG_ITMP1, REG_SP, p * 8 + 4);
4459 M_AST_IMM(m, REG_SP, TRACE_ARGS_NUM * 8);
4461 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
4464 M_AADD_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
4466 #endif /* !defined(NDEBUG) */
4468 /* get function address (this must happen before the stackframeinfo) */
4470 #if !defined(WITH_STATIC_CLASSPATH)
4472 codegen_addpatchref(cd, PATCHER_resolve_native, m, 0);
4474 if (opt_showdisassemble) {
4475 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4480 M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
4482 /* Mark the whole fpu stack as free for native functions (only for saved */
4483 /* register count == 0). */
4485 emit_ffree_reg(cd, 0);
4486 emit_ffree_reg(cd, 1);
4487 emit_ffree_reg(cd, 2);
4488 emit_ffree_reg(cd, 3);
4489 emit_ffree_reg(cd, 4);
4490 emit_ffree_reg(cd, 5);
4491 emit_ffree_reg(cd, 6);
4492 emit_ffree_reg(cd, 7);
4494 /* prepare data structures for native function call */
4496 M_MOV(REG_SP, REG_ITMP1);
4497 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
4499 M_AST(REG_ITMP1, REG_SP, 0 * 4);
4500 M_IST_IMM(0, REG_SP, 1 * 4);
4503 M_MOV(REG_SP, REG_ITMP2);
4504 M_AADD_IMM(stackframesize * 4 + SIZEOF_VOID_P, REG_ITMP2);
4506 M_AST(REG_ITMP2, REG_SP, 2 * 4);
4507 M_ALD(REG_ITMP3, REG_SP, stackframesize * 4);
4508 M_AST(REG_ITMP3, REG_SP, 3 * 4);
4509 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
4512 M_ALD(REG_ITMP3, REG_SP, 4 * 4);
4514 /* copy arguments into new stackframe */
4516 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4517 t = md->paramtypes[i].type;
4519 if (!md->params[i].inmemory) {
4520 /* no integer argument registers */
4521 } else { /* float/double in memory can be copied like int/longs */
4522 s1 = (md->params[i].regoff + stackframesize + 1) * 4;
4523 s2 = nmd->params[j].regoff * 4;
4525 M_ILD(REG_ITMP1, REG_SP, s1);
4526 M_IST(REG_ITMP1, REG_SP, s2);
4527 if (IS_2_WORD_TYPE(t)) {
4528 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
4529 M_IST(REG_ITMP1, REG_SP, s2 + 4);
4534 /* if function is static, put class into second argument */
4536 if (m->flags & ACC_STATIC)
4537 M_AST_IMM((ptrint) m->class, REG_SP, 1 * 4);
4539 /* put env into first argument */
4541 M_AST_IMM((ptrint) _Jv_env, REG_SP, 0 * 4);
4543 /* call the native function */
4547 /* save return value */
4549 if (md->returntype.type != TYPE_VOID) {
4550 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4551 if (IS_2_WORD_TYPE(md->returntype.type))
4552 M_IST(REG_RESULT2, REG_SP, 2 * 4);
4553 M_IST(REG_RESULT, REG_SP, 1 * 4);
4556 if (IS_2_WORD_TYPE(md->returntype.type))
4557 emit_fstl_membase(cd, REG_SP, 1 * 4);
4559 emit_fsts_membase(cd, REG_SP, 1 * 4);
4563 #if !defined(NDEBUG)
4564 if (opt_verbosecall) {
4565 /* restore return value */
4567 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4568 if (IS_2_WORD_TYPE(md->returntype.type))
4569 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
4570 M_ILD(REG_RESULT, REG_SP, 1 * 4);
4573 if (IS_2_WORD_TYPE(md->returntype.type))
4574 emit_fldl_membase(cd, REG_SP, 1 * 4);
4576 emit_flds_membase(cd, REG_SP, 1 * 4);
4579 M_ASUB_IMM(4 + 8 + 8 + 4, REG_SP);
4581 M_AST_IMM((ptrint) m, REG_SP, 0);
4583 M_IST(REG_RESULT, REG_SP, 4);
4584 M_IST(REG_RESULT2, REG_SP, 4 + 4);
4586 emit_fstl_membase(cd, REG_SP, 4 + 8);
4587 emit_fsts_membase(cd, REG_SP, 4 + 8 + 8);
4589 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
4592 M_AADD_IMM(4 + 8 + 8 + 4, REG_SP);
4594 #endif /* !defined(NDEBUG) */
4596 /* remove native stackframe info */
4598 M_MOV(REG_SP, REG_ITMP1);
4599 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
4601 M_AST(REG_ITMP1, REG_SP, 0 * 4);
4602 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
4604 M_MOV(REG_RESULT, REG_ITMP2); /* REG_ITMP3 == REG_RESULT2 */
4606 /* restore return value */
4608 if (md->returntype.type != TYPE_VOID) {
4609 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4610 if (IS_2_WORD_TYPE(md->returntype.type))
4611 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
4612 M_ILD(REG_RESULT, REG_SP, 1 * 4);
4615 if (IS_2_WORD_TYPE(md->returntype.type))
4616 emit_fldl_membase(cd, REG_SP, 1 * 4);
4618 emit_flds_membase(cd, REG_SP, 1 * 4);
4622 M_AADD_IMM(stackframesize * 4, REG_SP);
4624 /* check for exception */
4631 /* handle exception */
4633 M_MOV(REG_ITMP2, REG_ITMP1_XPTR);
4634 M_ALD(REG_ITMP2_XPC, REG_SP, 0);
4635 M_ASUB_IMM(2, REG_ITMP2_XPC);
4637 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
4641 /* process patcher calls **************************************************/
4649 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4650 /* Get machine code which is patched back in later. A
4651 `call rel32' is 5 bytes long. */
4653 xcodeptr = cd->mcodebase + pref->branchpos;
4654 mcode = *((u8 *) xcodeptr);
4656 /* patch in `call rel32' to call the following code */
4658 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
4659 cd->mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4661 M_CALL_IMM(tmpmcodeptr - (xcodeptr + PATCHER_CALL_SIZE));
4663 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4665 /* save REG_ITMP3 */
4669 /* move pointer to java_objectheader onto stack */
4671 #if defined(ENABLE_THREADS)
4672 /* create a virtual java_objectheader */
4674 (void) dseg_addaddress(cd, NULL); /* flcword */
4675 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
4676 disp = dseg_addaddress(cd, NULL); /* vftbl */
4678 M_MOV_IMM(0, REG_ITMP3);
4680 M_AADD_IMM(disp, REG_ITMP3);
4686 /* move machine code bytes and classinfo pointer onto stack */
4688 M_PUSH_IMM((mcode >> 32));
4690 M_PUSH_IMM(pref->ref);
4691 M_PUSH_IMM(pref->patcher);
4693 M_MOV_IMM(asm_patcher_wrapper, REG_ITMP3);
4700 return code->entrypoint;
4705 * These are local overrides for various environment variables in Emacs.
4706 * Please do not remove this and leave it at the end of the file, where
4707 * Emacs will automagically detect them.
4708 * ---------------------------------------------------------------------
4711 * indent-tabs-mode: t
4715 * vim:noexpandtab:sw=4:ts=4: