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 5228 2006-08-09 15:11:29Z 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->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_high(jd, iptr, src->prev, REG_ITMP2);
1171 s2 = emit_load_s2_low(jd, iptr, src, EDX);
1172 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EAX_EDX_PACKED);
1174 M_INTMOVE(s1, REG_ITMP2);
1175 M_IMUL(s2, REG_ITMP2);
1177 s1 = emit_load_s1_low(jd, iptr, src->prev, EAX);
1178 s2 = emit_load_s2_high(jd, iptr, src, EDX);
1181 M_IADD(EDX, REG_ITMP2);
1183 s1 = emit_load_s1_low(jd, iptr, src->prev, EAX);
1184 s2 = emit_load_s2_low(jd, iptr, src, EDX);
1187 M_INTMOVE(EAX, GET_LOW_REG(d));
1188 M_IADD(REG_ITMP2, GET_HIGH_REG(d));
1190 emit_store(jd, iptr, iptr->dst, d);
1193 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1194 /* val.l = constant */
1196 s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP2);
1197 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EAX_EDX_PACKED);
1198 ICONST(EAX, iptr->val.l);
1200 M_IMUL_IMM(s1, iptr->val.l >> 32, REG_ITMP2);
1201 M_IADD(REG_ITMP2, EDX);
1202 s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP2);
1203 M_IMUL_IMM(s1, iptr->val.l, REG_ITMP2);
1204 M_IADD(REG_ITMP2, EDX);
1205 M_LNGMOVE(EAX_EDX_PACKED, d);
1206 emit_store(jd, iptr, iptr->dst, d);
1209 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1211 s1 = emit_load_s1(jd, iptr, src->prev, EAX);
1212 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1213 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EAX);
1218 codegen_add_arithmeticexception_ref(cd);
1221 M_INTMOVE(s1, EAX); /* we need the first operand in EAX */
1223 /* check as described in jvm spec */
1225 M_CMP_IMM(0x80000000, EAX);
1232 M_INTMOVE(EAX, d); /* if INMEMORY then d is already EAX */
1233 emit_store(jd, iptr, iptr->dst, d);
1236 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1238 s1 = emit_load_s1(jd, iptr, src->prev, EAX);
1239 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1240 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, EDX);
1245 codegen_add_arithmeticexception_ref(cd);
1248 M_INTMOVE(s1, EAX); /* we need the first operand in EAX */
1250 /* check as described in jvm spec */
1252 M_CMP_IMM(0x80000000, EAX);
1260 M_INTMOVE(EDX, d); /* if INMEMORY then d is already EDX */
1261 emit_store(jd, iptr, iptr->dst, d);
1264 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1265 /* val.i = constant */
1267 /* TODO: optimize for `/ 2' */
1268 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1269 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1273 M_IADD_IMM32((1 << iptr->val.i) - 1, d); /* 32-bit for jump off. */
1274 M_SRA_IMM(iptr->val.i, d);
1275 emit_store(jd, iptr, iptr->dst, d);
1278 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1279 /* val.i = constant */
1281 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1282 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1284 M_MOV(s1, REG_ITMP1);
1288 M_AND_IMM(iptr->val.i, d);
1290 M_BGE(2 + 2 + 6 + 2);
1291 M_MOV(s1, d); /* don't use M_INTMOVE, so we know the jump offset */
1293 M_AND_IMM32(iptr->val.i, d); /* use 32-bit for jump offset */
1295 emit_store(jd, iptr, iptr->dst, d);
1298 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1299 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1301 s2 = emit_load_s2(jd, iptr, src, REG_ITMP12_PACKED);
1302 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
1304 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
1305 M_OR(GET_HIGH_REG(s2), REG_ITMP3);
1307 codegen_add_arithmeticexception_ref(cd);
1312 M_LST(s2, REG_SP, 2 * 4);
1314 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP12_PACKED);
1315 M_LST(s1, REG_SP, 0 * 4);
1317 M_MOV_IMM(bte->fp, REG_ITMP3);
1319 emit_store(jd, iptr, iptr->dst, d);
1322 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1323 /* val.i = constant */
1325 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1326 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
1328 M_TEST(GET_HIGH_REG(d));
1330 M_IADD_IMM32((1 << iptr->val.i) - 1, GET_LOW_REG(d));
1331 M_IADDC_IMM(0, GET_HIGH_REG(d));
1332 M_SRLD_IMM(iptr->val.i, GET_HIGH_REG(d), GET_LOW_REG(d));
1333 M_SRA_IMM(iptr->val.i, GET_HIGH_REG(d));
1334 emit_store(jd, iptr, iptr->dst, d);
1338 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1339 /* val.l = constant */
1341 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1342 if (iptr->dst->flags & INMEMORY) {
1343 if (src->flags & INMEMORY) {
1344 /* Alpha algorithm */
1346 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1348 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4 + 4);
1354 /* TODO: hmm, don't know if this is always correct */
1356 CALCIMMEDIATEBYTES(disp, iptr->val.l & 0x00000000ffffffff);
1358 CALCIMMEDIATEBYTES(disp, iptr->val.l >> 32);
1364 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1365 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1367 emit_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1368 emit_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1369 emit_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, src->regoff * 4 + 4);
1370 emit_jcc(cd, CC_GE, disp);
1372 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1);
1373 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP2);
1375 emit_neg_reg(cd, REG_ITMP1);
1376 emit_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1377 emit_neg_reg(cd, REG_ITMP2);
1379 emit_alu_imm_reg(cd, ALU_AND, iptr->val.l, REG_ITMP1);
1380 emit_alu_imm_reg(cd, ALU_AND, iptr->val.l >> 32, REG_ITMP2);
1382 emit_neg_reg(cd, REG_ITMP1);
1383 emit_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2);
1384 emit_neg_reg(cd, REG_ITMP2);
1386 emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 4);
1387 emit_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 4 + 4);
1391 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1392 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
1394 M_AND_IMM(iptr->val.l, GET_LOW_REG(d));
1395 M_AND_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1396 M_TEST(GET_LOW_REG(s1));
1402 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1404 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1405 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1406 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1407 M_INTMOVE(s2, ECX); /* s2 may be equal to d */
1410 emit_store(jd, iptr, iptr->dst, d);
1413 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1414 /* val.i = constant */
1416 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1417 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1419 M_SLL_IMM(iptr->val.i, d);
1420 emit_store(jd, iptr, iptr->dst, d);
1423 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1425 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1426 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1427 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1428 M_INTMOVE(s2, ECX); /* s2 may be equal to d */
1431 emit_store(jd, iptr, iptr->dst, d);
1434 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1435 /* val.i = constant */
1437 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1438 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1440 M_SRA_IMM(iptr->val.i, d);
1441 emit_store(jd, iptr, iptr->dst, d);
1444 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1446 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1447 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1448 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1449 M_INTMOVE(s2, ECX); /* s2 may be equal to d */
1452 emit_store(jd, iptr, iptr->dst, d);
1455 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1456 /* val.i = constant */
1458 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1459 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1461 M_SRL_IMM(iptr->val.i, d);
1462 emit_store(jd, iptr, iptr->dst, d);
1465 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1467 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP13_PACKED);
1468 s2 = emit_load_s2(jd, iptr, src, ECX);
1469 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP13_PACKED);
1472 M_TEST_IMM(32, ECX);
1474 M_MOV(GET_LOW_REG(d), GET_HIGH_REG(d));
1475 M_CLR(GET_LOW_REG(d));
1476 M_SLLD(GET_LOW_REG(d), GET_HIGH_REG(d));
1477 M_SLL(GET_LOW_REG(d));
1478 emit_store(jd, iptr, iptr->dst, d);
1481 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1482 /* val.i = constant */
1484 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1485 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1487 if (iptr->val.i & 0x20) {
1488 M_MOV(GET_LOW_REG(d), GET_HIGH_REG(d));
1489 M_CLR(GET_LOW_REG(d));
1490 M_SLLD_IMM(iptr->val.i & 0x3f, GET_LOW_REG(d), GET_HIGH_REG(d));
1493 M_SLLD_IMM(iptr->val.i & 0x3f, GET_LOW_REG(d), GET_HIGH_REG(d));
1494 M_SLL_IMM(iptr->val.i & 0x3f, GET_LOW_REG(d));
1496 emit_store(jd, iptr, iptr->dst, d);
1499 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1501 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP13_PACKED);
1502 s2 = emit_load_s2(jd, iptr, src, ECX);
1503 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP13_PACKED);
1506 M_TEST_IMM(32, ECX);
1508 M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d));
1509 M_SRA_IMM(31, GET_HIGH_REG(d));
1510 M_SRLD(GET_HIGH_REG(d), GET_LOW_REG(d));
1511 M_SRA(GET_HIGH_REG(d));
1512 emit_store(jd, iptr, iptr->dst, d);
1515 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1516 /* val.i = constant */
1518 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1519 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1521 if (iptr->val.i & 0x20) {
1522 M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d));
1523 M_SRA_IMM(31, GET_HIGH_REG(d));
1524 M_SRLD_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d), GET_LOW_REG(d));
1527 M_SRLD_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d), GET_LOW_REG(d));
1528 M_SRA_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d));
1530 emit_store(jd, iptr, iptr->dst, d);
1533 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1535 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP13_PACKED);
1536 s2 = emit_load_s2(jd, iptr, src, ECX);
1537 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP13_PACKED);
1540 M_TEST_IMM(32, ECX);
1542 M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d));
1543 M_CLR(GET_HIGH_REG(d));
1544 M_SRLD(GET_HIGH_REG(d), GET_LOW_REG(d));
1545 M_SRL(GET_HIGH_REG(d));
1546 emit_store(jd, iptr, iptr->dst, d);
1549 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1550 /* val.l = constant */
1552 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1553 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1555 if (iptr->val.i & 0x20) {
1556 M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d));
1557 M_CLR(GET_HIGH_REG(d));
1558 M_SRLD_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d), GET_LOW_REG(d));
1561 M_SRLD_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d), GET_LOW_REG(d));
1562 M_SRL_IMM(iptr->val.i & 0x3f, GET_HIGH_REG(d));
1564 emit_store(jd, iptr, iptr->dst, d);
1567 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1569 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1570 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1571 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1578 emit_store(jd, iptr, iptr->dst, d);
1581 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1582 /* val.i = constant */
1584 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1585 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1587 M_AND_IMM(iptr->val.i, d);
1588 emit_store(jd, iptr, iptr->dst, d);
1591 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1593 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1594 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1595 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1596 if (s2 == GET_LOW_REG(d))
1597 M_AND(s1, GET_LOW_REG(d));
1599 M_INTMOVE(s1, GET_LOW_REG(d));
1600 M_AND(s2, GET_LOW_REG(d));
1602 /* REG_ITMP1 probably contains low 32-bit of destination */
1603 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1604 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1605 if (s2 == GET_HIGH_REG(d))
1606 M_AND(s1, GET_HIGH_REG(d));
1608 M_INTMOVE(s1, GET_HIGH_REG(d));
1609 M_AND(s2, GET_HIGH_REG(d));
1611 emit_store(jd, iptr, iptr->dst, d);
1614 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1615 /* val.l = constant */
1617 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1618 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1620 M_AND_IMM(iptr->val.l, GET_LOW_REG(d));
1621 M_AND_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1622 emit_store(jd, iptr, iptr->dst, d);
1625 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1627 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1628 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1629 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1636 emit_store(jd, iptr, iptr->dst, d);
1639 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1640 /* val.i = constant */
1642 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1643 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1645 M_OR_IMM(iptr->val.i, d);
1646 emit_store(jd, iptr, iptr->dst, d);
1649 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1651 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1652 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1653 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1654 if (s2 == GET_LOW_REG(d))
1655 M_OR(s1, GET_LOW_REG(d));
1657 M_INTMOVE(s1, GET_LOW_REG(d));
1658 M_OR(s2, GET_LOW_REG(d));
1660 /* REG_ITMP1 probably contains low 32-bit of destination */
1661 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1662 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1663 if (s2 == GET_HIGH_REG(d))
1664 M_OR(s1, GET_HIGH_REG(d));
1666 M_INTMOVE(s1, GET_HIGH_REG(d));
1667 M_OR(s2, GET_HIGH_REG(d));
1669 emit_store(jd, iptr, iptr->dst, d);
1672 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1673 /* val.l = constant */
1675 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1676 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1678 M_OR_IMM(iptr->val.l, GET_LOW_REG(d));
1679 M_OR_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1680 emit_store(jd, iptr, iptr->dst, d);
1683 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1685 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1686 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1687 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1694 emit_store(jd, iptr, iptr->dst, d);
1697 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1698 /* val.i = constant */
1700 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1701 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1703 M_XOR_IMM(iptr->val.i, d);
1704 emit_store(jd, iptr, iptr->dst, d);
1707 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1709 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
1710 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
1711 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1712 if (s2 == GET_LOW_REG(d))
1713 M_XOR(s1, GET_LOW_REG(d));
1715 M_INTMOVE(s1, GET_LOW_REG(d));
1716 M_XOR(s2, GET_LOW_REG(d));
1718 /* REG_ITMP1 probably contains low 32-bit of destination */
1719 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
1720 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
1721 if (s2 == GET_HIGH_REG(d))
1722 M_XOR(s1, GET_HIGH_REG(d));
1724 M_INTMOVE(s1, GET_HIGH_REG(d));
1725 M_XOR(s2, GET_HIGH_REG(d));
1727 emit_store(jd, iptr, iptr->dst, d);
1730 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1731 /* val.l = constant */
1733 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
1734 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP12_PACKED);
1736 M_XOR_IMM(iptr->val.l, GET_LOW_REG(d));
1737 M_XOR_IMM(iptr->val.l >> 32, GET_HIGH_REG(d));
1738 emit_store(jd, iptr, iptr->dst, d);
1741 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1742 /* op1 = variable, val.i = constant */
1744 var = &(rd->locals[iptr->op1][TYPE_INT]);
1745 if (var->flags & INMEMORY) {
1747 M_ILD(s1, REG_SP, var->regoff * 4);
1752 /* `inc reg' is slower on p4's (regarding to ia32
1753 optimization reference manual and benchmarks) and as
1754 fast on athlon's. */
1756 M_IADD_IMM(iptr->val.i, s1);
1758 if (var->flags & INMEMORY)
1759 M_IST(s1, REG_SP, var->regoff * 4);
1763 /* floating operations ************************************************/
1765 case ICMD_FNEG: /* ..., value ==> ..., - value */
1767 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1768 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1770 emit_store(jd, iptr, iptr->dst, d);
1773 case ICMD_DNEG: /* ..., value ==> ..., - value */
1775 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1776 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1778 emit_store(jd, iptr, iptr->dst, d);
1781 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1783 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1784 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1785 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1787 emit_store(jd, iptr, iptr->dst, d);
1790 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1792 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1793 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1794 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1796 emit_store(jd, iptr, iptr->dst, d);
1799 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1801 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1802 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1803 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1805 emit_store(jd, iptr, iptr->dst, d);
1808 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1810 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1811 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1812 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1814 emit_store(jd, iptr, iptr->dst, d);
1817 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1819 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1820 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1821 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1823 emit_store(jd, iptr, iptr->dst, d);
1826 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1828 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1829 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1830 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1832 emit_store(jd, iptr, iptr->dst, d);
1835 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1837 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1838 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1839 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1841 emit_store(jd, iptr, iptr->dst, d);
1844 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1846 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1847 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1848 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1850 emit_store(jd, iptr, iptr->dst, d);
1853 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1855 /* exchanged to skip fxch */
1856 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1857 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1858 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1859 /* emit_fxch(cd); */
1864 emit_jcc(cd, CC_P, -(2 + 1 + 2 + 1 + 6));
1865 emit_store(jd, iptr, iptr->dst, d);
1866 emit_ffree_reg(cd, 0);
1870 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1872 /* exchanged to skip fxch */
1873 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1874 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1875 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1876 /* emit_fxch(cd); */
1881 emit_jcc(cd, CC_P, -(2 + 1 + 2 + 1 + 6));
1882 emit_store(jd, iptr, iptr->dst, d);
1883 emit_ffree_reg(cd, 0);
1887 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1888 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1890 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1891 if (src->flags & INMEMORY) {
1892 emit_fildl_membase(cd, REG_SP, src->regoff * 4);
1895 disp = dseg_adds4(cd, 0);
1896 emit_mov_imm_reg(cd, 0, REG_ITMP1);
1898 emit_mov_reg_membase(cd, src->regoff, REG_ITMP1, disp);
1899 emit_fildl_membase(cd, REG_ITMP1, disp);
1901 emit_store(jd, iptr, iptr->dst, d);
1904 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1905 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1907 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1908 if (src->flags & INMEMORY) {
1909 emit_fildll_membase(cd, REG_SP, src->regoff * 4);
1912 log_text("L2F: longs have to be in memory");
1915 emit_store(jd, iptr, iptr->dst, d);
1918 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1920 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1921 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1923 emit_mov_imm_reg(cd, 0, REG_ITMP1);
1926 /* Round to zero, 53-bit mode, exception masked */
1927 disp = dseg_adds4(cd, 0x0e7f);
1928 emit_fldcw_membase(cd, REG_ITMP1, disp);
1930 if (iptr->dst->flags & INMEMORY) {
1931 emit_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
1933 /* Round to nearest, 53-bit mode, exceptions masked */
1934 disp = dseg_adds4(cd, 0x027f);
1935 emit_fldcw_membase(cd, REG_ITMP1, disp);
1937 emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
1940 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1942 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
1945 disp = dseg_adds4(cd, 0);
1946 emit_fistpl_membase(cd, REG_ITMP1, disp);
1947 emit_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
1949 /* Round to nearest, 53-bit mode, exceptions masked */
1950 disp = dseg_adds4(cd, 0x027f);
1951 emit_fldcw_membase(cd, REG_ITMP1, disp);
1953 emit_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
1956 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1957 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
1960 emit_jcc(cd, CC_NE, disp);
1962 /* XXX: change this when we use registers */
1963 emit_flds_membase(cd, REG_SP, src->regoff * 4);
1964 emit_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP1);
1965 emit_call_reg(cd, REG_ITMP1);
1967 if (iptr->dst->flags & INMEMORY) {
1968 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
1971 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
1975 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1977 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1978 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1980 emit_mov_imm_reg(cd, 0, REG_ITMP1);
1983 /* Round to zero, 53-bit mode, exception masked */
1984 disp = dseg_adds4(cd, 0x0e7f);
1985 emit_fldcw_membase(cd, REG_ITMP1, disp);
1987 if (iptr->dst->flags & INMEMORY) {
1988 emit_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 4);
1990 /* Round to nearest, 53-bit mode, exceptions masked */
1991 disp = dseg_adds4(cd, 0x027f);
1992 emit_fldcw_membase(cd, REG_ITMP1, disp);
1994 emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4);
1997 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
1999 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2002 disp = dseg_adds4(cd, 0);
2003 emit_fistpl_membase(cd, REG_ITMP1, disp);
2004 emit_mov_membase_reg(cd, REG_ITMP1, disp, iptr->dst->regoff);
2006 /* Round to nearest, 53-bit mode, exceptions masked */
2007 disp = dseg_adds4(cd, 0x027f);
2008 emit_fldcw_membase(cd, REG_ITMP1, disp);
2010 emit_alu_imm_reg(cd, ALU_CMP, 0x80000000, iptr->dst->regoff);
2013 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2014 disp += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2017 emit_jcc(cd, CC_NE, disp);
2019 /* XXX: change this when we use registers */
2020 emit_fldl_membase(cd, REG_SP, src->regoff * 4);
2021 emit_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP1);
2022 emit_call_reg(cd, REG_ITMP1);
2024 if (iptr->dst->flags & INMEMORY) {
2025 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2027 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2031 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2033 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2034 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2036 emit_mov_imm_reg(cd, 0, REG_ITMP1);
2039 /* Round to zero, 53-bit mode, exception masked */
2040 disp = dseg_adds4(cd, 0x0e7f);
2041 emit_fldcw_membase(cd, REG_ITMP1, disp);
2043 if (iptr->dst->flags & INMEMORY) {
2044 emit_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2046 /* Round to nearest, 53-bit mode, exceptions masked */
2047 disp = dseg_adds4(cd, 0x027f);
2048 emit_fldcw_membase(cd, REG_ITMP1, disp);
2050 emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2053 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2055 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2058 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2060 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2062 emit_jcc(cd, CC_NE, disp);
2064 emit_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2067 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2069 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2071 emit_jcc(cd, CC_NE, disp);
2073 /* XXX: change this when we use registers */
2074 emit_flds_membase(cd, REG_SP, src->regoff * 4);
2075 emit_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP1);
2076 emit_call_reg(cd, REG_ITMP1);
2077 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2078 emit_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2081 log_text("F2L: longs have to be in memory");
2086 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2088 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2089 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
2091 emit_mov_imm_reg(cd, 0, REG_ITMP1);
2094 /* Round to zero, 53-bit mode, exception masked */
2095 disp = dseg_adds4(cd, 0x0e7f);
2096 emit_fldcw_membase(cd, REG_ITMP1, disp);
2098 if (iptr->dst->flags & INMEMORY) {
2099 emit_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 4);
2101 /* Round to nearest, 53-bit mode, exceptions masked */
2102 disp = dseg_adds4(cd, 0x027f);
2103 emit_fldcw_membase(cd, REG_ITMP1, disp);
2105 emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 4 + 4);
2108 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2110 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2113 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2115 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4 + 4);
2117 emit_jcc(cd, CC_NE, disp);
2119 emit_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->dst->regoff * 4);
2122 CALCOFFSETBYTES(disp, REG_SP, src->regoff * 4);
2124 CALCOFFSETBYTES(disp, REG_SP, iptr->dst->regoff * 4);
2126 emit_jcc(cd, CC_NE, disp);
2128 /* XXX: change this when we use registers */
2129 emit_fldl_membase(cd, REG_SP, src->regoff * 4);
2130 emit_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP1);
2131 emit_call_reg(cd, REG_ITMP1);
2132 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4);
2133 emit_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4);
2136 log_text("D2L: longs have to be in memory");
2141 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2143 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2144 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2146 emit_store(jd, iptr, iptr->dst, d);
2149 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2151 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
2152 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2154 emit_store(jd, iptr, iptr->dst, d);
2157 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2160 /* exchanged to skip fxch */
2161 s2 = emit_load_s2(jd, iptr, src->prev, REG_FTMP1);
2162 s1 = emit_load_s1(jd, iptr, src, REG_FTMP2);
2163 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2164 /* emit_fxch(cd); */
2167 emit_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2168 emit_jcc(cd, CC_E, 6);
2169 emit_alu_imm_reg(cd, ALU_AND, 0x000000ff, EAX);
2171 emit_mov_imm_reg(cd, 0, d); /* does not affect flags */
2172 emit_jcc(cd, CC_E, 6 + 3 + 5 + 3);
2173 emit_jcc(cd, CC_B, 3 + 5);
2174 emit_alu_imm_reg(cd, ALU_SUB, 1, d);
2175 emit_jmp_imm(cd, 3);
2176 emit_alu_imm_reg(cd, ALU_ADD, 1, d);
2177 emit_store(jd, iptr, iptr->dst, d);
2180 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2183 /* exchanged to skip fxch */
2184 s2 = emit_load_s2(jd, iptr, src->prev, REG_FTMP1);
2185 s1 = emit_load_s1(jd, iptr, src, REG_FTMP2);
2186 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2187 /* emit_fxch(cd); */
2190 emit_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2191 emit_jcc(cd, CC_E, 3);
2192 emit_movb_imm_reg(cd, 1, REG_AH);
2194 emit_mov_imm_reg(cd, 0, d); /* does not affect flags */
2195 emit_jcc(cd, CC_E, 6 + 3 + 5 + 3);
2196 emit_jcc(cd, CC_B, 3 + 5);
2197 emit_alu_imm_reg(cd, ALU_SUB, 1, d);
2198 emit_jmp_imm(cd, 3);
2199 emit_alu_imm_reg(cd, ALU_ADD, 1, d);
2200 emit_store(jd, iptr, iptr->dst, d);
2204 /* memory operations **************************************************/
2206 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2208 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2209 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2210 gen_nullptr_check(s1);
2211 M_ILD(d, s1, OFFSET(java_arrayheader, size));
2212 emit_store(jd, iptr, iptr->dst, d);
2215 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2217 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2218 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2219 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2220 if (iptr->op1 == 0) {
2221 gen_nullptr_check(s1);
2224 emit_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2225 emit_store(jd, iptr, iptr->dst, d);
2228 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2230 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2231 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2232 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2233 if (iptr->op1 == 0) {
2234 gen_nullptr_check(s1);
2237 emit_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2238 emit_store(jd, iptr, iptr->dst, d);
2241 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2243 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2244 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2245 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2246 if (iptr->op1 == 0) {
2247 gen_nullptr_check(s1);
2250 emit_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2251 emit_store(jd, iptr, iptr->dst, d);
2254 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2256 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2257 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2258 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2259 if (iptr->op1 == 0) {
2260 gen_nullptr_check(s1);
2263 emit_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2264 emit_store(jd, iptr, iptr->dst, d);
2267 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2269 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2270 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2271 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2272 if (iptr->op1 == 0) {
2273 gen_nullptr_check(s1);
2276 assert(iptr->dst->flags & INMEMORY);
2277 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2278 emit_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4);
2279 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2280 emit_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 4 + 4);
2283 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2285 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2286 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2287 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2288 if (iptr->op1 == 0) {
2289 gen_nullptr_check(s1);
2292 emit_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2293 emit_store(jd, iptr, iptr->dst, d);
2296 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2298 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2299 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2300 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2301 if (iptr->op1 == 0) {
2302 gen_nullptr_check(s1);
2305 emit_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2306 emit_store(jd, iptr, iptr->dst, d);
2309 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2311 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2312 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2313 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2314 if (iptr->op1 == 0) {
2315 gen_nullptr_check(s1);
2318 emit_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2319 emit_store(jd, iptr, iptr->dst, d);
2323 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2325 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2326 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2327 if (iptr->op1 == 0) {
2328 gen_nullptr_check(s1);
2331 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2332 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2333 M_INTMOVE(s3, REG_ITMP3);
2336 emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2339 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2341 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2342 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2343 if (iptr->op1 == 0) {
2344 gen_nullptr_check(s1);
2347 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2348 emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2351 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2353 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2354 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2355 if (iptr->op1 == 0) {
2356 gen_nullptr_check(s1);
2359 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2360 emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2363 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2365 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2366 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2367 if (iptr->op1 == 0) {
2368 gen_nullptr_check(s1);
2371 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2372 emit_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2375 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2377 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2378 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2379 if (iptr->op1 == 0) {
2380 gen_nullptr_check(s1);
2383 assert(src->flags & INMEMORY);
2384 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP3);
2385 emit_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2386 emit_mov_membase_reg(cd, REG_SP, src->regoff * 4 + 4, REG_ITMP3);
2387 emit_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2390 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2392 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2393 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2394 if (iptr->op1 == 0) {
2395 gen_nullptr_check(s1);
2398 s3 = emit_load_s3(jd, iptr, src, REG_FTMP1);
2399 emit_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2402 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2404 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2405 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2406 if (iptr->op1 == 0) {
2407 gen_nullptr_check(s1);
2410 s3 = emit_load_s3(jd, iptr, src, REG_FTMP1);
2411 emit_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2414 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2416 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2417 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2418 if (iptr->op1 == 0) {
2419 gen_nullptr_check(s1);
2422 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2424 M_AST(s1, REG_SP, 0 * 4);
2425 M_AST(s3, REG_SP, 1 * 4);
2426 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
2430 codegen_add_arraystoreexception_ref(cd);
2432 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2433 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2434 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2435 emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2438 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2440 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2441 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2442 if (iptr->op1 == 0) {
2443 gen_nullptr_check(s1);
2446 emit_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2449 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2451 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2452 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2453 if (iptr->op1 == 0) {
2454 gen_nullptr_check(s1);
2457 emit_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2460 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2462 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2463 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2464 if (iptr->op1 == 0) {
2465 gen_nullptr_check(s1);
2468 emit_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2471 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2473 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2474 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2475 if (iptr->op1 == 0) {
2476 gen_nullptr_check(s1);
2479 emit_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2482 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2484 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2485 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2486 if (iptr->op1 == 0) {
2487 gen_nullptr_check(s1);
2490 emit_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2491 emit_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2494 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2496 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2497 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2498 if (iptr->op1 == 0) {
2499 gen_nullptr_check(s1);
2502 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2506 case ICMD_GETSTATIC: /* ... ==> ..., value */
2507 /* op1 = type, val.a = field address */
2509 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2510 codegen_addpatchref(cd, PATCHER_get_putstatic,
2511 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2513 if (opt_showdisassemble) {
2514 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2521 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2523 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2524 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2526 if (opt_showdisassemble) {
2527 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2531 disp = (ptrint) &(fi->value);
2534 M_MOV_IMM(disp, REG_ITMP1);
2535 switch (iptr->op1) {
2538 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
2539 M_ILD(d, REG_ITMP1, 0);
2542 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP23_PACKED);
2543 M_LLD(d, REG_ITMP1, 0);
2546 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2547 M_FLD(d, REG_ITMP1, 0);
2550 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2551 M_DLD(d, REG_ITMP1, 0);
2554 emit_store(jd, iptr, iptr->dst, d);
2557 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2558 /* op1 = type, val.a = field address */
2560 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2561 codegen_addpatchref(cd, PATCHER_get_putstatic,
2562 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2564 if (opt_showdisassemble) {
2565 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2572 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2574 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2575 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2577 if (opt_showdisassemble) {
2578 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2582 disp = (ptrint) &(fi->value);
2585 M_MOV_IMM(disp, REG_ITMP1);
2586 switch (iptr->op1) {
2589 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2590 M_IST(s2, REG_ITMP1, 0);
2593 s2 = emit_load_s2(jd, iptr, src, REG_ITMP23_PACKED);
2594 M_LST(s2, REG_ITMP1, 0);
2597 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
2598 emit_fstps_membase(cd, REG_ITMP1, 0);
2601 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
2602 emit_fstpl_membase(cd, REG_ITMP1, 0);
2607 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2608 /* val = value (in current instruction) */
2609 /* op1 = type, val.a = field address (in */
2610 /* following NOP) */
2612 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2613 codegen_addpatchref(cd, PATCHER_get_putstatic,
2614 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
2616 if (opt_showdisassemble) {
2617 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2624 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1);
2626 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2627 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2629 if (opt_showdisassemble) {
2630 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2634 disp = (ptrint) &(fi->value);
2637 M_MOV_IMM(disp, REG_ITMP1);
2638 switch (iptr[1].op1) {
2642 M_IST_IMM(iptr->val.i, REG_ITMP1, 0);
2646 M_LST_IMM(iptr->val.l, REG_ITMP1, 0);
2651 case ICMD_GETFIELD: /* .., objectref. ==> ..., value */
2652 /* op1 = type, val.i = field offset */
2654 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2655 gen_nullptr_check(s1);
2657 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2658 codegen_addpatchref(cd, PATCHER_getfield,
2659 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2661 if (opt_showdisassemble) {
2662 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2669 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2671 switch (iptr->op1) {
2674 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
2675 M_ILD32(d, s1, disp);
2678 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP23_PACKED);
2679 M_LLD32(d, s1, disp);
2682 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2683 M_FLD32(d, s1, disp);
2686 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2687 M_DLD32(d, s1, disp);
2690 emit_store(jd, iptr, iptr->dst, d);
2693 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2694 /* op1 = type, val.a = field address */
2696 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2697 gen_nullptr_check(s1);
2699 /* must be done here because of code patching */
2701 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2702 if (IS_2_WORD_TYPE(iptr->op1))
2703 s2 = emit_load_s2(jd, iptr, src, REG_ITMP23_PACKED);
2705 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2708 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2710 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2711 codegen_addpatchref(cd, PATCHER_putfield,
2712 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2714 if (opt_showdisassemble) {
2715 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2722 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2724 switch (iptr->op1) {
2727 M_IST32(s2, s1, disp);
2730 M_LST32(s2, s1, disp);
2733 emit_fstps_membase32(cd, s1, disp);
2736 emit_fstpl_membase32(cd, s1, disp);
2741 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2742 /* val = value (in current instruction) */
2743 /* op1 = type, val.a = field address (in */
2744 /* following NOP) */
2746 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2747 gen_nullptr_check(s1);
2749 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2750 codegen_addpatchref(cd, PATCHER_putfieldconst,
2751 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
2753 if (opt_showdisassemble) {
2754 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2761 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1)->offset;
2763 switch (iptr[1].op1) {
2767 M_IST32_IMM(iptr->val.i, s1, disp);
2771 M_LST32_IMM(iptr->val.l, s1, disp);
2777 /* branch operations **************************************************/
2779 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2781 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2782 M_INTMOVE(s1, REG_ITMP1_XPTR);
2784 #ifdef ENABLE_VERIFIER
2786 codegen_addpatchref(cd, PATCHER_athrow_areturn,
2787 (unresolved_class *) iptr->val.a, 0);
2789 if (opt_showdisassemble) {
2790 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2793 #endif /* ENABLE_VERIFIER */
2795 M_CALL_IMM(0); /* passing exception pc */
2796 M_POP(REG_ITMP2_XPC);
2798 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
2802 case ICMD_INLINE_GOTO:
2804 M_COPY(src, iptr->dst);
2807 case ICMD_GOTO: /* ... ==> ... */
2808 /* op1 = target JavaVM pc */
2811 codegen_addreference(cd, (basicblock *) iptr->target);
2815 case ICMD_JSR: /* ... ==> ... */
2816 /* op1 = target JavaVM pc */
2819 codegen_addreference(cd, (basicblock *) iptr->target);
2822 case ICMD_RET: /* ... ==> ... */
2823 /* op1 = local variable */
2825 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2826 if (var->flags & INMEMORY) {
2827 M_ALD(REG_ITMP1, REG_SP, var->regoff * 4);
2834 case ICMD_IFNULL: /* ..., value ==> ... */
2835 /* op1 = target JavaVM pc */
2837 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2840 codegen_addreference(cd, (basicblock *) iptr->target);
2843 case ICMD_IFNONNULL: /* ..., value ==> ... */
2844 /* op1 = target JavaVM pc */
2846 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2849 codegen_addreference(cd, (basicblock *) iptr->target);
2852 case ICMD_IFEQ: /* ..., value ==> ... */
2853 /* op1 = target JavaVM pc, val.i = constant */
2855 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2856 M_CMP_IMM(iptr->val.i, s1);
2858 codegen_addreference(cd, (basicblock *) iptr->target);
2861 case ICMD_IFLT: /* ..., value ==> ... */
2862 /* op1 = target JavaVM pc, val.i = constant */
2864 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2865 M_CMP_IMM(iptr->val.i, s1);
2867 codegen_addreference(cd, (basicblock *) iptr->target);
2870 case ICMD_IFLE: /* ..., value ==> ... */
2871 /* op1 = target JavaVM pc, val.i = constant */
2873 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2874 M_CMP_IMM(iptr->val.i, s1);
2876 codegen_addreference(cd, (basicblock *) iptr->target);
2879 case ICMD_IFNE: /* ..., value ==> ... */
2880 /* op1 = target JavaVM pc, val.i = constant */
2882 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2883 M_CMP_IMM(iptr->val.i, s1);
2885 codegen_addreference(cd, (basicblock *) iptr->target);
2888 case ICMD_IFGT: /* ..., value ==> ... */
2889 /* op1 = target JavaVM pc, val.i = constant */
2891 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2892 M_CMP_IMM(iptr->val.i, s1);
2894 codegen_addreference(cd, (basicblock *) iptr->target);
2897 case ICMD_IFGE: /* ..., value ==> ... */
2898 /* op1 = target JavaVM pc, val.i = constant */
2900 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2901 M_CMP_IMM(iptr->val.i, s1);
2903 codegen_addreference(cd, (basicblock *) iptr->target);
2906 case ICMD_IF_LEQ: /* ..., value ==> ... */
2907 /* op1 = target JavaVM pc, val.l = constant */
2909 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
2910 if (iptr->val.l == 0) {
2911 M_INTMOVE(GET_LOW_REG(s1), REG_ITMP1);
2912 M_OR(GET_HIGH_REG(s1), REG_ITMP1);
2915 M_LNGMOVE(s1, REG_ITMP12_PACKED);
2916 M_XOR_IMM(iptr->val.l, REG_ITMP1);
2917 M_XOR_IMM(iptr->val.l >> 32, REG_ITMP2);
2918 M_OR(REG_ITMP2, REG_ITMP1);
2921 codegen_addreference(cd, (basicblock *) iptr->target);
2924 case ICMD_IF_LLT: /* ..., value ==> ... */
2925 /* op1 = target JavaVM pc, val.l = constant */
2927 if (iptr->val.l == 0) {
2928 /* If high 32-bit are less than zero, then the 64-bits
2930 s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP2);
2935 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
2936 M_CMP_IMM(iptr->val.l >> 32, GET_HIGH_REG(s1));
2938 codegen_addreference(cd, (basicblock *) iptr->target);
2940 M_CMP_IMM32(iptr->val.l, GET_LOW_REG(s1));
2943 codegen_addreference(cd, (basicblock *) iptr->target);
2946 case ICMD_IF_LLE: /* ..., value ==> ... */
2947 /* op1 = target JavaVM pc, val.l = constant */
2949 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
2950 M_CMP_IMM(iptr->val.l >> 32, GET_HIGH_REG(s1));
2952 codegen_addreference(cd, (basicblock *) iptr->target);
2954 M_CMP_IMM32(iptr->val.l, GET_LOW_REG(s1));
2956 codegen_addreference(cd, (basicblock *) iptr->target);
2959 case ICMD_IF_LNE: /* ..., value ==> ... */
2960 /* op1 = target JavaVM pc, val.l = constant */
2962 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
2963 if (iptr->val.l == 0) {
2964 M_INTMOVE(GET_LOW_REG(s1), REG_ITMP1);
2965 M_OR(GET_HIGH_REG(s1), REG_ITMP1);
2968 M_LNGMOVE(s1, REG_ITMP12_PACKED);
2969 M_XOR_IMM(iptr->val.l, REG_ITMP1);
2970 M_XOR_IMM(iptr->val.l >> 32, REG_ITMP2);
2971 M_OR(REG_ITMP2, REG_ITMP1);
2974 codegen_addreference(cd, (basicblock *) iptr->target);
2977 case ICMD_IF_LGT: /* ..., value ==> ... */
2978 /* op1 = target JavaVM pc, val.l = constant */
2980 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
2981 M_CMP_IMM(iptr->val.l >> 32, GET_HIGH_REG(s1));
2983 codegen_addreference(cd, (basicblock *) iptr->target);
2985 M_CMP_IMM32(iptr->val.l, GET_LOW_REG(s1));
2987 codegen_addreference(cd, (basicblock *) iptr->target);
2990 case ICMD_IF_LGE: /* ..., value ==> ... */
2991 /* op1 = target JavaVM pc, val.l = constant */
2993 if (iptr->val.l == 0) {
2994 /* If high 32-bit are greater equal zero, then the
2996 s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP2);
3001 s1 = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
3002 M_CMP_IMM(iptr->val.l >> 32, GET_HIGH_REG(s1));
3004 codegen_addreference(cd, (basicblock *) iptr->target);
3006 M_CMP_IMM32(iptr->val.l, GET_LOW_REG(s1));
3009 codegen_addreference(cd, (basicblock *) iptr->target);
3012 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3013 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3015 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3016 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3019 codegen_addreference(cd, (basicblock *) iptr->target);
3022 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3023 /* op1 = target JavaVM pc */
3025 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3026 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3027 M_INTMOVE(s1, REG_ITMP1);
3028 M_XOR(s2, REG_ITMP1);
3029 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
3030 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
3031 M_INTMOVE(s1, REG_ITMP2);
3032 M_XOR(s2, REG_ITMP2);
3033 M_OR(REG_ITMP1, REG_ITMP2);
3035 codegen_addreference(cd, (basicblock *) iptr->target);
3038 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3039 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3041 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3042 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3045 codegen_addreference(cd, (basicblock *) iptr->target);
3048 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3049 /* op1 = target JavaVM pc */
3051 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3052 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3053 M_INTMOVE(s1, REG_ITMP1);
3054 M_XOR(s2, REG_ITMP1);
3055 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP2);
3056 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);
3057 M_INTMOVE(s1, REG_ITMP2);
3058 M_XOR(s2, REG_ITMP2);
3059 M_OR(REG_ITMP1, REG_ITMP2);
3061 codegen_addreference(cd, (basicblock *) iptr->target);
3064 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3065 /* op1 = target JavaVM pc */
3067 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3068 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3071 codegen_addreference(cd, (basicblock *) iptr->target);
3074 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3075 /* op1 = target JavaVM pc */
3077 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
3078 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
3081 codegen_addreference(cd, (basicblock *) iptr->target);
3082 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3083 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3087 codegen_addreference(cd, (basicblock *) iptr->target);
3090 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3091 /* op1 = target JavaVM pc */
3093 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3094 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3097 codegen_addreference(cd, (basicblock *) iptr->target);
3100 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3101 /* op1 = target JavaVM pc */
3103 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
3104 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
3107 codegen_addreference(cd, (basicblock *) iptr->target);
3108 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3109 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3113 codegen_addreference(cd, (basicblock *) iptr->target);
3116 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3117 /* op1 = target JavaVM pc */
3119 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3120 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3123 codegen_addreference(cd, (basicblock *) iptr->target);
3126 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3127 /* op1 = target JavaVM pc */
3129 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
3130 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
3133 codegen_addreference(cd, (basicblock *) iptr->target);
3134 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3135 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3139 codegen_addreference(cd, (basicblock *) iptr->target);
3142 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3143 /* op1 = target JavaVM pc */
3145 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
3146 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
3149 codegen_addreference(cd, (basicblock *) iptr->target);
3152 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3153 /* op1 = target JavaVM pc */
3155 s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
3156 s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
3159 codegen_addreference(cd, (basicblock *) iptr->target);
3160 s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
3161 s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
3165 codegen_addreference(cd, (basicblock *) iptr->target);
3169 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3171 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
3172 M_INTMOVE(s1, REG_RESULT);
3173 goto nowperformreturn;
3175 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3177 s1 = emit_load_s1(jd, iptr, src, REG_RESULT_PACKED);
3178 M_LNGMOVE(s1, REG_RESULT_PACKED);
3179 goto nowperformreturn;
3181 case ICMD_ARETURN: /* ..., retvalue ==> ... */
3183 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
3184 M_INTMOVE(s1, REG_RESULT);
3186 #ifdef ENABLE_VERIFIER
3188 codegen_addpatchref(cd, PATCHER_athrow_areturn,
3189 (unresolved_class *) iptr->val.a, 0);
3191 if (opt_showdisassemble) {
3192 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3195 #endif /* ENABLE_VERIFIER */
3196 goto nowperformreturn;
3198 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3201 s1 = emit_load_s1(jd, iptr, src, REG_FRESULT);
3202 goto nowperformreturn;
3204 case ICMD_RETURN: /* ... ==> ... */
3212 #if !defined(NDEBUG)
3213 /* call trace function */
3215 if (opt_verbosecall) {
3216 M_ISUB_IMM(4 + 8 + 8 + 4, REG_SP);
3218 emit_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3220 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3221 emit_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3223 emit_fstl_membase(cd, REG_SP, 4 + 8);
3224 emit_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3226 emit_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3227 emit_call_reg(cd, REG_ITMP1);
3229 emit_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3230 emit_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3232 emit_alu_imm_reg(cd, ALU_ADD, 4 + 8 + 8 + 4, REG_SP);
3234 #endif /* !defined(NDEBUG) */
3236 #if defined(ENABLE_THREADS)
3237 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3238 M_ALD(REG_ITMP2, REG_SP, rd->memuse * 4);
3240 /* we need to save the proper return value */
3241 switch (iptr->opc) {
3244 M_IST(REG_RESULT, REG_SP, rd->memuse * 4);
3248 M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 4);
3252 emit_fstps_membase(cd, REG_SP, rd->memuse * 4);
3256 emit_fstpl_membase(cd, REG_SP, rd->memuse * 4);
3260 M_AST(REG_ITMP2, REG_SP, 0);
3261 M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3);
3264 /* and now restore the proper return value */
3265 switch (iptr->opc) {
3268 M_ILD(REG_RESULT, REG_SP, rd->memuse * 4);
3272 M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 4);
3276 emit_flds_membase(cd, REG_SP, rd->memuse * 4);
3280 emit_fldl_membase(cd, REG_SP, rd->memuse * 4);
3286 /* restore saved registers */
3288 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
3289 p--; M_ALD(rd->savintregs[i], REG_SP, p * 4);
3292 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
3294 emit_fldl_membase(cd, REG_SP, p * 4);
3295 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3297 /* emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1); */
3300 /* emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset); */
3304 /* deallocate stack */
3307 M_AADD_IMM(stackframesize * 4, REG_SP);
3314 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3319 tptr = (void **) iptr->target;
3321 s4ptr = iptr->val.a;
3322 l = s4ptr[1]; /* low */
3323 i = s4ptr[2]; /* high */
3325 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3326 M_INTMOVE(s1, REG_ITMP1);
3329 M_ISUB_IMM(l, REG_ITMP1);
3335 M_CMP_IMM(i - 1, REG_ITMP1);
3337 codegen_addreference(cd, (basicblock *) tptr[0]);
3339 /* build jump table top down and use address of lowest entry */
3344 dseg_addtarget(cd, (basicblock *) tptr[0]);
3348 /* length of dataseg after last dseg_addtarget is used
3351 M_MOV_IMM(0, REG_ITMP2);
3353 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3359 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3361 s4 i, l, val, *s4ptr;
3364 tptr = (void **) iptr->target;
3366 s4ptr = iptr->val.a;
3367 l = s4ptr[0]; /* default */
3368 i = s4ptr[1]; /* count */
3370 MCODECHECK((i<<2)+8);
3371 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3380 codegen_addreference(cd, (basicblock *) tptr[0]);
3385 tptr = (void **) iptr->target;
3386 codegen_addreference(cd, (basicblock *) tptr[0]);
3390 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
3391 /* op1 = arg count val.a = builtintable entry */
3397 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3398 /* op1 = arg count, val.a = method pointer */
3400 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3401 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
3402 case ICMD_INVOKEINTERFACE:
3404 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3405 md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
3409 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
3410 md = lm->parseddesc;
3414 s3 = md->paramcount;
3416 MCODECHECK((s3 << 1) + 64);
3418 /* copy arguments to registers or stack location */
3420 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
3421 if (src->varkind == ARGVAR)
3423 if (IS_INT_LNG_TYPE(src->type)) {
3424 if (!md->params[s3].inmemory) {
3425 log_text("No integer argument registers available!");
3429 if (IS_2_WORD_TYPE(src->type)) {
3430 d = emit_load_s1(jd, iptr, src, REG_ITMP12_PACKED);
3431 M_LST(d, REG_SP, md->params[s3].regoff * 4);
3433 d = emit_load_s1(jd, iptr, src, REG_ITMP1);
3434 M_IST(d, REG_SP, md->params[s3].regoff * 4);
3439 if (!md->params[s3].inmemory) {
3440 s1 = rd->argfltregs[md->params[s3].regoff];
3441 d = emit_load_s1(jd, iptr, src, s1);
3445 d = emit_load_s1(jd, iptr, src, REG_FTMP1);
3446 if (IS_2_WORD_TYPE(src->type))
3447 M_DST(d, REG_SP, md->params[s3].regoff * 4);
3449 M_FST(d, REG_SP, md->params[s3].regoff * 4);
3454 switch (iptr->opc) {
3456 disp = (ptrint) bte->fp;
3457 d = md->returntype.type;
3459 M_MOV_IMM(disp, REG_ITMP1);
3462 /* if op1 == true, we need to check for an exception */
3464 if (iptr->op1 == true) {
3467 codegen_add_fillinstacktrace_ref(cd);
3471 case ICMD_INVOKESPECIAL:
3472 M_ALD(REG_ITMP1, REG_SP, 0);
3475 codegen_add_nullpointerexception_ref(cd);
3479 case ICMD_INVOKESTATIC:
3481 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3483 codegen_addpatchref(cd, PATCHER_invokestatic_special,
3486 if (opt_showdisassemble) {
3487 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3491 d = md->returntype.type;
3494 disp = (ptrint) lm->stubroutine;
3495 d = lm->parseddesc->returntype.type;
3498 M_MOV_IMM(disp, REG_ITMP2);
3502 case ICMD_INVOKEVIRTUAL:
3503 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
3504 gen_nullptr_check(REG_ITMP1);
3507 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3509 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
3511 if (opt_showdisassemble) {
3512 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3516 d = md->returntype.type;
3519 s1 = OFFSET(vftbl_t, table[0]) +
3520 sizeof(methodptr) * lm->vftblindex;
3521 d = md->returntype.type;
3524 M_ALD(REG_METHODPTR, REG_ITMP1,
3525 OFFSET(java_objectheader, vftbl));
3526 M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
3530 case ICMD_INVOKEINTERFACE:
3531 M_ALD(REG_ITMP1, REG_SP, 0 * 4);
3532 gen_nullptr_check(REG_ITMP1);
3535 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3537 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
3539 if (opt_showdisassemble) {
3540 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3545 d = md->returntype.type;
3548 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3549 sizeof(methodptr) * lm->class->index;
3551 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3553 d = md->returntype.type;
3556 M_ALD(REG_METHODPTR, REG_ITMP1,
3557 OFFSET(java_objectheader, vftbl));
3558 M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
3559 M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
3564 /* d contains return type */
3566 if (d != TYPE_VOID) {
3567 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3568 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3569 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_PACKED);
3570 M_LNGMOVE(REG_RESULT_PACKED, s1);
3573 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3574 M_INTMOVE(REG_RESULT, s1);
3578 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
3580 emit_store(jd, iptr, iptr->dst, s1);
3585 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3586 /* op1: 0 == array, 1 == class */
3587 /* val.a: (classinfo*) superclass */
3589 /* superclass is an interface:
3591 * OK if ((sub == NULL) ||
3592 * (sub->vftbl->interfacetablelength > super->index) &&
3593 * (sub->vftbl->interfacetable[-super->index] != NULL));
3595 * superclass is a class:
3597 * OK if ((sub == NULL) || (0
3598 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3599 * super->vftbl->diffval));
3602 if (iptr->op1 == 1) {
3603 /* object type cast-check */
3606 vftbl_t *supervftbl;
3609 super = (classinfo *) iptr->val.a;
3616 superindex = super->index;
3617 supervftbl = super->vftbl;
3620 #if defined(ENABLE_THREADS)
3621 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3623 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3625 /* calculate interface checkcast code size */
3627 s2 = 2; /* mov_membase_reg */
3628 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3630 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ +
3631 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
3632 2 /* test */ + 6 /* jcc */);
3635 s2 += (opt_showdisassemble ? 5 : 0);
3637 /* calculate class checkcast code size */
3639 s3 = 2; /* mov_membase_reg */
3640 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3642 s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */;
3645 if (s1 != REG_ITMP1) {
3647 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
3650 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
3657 s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ +
3658 5 /* mov_imm_reg */ + 2 /* mov_membase_reg */);
3659 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3662 s3 += 2 /* cmp */ + 6 /* jcc */;
3665 s3 += (opt_showdisassemble ? 5 : 0);
3667 /* if class is not resolved, check which code to call */
3669 if (super == NULL) {
3671 M_BEQ(5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
3673 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3674 (constant_classref *) iptr->target, 0);
3676 if (opt_showdisassemble) {
3677 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3680 M_MOV_IMM(0, REG_ITMP2); /* super->flags */
3681 M_AND_IMM32(ACC_INTERFACE, REG_ITMP2);
3685 /* interface checkcast code */
3687 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3688 if (super != NULL) {
3693 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3695 if (super == NULL) {
3696 codegen_addpatchref(cd,
3697 PATCHER_checkcast_instanceof_interface,
3698 (constant_classref *) iptr->target,
3701 if (opt_showdisassemble) {
3702 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3707 REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3708 M_ISUB_IMM32(superindex, REG_ITMP3);
3711 codegen_add_classcastexception_ref(cd, s1);
3712 M_ALD32(REG_ITMP3, REG_ITMP2,
3713 OFFSET(vftbl_t, interfacetable[0]) -
3714 superindex * sizeof(methodptr*));
3717 codegen_add_classcastexception_ref(cd, s1);
3723 /* class checkcast code */
3725 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3726 if (super != NULL) {
3731 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3733 if (super == NULL) {
3734 codegen_addpatchref(cd, PATCHER_checkcast_class,
3735 (constant_classref *) iptr->target,
3738 if (opt_showdisassemble) {
3739 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3743 M_MOV_IMM(supervftbl, REG_ITMP3);
3744 #if defined(ENABLE_THREADS)
3745 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3747 M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3749 /* if (s1 != REG_ITMP1) { */
3750 /* emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
3751 /* emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
3752 /* #if defined(ENABLE_THREADS) */
3753 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
3755 /* emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
3758 M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3759 M_ISUB(REG_ITMP3, REG_ITMP2);
3760 M_MOV_IMM(supervftbl, REG_ITMP3);
3761 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3762 #if defined(ENABLE_THREADS)
3763 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3767 M_CMP(REG_ITMP3, REG_ITMP2);
3768 M_BA(0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
3769 codegen_add_classcastexception_ref(cd, s1);
3772 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
3775 /* array type cast-check */
3777 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
3778 M_AST(s1, REG_SP, 0 * 4);
3780 if (iptr->val.a == NULL) {
3781 codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
3784 if (opt_showdisassemble) {
3785 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3789 M_AST_IMM(iptr->val.a, REG_SP, 1 * 4);
3790 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP3);
3793 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
3796 codegen_add_classcastexception_ref(cd, s1);
3798 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
3802 emit_store(jd, iptr, iptr->dst, d);
3805 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3806 /* op1: 0 == array, 1 == class */
3807 /* val.a: (classinfo*) superclass */
3809 /* superclass is an interface:
3811 * return (sub != NULL) &&
3812 * (sub->vftbl->interfacetablelength > super->index) &&
3813 * (sub->vftbl->interfacetable[-super->index] != NULL);
3815 * superclass is a class:
3817 * return ((sub != NULL) && (0
3818 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3819 * super->vftbl->diffvall));
3824 vftbl_t *supervftbl;
3827 super = (classinfo *) iptr->val.a;
3834 superindex = super->index;
3835 supervftbl = super->vftbl;
3838 #if defined(ENABLE_THREADS)
3839 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3842 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3843 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3845 M_INTMOVE(s1, REG_ITMP1);
3849 /* calculate interface instanceof code size */
3851 s2 = 2; /* mov_membase_reg */
3852 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3854 s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
3855 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
3856 2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
3859 s2 += (opt_showdisassemble ? 5 : 0);
3861 /* calculate class instanceof code size */
3863 s3 = 2; /* mov_membase_reg */
3864 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3865 s3 += 5; /* mov_imm_reg */
3867 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
3869 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3871 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3873 s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
3874 2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
3877 s3 += (opt_showdisassemble ? 5 : 0);
3881 /* if class is not resolved, check which code to call */
3885 M_BEQ(5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
3887 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3888 (constant_classref *) iptr->target, 0);
3890 if (opt_showdisassemble) {
3891 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3894 M_MOV_IMM(0, REG_ITMP3); /* super->flags */
3895 M_AND_IMM32(ACC_INTERFACE, REG_ITMP3);
3899 /* interface instanceof code */
3901 if (!super || (super->flags & ACC_INTERFACE)) {
3907 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3910 codegen_addpatchref(cd,
3911 PATCHER_checkcast_instanceof_interface,
3912 (constant_classref *) iptr->target, 0);
3914 if (opt_showdisassemble) {
3915 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3920 REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3921 M_ISUB_IMM32(superindex, REG_ITMP3);
3924 disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
3925 6 /* jcc */ + 5 /* mov_imm_reg */);
3928 M_ALD32(REG_ITMP1, REG_ITMP1,
3929 OFFSET(vftbl_t, interfacetable[0]) -
3930 superindex * sizeof(methodptr*));
3932 /* emit_setcc_reg(cd, CC_A, d); */
3933 /* emit_jcc(cd, CC_BE, 5); */
3941 /* class instanceof code */
3943 if (!super || !(super->flags & ACC_INTERFACE)) {
3949 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3952 codegen_addpatchref(cd, PATCHER_instanceof_class,
3953 (constant_classref *) iptr->target, 0);
3955 if (opt_showdisassemble) {
3956 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3960 M_MOV_IMM(supervftbl, REG_ITMP2);
3961 #if defined(ENABLE_THREADS)
3962 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3964 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3965 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3966 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3967 #if defined(ENABLE_THREADS)
3968 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3970 M_ISUB(REG_ITMP2, REG_ITMP1);
3971 M_CLR(d); /* may be REG_ITMP2 */
3972 M_CMP(REG_ITMP3, REG_ITMP1);
3976 emit_store(jd, iptr, iptr->dst, d);
3982 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3983 /* op1 = dimension, val.a = class */
3985 /* check for negative sizes and copy sizes to stack if necessary */
3987 MCODECHECK((iptr->op1 << 1) + 64);
3989 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3990 /* copy SAVEDVAR sizes to stack */
3992 if (src->varkind != ARGVAR) {
3993 if (src->flags & INMEMORY) {
3994 M_ILD(REG_ITMP1, REG_SP, src->regoff * 4);
3995 M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4);
3998 M_IST(src->regoff, REG_SP, (s1 + 3) * 4);
4002 /* is a patcher function set? */
4004 if (iptr->val.a == NULL) {
4005 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
4006 (constant_classref *) iptr->target, 0);
4008 if (opt_showdisassemble) {
4009 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4016 disp = (ptrint) iptr->val.a;
4018 /* a0 = dimension count */
4020 M_IST_IMM(iptr->op1, REG_SP, 0 * 4);
4022 /* a1 = arraydescriptor */
4024 M_IST_IMM(disp, REG_SP, 1 * 4);
4026 /* a2 = pointer to dimensions = stack pointer */
4028 M_MOV(REG_SP, REG_ITMP1);
4029 M_AADD_IMM(3 * 4, REG_ITMP1);
4030 M_AST(REG_ITMP1, REG_SP, 2 * 4);
4032 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
4035 /* check for exception before result assignment */
4039 codegen_add_fillinstacktrace_ref(cd);
4041 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
4042 M_INTMOVE(REG_RESULT, s1);
4043 emit_store(jd, iptr, iptr->dst, s1);
4048 new_internalerror("Unknown ICMD %d", iptr->opc);
4052 } /* for instruction */
4054 /* copy values to interface registers */
4056 src = bptr->outstack;
4057 len = bptr->outdepth;
4059 #if defined(ENABLE_LSRA)
4064 if ((src->varkind != STACKVAR)) {
4066 if (IS_FLT_DBL_TYPE(s2)) {
4067 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
4068 if (!(rd->interfaces[len][s2].flags & INMEMORY))
4069 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
4071 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
4074 if (IS_2_WORD_TYPE(s2))
4076 /* s1 = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP1, REG_ITMP2)); */
4078 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
4080 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4081 if (IS_2_WORD_TYPE(s2))
4082 M_LNGMOVE(s1, rd->interfaces[len][s2].regoff);
4084 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
4087 if (IS_2_WORD_TYPE(s2))
4088 M_LST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
4090 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
4097 /* At the end of a basic block we may have to append some nops,
4098 because the patcher stub calling code might be longer than the
4099 actual instruction. So codepatching does not change the
4100 following block unintentionally. */
4102 if (cd->mcodeptr < cd->lastmcodeptr) {
4103 while (cd->mcodeptr < cd->lastmcodeptr) {
4108 } /* if (bptr -> flags >= BBREACHED) */
4109 } /* for basic block */
4111 dseg_createlinenumbertable(cd);
4114 /* generate exception and patcher stubs */
4123 savedmcodeptr = NULL;
4125 /* generate exception stubs */
4127 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
4128 gen_resolvebranch(cd->mcodebase + eref->branchpos,
4130 cd->mcodeptr - cd->mcodebase);
4134 /* Check if the exception is an
4135 ArrayIndexOutOfBoundsException. If so, move index register
4138 if (eref->reg != -1)
4139 M_INTMOVE(eref->reg, REG_ITMP1);
4141 /* calcuate exception address */
4143 M_MOV_IMM(0, REG_ITMP2_XPC);
4145 M_AADD_IMM32(eref->branchpos - 6, REG_ITMP2_XPC);
4147 /* move function to call into REG_ITMP3 */
4149 M_MOV_IMM(eref->function, REG_ITMP3);
4151 if (savedmcodeptr != NULL) {
4152 M_JMP_IMM((savedmcodeptr - cd->mcodeptr) - 5);
4155 savedmcodeptr = cd->mcodeptr;
4157 M_ASUB_IMM(5 * 4, REG_SP);
4159 /* first save REG_ITMP1 so we can use it */
4161 M_AST(REG_ITMP1, REG_SP, 4 * 4); /* for AIOOBE */
4163 M_AST_IMM(0, REG_SP, 0 * 4);
4165 M_MOV(REG_SP, REG_ITMP1);
4166 M_AADD_IMM(5 * 4, REG_ITMP1);
4167 M_AST(REG_ITMP1, REG_SP, 1 * 4);
4168 M_ALD(REG_ITMP1, REG_SP, (5 + stackframesize) * 4);
4169 M_AST(REG_ITMP1, REG_SP, 2 * 4);
4170 M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
4174 M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
4175 M_AADD_IMM(5 * 4, REG_SP);
4177 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
4183 /* generate code patching stub call code */
4185 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4186 /* check code segment size */
4190 /* Get machine code which is patched back in later. A
4191 `call rel32' is 5 bytes long. */
4193 savedmcodeptr = cd->mcodebase + pref->branchpos;
4194 mcode = *((u8 *) savedmcodeptr);
4196 /* patch in `call rel32' to call the following code */
4198 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
4199 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
4201 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
4203 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4205 /* save REG_ITMP3 */
4209 /* move pointer to java_objectheader onto stack */
4211 #if defined(ENABLE_THREADS)
4212 (void) dseg_addaddress(cd, NULL); /* flcword */
4213 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
4214 off = dseg_addaddress(cd, NULL); /* vftbl */
4216 M_MOV_IMM(0, REG_ITMP3);
4218 M_AADD_IMM(off, REG_ITMP3);
4224 /* move machine code bytes and classinfo pointer into registers */
4226 M_PUSH_IMM(mcode >> 32);
4228 M_PUSH_IMM(pref->ref);
4229 M_PUSH_IMM(pref->patcher);
4231 M_MOV_IMM(asm_patcher_wrapper, REG_ITMP3);
4236 /* generate replacement-out stubs */
4241 replacementpoint = jd->code->rplpoints;
4243 for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
4244 /* check code segment size */
4248 /* note start of stub code */
4250 replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
4252 /* make machine code for patching */
4254 disp = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
4255 replacementpoint->mcode = 0xe9 | ((u8)disp << 8);
4257 /* push address of `rplpoint` struct */
4259 M_PUSH_IMM(replacementpoint);
4261 /* jump to replacement function */
4263 M_PUSH_IMM(asm_replacement_out);
4270 /* everything's ok */
4276 /* createcompilerstub **********************************************************
4278 Creates a stub routine which calls the compiler.
4280 *******************************************************************************/
4282 #define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P
4283 #define COMPILERSTUB_CODESIZE 12
4285 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4288 u1 *createcompilerstub(methodinfo *m)
4290 u1 *s; /* memory to hold the stub */
4296 s = CNEW(u1, COMPILERSTUB_SIZE);
4298 /* set data pointer and code pointer */
4301 s = s + COMPILERSTUB_DATASIZE;
4303 /* mark start of dump memory area */
4305 dumpsize = dump_size();
4307 cd = DNEW(codegendata);
4310 /* Store the codeinfo pointer in the same place as in the
4311 methodheader for compiled methods. */
4313 code = code_codeinfo_new(m);
4315 d[0] = (ptrint) asm_call_jit_compiler;
4317 d[2] = (ptrint) code;
4319 /* code for the stub */
4321 M_MOV_IMM(m, REG_ITMP1); /* method info */
4322 M_MOV_IMM(asm_call_jit_compiler, REG_ITMP3);
4325 #if defined(ENABLE_STATISTICS)
4327 count_cstub_len += COMPILERSTUB_SIZE;
4330 /* release dump area */
4332 dump_release(dumpsize);
4338 /* createnativestub ************************************************************
4340 Creates a stub routine which calls a native method.
4342 *******************************************************************************/
4344 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
4353 s4 i, j; /* count variables */
4357 /* get required compiler data */
4364 /* set some variables */
4367 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4369 /* calculate stackframe size */
4372 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4373 sizeof(localref_table) / SIZEOF_VOID_P +
4374 1 + /* function pointer */
4375 4 * 4 + /* 4 arguments (start_native_call) */
4378 /* create method header */
4380 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
4381 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
4382 (void) dseg_adds4(cd, 0); /* IsSync */
4383 (void) dseg_adds4(cd, 0); /* IsLeaf */
4384 (void) dseg_adds4(cd, 0); /* IntSave */
4385 (void) dseg_adds4(cd, 0); /* FltSave */
4386 (void) dseg_addlinenumbertablesize(cd);
4387 (void) dseg_adds4(cd, 0); /* ExTableSize */
4389 /* generate native method profiling code */
4391 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
4392 /* count frequency */
4394 M_MOV_IMM(code, REG_ITMP1);
4395 M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(codeinfo, frequency));
4398 /* calculate stackframe size for native function */
4400 M_ASUB_IMM(stackframesize * 4, REG_SP);
4402 #if !defined(NDEBUG)
4403 if (opt_verbosecall) {
4406 disp = stackframesize * 4;
4408 M_ASUB_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
4410 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
4411 t = md->paramtypes[p].type;
4412 if (IS_INT_LNG_TYPE(t)) {
4413 if (IS_2_WORD_TYPE(t)) {
4414 M_ILD(REG_ITMP1, REG_SP,
4415 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4416 M_ILD(REG_ITMP2, REG_SP,
4417 4 + TRACE_ARGS_NUM * 8 + 4 + disp + 4);
4418 M_IST(REG_ITMP1, REG_SP, p * 8);
4419 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
4421 } else if (t == TYPE_ADR) {
4422 M_ALD(REG_ITMP1, REG_SP,
4423 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4425 M_AST(REG_ITMP1, REG_SP, p * 8);
4426 M_AST(REG_ITMP2, REG_SP, p * 8 + 4);
4429 M_ILD(EAX, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4431 M_IST(EAX, REG_SP, p * 8);
4432 M_IST(EDX, REG_SP, p * 8 + 4);
4436 if (!IS_2_WORD_TYPE(t)) {
4437 emit_flds_membase(cd, REG_SP,
4438 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4439 emit_fstps_membase(cd, REG_SP, p * 8);
4440 emit_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2);
4441 M_IST(REG_ITMP2, REG_SP, p * 8 + 4);
4444 emit_fldl_membase(cd, REG_SP,
4445 4 + TRACE_ARGS_NUM * 8 + 4 + disp);
4446 emit_fstpl_membase(cd, REG_SP, p * 8);
4449 disp += (IS_2_WORD_TYPE(t)) ? 8 : 4;
4453 for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) {
4454 M_IST(REG_ITMP1, REG_SP, p * 8);
4455 M_IST(REG_ITMP1, REG_SP, p * 8 + 4);
4458 M_AST_IMM(m, REG_SP, TRACE_ARGS_NUM * 8);
4460 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
4463 M_AADD_IMM(TRACE_ARGS_NUM * 8 + 4, REG_SP);
4465 #endif /* !defined(NDEBUG) */
4467 /* get function address (this must happen before the stackframeinfo) */
4469 #if !defined(WITH_STATIC_CLASSPATH)
4471 codegen_addpatchref(cd, PATCHER_resolve_native, m, 0);
4473 if (opt_showdisassemble) {
4474 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4479 M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
4481 /* Mark the whole fpu stack as free for native functions (only for saved */
4482 /* register count == 0). */
4484 emit_ffree_reg(cd, 0);
4485 emit_ffree_reg(cd, 1);
4486 emit_ffree_reg(cd, 2);
4487 emit_ffree_reg(cd, 3);
4488 emit_ffree_reg(cd, 4);
4489 emit_ffree_reg(cd, 5);
4490 emit_ffree_reg(cd, 6);
4491 emit_ffree_reg(cd, 7);
4493 /* prepare data structures for native function call */
4495 M_MOV(REG_SP, REG_ITMP1);
4496 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
4498 M_AST(REG_ITMP1, REG_SP, 0 * 4);
4499 M_IST_IMM(0, REG_SP, 1 * 4);
4502 M_MOV(REG_SP, REG_ITMP2);
4503 M_AADD_IMM(stackframesize * 4 + SIZEOF_VOID_P, REG_ITMP2);
4505 M_AST(REG_ITMP2, REG_SP, 2 * 4);
4506 M_ALD(REG_ITMP3, REG_SP, stackframesize * 4);
4507 M_AST(REG_ITMP3, REG_SP, 3 * 4);
4508 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
4511 M_ALD(REG_ITMP3, REG_SP, 4 * 4);
4513 /* copy arguments into new stackframe */
4515 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4516 t = md->paramtypes[i].type;
4518 if (!md->params[i].inmemory) {
4519 /* no integer argument registers */
4520 } else { /* float/double in memory can be copied like int/longs */
4521 s1 = (md->params[i].regoff + stackframesize + 1) * 4;
4522 s2 = nmd->params[j].regoff * 4;
4524 M_ILD(REG_ITMP1, REG_SP, s1);
4525 M_IST(REG_ITMP1, REG_SP, s2);
4526 if (IS_2_WORD_TYPE(t)) {
4527 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
4528 M_IST(REG_ITMP1, REG_SP, s2 + 4);
4533 /* if function is static, put class into second argument */
4535 if (m->flags & ACC_STATIC)
4536 M_AST_IMM((ptrint) m->class, REG_SP, 1 * 4);
4538 /* put env into first argument */
4540 M_AST_IMM((ptrint) _Jv_env, REG_SP, 0 * 4);
4542 /* call the native function */
4546 /* save return value */
4548 if (md->returntype.type != TYPE_VOID) {
4549 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4550 if (IS_2_WORD_TYPE(md->returntype.type))
4551 M_IST(REG_RESULT2, REG_SP, 2 * 4);
4552 M_IST(REG_RESULT, REG_SP, 1 * 4);
4555 if (IS_2_WORD_TYPE(md->returntype.type))
4556 emit_fstl_membase(cd, REG_SP, 1 * 4);
4558 emit_fsts_membase(cd, REG_SP, 1 * 4);
4562 #if !defined(NDEBUG)
4563 if (opt_verbosecall) {
4564 /* restore return value */
4566 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4567 if (IS_2_WORD_TYPE(md->returntype.type))
4568 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
4569 M_ILD(REG_RESULT, REG_SP, 1 * 4);
4572 if (IS_2_WORD_TYPE(md->returntype.type))
4573 emit_fldl_membase(cd, REG_SP, 1 * 4);
4575 emit_flds_membase(cd, REG_SP, 1 * 4);
4578 M_ASUB_IMM(4 + 8 + 8 + 4, REG_SP);
4580 M_AST_IMM((ptrint) m, REG_SP, 0);
4582 M_IST(REG_RESULT, REG_SP, 4);
4583 M_IST(REG_RESULT2, REG_SP, 4 + 4);
4585 emit_fstl_membase(cd, REG_SP, 4 + 8);
4586 emit_fsts_membase(cd, REG_SP, 4 + 8 + 8);
4588 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
4591 M_AADD_IMM(4 + 8 + 8 + 4, REG_SP);
4593 #endif /* !defined(NDEBUG) */
4595 /* remove native stackframe info */
4597 M_MOV(REG_SP, REG_ITMP1);
4598 M_AADD_IMM(stackframesize * 4, REG_ITMP1);
4600 M_AST(REG_ITMP1, REG_SP, 0 * 4);
4601 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
4603 M_MOV(REG_RESULT, REG_ITMP2); /* REG_ITMP3 == REG_RESULT2 */
4605 /* restore return value */
4607 if (md->returntype.type != TYPE_VOID) {
4608 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4609 if (IS_2_WORD_TYPE(md->returntype.type))
4610 M_ILD(REG_RESULT2, REG_SP, 2 * 4);
4611 M_ILD(REG_RESULT, REG_SP, 1 * 4);
4614 if (IS_2_WORD_TYPE(md->returntype.type))
4615 emit_fldl_membase(cd, REG_SP, 1 * 4);
4617 emit_flds_membase(cd, REG_SP, 1 * 4);
4621 M_AADD_IMM(stackframesize * 4, REG_SP);
4623 /* check for exception */
4630 /* handle exception */
4632 M_MOV(REG_ITMP2, REG_ITMP1_XPTR);
4633 M_ALD(REG_ITMP2_XPC, REG_SP, 0);
4634 M_ASUB_IMM(2, REG_ITMP2_XPC);
4636 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
4640 /* process patcher calls **************************************************/
4648 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4649 /* Get machine code which is patched back in later. A
4650 `call rel32' is 5 bytes long. */
4652 xcodeptr = cd->mcodebase + pref->branchpos;
4653 mcode = *((u8 *) xcodeptr);
4655 /* patch in `call rel32' to call the following code */
4657 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
4658 cd->mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4660 M_CALL_IMM(tmpmcodeptr - (xcodeptr + PATCHER_CALL_SIZE));
4662 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4664 /* save REG_ITMP3 */
4668 /* move pointer to java_objectheader onto stack */
4670 #if defined(ENABLE_THREADS)
4671 /* create a virtual java_objectheader */
4673 (void) dseg_addaddress(cd, NULL); /* flcword */
4674 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
4675 disp = dseg_addaddress(cd, NULL); /* vftbl */
4677 M_MOV_IMM(0, REG_ITMP3);
4679 M_AADD_IMM(disp, REG_ITMP3);
4685 /* move machine code bytes and classinfo pointer onto stack */
4687 M_PUSH_IMM((mcode >> 32));
4689 M_PUSH_IMM(pref->ref);
4690 M_PUSH_IMM(pref->patcher);
4692 M_MOV_IMM(asm_patcher_wrapper, REG_ITMP3);
4699 return code->entrypoint;
4704 * These are local overrides for various environment variables in Emacs.
4705 * Please do not remove this and leave it at the end of the file, where
4706 * Emacs will automagically detect them.
4707 * ---------------------------------------------------------------------
4710 * indent-tabs-mode: t
4714 * vim:noexpandtab:sw=4:ts=4: