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 5145 2006-07-17 11:48:38Z 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);
3169 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3171 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3174 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3175 /* val.i = constant */
3177 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
3178 emit_ifcc_iconst(cd, CC_NE, src, iptr);
3181 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3182 /* val.i = constant */
3184 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
3185 emit_ifcc_iconst(cd, CC_E, src, iptr);
3188 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3189 /* val.i = constant */
3191 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
3192 emit_ifcc_iconst(cd, CC_GE, src, iptr);
3195 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3196 /* val.i = constant */
3198 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
3199 emit_ifcc_iconst(cd, CC_L, src, iptr);
3202 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3203 /* val.i = constant */
3205 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
3206 emit_ifcc_iconst(cd, CC_LE, src, iptr);
3209 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3210 /* val.i = constant */
3212 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
3213 emit_ifcc_iconst(cd, CC_G, src, iptr);
3217 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3219 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
3220 M_INTMOVE(s1, REG_RESULT);
3221 goto nowperformreturn;
3223 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3225 s1 = emit_load_s1(jd, iptr, src, REG_RESULT_PACKED);
3226 M_LNGMOVE(s1, REG_RESULT_PACKED);
3227 goto nowperformreturn;
3229 case ICMD_ARETURN: /* ..., retvalue ==> ... */
3231 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
3232 M_INTMOVE(s1, REG_RESULT);
3234 #ifdef ENABLE_VERIFIER
3236 codegen_addpatchref(cd, PATCHER_athrow_areturn,
3237 (unresolved_class *) iptr->val.a, 0);
3239 if (opt_showdisassemble) {
3240 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3243 #endif /* ENABLE_VERIFIER */
3244 goto nowperformreturn;
3246 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3249 s1 = emit_load_s1(jd, iptr, src, REG_FRESULT);
3250 goto nowperformreturn;
3252 case ICMD_RETURN: /* ... ==> ... */
3260 #if !defined(NDEBUG)
3261 /* call trace function */
3263 if (opt_verbosecall) {
3264 M_ISUB_IMM(4 + 8 + 8 + 4, REG_SP);
3266 emit_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3268 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3269 emit_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3271 emit_fstl_membase(cd, REG_SP, 4 + 8);
3272 emit_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3274 emit_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3275 emit_call_reg(cd, REG_ITMP1);
3277 emit_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3278 emit_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3280 emit_alu_imm_reg(cd, ALU_ADD, 4 + 8 + 8 + 4, REG_SP);
3282 #endif /* !defined(NDEBUG) */
3284 #if defined(ENABLE_THREADS)
3285 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3286 M_ALD(REG_ITMP2, REG_SP, rd->memuse * 4);
3288 /* we need to save the proper return value */
3289 switch (iptr->opc) {
3292 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
3296 M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 4);
3300 emit_fstps_membase(cd, REG_SP, rd->memuse * 4);
3304 emit_fstpl_membase(cd, REG_SP, rd->memuse * 4);
3308 M_AST(REG_ITMP2, REG_SP, 0);
3309 M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3);
3312 /* and now restore the proper return value */
3313 switch (iptr->opc) {
3316 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
3320 M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 4);
3324 emit_flds_membase(cd, REG_SP, rd->memuse * 4);
3328 emit_fldl_membase(cd, REG_SP, rd->memuse * 4);
3334 /* restore saved registers */
3336 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
3337 p--; M_ALD(rd->savintregs[i], REG_SP, p * 4);
3340 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
3342 emit_fldl_membase(cd, REG_SP, p * 4);
3343 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3345 /* emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1); */
3348 /* emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset); */
3352 /* deallocate stack */
3355 M_AADD_IMM(stackframesize * 4, REG_SP);
3362 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3367 tptr = (void **) iptr->target;
3369 s4ptr = iptr->val.a;
3370 l = s4ptr[1]; /* low */
3371 i = s4ptr[2]; /* high */
3373 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3374 M_INTMOVE(s1, REG_ITMP1);
3377 M_ISUB_IMM(l, REG_ITMP1);
3383 M_CMP_IMM(i - 1, REG_ITMP1);
3385 codegen_addreference(cd, (basicblock *) tptr[0]);
3387 /* build jump table top down and use address of lowest entry */
3392 dseg_addtarget(cd, (basicblock *) tptr[0]);
3396 /* length of dataseg after last dseg_addtarget is used
3399 M_MOV_IMM(0, REG_ITMP2);
3401 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3407 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3409 s4 i, l, val, *s4ptr;
3412 tptr = (void **) iptr->target;
3414 s4ptr = iptr->val.a;
3415 l = s4ptr[0]; /* default */
3416 i = s4ptr[1]; /* count */
3418 MCODECHECK((i<<2)+8);
3419 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3428 codegen_addreference(cd, (basicblock *) tptr[0]);
3433 tptr = (void **) iptr->target;
3434 codegen_addreference(cd, (basicblock *) tptr[0]);
3438 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
3439 /* op1 = arg count val.a = builtintable entry */
3445 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3446 /* op1 = arg count, val.a = method pointer */
3448 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3449 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
3450 case ICMD_INVOKEINTERFACE:
3452 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3453 md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
3457 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
3458 md = lm->parseddesc;
3462 s3 = md->paramcount;
3464 MCODECHECK((s3 << 1) + 64);
3466 /* copy arguments to registers or stack location */
3468 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
3469 if (src->varkind == ARGVAR)
3471 if (IS_INT_LNG_TYPE(src->type)) {
3472 if (!md->params[s3].inmemory) {
3473 log_text("No integer argument registers available!");
3477 if (IS_2_WORD_TYPE(src->type)) {
3478 d = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
3479 M_LST(d, REG_SP, md->params[s3].regoff * 4);
3481 d = emit_load_s1(jd, iptr, src, REG_ITMP1);
3482 M_IST(d, REG_SP, md->params[s3].regoff * 4);
3487 if (!md->params[s3].inmemory) {
3488 s1 = rd->argfltregs[md->params[s3].regoff];
3489 d = emit_load_s1(jd, iptr, src, s1);
3493 d = emit_load_s1(jd, iptr, src, REG_FTMP1);
3494 if (IS_2_WORD_TYPE(src->type))
3495 M_DST(d, REG_SP, md->params[s3].regoff * 4);
3497 M_FST(d, REG_SP, md->params[s3].regoff * 4);
3502 switch (iptr->opc) {
3504 disp = (ptrint) bte->fp;
3505 d = md->returntype.type;
3507 M_MOV_IMM(disp, REG_ITMP1);
3510 /* if op1 == true, we need to check for an exception */
3512 if (iptr->op1 == true) {
3515 codegen_add_fillinstacktrace_ref(cd);
3519 case ICMD_INVOKESPECIAL:
3520 M_ALD(REG_ITMP1, REG_SP, 0);
3523 codegen_add_nullpointerexception_ref(cd);
3527 case ICMD_INVOKESTATIC:
3529 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3531 codegen_addpatchref(cd, PATCHER_invokestatic_special,
3534 if (opt_showdisassemble) {
3535 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3539 d = md->returntype.type;
3542 disp = (ptrint) lm->stubroutine;
3543 d = lm->parseddesc->returntype.type;
3546 M_MOV_IMM(disp, REG_ITMP2);
3550 case ICMD_INVOKEVIRTUAL:
3551 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
3552 gen_nullptr_check(REG_ITMP1);
3555 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3557 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
3559 if (opt_showdisassemble) {
3560 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3564 d = md->returntype.type;
3567 s1 = OFFSET(vftbl_t, table[0]) +
3568 sizeof(methodptr) * lm->vftblindex;
3569 d = md->returntype.type;
3572 M_ALD(REG_METHODPTR, REG_ITMP1,
3573 OFFSET(java_objectheader, vftbl));
3574 M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
3578 case ICMD_INVOKEINTERFACE:
3579 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
3580 gen_nullptr_check(REG_ITMP1);
3583 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3585 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
3587 if (opt_showdisassemble) {
3588 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3593 d = md->returntype.type;
3596 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3597 sizeof(methodptr) * lm->class->index;
3599 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3601 d = md->returntype.type;
3604 M_ALD(REG_METHODPTR, REG_ITMP1,
3605 OFFSET(java_objectheader, vftbl));
3606 M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
3607 M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
3612 /* d contains return type */
3614 if (d != TYPE_VOID) {
3615 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3616 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3617 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
3618 M_LNGMOVE(REG_RESULT_PACKED, s1);
3621 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3622 M_INTMOVE(REG_RESULT, s1);
3626 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
3628 emit_store(jd, iptr, iptr->dst, s1);
3633 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3634 /* op1: 0 == array, 1 == class */
3635 /* val.a: (classinfo*) superclass */
3637 /* superclass is an interface:
3639 * OK if ((sub == NULL) ||
3640 * (sub->vftbl->interfacetablelength > super->index) &&
3641 * (sub->vftbl->interfacetable[-super->index] != NULL));
3643 * superclass is a class:
3645 * OK if ((sub == NULL) || (0
3646 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3647 * super->vftbl->diffval));
3650 if (iptr->op1 == 1) {
3651 /* object type cast-check */
3654 vftbl_t *supervftbl;
3657 super = (classinfo *) iptr->val.a;
3664 superindex = super->index;
3665 supervftbl = super->vftbl;
3668 #if defined(ENABLE_THREADS)
3669 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3671 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3673 /* calculate interface checkcast code size */
3675 s2 = 2; /* mov_membase_reg */
3676 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3678 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ +
3679 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
3680 2 /* test */ + 6 /* jcc */);
3683 s2 += (opt_showdisassemble ? 5 : 0);
3685 /* calculate class checkcast code size */
3687 s3 = 2; /* mov_membase_reg */
3688 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3690 s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */;
3693 if (s1 != REG_ITMP1) {
3695 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
3698 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
3705 s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ +
3706 5 /* mov_imm_reg */ + 2 /* mov_membase_reg */);
3707 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3710 s3 += 2 /* cmp */ + 6 /* jcc */;
3713 s3 += (opt_showdisassemble ? 5 : 0);
3715 /* if class is not resolved, check which code to call */
3717 if (super == NULL) {
3719 M_BEQ(5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
3721 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3722 (constant_classref *) iptr->target, 0);
3724 if (opt_showdisassemble) {
3725 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3728 M_MOV_IMM(0, REG_ITMP2); /* super->flags */
3729 M_AND_IMM32(ACC_INTERFACE, REG_ITMP2);
3733 /* interface checkcast code */
3735 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3736 if (super != NULL) {
3741 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3743 if (super == NULL) {
3744 codegen_addpatchref(cd,
3745 PATCHER_checkcast_instanceof_interface,
3746 (constant_classref *) iptr->target,
3749 if (opt_showdisassemble) {
3750 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3755 REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3756 M_ISUB_IMM32(superindex, REG_ITMP3);
3759 codegen_add_classcastexception_ref(cd, s1);
3760 M_ALD32(REG_ITMP3, REG_ITMP2,
3761 OFFSET(vftbl_t, interfacetable[0]) -
3762 superindex * sizeof(methodptr*));
3765 codegen_add_classcastexception_ref(cd, s1);
3771 /* class checkcast code */
3773 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3774 if (super != NULL) {
3779 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3781 if (super == NULL) {
3782 codegen_addpatchref(cd, PATCHER_checkcast_class,
3783 (constant_classref *) iptr->target,
3786 if (opt_showdisassemble) {
3787 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3791 M_MOV_IMM(supervftbl, REG_ITMP3);
3792 #if defined(ENABLE_THREADS)
3793 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3795 M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3797 /* if (s1 != REG_ITMP1) { */
3798 /* emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
3799 /* emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
3800 /* #if defined(ENABLE_THREADS) */
3801 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
3803 /* emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
3806 M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3807 M_ISUB(REG_ITMP3, REG_ITMP2);
3808 M_MOV_IMM(supervftbl, REG_ITMP3);
3809 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3810 #if defined(ENABLE_THREADS)
3811 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3815 M_CMP(REG_ITMP3, REG_ITMP2);
3816 M_BA(0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
3817 codegen_add_classcastexception_ref(cd, s1);
3820 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
3823 /* array type cast-check */
3825 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
3826 M_AST(s1, REG_SP, 0 * 4);
3828 if (iptr->val.a == NULL) {
3829 codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
3832 if (opt_showdisassemble) {
3833 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3837 M_AST_IMM(iptr->val.a, REG_SP, 1 * 4);
3838 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP3);
3841 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
3844 codegen_add_classcastexception_ref(cd, s1);
3846 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
3850 emit_store(jd, iptr, iptr->dst, d);
3853 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3854 /* op1: 0 == array, 1 == class */
3855 /* val.a: (classinfo*) superclass */
3857 /* superclass is an interface:
3859 * return (sub != NULL) &&
3860 * (sub->vftbl->interfacetablelength > super->index) &&
3861 * (sub->vftbl->interfacetable[-super->index] != NULL);
3863 * superclass is a class:
3865 * return ((sub != NULL) && (0
3866 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3867 * super->vftbl->diffvall));
3872 vftbl_t *supervftbl;
3875 super = (classinfo *) iptr->val.a;
3882 superindex = super->index;
3883 supervftbl = super->vftbl;
3886 #if defined(ENABLE_THREADS)
3887 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3890 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3891 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3893 M_INTMOVE(s1, REG_ITMP1);
3897 /* calculate interface instanceof code size */
3899 s2 = 2; /* mov_membase_reg */
3900 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3902 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
3903 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
3904 2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
3907 s2 += (opt_showdisassemble ? 5 : 0);
3909 /* calculate class instanceof code size */
3911 s3 = 2; /* mov_membase_reg */
3912 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3913 s3 += 5; /* mov_imm_reg */
3915 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
3917 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3919 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3921 s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
3922 2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
3925 s3 += (opt_showdisassemble ? 5 : 0);
3929 /* if class is not resolved, check which code to call */
3933 M_BEQ(5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
3935 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3936 (constant_classref *) iptr->target, 0);
3938 if (opt_showdisassemble) {
3939 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3942 M_MOV_IMM(0, REG_ITMP3); /* super->flags */
3943 M_AND_IMM32(ACC_INTERFACE, REG_ITMP3);
3947 /* interface instanceof code */
3949 if (!super || (super->flags & ACC_INTERFACE)) {
3955 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3958 codegen_addpatchref(cd,
3959 PATCHER_checkcast_instanceof_interface,
3960 (constant_classref *) iptr->target, 0);
3962 if (opt_showdisassemble) {
3963 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3968 REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3969 M_ISUB_IMM32(superindex, REG_ITMP3);
3972 disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
3973 6 /* jcc */ + 5 /* mov_imm_reg */);
3976 M_ALD32(REG_ITMP1, REG_ITMP1,
3977 OFFSET(vftbl_t, interfacetable[0]) -
3978 superindex * sizeof(methodptr*));
3980 /* emit_setcc_reg(cd, CC_A, d); */
3981 /* emit_jcc(cd, CC_BE, 5); */
3989 /* class instanceof code */
3991 if (!super || !(super->flags & ACC_INTERFACE)) {
3997 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
4000 codegen_addpatchref(cd, PATCHER_instanceof_class,
4001 (constant_classref *) iptr->target, 0);
4003 if (opt_showdisassemble) {
4004 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4008 M_MOV_IMM(supervftbl, REG_ITMP2);
4009 #if defined(ENABLE_THREADS)
4010 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4012 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
4013 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval));
4014 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
4015 #if defined(ENABLE_THREADS)
4016 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4018 M_ISUB(REG_ITMP2, REG_ITMP1);
4019 M_CLR(d); /* may be REG_ITMP2 */
4020 M_CMP(REG_ITMP3, REG_ITMP1);
4024 emit_store(jd, iptr, iptr->dst, d);
4030 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4031 /* op1 = dimension, val.a = class */
4033 /* check for negative sizes and copy sizes to stack if necessary */
4035 MCODECHECK((iptr->op1 << 1) + 64);
4037 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4038 /* copy SAVEDVAR sizes to stack */
4040 if (src->varkind != ARGVAR) {
4041 if (src->flags & INMEMORY) {
4042 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
4043 M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4);
4046 M_IST(src->regoff, REG_SP, (s1 + 3) * 4);
4050 /* is a patcher function set? */
4052 if (iptr->val.a == NULL) {
4053 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
4054 (constant_classref *) iptr->target, 0);
4056 if (opt_showdisassemble) {
4057 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4064 disp = (ptrint) iptr->val.a;
4066 /* a0 = dimension count */
4068 M_IST_IMM(iptr->op1, REG_SP, 0 * 4);
4070 /* a1 = arraydescriptor */
4072 M_IST_IMM(disp, REG_SP, 1 * 4);
4074 /* a2 = pointer to dimensions = stack pointer */
4076 M_MOV(REG_SP, REG_ITMP1);
4077 M_AADD_IMM(3 * 4, REG_ITMP1);
4078 M_AST(REG_ITMP1, REG_SP, 2 * 4);
4080 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
4083 /* check for exception before result assignment */
4087 codegen_add_fillinstacktrace_ref(cd);
4089 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
4090 M_INTMOVE(REG_RESULT, s1);
4091 emit_store(jd, iptr, iptr->dst, s1);
4096 new_internalerror("Unknown ICMD %d", iptr->opc);
4100 } /* for instruction */
4102 /* copy values to interface registers */
4104 src = bptr->outstack;
4105 len = bptr->outdepth;
4107 #if defined(ENABLE_LSRA)
4112 if ((src->varkind != STACKVAR)) {
4114 if (IS_FLT_DBL_TYPE(s2)) {
4115 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
4116 if (!(rd->interfaces[len][s2].flags & INMEMORY))
4117 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
4119 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
4122 if (IS_2_WORD_TYPE(s2))
4124 /* s1 = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP1, REG_ITMP2)); */
4126 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4128 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4129 if (IS_2_WORD_TYPE(s2))
4130 M_LNGMOVE(s1, rd->interfaces[len][s2].regoff);
4132 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
4135 if (IS_2_WORD_TYPE(s2))
4136 M_LST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
4138 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
4145 /* At the end of a basic block we may have to append some nops,
4146 because the patcher stub calling code might be longer than the
4147 actual instruction. So codepatching does not change the
4148 following block unintentionally. */
4150 if (cd->mcodeptr < cd->lastmcodeptr) {
4151 while (cd->mcodeptr < cd->lastmcodeptr) {
4156 } /* if (bptr -> flags >= BBREACHED) */
4157 } /* for basic block */
4159 dseg_createlinenumbertable(cd);
4162 /* generate exception and patcher stubs */
4171 savedmcodeptr = NULL;
4173 /* generate exception stubs */
4175 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
4176 gen_resolvebranch(cd->mcodebase + eref->branchpos,
4178 cd->mcodeptr - cd->mcodebase);
4182 /* Check if the exception is an
4183 ArrayIndexOutOfBoundsException. If so, move index register
4186 if (eref->reg != -1)
4187 M_INTMOVE(eref->reg, REG_ITMP1);
4189 /* calcuate exception address */
4191 M_MOV_IMM(0, REG_ITMP2_XPC);
4193 M_AADD_IMM32(eref->branchpos - 6, REG_ITMP2_XPC);
4195 /* move function to call into REG_ITMP3 */
4197 M_MOV_IMM(eref->function, REG_ITMP3);
4199 if (savedmcodeptr != NULL) {
4200 M_JMP_IMM((savedmcodeptr - cd->mcodeptr) - 5);
4203 savedmcodeptr = cd->mcodeptr;
4205 M_ASUB_IMM(5 * 4, REG_SP);
4207 /* first save REG_ITMP1 so we can use it */
4209 M_AST(REG_ITMP1, REG_SP, 4 * 4); /* for AIOOBE */
4211 M_AST_IMM(0, REG_SP, 0 * 4);
4213 M_MOV(REG_SP, REG_ITMP1);
4214 M_AADD_IMM(5 * 4, REG_ITMP1);
4215 M_AST(REG_ITMP1, REG_SP, 1 * 4);
4216 M_ALD(REG_ITMP1, REG_SP, (5 + stackframesize) * 4);
4217 M_AST(REG_ITMP1, REG_SP, 2 * 4);
4218 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
4222 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
4223 M_AADD_IMM(5 * 4, REG_SP);
4225 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
4231 /* generate code patching stub call code */
4233 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4234 /* check code segment size */
4238 /* Get machine code which is patched back in later. A
4239 `call rel32' is 5 bytes long. */
4241 savedmcodeptr = cd->mcodebase + pref->branchpos;
4242 mcode = *((u8 *) savedmcodeptr);
4244 /* patch in `call rel32' to call the following code */
4246 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
4247 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
4249 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
4251 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4253 /* save REG_ITMP3 */
4257 /* move pointer to java_objectheader onto stack */
4259 #if defined(ENABLE_THREADS)
4260 (void) dseg_addaddress(cd, NULL); /* flcword */
4261 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
4262 off = dseg_addaddress(cd, NULL); /* vftbl */
4264 M_MOV_IMM(0, REG_ITMP3);
4266 M_AADD_IMM(off, REG_ITMP3);
4272 /* move machine code bytes and classinfo pointer into registers */
4274 M_PUSH_IMM(mcode >> 32);
4276 M_PUSH_IMM(pref->ref);
4277 M_PUSH_IMM(pref->patcher);
4279 M_MOV_IMM(asm_patcher_wrapper, REG_ITMP3);
4284 /* generate replacement-out stubs */
4289 replacementpoint = jd->code->rplpoints;
4291 for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
4292 /* check code segment size */
4296 /* note start of stub code */
4298 replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
4300 /* make machine code for patching */
4302 disp = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
4303 replacementpoint->mcode = 0xe9 | ((u8)disp << 8);
4305 /* push address of `rplpoint` struct */
4307 M_PUSH_IMM(replacementpoint);
4309 /* jump to replacement function */
4311 M_PUSH_IMM(asm_replacement_out);
4318 /* everything's ok */
4324 /* createcompilerstub **********************************************************
4326 Creates a stub routine which calls the compiler.
4328 *******************************************************************************/
4330 #define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P
4331 #define COMPILERSTUB_CODESIZE 12
4333 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4336 u1 *createcompilerstub(methodinfo *m)
4338 u1 *s; /* memory to hold the stub */
4344 s = CNEW(u1, COMPILERSTUB_SIZE);
4346 /* set data pointer and code pointer */
4349 s = s + COMPILERSTUB_DATASIZE;
4351 /* mark start of dump memory area */
4353 dumpsize = dump_size();
4355 cd = DNEW(codegendata);
4358 /* Store the codeinfo pointer in the same place as in the
4359 methodheader for compiled methods. */
4361 code = code_codeinfo_new(m);
4363 d[0] = (ptrint) asm_call_jit_compiler;
4365 d[2] = (ptrint) code;
4367 /* code for the stub */
4369 M_MOV_IMM(m, REG_ITMP1); /* method info */
4370 M_MOV_IMM(asm_call_jit_compiler, REG_ITMP3);
4373 #if defined(ENABLE_STATISTICS)
4375 count_cstub_len += COMPILERSTUB_SIZE;
4378 /* release dump area */
4380 dump_release(dumpsize);
4386 /* createnativestub ************************************************************
4388 Creates a stub routine which calls a native method.
4390 *******************************************************************************/
4392 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
4401 s4 i, j; /* count variables */
4405 /* get required compiler data */
4412 /* set some variables */
4415 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4417 /* calculate stackframe size */
4420 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4421 sizeof(localref_table) / SIZEOF_VOID_P +
4422 1 + /* function pointer */
4423 4 * 4 + /* 4 arguments (start_native_call) */
4426 /* create method header */
4428 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
4429 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
4430 (void) dseg_adds4(cd, 0); /* IsSync */
4431 (void) dseg_adds4(cd, 0); /* IsLeaf */
4432 (void) dseg_adds4(cd, 0); /* IntSave */
4433 (void) dseg_adds4(cd, 0); /* FltSave */
4434 (void) dseg_addlinenumbertablesize(cd);
4435 (void) dseg_adds4(cd, 0); /* ExTableSize */
4437 /* generate native method profiling code */
4439 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
4440 /* count frequency */
4442 M_MOV_IMM(code, REG_ITMP1);
4443 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(codeinfo, frequency));
4446 /* calculate stackframe size for native function */
4448 M_ASUB_IMM(stackframesize * 4, REG_SP);
4450 #if !defined(NDEBUG)
4451 if (opt_verbosecall) {
4454 disp = stackframesize * 4;
4456 M_ASUB_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
4458 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
4459 t = md->paramtypes[p].type;
4460 if (IS_INT_LNG_TYPE(t)) {
4461 if (IS_2_WORD_TYPE(t)) {
4462 M_ILD(REG_ITMP1, REG_SP,
4463 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4464 M_ILD(REG_ITMP2, REG_SP,
4465 4 + TRACE_ARGS_NUM * 8 + 4 + disp + 4);
4466 M_IST(REG_ITMP1, REG_SP, p * 8);
4467 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
4469 } else if (t == TYPE_ADR) {
4470 M_ALD(REG_ITMP1, REG_SP,
4471 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4473 M_AST(REG_ITMP1, REG_SP, p * 8);
4474 M_AST(REG_ITMP2, REG_SP, p * 8 + 4);
4477 M_ILD(EAX, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4479 M_IST(EAX, REG_SP, p * 8);
4480 M_IST(EDX, REG_SP, p * 8 + 4);
4484 if (!IS_2_WORD_TYPE(t)) {
4485 emit_flds_membase(cd, REG_SP,
4486 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4487 emit_fstps_membase(cd, REG_SP, p * 8);
4488 emit_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
4489 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
4492 emit_fldl_membase(cd, REG_SP,
4493 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4494 emit_fstpl_membase(cd, REG_SP, p * 8);
4497 disp += (IS_2_WORD_TYPE(t)) ? 8 : 4;
4501 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
4502 M_IST(REG_ITMP1, REG_SP, p * 8);
4503 M_IST(REG_ITMP1, REG_SP, p * 8 + 4);
4506 M_AST_IMM(m, REG_SP, TRACE_ARGS_NUM * 8);
4508 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
4511 M_AADD_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
4513 #endif /* !defined(NDEBUG) */
4515 /* get function address (this must happen before the stackframeinfo) */
4517 #if !defined(WITH_STATIC_CLASSPATH)
4519 codegen_addpatchref(cd, PATCHER_resolve_native, m, 0);
4521 if (opt_showdisassemble) {
4522 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4527 M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
4529 /* Mark the whole fpu stack as free for native functions (only for saved */
4530 /* register count == 0). */
4532 emit_ffree_reg(cd, 0);
4533 emit_ffree_reg(cd, 1);
4534 emit_ffree_reg(cd, 2);
4535 emit_ffree_reg(cd, 3);
4536 emit_ffree_reg(cd, 4);
4537 emit_ffree_reg(cd, 5);
4538 emit_ffree_reg(cd, 6);
4539 emit_ffree_reg(cd, 7);
4541 /* prepare data structures for native function call */
4543 M_MOV(REG_SP, REG_ITMP1);
4544 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
4546 M_AST(REG_ITMP1, REG_SP, 0 * 4);
4547 M_IST_IMM(0, REG_SP, 1 * 4);
4550 M_MOV(REG_SP, REG_ITMP2);
4551 M_AADD_IMM(stackframesize * 4 + SIZEOF_VOID_P, REG_ITMP2);
4553 M_AST(REG_ITMP2, REG_SP, 2 * 4);
4554 M_ALD(REG_ITMP3, REG_SP, stackframesize * 4);
4555 M_AST(REG_ITMP3, REG_SP, 3 * 4);
4556 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
4559 M_ALD(REG_ITMP3, REG_SP, 4 * 4);
4561 /* copy arguments into new stackframe */
4563 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4564 t = md->paramtypes[i].type;
4566 if (!md->params[i].inmemory) {
4567 /* no integer argument registers */
4568 } else { /* float/double in memory can be copied like int/longs */
4569 s1 = (md->params[i].regoff + stackframesize + 1) * 4;
4570 s2 = nmd->params[j].regoff * 4;
4572 M_ILD(REG_ITMP1, REG_SP, s1);
4573 M_IST(REG_ITMP1, REG_SP, s2);
4574 if (IS_2_WORD_TYPE(t)) {
4575 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
4576 M_IST(REG_ITMP1, REG_SP, s2 + 4);
4581 /* if function is static, put class into second argument */
4583 if (m->flags & ACC_STATIC)
4584 M_AST_IMM((ptrint) m->class, REG_SP, 1 * 4);
4586 /* put env into first argument */
4588 M_AST_IMM((ptrint) _Jv_env, REG_SP, 0 * 4);
4590 /* call the native function */
4594 /* save return value */
4596 if (md->returntype.type != TYPE_VOID) {
4597 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4598 if (IS_2_WORD_TYPE(md->returntype.type))
4599 M_IST(REG_RESULT2, REG_SP, 2 * 4);
4600 M_IST(REG_RESULT, REG_SP, 1 * 4);
4603 if (IS_2_WORD_TYPE(md->returntype.type))
4604 emit_fstl_membase(cd, REG_SP, 1 * 4);
4606 emit_fsts_membase(cd, REG_SP, 1 * 4);
4610 #if !defined(NDEBUG)
4611 if (opt_verbosecall) {
4612 /* restore return value */
4614 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4615 if (IS_2_WORD_TYPE(md->returntype.type))
4616 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
4617 M_ILD(REG_RESULT, REG_SP, 1 * 4);
4620 if (IS_2_WORD_TYPE(md->returntype.type))
4621 emit_fldl_membase(cd, REG_SP, 1 * 4);
4623 emit_flds_membase(cd, REG_SP, 1 * 4);
4626 M_ASUB_IMM(4 + 8 + 8 + 4, REG_SP);
4628 M_AST_IMM((ptrint) m, REG_SP, 0);
4630 M_IST(REG_RESULT, REG_SP, 4);
4631 M_IST(REG_RESULT2, REG_SP, 4 + 4);
4633 emit_fstl_membase(cd, REG_SP, 4 + 8);
4634 emit_fsts_membase(cd, REG_SP, 4 + 8 + 8);
4636 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
4639 M_AADD_IMM(4 + 8 + 8 + 4, REG_SP);
4641 #endif /* !defined(NDEBUG) */
4643 /* remove native stackframe info */
4645 M_MOV(REG_SP, REG_ITMP1);
4646 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
4648 M_AST(REG_ITMP1, REG_SP, 0 * 4);
4649 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
4651 M_MOV(REG_RESULT, REG_ITMP2); /* REG_ITMP3 == REG_RESULT2 */
4653 /* restore return value */
4655 if (md->returntype.type != TYPE_VOID) {
4656 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4657 if (IS_2_WORD_TYPE(md->returntype.type))
4658 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
4659 M_ILD(REG_RESULT, REG_SP, 1 * 4);
4662 if (IS_2_WORD_TYPE(md->returntype.type))
4663 emit_fldl_membase(cd, REG_SP, 1 * 4);
4665 emit_flds_membase(cd, REG_SP, 1 * 4);
4669 M_AADD_IMM(stackframesize * 4, REG_SP);
4671 /* check for exception */
4678 /* handle exception */
4680 M_MOV(REG_ITMP2, REG_ITMP1_XPTR);
4681 M_ALD(REG_ITMP2_XPC, REG_SP, 0);
4682 M_ASUB_IMM(2, REG_ITMP2_XPC);
4684 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
4688 /* process patcher calls **************************************************/
4696 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4697 /* Get machine code which is patched back in later. A
4698 `call rel32' is 5 bytes long. */
4700 xcodeptr = cd->mcodebase + pref->branchpos;
4701 mcode = *((u8 *) xcodeptr);
4703 /* patch in `call rel32' to call the following code */
4705 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
4706 cd->mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4708 M_CALL_IMM(tmpmcodeptr - (xcodeptr + PATCHER_CALL_SIZE));
4710 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4712 /* save REG_ITMP3 */
4716 /* move pointer to java_objectheader onto stack */
4718 #if defined(ENABLE_THREADS)
4719 /* create a virtual java_objectheader */
4721 (void) dseg_addaddress(cd, NULL); /* flcword */
4722 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
4723 disp = dseg_addaddress(cd, NULL); /* vftbl */
4725 M_MOV_IMM(0, REG_ITMP3);
4727 M_AADD_IMM(disp, REG_ITMP3);
4733 /* move machine code bytes and classinfo pointer onto stack */
4735 M_PUSH_IMM((mcode >> 32));
4737 M_PUSH_IMM(pref->ref);
4738 M_PUSH_IMM(pref->patcher);
4740 M_MOV_IMM(asm_patcher_wrapper, REG_ITMP3);
4747 return code->entrypoint;
4752 * These are local overrides for various environment variables in Emacs.
4753 * Please do not remove this and leave it at the end of the file, where
4754 * Emacs will automagically detect them.
4755 * ---------------------------------------------------------------------
4758 * indent-tabs-mode: t
4762 * vim:noexpandtab:sw=4:ts=4: