1 /* src/vm/jit/arm/codegen.c - machine code generator for Arm
3 Copyright (C) 1996-2005, 2006, 2007 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
37 #include "vm/jit/arm/arch.h"
38 #include "vm/jit/arm/codegen.h"
40 #include "mm/memory.h"
42 #include "native/localref.h"
43 #include "native/native.h"
45 #include "threads/lock-common.h"
47 #include "vm/builtin.h"
48 #include "vm/exceptions.h"
49 #include "vm/global.h"
52 #include "vm/jit/abi.h"
53 #include "vm/jit/asmpart.h"
54 #include "vm/jit/codegen-common.h"
55 #include "vm/jit/dseg.h"
56 #include "vm/jit/emit-common.h"
57 #include "vm/jit/jit.h"
58 #include "vm/jit/md.h"
59 #include "vm/jit/methodheader.h"
60 #include "vm/jit/parse.h"
61 #include "vm/jit/patcher-common.h"
62 #include "vm/jit/reg.h"
64 #if defined(ENABLE_LSRA)
65 #include "vm/jit/allocator/lsra.h"
68 #include "vmcore/loader.h"
69 #include "vmcore/options.h"
72 /* codegen_emit ****************************************************************
74 Generates machine code.
76 *******************************************************************************/
78 bool codegen_emit(jitdata *jd)
97 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
98 unresolved_method *um;
99 builtintable_entry *bte;
102 unresolved_field *uf;
106 /* get required compiler data */
113 /* prevent compiler warnings */
121 /* space to save used callee saved registers */
123 savedregs_num = (jd->isleafmethod) ? 0 : 1; /* space to save the LR */
124 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
125 /*savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);*/
126 assert((FLT_SAV_CNT - rd->savfltreguse) == 0);
128 spilledregs_num = rd->memuse;
130 #if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */
131 if (checksync && (m->flags & ACC_SYNCHRONIZED))
135 cd->stackframesize = spilledregs_num * 8 + savedregs_num * 4;
137 /* XXX QUICK FIX: We shouldn't align the stack in Java code, but
138 only in native stubs. */
139 /* align stack to 8-byte */
141 cd->stackframesize = (cd->stackframesize + 4) & ~4;
143 /* SECTION: Method Header */
144 /* create method header */
146 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
147 (void) dseg_add_unique_s4(cd, cd->stackframesize); /* FrameSize */
149 #if defined(ENABLE_THREADS)
150 /* IsSync contains the offset relative to the stack pointer for the
151 argument of monitor_exit used in the exception handler. Since the
152 offset could be zero and give a wrong meaning of the flag it is
156 if (checksync && (m->flags & ACC_SYNCHRONIZED))
157 (void) dseg_add_unique_s4(cd, rd->memuse * 8 + 4);/* IsSync */
160 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
162 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
163 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
164 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
165 (void) dseg_addlinenumbertablesize(cd);
166 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
168 /* create exception table */
170 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
171 dseg_add_target(cd, ex->start);
172 dseg_add_target(cd, ex->end);
173 dseg_add_target(cd, ex->handler);
174 (void) dseg_add_unique_address(cd, ex->catchtype.any);
177 /* save return address and used callee saved registers */
179 savedregs_bitmask = 0;
181 if (!jd->isleafmethod)
182 savedregs_bitmask = (1<<REG_LR);
184 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--)
185 savedregs_bitmask |= (1<<(rd->savintregs[i]));
188 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
189 log_text("!!! CODEGEN: floating-point callee saved registers are not saved to stack (SEVERE! STACK IS MESSED UP!)");
190 /* TODO: floating-point */
194 if (savedregs_bitmask)
195 M_STMFD(savedregs_bitmask, REG_SP);
197 /* create additional stack frame for spilled variables (if necessary) */
199 if ((cd->stackframesize / 4 - savedregs_num) > 0)
200 M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - savedregs_num);
202 /* take arguments out of register or stack frame */
205 for (i = 0, len = 0; i < md->paramcount; i++) {
206 s1 = md->params[i].regoff;
207 t = md->paramtypes[i].type;
209 varindex = jd->local_map[len * 5 + t];
211 len += (IS_2_WORD_TYPE(t)) ? 2 : 1; /* 2 word type arguments */
213 if (varindex == UNUSED)
218 /* ATTENTION: we use interger registers for all arguments (even float) */
219 #if !defined(ENABLE_SOFTFLOAT)
220 if (IS_INT_LNG_TYPE(t)) {
222 if (!md->params[i].inmemory) {
223 if (!(var->flags & INMEMORY)) {
224 if (IS_2_WORD_TYPE(t))
225 M_LNGMOVE(s1, var->vv.regoff);
227 M_INTMOVE(s1, var->vv.regoff);
230 if (IS_2_WORD_TYPE(t))
231 M_LST(s1, REG_SP, var->vv.regoff);
233 M_IST(s1, REG_SP, var->vv.regoff);
236 else { /* stack arguments */
237 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
238 if (IS_2_WORD_TYPE(t))
239 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
241 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
243 else { /* stack arg -> spilled */
244 /* Reuse Memory Position on Caller Stack */
245 var->vv.regoff = cd->stackframesize + s1;
248 #if !defined(ENABLE_SOFTFLOAT)
251 if (!md->params[i].inmemory) {
252 if (!(var->flags & INMEMORY)) {
253 if (IS_2_WORD_TYPE(t))
254 M_CAST_L2D(s1, var->vv.regoff);
256 M_CAST_I2F(s1, var->vv.regoff);
259 if (IS_2_WORD_TYPE(t))
260 M_LST(s1, REG_SP, var->vv.regoff);
262 M_IST(s1, REG_SP, var->vv.regoff);
266 if (!(var->flags & INMEMORY)) {
267 if (IS_2_WORD_TYPE(t))
268 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
270 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
273 /* Reuse Memory Position on Caller Stack */
274 var->vv.regoff = cd->stackframesize + s1;
278 #endif /* !defined(ENABLE_SOFTFLOAT) */
281 #if defined(ENABLE_THREADS)
282 /* call monitorenter function */
284 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
285 /* stack offset for monitor argument */
289 # if !defined(NDEBUG)
290 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
291 M_STMFD(BITMASK_ARGS, REG_SP);
296 /* get the correct lock object */
298 if (m->flags & ACC_STATIC) {
299 disp = dseg_add_address(cd, &m->class->object.header);
300 M_DSEG_LOAD(REG_A0, disp);
303 emit_nullpointer_check_force(cd, iptr, REG_A0);
306 M_STR(REG_A0, REG_SP, s1);
307 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
309 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
312 # if !defined(NDEBUG)
313 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
314 M_LDMFD(BITMASK_ARGS, REG_SP);
320 /* call trace function */
322 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
323 emit_verbosecall_enter(jd);
326 /* end of header generation */
328 /* create replacement points */
329 REPLACEMENT_POINTS_INIT(cd, jd);
331 /* SECTION: ICMD Code Generation */
332 /* for all basic blocks */
334 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
336 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
338 /* is this basic block reached? */
340 if (bptr->flags < BBREACHED)
343 /* branch resolving */
345 codegen_resolve_branchrefs(cd, bptr);
347 /* handle replacement points */
348 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
350 /* copy interface registers to their destination */
356 #if defined(ENABLE_LSRA)
360 var = VAR(bptr->invars[len]);
361 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
362 if (!(var->flags & INMEMORY))
366 M_INTMOVE(REG_ITMP1, d);
367 emit_store(jd, NULL, var, d);
374 var = VAR(bptr->invars[len]);
376 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
377 d = codegen_reg_of_var(0, var, REG_ITMP1);
378 M_INTMOVE(REG_ITMP1, d);
379 emit_store(jd, NULL, var, d);
382 assert((var->flags & INOUT));
385 #if defined(ENABLE_LSRA)
389 /* for all instructions */
392 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
394 /* add line number */
395 if (iptr->line != currentline) {
396 dseg_addlinenumber(cd, iptr->line);
397 currentline = iptr->line;
400 MCODECHECK(64); /* an instruction usually needs < 64 words */
404 case ICMD_NOP: /* ... ==> ... */
407 /* constant operations ************************************************/
409 case ICMD_ICONST: /* ... ==> ..., constant */
411 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
412 ICONST(d, iptr->sx.val.i);
413 emit_store_dst(jd, iptr, d);
416 case ICMD_ACONST: /* ... ==> ..., constant */
418 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
419 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
420 disp = dseg_add_unique_address(cd, NULL);
422 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
423 iptr->sx.val.c.ref, disp);
425 M_DSEG_LOAD(d, disp);
428 ICONST(d, (u4) iptr->sx.val.anyptr);
430 emit_store_dst(jd, iptr, d);
433 case ICMD_LCONST: /* ... ==> ..., constant */
435 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
436 LCONST(d, iptr->sx.val.l);
437 emit_store_dst(jd, iptr, d);
440 case ICMD_FCONST: /* ... ==> ..., constant */
442 #if defined(ENABLE_SOFTFLOAT)
443 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
444 ICONST(d, iptr->sx.val.i);
445 emit_store_dst(jd, iptr, d);
447 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
448 FCONST(d, iptr->sx.val.f);
449 emit_store_dst(jd, iptr, d);
453 case ICMD_DCONST: /* ... ==> ..., constant */
455 #if defined(ENABLE_SOFTFLOAT)
456 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
457 LCONST(d, iptr->sx.val.l);
458 emit_store_dst(jd, iptr, d);
460 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
461 DCONST(d, iptr->sx.val.d);
462 emit_store_dst(jd, iptr, d);
467 /* load/store/copy/move operations ************************************/
469 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
470 case ICMD_ALOAD: /* op1 = local variable */
474 case ICMD_ISTORE: /* ..., value ==> ... */
485 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
489 /* pop operations *****************************************************/
491 /* attention: double and longs are only one entry in CACAO ICMDs */
493 case ICMD_POP: /* ..., value ==> ... */
494 case ICMD_POP2: /* ..., value, value ==> ... */
499 /* integer operations *************************************************/
501 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
503 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
504 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
505 M_MOV(d, REG_LSL(s1, 24));
506 M_MOV(d, REG_ASR(d, 24));
507 emit_store_dst(jd, iptr, d);
510 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
512 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
513 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
514 M_MOV(d, REG_LSL(s1, 16));
515 M_MOV(d, REG_LSR(d, 16)); /* ATTENTION: char is unsigned */
516 emit_store_dst(jd, iptr, d);
519 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
521 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
522 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
523 M_MOV(d, REG_LSL(s1, 16));
524 M_MOV(d, REG_ASR(d, 16));
525 emit_store_dst(jd, iptr, d);
528 case ICMD_I2L: /* ..., value ==> ..., value */
530 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
531 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
532 M_INTMOVE(s1, GET_LOW_REG(d));
533 M_MOV(GET_HIGH_REG(d), REG_ASR(s1, 31));
534 emit_store_dst(jd, iptr, d);
537 case ICMD_L2I: /* ..., value ==> ..., value */
539 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
540 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
542 emit_store_dst(jd, iptr, d);
545 case ICMD_INEG: /* ..., value ==> ..., - value */
547 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
548 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
550 emit_store_dst(jd, iptr, d);
553 case ICMD_LNEG: /* ..., value ==> ..., - value */
555 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
556 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
557 M_RSB_IMMS(GET_LOW_REG(d), GET_LOW_REG(s1), 0);
558 M_RSC_IMM(GET_HIGH_REG(d), GET_HIGH_REG(s1), 0);
559 emit_store_dst(jd, iptr, d);
562 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
564 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
565 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
566 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
568 emit_store_dst(jd, iptr, d);
571 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
573 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
574 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
575 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
576 M_ADD_S(GET_LOW_REG(d), s1, s2);
577 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
578 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
579 M_ADC(GET_HIGH_REG(d), s1, s2);
580 emit_store_dst(jd, iptr, d);
586 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
587 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
589 if (IS_IMM(iptr->sx.val.i)) {
590 M_ADD_IMM(d, s1, iptr->sx.val.i);
591 } else if (IS_IMM(-iptr->sx.val.i)) {
592 M_SUB_IMM(d, s1, (-iptr->sx.val.i));
594 ICONST(REG_ITMP3, iptr->sx.val.i);
595 M_ADD(d, s1, REG_ITMP3);
598 emit_store_dst(jd, iptr, d);
601 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
602 /* sx.val.l = constant */
604 s3 = iptr->sx.val.l & 0xffffffff;
605 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
606 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
608 M_ADD_IMMS(GET_LOW_REG(d), s1, s3);
610 ICONST(REG_ITMP3, s3);
611 M_ADD_S(GET_LOW_REG(d), s1, REG_ITMP3);
613 s3 = iptr->sx.val.l >> 32;
614 s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
616 M_ADC_IMM(GET_HIGH_REG(d), s1, s3);
618 ICONST(REG_ITMP3, s3);
619 M_ADC(GET_HIGH_REG(d), s1, REG_ITMP3);
621 emit_store_dst(jd, iptr, d);
624 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
626 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
627 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
628 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
630 emit_store_dst(jd, iptr, d);
633 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
635 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
636 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
637 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
638 M_SUB_S(GET_LOW_REG(d), s1, s2);
639 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
640 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
641 M_SBC(GET_HIGH_REG(d), s1, s2);
642 emit_store_dst(jd, iptr, d);
645 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
646 /* sx.val.i = constant */
648 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
649 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
650 if (IS_IMM(iptr->sx.val.i))
651 M_SUB_IMM(d, s1, iptr->sx.val.i);
653 ICONST(REG_ITMP3, iptr->sx.val.i);
654 M_SUB(d, s1, REG_ITMP3);
656 emit_store_dst(jd, iptr, d);
659 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
660 /* sx.val.l = constant */
662 s3 = iptr->sx.val.l & 0xffffffff;
663 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
664 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
666 M_SUB_IMMS(GET_LOW_REG(d), s1, s3);
668 ICONST(REG_ITMP3, s3);
669 M_SUB_S(GET_LOW_REG(d), s1, REG_ITMP3);
671 s3 = iptr->sx.val.l >> 32;
672 s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
674 M_SBC_IMM(GET_HIGH_REG(d), s1, s3);
676 ICONST(REG_ITMP3, s3);
677 M_SBC(GET_HIGH_REG(d), s1, REG_ITMP3);
679 emit_store_dst(jd, iptr, d);
682 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
684 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
685 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
686 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
688 emit_store_dst(jd, iptr, d);
691 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
692 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
694 s1 = emit_load_s1(jd, iptr, REG_A0);
695 s2 = emit_load_s2(jd, iptr, REG_A1);
696 emit_arithmetic_check(cd, iptr, s2);
698 /* move arguments into argument registers */
699 M_INTMOVE(s1, REG_A0);
700 M_INTMOVE(s2, REG_A1);
702 /* call builtin function */
703 bte = iptr->sx.s23.s3.bte;
704 disp = dseg_add_functionptr(cd, bte->fp);
708 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
711 /* move result into destination register */
712 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
713 M_INTMOVE(REG_RESULT, d);
714 emit_store_dst(jd, iptr, d);
717 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
718 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
720 /* move arguments into argument registers */
722 s1 = emit_load_s1(jd, iptr, REG_A0_A1_PACKED);
723 s2 = emit_load_s2(jd, iptr, REG_A2_A3_PACKED);
724 /* XXX TODO: only do this if arithmetic check is really done! */
725 M_ORR(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
726 emit_arithmetic_check(cd, iptr, REG_ITMP3);
728 M_LNGMOVE(s1, REG_A0_A1_PACKED);
729 M_LNGMOVE(s2, REG_A2_A3_PACKED);
731 /* call builtin function */
732 bte = iptr->sx.s23.s3.bte;
733 disp = dseg_add_functionptr(cd, bte->fp);
737 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
740 /* move result into destination register */
741 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
742 M_LNGMOVE(REG_RESULT_PACKED, d);
743 emit_store_dst(jd, iptr, d);
746 case ICMD_IMULPOW2: /* ..., value ==> ..., value * (2 ^ constant) */
747 /* sx.val.i = constant */
749 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
750 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
751 M_MOV(d, REG_LSL(s1, iptr->sx.val.i));
752 emit_store_dst(jd, iptr, d);
755 case ICMD_IDIVPOW2: /* ..., value ==> ..., value / (2 ^ constant) */
756 /* sx.val.i = constant */
758 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
759 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
760 /* this rounds towards 0 as java likes it */
761 M_MOV(REG_ITMP3, REG_ASR(s1, 31));
762 M_ADD(REG_ITMP3, s1, REG_LSR(REG_ITMP3, 32 - iptr->sx.val.i));
763 M_MOV(d, REG_ASR(REG_ITMP3, iptr->sx.val.i));
764 /* this rounds towards nearest, not java style */
765 /*M_MOV_S(d, REG_ASR(s1, iptr->sx.val.i));
766 M_ADCMI_IMM(d, d, 0);*/
767 emit_store_dst(jd, iptr, d);
770 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
771 /* sx.val.i = constant [ (2 ^ x) - 1 ] */
773 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
774 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
775 M_MOV_S(REG_ITMP1, s1);
776 M_RSBMI_IMM(REG_ITMP1, REG_ITMP1, 0);
777 if (IS_IMM(iptr->sx.val.i))
778 M_AND_IMM(REG_ITMP1, iptr->sx.val.i, d);
780 ICONST(REG_ITMP3, iptr->sx.val.i);
781 M_AND(REG_ITMP1, REG_ITMP3, d);
783 M_RSBMI_IMM(d, d, 0);
784 emit_store_dst(jd, iptr, d);
787 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
789 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
790 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
791 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
792 M_AND_IMM(s2, 0x1f, REG_ITMP2);
793 M_MOV(d, REG_LSL_REG(s1, REG_ITMP2));
794 emit_store_dst(jd, iptr, d);
797 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
799 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
800 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
801 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
802 M_AND_IMM(s2, 0x1f, REG_ITMP2);
803 M_MOV(d, REG_ASR_REG(s1, REG_ITMP2));
804 emit_store_dst(jd, iptr, d);
807 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
809 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
810 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
811 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
812 M_AND_IMM(s2, 0x1f, REG_ITMP2);
813 M_MOV(d, REG_LSR_REG(s1, REG_ITMP2));
814 emit_store_dst(jd, iptr, d);
817 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
818 /* sx.val.i = constant */
820 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
821 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
822 M_MOV(d, REG_LSL(s1, iptr->sx.val.i & 0x1f));
823 emit_store_dst(jd, iptr, d);
826 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
827 /* sx.val.i = constant */
829 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
830 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
831 /* we need to check for zero here because arm interprets it as SHR by 32 */
832 if ((iptr->sx.val.i & 0x1f) == 0) {
835 M_MOV(d, REG_ASR(s1, iptr->sx.val.i & 0x1f));
837 emit_store_dst(jd, iptr, d);
840 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
841 /* sx.val.i = constant */
843 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
844 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
845 /* we need to check for zero here because arm interprets it as SHR by 32 */
846 if ((iptr->sx.val.i & 0x1f) == 0)
849 M_MOV(d, REG_LSR(s1, iptr->sx.val.i & 0x1f));
850 emit_store_dst(jd, iptr, d);
853 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
855 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
856 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
857 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
859 emit_store_dst(jd, iptr, d);
862 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
864 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
865 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
866 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
867 M_AND(s1, s2, GET_LOW_REG(d));
868 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
869 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
870 M_AND(s1, s2, GET_HIGH_REG(d));
871 emit_store_dst(jd, iptr, d);
874 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
876 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
877 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
878 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
880 emit_store_dst(jd, iptr, d);
883 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
885 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
886 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
887 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
888 M_ORR(s1, s2, GET_LOW_REG(d));
889 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
890 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
891 M_ORR(s1, s2, GET_HIGH_REG(d));
892 emit_store_dst(jd, iptr, d);
895 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
897 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
898 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
899 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
901 emit_store_dst(jd, iptr, d);
904 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
906 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
907 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
908 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
909 M_EOR(s1, s2, GET_LOW_REG(d));
910 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
911 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
912 M_EOR(s1, s2, GET_HIGH_REG(d));
913 emit_store_dst(jd, iptr, d);
917 /* floating operations ************************************************/
919 #if !defined(ENABLE_SOFTFLOAT)
921 case ICMD_FNEG: /* ..., value ==> ..., - value */
923 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
924 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
926 emit_store_dst(jd, iptr, d);
929 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
931 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
932 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
933 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
935 emit_store_dst(jd, iptr, d);
938 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
940 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
941 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
942 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
944 emit_store_dst(jd, iptr, d);
947 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
949 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
950 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
951 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
953 emit_store_dst(jd, iptr, d);
956 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
957 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
958 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
959 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
961 emit_store_dst(jd, iptr, d);
964 /* ATTENTION: Jave does not want IEEE behaviour in FREM, do
968 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
970 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
971 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
972 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
974 emit_store_dst(jd, iptr, d);
978 case ICMD_DNEG: /* ..., value ==> ..., - value */
980 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
981 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
983 emit_store_dst(jd, iptr, d);
986 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
988 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
989 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
990 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
992 emit_store_dst(jd, iptr, d);
995 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
997 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
998 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
999 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1001 emit_store_dst(jd, iptr, d);
1004 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1006 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1007 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1008 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1010 emit_store_dst(jd, iptr, d);
1013 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1015 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1016 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1017 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1019 emit_store_dst(jd, iptr, d);
1022 /* ATTENTION: Jave does not want IEEE behaviour in DREM, do
1026 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1028 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1029 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1030 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1032 emit_store_dst(jd, iptr, d);
1036 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1038 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1039 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1041 emit_store_dst(jd, iptr, d);
1044 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1046 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1047 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1049 emit_store_dst(jd, iptr, d);
1052 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1054 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1055 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1056 /* this uses round towards zero, as Java likes it */
1058 #if !defined(__VFP_FP__)
1059 /* this checks for NaN; to return zero as Java likes it */
1063 emit_store_dst(jd, iptr, d);
1066 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1068 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1069 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1070 /* this uses round towards zero, as Java likes it */
1072 #if !defined(__VFP_FP__)
1073 /* this checks for NaN; to return zero as Java likes it */
1077 emit_store_dst(jd, iptr, d);
1080 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1082 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1083 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1085 emit_store_dst(jd, iptr, d);
1088 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1090 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1091 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1093 emit_store_dst(jd, iptr, d);
1096 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1098 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1099 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1100 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1103 #if defined(__VFP_FP__)
1104 M_FMSTAT; /* on VFP we need to transfer the flags */
1106 M_SUBGT_IMM(d, d, 1);
1107 M_ADDLT_IMM(d, d, 1);
1108 emit_store_dst(jd, iptr, d);
1111 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 dcmpg val2 */
1113 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1114 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1115 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1118 #if defined(__VFP_FP__)
1119 M_FMSTAT; /* on VFP we need to transfer the flags */
1121 M_SUBGT_IMM(d, d, 1);
1122 M_ADDLT_IMM(d, d, 1);
1123 emit_store_dst(jd, iptr, d);
1126 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1128 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1129 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1130 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1133 #if defined(__VFP_FP__)
1134 M_FMSTAT; /* on VFP we need to transfer the flags */
1136 M_SUBLT_IMM(d, d, 1);
1137 M_ADDGT_IMM(d, d, 1);
1138 emit_store_dst(jd, iptr, d);
1141 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 dcmpl val2 */
1143 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1144 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1145 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1148 #if defined(__VFP_FP__)
1149 M_FMSTAT; /* on VFP we need to transfer the flags */
1151 M_SUBLT_IMM(d, d, 1);
1152 M_ADDGT_IMM(d, d, 1);
1153 emit_store_dst(jd, iptr, d);
1156 #endif /* !defined(ENABLE_SOFTFLOAT) */
1159 /* memory operations **************************************************/
1161 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1163 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1164 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1165 /* implicit null-pointer check */
1166 M_ILD_INTERN(d, s1, OFFSET(java_array_t, size));
1167 emit_store_dst(jd, iptr, d);
1170 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1172 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1173 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1174 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1175 /* implicit null-pointer check */
1176 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1177 M_ADD(REG_ITMP1, s1, s2); /* REG_ITMP1 = s1 + 1 * s2 */
1178 M_LDRSB(d, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1179 emit_store_dst(jd, iptr, d);
1182 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1184 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1185 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1186 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1187 /* implicit null-pointer check */
1188 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1189 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1190 M_LDRH(d, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1191 emit_store_dst(jd, iptr, d);
1194 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1196 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1197 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1198 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1199 /* implicit null-pointer check */
1200 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1201 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1202 M_LDRSH(d, REG_ITMP1, OFFSET(java_shortarray_t, data[0]));
1203 emit_store_dst(jd, iptr, d);
1206 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1208 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1209 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1210 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1211 /* implicit null-pointer check */
1212 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1213 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1214 M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1215 emit_store_dst(jd, iptr, d);
1218 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1220 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1221 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1222 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1223 /* implicit null-pointer check */
1224 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1225 M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
1226 M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1227 emit_store_dst(jd, iptr, d);
1230 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1232 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1233 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1234 /* implicit null-pointer check */
1235 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1236 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1237 #if !defined(ENABLE_SOFTFLOAT)
1238 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1239 M_FLD_INTERN(d, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1241 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1242 M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1244 emit_store_dst(jd, iptr, d);
1247 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1249 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1250 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1251 /* implicit null-pointer check */
1252 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1253 M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
1254 #if !defined(ENABLE_SOFTFLOAT)
1255 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1256 M_DLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1258 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1259 M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1261 emit_store_dst(jd, iptr, d);
1264 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1266 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1267 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1268 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1269 /* implicit null-pointer check */
1270 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1271 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1272 M_LDR_INTERN(d, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1273 emit_store_dst(jd, iptr, d);
1276 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1278 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1279 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1280 /* implicit null-pointer check */
1281 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1282 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1283 M_ADD(REG_ITMP1, s1, s2); /* REG_ITMP1 = s1 + 1 * s2 */
1284 M_STRB(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1287 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1289 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1290 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1291 /* implicit null-pointer check */
1292 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1293 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1294 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1295 M_STRH(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1298 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1300 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1301 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1302 /* implicit null-pointer check */
1303 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1304 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1305 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1306 M_STRH(s3, REG_ITMP1, OFFSET(java_shortarray_t, data[0]));
1309 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1311 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1312 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1313 /* implicit null-pointer check */
1314 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1315 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1316 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1317 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1320 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1322 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1323 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1324 /* implicit null-pointer check */
1325 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1326 M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
1327 s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1328 M_LST_INTERN(s3, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1331 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1333 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1334 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1335 /* implicit null-pointer check */
1336 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1337 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1338 #if !defined(ENABLE_SOFTFLOAT)
1339 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1340 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1342 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1343 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1347 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1349 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1350 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1351 /* implicit null-pointer check */
1352 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1353 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 3)); /* REG_ITMP1 = s1 + 8 * s2 */
1354 #if !defined(ENABLE_SOFTFLOAT)
1355 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1356 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1358 s3 = emit_load_s3(jd, iptr, REG_ITMP23_PACKED);
1359 M_LST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1363 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1365 s1 = emit_load_s1(jd, iptr, REG_A0);
1366 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1367 s3 = emit_load_s3(jd, iptr, REG_A1);
1369 /* implicit null-pointer check */
1370 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1372 /* move arguments to argument registers */
1373 M_INTMOVE(s1, REG_A0);
1374 M_INTMOVE(s3, REG_A1);
1376 /* call builtin function */
1377 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1378 M_DSEG_BRANCH(disp);
1381 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
1384 /* check resturn value of builtin */
1385 emit_arraystore_check(cd, iptr);
1387 /* finally store address into array */
1388 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1389 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1390 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1391 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1392 M_STR_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1395 case ICMD_GETSTATIC: /* ... ==> ..., value */
1397 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1398 uf = iptr->sx.s23.s3.uf;
1399 fieldtype = uf->fieldref->parseddesc.fd->type;
1400 disp = dseg_add_unique_address(cd, NULL);
1402 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1405 fi = iptr->sx.s23.s3.fmiref->p.field;
1406 fieldtype = fi->type;
1407 disp = dseg_add_address(cd, fi->value);
1409 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1410 patcher_add_patch_ref(jd, PATCHER_initialize_class,
1415 M_DSEG_LOAD(REG_ITMP3, disp);
1416 switch (fieldtype) {
1418 #if defined(ENABLE_SOFTFLOAT)
1422 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1423 M_ILD_INTERN(d, REG_ITMP3, 0);
1426 #if defined(ENABLE_SOFTFLOAT)
1429 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1430 M_LLD_INTERN(d, REG_ITMP3, 0);
1432 #if !defined(ENABLE_SOFTFLOAT)
1434 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1435 M_FLD_INTERN(d, REG_ITMP3, 0);
1438 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1439 M_DLD_INTERN(d, REG_ITMP3, 0);
1445 emit_store_dst(jd, iptr, d);
1448 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1450 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1451 uf = iptr->sx.s23.s3.uf;
1452 fieldtype = uf->fieldref->parseddesc.fd->type;
1453 disp = dseg_add_unique_address(cd, NULL);
1455 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1458 fi = iptr->sx.s23.s3.fmiref->p.field;
1459 fieldtype = fi->type;
1460 disp = dseg_add_address(cd, fi->value);
1462 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1463 patcher_add_patch_ref(jd, PATCHER_initialize_class,
1468 M_DSEG_LOAD(REG_ITMP3, disp);
1469 switch (fieldtype) {
1471 #if defined(ENABLE_SOFTFLOAT)
1475 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1476 M_IST_INTERN(s1, REG_ITMP3, 0);
1479 #if defined(ENABLE_SOFTFLOAT)
1482 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
1483 M_LST_INTERN(s1, REG_ITMP3, 0);
1485 #if !defined(ENABLE_SOFTFLOAT)
1487 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1488 M_FST_INTERN(s1, REG_ITMP3, 0);
1491 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1492 M_DST_INTERN(s1, REG_ITMP3, 0);
1500 case ICMD_GETFIELD: /* ..., objectref, value ==> ... */
1502 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
1503 emit_nullpointer_check(cd, iptr, s1);
1506 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1507 uf = iptr->sx.s23.s3.uf;
1508 fieldtype = uf->fieldref->parseddesc.fd->type;
1512 fi = iptr->sx.s23.s3.fmiref->p.field;
1513 fieldtype = fi->type;
1517 #if !defined(ENABLE_SOFTFLOAT)
1518 /* HACK: softnull checks on floats */
1519 if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
1520 emit_nullpointer_check_force(cd, iptr, s1);
1523 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1525 uf = iptr->sx.s23.s3.uf;
1527 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1530 switch (fieldtype) {
1532 #if defined(ENABLE_SOFTFLOAT)
1536 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1540 #if defined(ENABLE_SOFTFLOAT)
1543 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1546 #if !defined(ENABLE_SOFTFLOAT)
1548 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1552 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1559 emit_store_dst(jd, iptr, d);
1562 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1564 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
1565 emit_nullpointer_check(cd, iptr, s1);
1567 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1568 uf = iptr->sx.s23.s3.uf;
1569 fieldtype = uf->fieldref->parseddesc.fd->type;
1573 fi = iptr->sx.s23.s3.fmiref->p.field;
1574 fieldtype = fi->type;
1578 #if !defined(ENABLE_SOFTFLOAT)
1579 /* HACK: softnull checks on floats */
1580 if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
1581 emit_nullpointer_check_force(cd, iptr, s1);
1584 switch (fieldtype) {
1586 #if defined(ENABLE_SOFTFLOAT)
1590 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1592 #if defined(ENABLE_SOFTFLOAT)
1593 case TYPE_DBL: /* fall through */
1596 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
1598 #if !defined(ENABLE_SOFTFLOAT)
1601 s2 = emit_load_s2(jd, iptr, REG_FTMP1);
1608 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1610 uf = iptr->sx.s23.s3.uf;
1612 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1615 switch (fieldtype) {
1617 #if defined(ENABLE_SOFTFLOAT)
1621 M_IST(s2, s1, disp);
1624 #if defined(ENABLE_SOFTFLOAT)
1627 M_LST(s2, s1, disp);
1629 #if !defined(ENABLE_SOFTFLOAT)
1631 M_FST(s2, s1, disp);
1634 M_DST(s2, s1, disp);
1643 /* branch operations **************************************************/
1645 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1647 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1648 M_INTMOVE(s1, REG_ITMP1_XPTR);
1649 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1650 patcher_add_patch_ref(jd, PATCHER_resolve_class,
1651 iptr->sx.s23.s2.uc, 0);
1653 disp = dseg_add_functionptr(cd, asm_handle_exception);
1654 M_DSEG_LOAD(REG_ITMP3, disp);
1655 M_MOV(REG_ITMP2_XPC, REG_PC);
1656 M_MOV(REG_PC, REG_ITMP3);
1657 M_NOP; /* nop ensures that XPC is less than the end */
1658 /* of basic block */
1661 case ICMD_GOTO: /* ... ==> ... */
1664 emit_br(cd, iptr->dst.block);
1667 case ICMD_JSR: /* ... ==> ... */
1669 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1672 case ICMD_IFNULL: /* ..., value ==> ... */
1673 case ICMD_IFNONNULL:
1675 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1677 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
1680 case ICMD_IFLT: /* ..., value ==> ... */
1681 case ICMD_IFLE: /* op1 = target JavaVM pc, val.i = constant */
1687 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1688 M_COMPARE(s1, iptr->sx.val.i);
1689 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
1692 case ICMD_IF_LEQ: /* ..., value ==> ... */
1694 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1695 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1696 if (iptr->sx.val.l == 0) {
1697 M_ORR_S(s1, s2, REG_ITMP3);
1700 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1701 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1702 M_CMP(s1, REG_ITMP3);*/
1703 ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1704 M_CMPEQ(s2, REG_ITMP3);
1706 emit_beq(cd, iptr->dst.block);
1709 case ICMD_IF_LLT: /* ..., value ==> ... */
1711 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1712 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1713 if (iptr->sx.val.l == 0) {
1714 /* if high word is less than zero, the whole long is too */
1716 emit_blt(cd, iptr->dst.block);
1719 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1720 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1721 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1722 M_CMP(s1, REG_ITMP3);*/
1723 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1724 M_MOVGT_IMM(2, REG_ITMP1);
1725 M_MOVEQ_IMM(1, REG_ITMP1);
1727 /* low compare: x=x-1(ifLO) */
1728 M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
1729 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1730 M_CMP(s2, REG_ITMP3);*/
1731 M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
1733 /* branch if (x LT 1) */
1734 M_CMP_IMM(REG_ITMP1, 1);
1735 emit_blt(cd, iptr->dst.block);
1739 case ICMD_IF_LLE: /* ..., value ==> ... */
1741 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1742 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1743 if (iptr->sx.val.l == 0) {
1744 /* if high word is less than zero, the whole long is too */
1746 emit_blt(cd, iptr->dst.block);
1748 /* ... otherwise the low word has to be zero (tricky!) */
1750 emit_beq(cd, iptr->dst.block);
1753 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1754 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1755 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1756 M_CMP(s1, REG_ITMP3);*/
1757 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1758 M_MOVGT_IMM(2, REG_ITMP1);
1759 M_MOVEQ_IMM(1, REG_ITMP1);
1761 /* low compare: x=x+1(ifHI) */
1762 M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
1763 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1764 M_CMP(s2, REG_ITMP3);*/
1765 M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
1767 /* branch if (x LE 1) */
1768 M_CMP_IMM(REG_ITMP1, 1);
1769 emit_ble(cd, iptr->dst.block);
1773 case ICMD_IF_LGE: /* ..., value ==> ... */
1775 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1776 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1777 if (iptr->sx.val.l == 0) {
1778 /* if high word is greater or equal zero, the whole long is too */
1780 emit_bge(cd, iptr->dst.block);
1783 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1784 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1785 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1786 M_CMP(s1, REG_ITMP3);*/
1787 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1788 M_MOVGT_IMM(2, REG_ITMP1);
1789 M_MOVEQ_IMM(1, REG_ITMP1);
1791 /* low compare: x=x-1(ifLO) */
1792 M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
1793 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1794 M_CMP(s2, REG_ITMP3);*/
1795 M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
1797 /* branch if (x GE 1) */
1798 M_CMP_IMM(REG_ITMP1, 1);
1799 emit_bge(cd, iptr->dst.block);
1803 case ICMD_IF_LGT: /* ..., value ==> ... */
1805 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1806 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1808 if (iptr->sx.val.l == 0) {
1809 /* if high word is greater than zero, the whole long is too */
1812 codegen_add_branch_ref(cd, iptr->dst.block);
1814 /* ... or high was zero and low is non zero (tricky!) */
1815 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1816 M_MOVLT_IMM(1, REG_ITMP3);
1817 M_ORR_S(REG_ITMP3, s2, REG_ITMP3);
1819 codegen_add_branch_ref(cd, iptr->dst.block);
1823 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1824 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1825 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1826 M_CMP(s1, REG_ITMP3);*/
1827 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1828 M_MOVGT_IMM(2, REG_ITMP1);
1829 M_MOVEQ_IMM(1, REG_ITMP1);
1831 /* low compare: x=x+1(ifHI) */
1832 M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
1833 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1834 M_CMP(s2, REG_ITMP3);*/
1835 M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
1837 /* branch if (x GT 1) */
1838 M_CMP_IMM(REG_ITMP1, 1);
1839 emit_bgt(cd, iptr->dst.block);
1845 case ICMD_IF_LNE: /* ..., value ==> ... */
1847 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1848 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1849 if (iptr->sx.val.l == 0) {
1850 M_ORR_S(s1, s2, REG_ITMP3);
1853 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1854 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1855 M_CMP(s1, REG_ITMP3);*/
1856 ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1857 M_CMPEQ(s2, REG_ITMP3);
1859 emit_bne(cd, iptr->dst.block);
1862 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1863 case ICMD_IF_ICMPNE:
1864 case ICMD_IF_ICMPLT:
1865 case ICMD_IF_ICMPLE:
1866 case ICMD_IF_ICMPGT:
1867 case ICMD_IF_ICMPGE:
1869 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1870 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1872 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
1875 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
1876 case ICMD_IF_ACMPNE:
1878 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1879 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1881 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
1884 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1885 /* op1 = target JavaVM pc */
1887 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1888 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1891 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1892 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1895 emit_beq(cd, iptr->dst.block);
1898 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
1899 /* op1 = target JavaVM pc */
1901 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1902 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1905 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1906 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1909 emit_bne(cd, iptr->dst.block);
1912 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
1913 /* op1 = target JavaVM pc */
1915 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1916 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1917 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1919 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1920 M_MOVGT_IMM(2, REG_ITMP3);
1921 M_MOVEQ_IMM(1, REG_ITMP3);
1923 /* low compare: x=x-1(ifLO) */
1924 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1925 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1927 M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1);
1929 /* branch if (x LT 1) */
1930 M_CMP_IMM(REG_ITMP3, 1);
1931 emit_blt(cd, iptr->dst.block);
1934 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
1935 /* op1 = target JavaVM pc */
1937 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1938 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1939 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1941 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1942 M_MOVGT_IMM(2, REG_ITMP3);
1943 M_MOVEQ_IMM(1, REG_ITMP3);
1945 /* low compare: x=x-1(ifLO) */
1946 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1947 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1949 M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1);
1951 /* branch if (x LE 1) */
1952 M_CMP_IMM(REG_ITMP3, 1);
1953 emit_ble(cd, iptr->dst.block);
1956 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
1957 /* op1 = target JavaVM pc */
1959 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1960 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1961 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1963 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1964 M_MOVGT_IMM(2, REG_ITMP3);
1965 M_MOVEQ_IMM(1, REG_ITMP3);
1967 /* low compare: x=x-1(ifLO) */
1968 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1969 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1971 M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1);
1973 /* branch if (x GT 1) */
1974 M_CMP_IMM(REG_ITMP3, 1);
1975 emit_bgt(cd, iptr->dst.block);
1978 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
1979 /* op1 = target JavaVM pc */
1981 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1982 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1983 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1985 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1986 M_MOVGT_IMM(2, REG_ITMP3);
1987 M_MOVEQ_IMM(1, REG_ITMP3);
1989 /* low compare: x=x-1(ifLO) */
1990 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1991 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1993 M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1);
1995 /* branch if (x GE 1) */
1996 M_CMP_IMM(REG_ITMP3, 1);
1997 emit_bge(cd, iptr->dst.block);
2000 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2003 branch_target_t *table;
2005 table = iptr->dst.table;
2007 l = iptr->sx.s23.s2.tablelow;
2008 i = iptr->sx.s23.s3.tablehigh;
2010 /* calculate new index (index - low) */
2011 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2013 M_INTMOVE(s1, REG_ITMP1);
2014 } else if (IS_IMM(l)) {
2015 M_SUB_IMM(REG_ITMP1, s1, l);
2017 ICONST(REG_ITMP2, l);
2018 M_SUB(REG_ITMP1, s1, REG_ITMP2);
2021 /* range check (index <= high-low) */
2023 M_COMPARE(REG_ITMP1, i-1);
2024 emit_bugt(cd, table[0].block);
2026 /* build jump table top down and use address of lowest entry */
2031 dseg_add_target(cd, table->block);
2036 /* length of dataseg after last dseg_add_target is used by load */
2037 /* TODO: this loads from data-segment */
2038 M_ADD(REG_ITMP2, REG_PV, REG_LSL(REG_ITMP1, 2));
2039 M_LDR(REG_PC, REG_ITMP2, -(cd->dseglen));
2042 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2045 lookup_target_t *lookup;
2047 lookup = iptr->dst.lookup;
2049 i = iptr->sx.s23.s2.lookupcount;
2052 MCODECHECK((i<<2)+8);
2053 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2056 M_COMPARE(s1, lookup->value);
2057 emit_beq(cd, lookup->target.block);
2061 /* default branch */
2062 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2066 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2068 #if !defined(ENABLE_SOFTFLOAT)
2069 REPLACEMENT_POINT_RETURN(cd, iptr);
2070 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
2071 M_CAST_F2I(s1, REG_RESULT);
2072 goto ICMD_RETURN_do;
2075 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2077 REPLACEMENT_POINT_RETURN(cd, iptr);
2078 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2079 M_INTMOVE(s1, REG_RESULT);
2080 goto ICMD_RETURN_do;
2082 case ICMD_DRETURN: /* ..., retvalue ==> ... */
2084 #if !defined(ENABLE_SOFTFLOAT)
2085 REPLACEMENT_POINT_RETURN(cd, iptr);
2086 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
2087 M_CAST_D2L(s1, REG_RESULT_PACKED);
2088 goto ICMD_RETURN_do;
2091 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2093 REPLACEMENT_POINT_RETURN(cd, iptr);
2094 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2095 M_LNGMOVE(s1, REG_RESULT_PACKED);
2096 goto ICMD_RETURN_do;
2098 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2100 REPLACEMENT_POINT_RETURN(cd, iptr);
2101 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2102 M_INTMOVE(s1, REG_RESULT);
2103 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2104 patcher_add_patch_ref(jd, PATCHER_resolve_class,
2105 iptr->sx.s23.s2.uc, 0);
2107 goto ICMD_RETURN_do;
2109 case ICMD_RETURN: /* ... ==> ... */
2111 REPLACEMENT_POINT_RETURN(cd, iptr);
2114 #if !defined(NDEBUG)
2115 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2116 emit_verbosecall_exit(jd);
2119 #if defined(ENABLE_THREADS)
2120 /* call monitorexit function */
2122 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2123 /* stack offset for monitor argument */
2125 s1 = rd->memuse * 8;
2127 /* we need to save the proper return value */
2129 switch (iptr->opc) {
2133 case ICMD_FRETURN: /* XXX TWISTI: is that correct? */
2135 M_STMFD(BITMASK_RESULT, REG_SP);
2140 M_LDR(REG_A0, REG_SP, s1);
2141 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2142 M_DSEG_BRANCH(disp);
2144 /* we no longer need PV here, no more loading */
2145 /*s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2146 M_RECOMPUTE_PV(s1);*/
2148 switch (iptr->opc) {
2152 case ICMD_FRETURN: /* XXX TWISTI: is that correct? */
2154 M_LDMFD(BITMASK_RESULT, REG_SP);
2160 /* deallocate stackframe for spilled variables */
2162 if ((cd->stackframesize / 4 - savedregs_num) > 0)
2163 M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - savedregs_num);
2165 /* restore callee saved registers + do return */
2167 if (savedregs_bitmask) {
2168 if (!jd->isleafmethod) {
2169 savedregs_bitmask &= ~(1<<REG_LR);
2170 savedregs_bitmask |= (1<<REG_PC);
2172 M_LDMFD(savedregs_bitmask, REG_SP);
2175 /* if LR was not on stack, we need to return manually */
2177 if (jd->isleafmethod)
2178 M_MOV(REG_PC, REG_LR);
2181 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
2183 bte = iptr->sx.s23.s3.bte;
2185 goto ICMD_INVOKE_do;
2187 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2188 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2189 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2190 case ICMD_INVOKEINTERFACE:
2192 REPLACEMENT_POINT_INVOKE(cd, iptr);
2194 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2196 um = iptr->sx.s23.s3.um;
2197 md = um->methodref->parseddesc.md;
2200 lm = iptr->sx.s23.s3.fmiref->p.method;
2202 md = lm->parseddesc;
2206 /* copy arguments to registers or stack location */
2208 s3 = md->paramcount;
2210 MCODECHECK((s3 << 1) + 64);
2212 for (s3 = s3 - 1; s3 >= 0; s3--) {
2213 var = VAR(iptr->sx.s23.s2.args[s3]);
2214 d = md->params[s3].regoff;
2216 if (var->flags & PREALLOC) /* argument was precolored? */
2219 /* TODO: document me */
2220 #if !defined(ENABLE_SOFTFLOAT)
2221 if (IS_INT_LNG_TYPE(var->type)) {
2222 #endif /* !defined(ENABLE_SOFTFLOAT) */
2223 if (!md->params[s3].inmemory) {
2224 s1 = emit_load(jd, iptr, var, d);
2226 if (IS_2_WORD_TYPE(var->type))
2232 if (IS_2_WORD_TYPE(var->type)) {
2233 s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2234 M_LST(s1, REG_SP, d);
2237 s1 = emit_load(jd, iptr, var, REG_ITMP1);
2238 M_IST(s1, REG_SP, d);
2241 #if !defined(ENABLE_SOFTFLOAT)
2244 if (!md->params[s3].inmemory) {
2245 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2246 if (IS_2_WORD_TYPE(var->type))
2252 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2253 if (IS_2_WORD_TYPE(var->type))
2254 M_DST(s1, REG_SP, d);
2256 M_FST(s1, REG_SP, d);
2259 #endif /* !defined(ENABLE_SOFTFLOAT) */
2262 switch (iptr->opc) {
2265 if (bte->stub == NULL) {
2266 disp = dseg_add_functionptr(cd, bte->fp);
2268 disp = dseg_add_functionptr(cd, bte->stub);
2271 M_DSEG_LOAD(REG_PV, disp); /* pointer to built-in-function */
2273 /* generate the actual call */
2275 M_MOV(REG_LR, REG_PC);
2276 M_MOV(REG_PC, REG_PV);
2277 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2281 case ICMD_INVOKESPECIAL:
2282 emit_nullpointer_check(cd, iptr, REG_A0);
2285 case ICMD_INVOKESTATIC:
2287 disp = dseg_add_unique_address(cd, NULL);
2289 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2293 disp = dseg_add_address(cd, lm->stubroutine);
2295 M_DSEG_LOAD(REG_PV, disp); /* Pointer to method */
2297 /* generate the actual call */
2299 M_MOV(REG_LR, REG_PC);
2300 M_MOV(REG_PC, REG_PV);
2301 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2305 case ICMD_INVOKEVIRTUAL:
2307 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2312 s1 = OFFSET(vftbl_t, table[0]) +
2313 sizeof(methodptr) * lm->vftblindex;
2315 /* implicit null-pointer check */
2316 M_LDR_INTERN(REG_METHODPTR, REG_A0,
2317 OFFSET(java_object_t, vftbl));
2318 M_LDR_INTERN(REG_PV, REG_METHODPTR, s1);
2320 /* generate the actual call */
2322 M_MOV(REG_LR, REG_PC);
2323 M_MOV(REG_PC, REG_PV);
2324 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2328 case ICMD_INVOKEINTERFACE:
2330 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2336 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2337 sizeof(methodptr*) * lm->class->index;
2338 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2341 /* implicit null-pointer check */
2342 M_LDR_INTERN(REG_METHODPTR, REG_A0,
2343 OFFSET(java_object_t, vftbl));
2344 M_LDR_INTERN(REG_METHODPTR, REG_METHODPTR, s1);
2345 M_LDR_INTERN(REG_PV, REG_METHODPTR, s2);
2347 /* generate the actual call */
2349 M_MOV(REG_LR, REG_PC);
2350 M_MOV(REG_PC, REG_PV);
2351 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2356 /* store size of call code in replacement point */
2357 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2359 /* store return value */
2361 d = md->returntype.type;
2363 #if !defined(__SOFTFP__)
2364 /* TODO: this is only a hack, since we use R0/R1 for float
2365 return! this depends on gcc; it is independent from
2366 our ENABLE_SOFTFLOAT define */
2367 if (iptr->opc == ICMD_BUILTIN && d != TYPE_VOID && IS_FLT_DBL_TYPE(d)) {
2368 #if 0 && !defined(NDEBUG)
2369 dolog("BUILTIN that returns float or double (%s.%s)", m->class->name->text, m->name->text);
2371 /* we cannot use this macro, since it is not defined
2372 in ENABLE_SOFTFLOAT M_CAST_FLT_TO_INT_TYPED(d,
2373 REG_FRESULT, REG_RESULT_TYPED(d)); */
2374 if (IS_2_WORD_TYPE(d)) {
2375 DCD(0xed2d8102); /* stfd f0, [sp, #-8]! */
2376 M_LDRD_UPDATE(REG_RESULT_PACKED, REG_SP, 8);
2378 DCD(0xed2d0101); /* stfs f0, [sp, #-4]!*/
2379 M_LDR_UPDATE(REG_RESULT, REG_SP, 4);
2384 if (d != TYPE_VOID) {
2385 #if !defined(ENABLE_SOFTFLOAT)
2386 if (IS_INT_LNG_TYPE(d)) {
2387 #endif /* !defined(ENABLE_SOFTFLOAT) */
2388 if (IS_2_WORD_TYPE(d)) {
2389 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2390 M_LNGMOVE(REG_RESULT_PACKED, s1);
2393 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2394 M_INTMOVE(REG_RESULT, s1);
2397 #if !defined(ENABLE_SOFTFLOAT)
2399 s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2400 if (IS_2_WORD_TYPE(d))
2401 M_CAST_L2D(REG_RESULT_PACKED, s1);
2403 M_CAST_I2F(REG_RESULT, s1);
2405 #endif /* !defined(ENABLE_SOFTFLOAT) */
2407 emit_store_dst(jd, iptr, s1);
2411 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2413 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2414 /* object type cast-check */
2419 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2424 super = iptr->sx.s23.s3.c.cls;
2425 superindex = super->index;
2428 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2429 CODEGEN_CRITICAL_SECTION_NEW;
2431 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2433 /* if class is not resolved, check which code to call */
2435 if (super == NULL) {
2437 emit_label_beq(cd, BRANCH_LABEL_1);
2439 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2440 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2441 iptr->sx.s23.s3.c.ref, disp);
2443 M_DSEG_LOAD(REG_ITMP2, disp);
2444 disp = dseg_add_s4(cd, ACC_INTERFACE);
2445 M_DSEG_LOAD(REG_ITMP3, disp);
2446 M_TST(REG_ITMP2, REG_ITMP3);
2447 emit_label_beq(cd, BRANCH_LABEL_2);
2450 /* interface checkcast code */
2452 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2453 if ((super == NULL) || !IS_IMM(superindex)) {
2454 disp = dseg_add_unique_s4(cd, superindex);
2456 if (super == NULL) {
2457 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
2458 iptr->sx.s23.s3.c.ref, disp);
2462 emit_label_beq(cd, BRANCH_LABEL_3);
2465 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2466 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2468 /* we put unresolved or non-immediate superindices onto dseg */
2469 if ((super == NULL) || !IS_IMM(superindex)) {
2470 /* disp was computed before we added the patcher */
2471 M_DSEG_LOAD(REG_ITMP2, disp);
2472 M_CMP(REG_ITMP3, REG_ITMP2);
2474 assert(IS_IMM(superindex));
2475 M_CMP_IMM(REG_ITMP3, superindex);
2478 emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
2480 /* if we loaded the superindex out of the dseg above, we do
2481 things differently here! */
2482 if ((super == NULL) || !IS_IMM(superindex)) {
2484 M_LDR_INTERN(REG_ITMP3, s1, OFFSET(java_object_t, vftbl));
2486 /* this assumes something */
2487 assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
2489 /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
2490 assert(sizeof(methodptr*) == 4);
2491 M_SUB(REG_ITMP2, REG_ITMP3, REG_LSL(REG_ITMP2, 2));
2497 s2 = OFFSET(vftbl_t, interfacetable[0]) -
2498 superindex * sizeof(methodptr*);
2502 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, s2);
2503 M_TST(REG_ITMP3, REG_ITMP3);
2504 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
2507 emit_label_br(cd, BRANCH_LABEL_4);
2509 emit_label(cd, BRANCH_LABEL_3);
2512 /* class checkcast code */
2514 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2515 if (super == NULL) {
2516 emit_label(cd, BRANCH_LABEL_2);
2518 disp = dseg_add_unique_address(cd, NULL);
2520 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2521 iptr->sx.s23.s3.c.ref,
2525 disp = dseg_add_address(cd, super->vftbl);
2528 emit_label_beq(cd, BRANCH_LABEL_5);
2531 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2532 M_DSEG_LOAD(REG_ITMP3, disp);
2534 CODEGEN_CRITICAL_SECTION_START;
2536 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2537 M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2538 M_SUB(REG_ITMP2, REG_ITMP2, REG_ITMP3);
2539 M_DSEG_LOAD(REG_ITMP3, disp);
2540 M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2542 CODEGEN_CRITICAL_SECTION_END;
2544 M_CMP(REG_ITMP2, REG_ITMP3);
2545 emit_classcast_check(cd, iptr, BRANCH_UGT, 0, s1);
2548 emit_label(cd, BRANCH_LABEL_5);
2551 if (super == NULL) {
2552 emit_label(cd, BRANCH_LABEL_1);
2553 emit_label(cd, BRANCH_LABEL_4);
2556 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
2559 /* array type cast-check */
2561 s1 = emit_load_s1(jd, iptr, REG_A0);
2562 M_INTMOVE(s1, REG_A0);
2564 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2565 disp = dseg_add_unique_address(cd, NULL);
2567 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2568 iptr->sx.s23.s3.c.ref,
2572 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2574 M_DSEG_LOAD(REG_A1, disp);
2575 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2576 M_DSEG_BRANCH(disp);
2579 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2580 M_RECOMPUTE_PV(disp);
2582 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2583 M_TST(REG_RESULT, REG_RESULT);
2584 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2586 d = codegen_reg_of_dst(jd, iptr, s1);
2590 emit_store_dst(jd, iptr, d);
2593 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2599 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2604 super = iptr->sx.s23.s3.c.cls;
2605 superindex = super->index;
2608 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2609 CODEGEN_CRITICAL_SECTION_NEW;
2611 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2612 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2615 M_MOV(REG_ITMP1, s1);
2619 /* if class is not resolved, check which code to call */
2621 if (super == NULL) {
2625 emit_label_beq(cd, BRANCH_LABEL_1);
2627 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2628 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2629 iptr->sx.s23.s3.c.ref, disp);
2631 M_DSEG_LOAD(REG_ITMP2, disp);
2632 disp = dseg_add_s4(cd, ACC_INTERFACE);
2633 M_DSEG_LOAD(REG_ITMP3, disp);
2634 M_TST(REG_ITMP2, REG_ITMP3);
2635 emit_label_beq(cd, BRANCH_LABEL_2);
2638 /* interface checkcast code */
2640 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2641 if ((super == NULL) || !IS_IMM(superindex)) {
2642 disp = dseg_add_unique_s4(cd, superindex);
2644 if (super == NULL) {
2645 /* If d == REG_ITMP2, then it's destroyed in check
2650 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
2651 iptr->sx.s23.s3.c.ref, disp);
2656 emit_label_beq(cd, BRANCH_LABEL_3);
2659 M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2660 M_LDR_INTERN(REG_ITMP3,
2661 REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2663 /* we put unresolved or non-immediate superindices onto dseg
2664 and do things slightly different */
2665 if ((super == NULL) || !IS_IMM(superindex)) {
2666 /* disp was computed before we added the patcher */
2667 M_DSEG_LOAD(REG_ITMP2, disp);
2668 M_CMP(REG_ITMP3, REG_ITMP2);
2670 if (d == REG_ITMP2) {
2677 /* this assumes something */
2678 assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
2680 /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
2681 assert(sizeof(methodptr*) == 4);
2682 M_SUB(REG_ITMP1, REG_ITMP1, REG_LSL(REG_ITMP2, 2));
2684 if (d == REG_ITMP2) {
2691 assert(IS_IMM(superindex));
2692 M_CMP_IMM(REG_ITMP3, superindex);
2696 s2 = OFFSET(vftbl_t, interfacetable[0]) -
2697 superindex * sizeof(methodptr*);
2701 M_LDR_INTERN(REG_ITMP3, REG_ITMP1, s2);
2702 M_TST(REG_ITMP3, REG_ITMP3);
2706 emit_label_br(cd, BRANCH_LABEL_4);
2708 emit_label(cd, BRANCH_LABEL_3);
2711 /* class checkcast code */
2713 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2714 if (super == NULL) {
2715 emit_label(cd, BRANCH_LABEL_2);
2717 disp = dseg_add_unique_address(cd, NULL);
2719 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2720 iptr->sx.s23.s3.c.ref, disp);
2723 disp = dseg_add_address(cd, super->vftbl);
2727 emit_label_beq(cd, BRANCH_LABEL_5);
2730 M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2731 M_DSEG_LOAD(REG_ITMP2, disp);
2733 CODEGEN_CRITICAL_SECTION_START;
2735 M_LDR_INTERN(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2736 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2737 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2739 CODEGEN_CRITICAL_SECTION_END;
2741 M_SUB(REG_ITMP1, REG_ITMP1, REG_ITMP3);
2742 M_CMP(REG_ITMP1, REG_ITMP2);
2743 /* If d == REG_ITMP2, then it's destroyed */
2749 emit_label(cd, BRANCH_LABEL_5);
2752 if (super == NULL) {
2753 emit_label(cd, BRANCH_LABEL_1);
2754 emit_label(cd, BRANCH_LABEL_4);
2759 emit_store_dst(jd, iptr, d);
2762 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2764 /* copy sizes to stack if necessary */
2766 MCODECHECK((iptr->s1.argcount << 1) + 64);
2768 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2770 var = VAR(iptr->sx.s23.s2.args[s1]);
2772 /* copy SAVEDVAR sizes to stack */
2774 if (!(var->flags & PREALLOC)) {
2775 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2776 M_STR(s2, REG_SP, s1 * 4);
2780 /* a0 = dimension count */
2782 assert(IS_IMM(iptr->s1.argcount));
2783 M_MOV_IMM(REG_A0, iptr->s1.argcount);
2785 /* is patcher function set? */
2787 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2788 disp = dseg_add_unique_address(cd, NULL);
2790 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2791 iptr->sx.s23.s3.c.ref, disp);
2794 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2796 /* a1 = arraydescriptor */
2798 M_DSEG_LOAD(REG_A1, disp);
2800 /* a2 = pointer to dimensions = stack pointer */
2802 M_INTMOVE(REG_SP, REG_A2);
2804 /* call builtin_multianewarray here */
2806 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2807 M_DSEG_BRANCH(disp);
2811 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2814 /* check for exception before result assignment */
2816 emit_exception_check(cd, iptr);
2820 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2821 M_INTMOVE(REG_RESULT, d);
2822 emit_store_dst(jd, iptr, d);
2825 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
2827 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2828 emit_nullpointer_check(cd, iptr, s1);
2832 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
2835 } /* the big switch */
2837 } /* for all instructions */
2839 } /* for all basic blocks */
2841 dseg_createlinenumbertable(cd);
2844 /* generate traps */
2846 emit_patcher_traps(jd);
2848 /* everything's ok */
2854 /* codegen_emit_stub_compiler **************************************************
2856 Emits a stub routine which calls the compiler.
2858 *******************************************************************************/
2860 void codegen_emit_stub_compiler(jitdata *jd)
2865 /* get required compiler data */
2870 /* code for the stub */
2872 M_LDR_INTERN(REG_ITMP1, REG_PC, -(2 * 4 + 2 * SIZEOF_VOID_P));
2873 M_LDR_INTERN(REG_PC, REG_PC, -(3 * 4 + 3 * SIZEOF_VOID_P));
2877 /* codegen_emit_stub_native ****************************************************
2879 Emits a stub routine which calls a native method.
2881 *******************************************************************************/
2883 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2891 s4 disp, funcdisp, s1, s2;
2893 /* get required compiler data */
2899 /* initialize variables */
2903 /* calculate stackframe size */
2905 cd->stackframesize =
2906 4 + /* return address */
2907 sizeof(stackframeinfo) + /* stackframeinfo */
2908 sizeof(localref_table) + /* localref_table */
2909 nmd->memuse * 4; /* stack arguments */
2911 /* align stack to 8-byte */
2913 cd->stackframesize = (cd->stackframesize + 4) & ~4;
2915 /* create method header */
2917 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2918 (void) dseg_add_unique_s4(cd, cd->stackframesize); /* FrameSize */
2919 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2920 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2921 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2922 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2923 (void) dseg_addlinenumbertablesize(cd);
2924 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2926 /* generate stub code */
2928 M_STMFD(1<<REG_LR, REG_SP);
2929 M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - 1);
2931 #if !defined(NDEBUG)
2932 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2933 emit_verbosecall_enter(jd);
2936 /* get function address (this must happen before the stackframeinfo) */
2938 funcdisp = dseg_add_functionptr(cd, f);
2941 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
2943 #if defined(ENABLE_GC_CACAO)
2944 /* Save callee saved integer registers in stackframeinfo (GC may
2945 need to recover them during a collection). */
2947 disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo) +
2948 OFFSET(stackframeinfo, intregs);
2950 for (i = 0; i < INT_SAV_CNT; i++)
2951 M_STR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2954 /* Save integer and float argument registers (these are 4
2955 registers, stack is 8-byte aligned). */
2957 M_STMFD(BITMASK_ARGS, REG_SP);
2958 /* TODO: floating point */
2960 /* create native stackframe info */
2962 M_ADD_IMM(REG_A0, REG_SP, 4*4);
2963 M_MOV(REG_A1, REG_PV);
2964 disp = dseg_add_functionptr(cd, codegen_start_native_call);
2965 M_DSEG_BRANCH(disp);
2969 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2972 /* remember class argument */
2974 if (m->flags & ACC_STATIC)
2975 M_MOV(REG_ITMP3, REG_RESULT);
2977 /* Restore integer and float argument registers (these are 4
2978 registers, stack is 8-byte aligned). */
2980 M_LDMFD(BITMASK_ARGS, REG_SP);
2981 /* TODO: floating point */
2983 /* copy or spill arguments to new locations */
2984 /* ATTENTION: the ARM has only integer argument registers! */
2986 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2987 t = md->paramtypes[i].type;
2989 if (!md->params[i].inmemory) {
2990 s1 = md->params[i].regoff;
2991 s2 = nmd->params[j].regoff;
2993 if (!nmd->params[j].inmemory) {
2994 #if !defined(__ARM_EABI__)
2995 SPLIT_OPEN(t, s2, REG_ITMP1);
2998 if (IS_2_WORD_TYPE(t))
3003 #if !defined(__ARM_EABI__)
3004 SPLIT_STORE_AND_CLOSE(t, s2, 0);
3008 if (IS_2_WORD_TYPE(t))
3009 M_LST(s1, REG_SP, s2);
3011 M_IST(s1, REG_SP, s2);
3015 s1 = md->params[i].regoff + cd->stackframesize;
3016 s2 = nmd->params[j].regoff;
3018 if (IS_2_WORD_TYPE(t)) {
3019 M_LLD(REG_ITMP12_PACKED, REG_SP, s1);
3020 M_LST(REG_ITMP12_PACKED, REG_SP, s2);
3023 M_ILD(REG_ITMP1, REG_SP, s1);
3024 M_IST(REG_ITMP1, REG_SP, s2);
3029 /* Handle native Java methods. */
3031 if (m->flags & ACC_NATIVE) {
3032 /* put class into second argument register */
3034 if (m->flags & ACC_STATIC)
3035 M_MOV(REG_A1, REG_ITMP3);
3037 /* put env into first argument register */
3039 disp = dseg_add_address(cd, _Jv_env);
3040 M_DSEG_LOAD(REG_A0, disp);
3043 /* do the native function call */
3045 M_DSEG_BRANCH(funcdisp);
3048 /* TODO: this is only needed because of the tracer ... do we
3051 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
3054 #if !defined(__SOFTFP__)
3055 /* TODO: this is only a hack, since we use R0/R1 for float return! */
3056 /* this depends on gcc; it is independent from our ENABLE_SOFTFLOAT define */
3057 if (md->returntype.type != TYPE_VOID && IS_FLT_DBL_TYPE(md->returntype.type)) {
3058 #if 0 && !defined(NDEBUG)
3059 dolog("NATIVESTUB that returns float or double (%s.%s)", m->class->name->text, m->name->text);
3061 /* we cannot use this macro, since it is not defined in ENABLE_SOFTFLOAT */
3062 /* M_CAST_FLT_TO_INT_TYPED(md->returntype.type, REG_FRESULT, REG_RESULT_TYPED(md->returntype.type)); */
3063 if (IS_2_WORD_TYPE(md->returntype.type)) {
3064 DCD(0xed2d8102); /* stfd f0, [sp, #-8]! */
3065 M_LDRD_UPDATE(REG_RESULT_PACKED, REG_SP, 8);
3067 DCD(0xed2d0101); /* stfs f0, [sp, #-4]!*/
3068 M_LDR_UPDATE(REG_RESULT, REG_SP, 4);
3073 #if !defined(NDEBUG)
3074 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3075 emit_verbosecall_exit(jd);
3078 /* remove native stackframe info */
3079 /* TODO: improve this store/load */
3081 M_STMFD(BITMASK_RESULT, REG_SP);
3083 M_ADD_IMM(REG_A0, REG_SP, 2*4);
3084 M_MOV(REG_A1, REG_PV);
3085 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3086 M_DSEG_BRANCH(disp);
3087 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
3090 M_MOV(REG_ITMP1_XPTR, REG_RESULT);
3091 M_LDMFD(BITMASK_RESULT, REG_SP);
3093 #if defined(ENABLE_GC_CACAO)
3094 /* restore callee saved int registers from stackframeinfo (GC might have */
3095 /* modified them during a collection). */
3097 disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo) +
3098 OFFSET(stackframeinfo, intregs);
3100 for (i = 0; i < INT_SAV_CNT; i++)
3101 M_LDR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3104 /* finish stub code, but do not yet return to caller */
3106 M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - 1);
3107 M_LDMFD(1<<REG_LR, REG_SP);
3109 /* check for exception */
3111 M_TST(REG_ITMP1_XPTR, REG_ITMP1_XPTR);
3112 M_MOVEQ(REG_LR, REG_PC); /* if no exception, return to caller */
3114 /* handle exception here */
3116 M_SUB_IMM(REG_ITMP2_XPC, REG_LR, 4);/* move fault address into xpc */
3118 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3119 M_DSEG_LOAD(REG_ITMP3, disp); /* load asm exception handler address */
3120 M_MOV(REG_PC, REG_ITMP3); /* jump to asm exception handler */
3122 /* generate patcher stubs */
3124 emit_patcher_traps(jd);
3128 /* asm_debug *******************************************************************
3132 *******************************************************************************/
3134 void asm_debug(int a1, int a2, int a3, int a4)
3136 printf("===> i am going to exit after this debugging message!\n");
3137 printf("got asm_debug(%p, %p, %p, %p)\n",(void*)a1,(void*)a2,(void*)a3,(void*)a4);
3138 vm_abort("leave you now");
3143 * These are local overrides for various environment variables in Emacs.
3144 * Please do not remove this and leave it at the end of the file, where
3145 * Emacs will automagically detect them.
3146 * ---------------------------------------------------------------------
3149 * indent-tabs-mode: t
3153 * vim:noexpandtab:sw=4:ts=4: