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
25 $Id: codegen.c 8318 2007-08-16 10:05:34Z michi $
39 #include "vm/jit/arm/arch.h"
40 #include "vm/jit/arm/codegen.h"
42 #include "mm/memory.h"
44 #include "native/localref.h"
45 #include "native/native.h"
47 #include "threads/lock-common.h"
49 #include "vm/builtin.h"
50 #include "vm/exceptions.h"
51 #include "vm/global.h"
54 #include "vm/jit/asmpart.h"
55 #include "vm/jit/codegen-common.h"
56 #include "vm/jit/dseg.h"
57 #include "vm/jit/emit-common.h"
58 #include "vm/jit/jit.h"
59 #include "vm/jit/md.h"
60 #include "vm/jit/methodheader.h"
61 #include "vm/jit/parse.h"
62 #include "vm/jit/patcher-common.h"
63 #include "vm/jit/reg.h"
65 #if defined(ENABLE_LSRA)
66 #include "vm/jit/allocator/lsra.h"
69 #include "vmcore/loader.h"
70 #include "vmcore/options.h"
73 /* codegen_emit ****************************************************************
75 Generates machine code.
77 *******************************************************************************/
79 bool codegen_emit(jitdata *jd)
98 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
99 unresolved_method *um;
100 builtintable_entry *bte;
103 unresolved_field *uf;
107 /* get required compiler data */
114 /* prevent compiler warnings */
122 /* space to save used callee saved registers */
124 savedregs_num = (jd->isleafmethod) ? 0 : 1; /* space to save the LR */
125 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
126 /*savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);*/
127 assert((FLT_SAV_CNT - rd->savfltreguse) == 0);
129 spilledregs_num = rd->memuse;
131 #if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */
132 if (checksync && (m->flags & ACC_SYNCHRONIZED))
136 cd->stackframesize = spilledregs_num * 8 + savedregs_num * 4;
138 /* XXX QUICK FIX: We shouldn't align the stack in Java code, but
139 only in native stubs. */
140 /* align stack to 8-byte */
142 cd->stackframesize = (cd->stackframesize + 4) & ~4;
144 /* SECTION: Method Header */
145 /* create method header */
147 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
148 (void) dseg_add_unique_s4(cd, cd->stackframesize); /* FrameSize */
150 #if defined(ENABLE_THREADS)
151 /* IsSync contains the offset relative to the stack pointer for the
152 argument of monitor_exit used in the exception handler. Since the
153 offset could be zero and give a wrong meaning of the flag it is
157 if (checksync && (m->flags & ACC_SYNCHRONIZED))
158 (void) dseg_add_unique_s4(cd, rd->memuse * 8 + 4);/* IsSync */
161 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
163 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
164 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
165 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
166 (void) dseg_addlinenumbertablesize(cd);
167 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
169 /* create exception table */
171 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
172 dseg_add_target(cd, ex->start);
173 dseg_add_target(cd, ex->end);
174 dseg_add_target(cd, ex->handler);
175 (void) dseg_add_unique_address(cd, ex->catchtype.any);
178 /* save return address and used callee saved registers */
180 savedregs_bitmask = 0;
182 if (!jd->isleafmethod)
183 savedregs_bitmask = (1<<REG_LR);
185 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--)
186 savedregs_bitmask |= (1<<(rd->savintregs[i]));
189 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
190 log_text("!!! CODEGEN: floating-point callee saved registers are not saved to stack (SEVERE! STACK IS MESSED UP!)");
191 /* TODO: floating-point */
195 if (savedregs_bitmask)
196 M_STMFD(savedregs_bitmask, REG_SP);
198 /* create additional stack frame for spilled variables (if necessary) */
200 if ((cd->stackframesize / 4 - savedregs_num) > 0)
201 M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - savedregs_num);
203 /* take arguments out of register or stack frame */
206 for (i = 0, len = 0; i < md->paramcount; i++) {
207 s1 = md->params[i].regoff;
208 t = md->paramtypes[i].type;
210 varindex = jd->local_map[len * 5 + t];
212 len += (IS_2_WORD_TYPE(t)) ? 2 : 1; /* 2 word type arguments */
214 if (varindex == UNUSED)
219 /* ATTENTION: we use interger registers for all arguments (even float) */
220 #if !defined(ENABLE_SOFTFLOAT)
221 if (IS_INT_LNG_TYPE(t)) {
223 if (!md->params[i].inmemory) {
224 if (!(var->flags & INMEMORY)) {
225 if (IS_2_WORD_TYPE(t))
226 M_LNGMOVE(s1, var->vv.regoff);
228 M_INTMOVE(s1, var->vv.regoff);
231 if (IS_2_WORD_TYPE(t))
232 M_LST(s1, REG_SP, var->vv.regoff);
234 M_IST(s1, REG_SP, var->vv.regoff);
237 else { /* stack arguments */
238 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
239 if (IS_2_WORD_TYPE(t))
240 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
242 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
244 else { /* stack arg -> spilled */
245 /* Reuse Memory Position on Caller Stack */
246 var->vv.regoff = cd->stackframesize + s1;
249 #if !defined(ENABLE_SOFTFLOAT)
252 if (!md->params[i].inmemory) {
253 if (!(var->flags & INMEMORY)) {
254 M_CAST_INT_TO_FLT_TYPED(t, s1, var->vv.regoff);
257 if (IS_2_WORD_TYPE(t))
258 M_LST(s1, REG_SP, var->vv.regoff);
260 M_IST(s1, REG_SP, var->vv.regoff);
264 if (!(var->flags & INMEMORY)) {
265 if (IS_2_WORD_TYPE(t))
266 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
268 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
271 /* Reuse Memory Position on Caller Stack */
272 var->vv.regoff = cd->stackframesize + s1;
276 #endif /* !defined(ENABLE_SOFTFLOAT) */
279 #if defined(ENABLE_THREADS)
280 /* call monitorenter function */
282 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
283 /* stack offset for monitor argument */
287 # if !defined(NDEBUG)
288 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
289 M_STMFD(BITMASK_ARGS, REG_SP);
294 /* get the correct lock object */
296 if (m->flags & ACC_STATIC) {
297 disp = dseg_add_address(cd, &m->class->object.header);
298 M_DSEG_LOAD(REG_A0, disp);
301 emit_nullpointer_check_force(cd, iptr, REG_A0);
304 M_STR(REG_A0, REG_SP, s1);
305 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
307 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
310 # if !defined(NDEBUG)
311 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
312 M_LDMFD(BITMASK_ARGS, REG_SP);
318 /* call trace function */
320 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
321 emit_verbosecall_enter(jd);
324 /* end of header generation */
326 /* create replacement points */
327 REPLACEMENT_POINTS_INIT(cd, jd);
329 /* SECTION: ICMD Code Generation */
330 /* for all basic blocks */
332 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
334 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
336 /* is this basic block reached? */
338 if (bptr->flags < BBREACHED)
341 /* branch resolving */
343 codegen_resolve_branchrefs(cd, bptr);
345 /* handle replacement points */
346 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
348 /* copy interface registers to their destination */
354 #if defined(ENABLE_LSRA)
358 var = VAR(bptr->invars[len]);
359 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
360 if (!(var->flags & INMEMORY))
364 M_INTMOVE(REG_ITMP1, d);
365 emit_store(jd, NULL, var, d);
372 var = VAR(bptr->invars[len]);
374 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
375 d = codegen_reg_of_var(0, var, REG_ITMP1);
376 M_INTMOVE(REG_ITMP1, d);
377 emit_store(jd, NULL, var, d);
380 assert((var->flags & INOUT));
383 #if defined(ENABLE_LSRA)
387 /* for all instructions */
390 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
392 /* add line number */
393 if (iptr->line != currentline) {
394 dseg_addlinenumber(cd, iptr->line);
395 currentline = iptr->line;
398 MCODECHECK(64); /* an instruction usually needs < 64 words */
402 case ICMD_NOP: /* ... ==> ... */
405 /* constant operations ************************************************/
407 case ICMD_ICONST: /* ... ==> ..., constant */
409 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
410 ICONST(d, iptr->sx.val.i);
411 emit_store_dst(jd, iptr, d);
414 case ICMD_ACONST: /* ... ==> ..., constant */
416 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
417 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
418 disp = dseg_add_unique_address(cd, NULL);
420 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
421 iptr->sx.val.c.ref, disp);
423 if (opt_showdisassemble)
426 M_DSEG_LOAD(d, disp);
429 ICONST(d, (u4) iptr->sx.val.anyptr);
431 emit_store_dst(jd, iptr, d);
434 case ICMD_LCONST: /* ... ==> ..., constant */
436 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
437 LCONST(d, iptr->sx.val.l);
438 emit_store_dst(jd, iptr, d);
441 case ICMD_FCONST: /* ... ==> ..., constant */
443 #if defined(ENABLE_SOFTFLOAT)
444 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
445 ICONST(d, iptr->sx.val.i);
446 emit_store_dst(jd, iptr, d);
448 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
449 FCONST(d, iptr->sx.val.f);
450 emit_store_dst(jd, iptr, d);
454 case ICMD_DCONST: /* ... ==> ..., constant */
456 #if defined(ENABLE_SOFTFLOAT)
457 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
458 LCONST(d, iptr->sx.val.l);
459 emit_store_dst(jd, iptr, d);
461 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
462 DCONST(d, iptr->sx.val.d);
463 emit_store_dst(jd, iptr, d);
468 /* load/store/copy/move operations ************************************/
470 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
471 case ICMD_ALOAD: /* op1 = local variable */
475 case ICMD_ISTORE: /* ..., value ==> ... */
486 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
490 /* pop operations *****************************************************/
492 /* attention: double and longs are only one entry in CACAO ICMDs */
494 case ICMD_POP: /* ..., value ==> ... */
495 case ICMD_POP2: /* ..., value, value ==> ... */
500 /* integer operations *************************************************/
502 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
504 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
505 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
506 M_MOV(d, REG_LSL(s1, 24));
507 M_MOV(d, REG_ASR(d, 24));
508 emit_store_dst(jd, iptr, d);
511 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
513 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
514 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
515 M_MOV(d, REG_LSL(s1, 16));
516 M_MOV(d, REG_LSR(d, 16)); /* ATTENTION: char is unsigned */
517 emit_store_dst(jd, iptr, d);
520 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
522 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
523 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
524 M_MOV(d, REG_LSL(s1, 16));
525 M_MOV(d, REG_ASR(d, 16));
526 emit_store_dst(jd, iptr, d);
529 case ICMD_I2L: /* ..., value ==> ..., value */
531 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
532 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
533 M_INTMOVE(s1, GET_LOW_REG(d));
534 M_MOV(GET_HIGH_REG(d), REG_ASR(s1, 31));
535 emit_store_dst(jd, iptr, d);
538 case ICMD_L2I: /* ..., value ==> ..., value */
540 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
541 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
543 emit_store_dst(jd, iptr, d);
546 case ICMD_INEG: /* ..., value ==> ..., - value */
548 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
549 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
551 emit_store_dst(jd, iptr, d);
554 case ICMD_LNEG: /* ..., value ==> ..., - value */
556 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
557 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
558 M_RSB_IMMS(GET_LOW_REG(d), GET_LOW_REG(s1), 0);
559 M_RSC_IMM(GET_HIGH_REG(d), GET_HIGH_REG(s1), 0);
560 emit_store_dst(jd, iptr, d);
563 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
565 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
566 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
567 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
569 emit_store_dst(jd, iptr, d);
572 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
574 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
575 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
576 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
577 M_ADD_S(GET_LOW_REG(d), s1, s2);
578 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
579 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
580 M_ADC(GET_HIGH_REG(d), s1, s2);
581 emit_store_dst(jd, iptr, d);
587 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
588 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
590 if (IS_IMM(iptr->sx.val.i)) {
591 M_ADD_IMM(d, s1, iptr->sx.val.i);
592 } else if (IS_IMM(-iptr->sx.val.i)) {
593 M_SUB_IMM(d, s1, (-iptr->sx.val.i));
595 ICONST(REG_ITMP3, iptr->sx.val.i);
596 M_ADD(d, s1, REG_ITMP3);
599 emit_store_dst(jd, iptr, d);
602 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
603 /* sx.val.l = constant */
605 s3 = iptr->sx.val.l & 0xffffffff;
606 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
607 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
609 M_ADD_IMMS(GET_LOW_REG(d), s1, s3);
611 ICONST(REG_ITMP3, s3);
612 M_ADD_S(GET_LOW_REG(d), s1, REG_ITMP3);
614 s3 = iptr->sx.val.l >> 32;
615 s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
617 M_ADC_IMM(GET_HIGH_REG(d), s1, s3);
619 ICONST(REG_ITMP3, s3);
620 M_ADC(GET_HIGH_REG(d), s1, REG_ITMP3);
622 emit_store_dst(jd, iptr, d);
625 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
627 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
628 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
629 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
631 emit_store_dst(jd, iptr, d);
634 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
636 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
637 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
638 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
639 M_SUB_S(GET_LOW_REG(d), s1, s2);
640 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
641 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
642 M_SBC(GET_HIGH_REG(d), s1, s2);
643 emit_store_dst(jd, iptr, d);
646 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
647 /* sx.val.i = constant */
649 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
650 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
651 if (IS_IMM(iptr->sx.val.i))
652 M_SUB_IMM(d, s1, iptr->sx.val.i);
654 ICONST(REG_ITMP3, iptr->sx.val.i);
655 M_SUB(d, s1, REG_ITMP3);
657 emit_store_dst(jd, iptr, d);
660 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
661 /* sx.val.l = constant */
663 s3 = iptr->sx.val.l & 0xffffffff;
664 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
665 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
667 M_SUB_IMMS(GET_LOW_REG(d), s1, s3);
669 ICONST(REG_ITMP3, s3);
670 M_SUB_S(GET_LOW_REG(d), s1, REG_ITMP3);
672 s3 = iptr->sx.val.l >> 32;
673 s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
675 M_SBC_IMM(GET_HIGH_REG(d), s1, s3);
677 ICONST(REG_ITMP3, s3);
678 M_SBC(GET_HIGH_REG(d), s1, REG_ITMP3);
680 emit_store_dst(jd, iptr, d);
683 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
685 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
686 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
687 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
689 emit_store_dst(jd, iptr, d);
692 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
693 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
695 s1 = emit_load_s1(jd, iptr, REG_A0);
696 s2 = emit_load_s2(jd, iptr, REG_A1);
697 emit_arithmetic_check(cd, iptr, s2);
699 /* move arguments into argument registers */
700 M_INTMOVE(s1, REG_A0);
701 M_INTMOVE(s2, REG_A1);
703 /* call builtin function */
704 bte = iptr->sx.s23.s3.bte;
705 disp = dseg_add_functionptr(cd, bte->fp);
709 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
712 /* move result into destination register */
713 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
714 M_INTMOVE(REG_RESULT, d);
715 emit_store_dst(jd, iptr, d);
718 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
719 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
721 /* move arguments into argument registers */
723 s1 = emit_load_s1(jd, iptr, REG_A0_A1_PACKED);
724 s2 = emit_load_s2(jd, iptr, REG_A2_A3_PACKED);
725 /* XXX TODO: only do this if arithmetic check is really done! */
726 M_ORR(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
727 emit_arithmetic_check(cd, iptr, REG_ITMP3);
729 M_LNGMOVE(s1, REG_A0_A1_PACKED);
730 M_LNGMOVE(s2, REG_A2_A3_PACKED);
732 /* call builtin function */
733 bte = iptr->sx.s23.s3.bte;
734 disp = dseg_add_functionptr(cd, bte->fp);
738 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
741 /* move result into destination register */
742 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
743 M_LNGMOVE(REG_RESULT_PACKED, d);
744 emit_store_dst(jd, iptr, d);
747 case ICMD_IMULPOW2: /* ..., value ==> ..., value * (2 ^ constant) */
748 /* sx.val.i = constant */
750 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
751 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
752 M_MOV(d, REG_LSL(s1, iptr->sx.val.i));
753 emit_store_dst(jd, iptr, d);
756 case ICMD_IDIVPOW2: /* ..., value ==> ..., value / (2 ^ constant) */
757 /* sx.val.i = constant */
759 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
760 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
761 /* this rounds towards 0 as java likes it */
762 M_MOV(REG_ITMP3, REG_ASR(s1, 31));
763 M_ADD(REG_ITMP3, s1, REG_LSR(REG_ITMP3, 32 - iptr->sx.val.i));
764 M_MOV(d, REG_ASR(REG_ITMP3, iptr->sx.val.i));
765 /* this rounds towards nearest, not java style */
766 /*M_MOV_S(d, REG_ASR(s1, iptr->sx.val.i));
767 M_ADCMI_IMM(d, d, 0);*/
768 emit_store_dst(jd, iptr, d);
771 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
772 /* sx.val.i = constant [ (2 ^ x) - 1 ] */
774 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
775 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
776 M_MOV_S(REG_ITMP1, s1);
777 M_RSBMI_IMM(REG_ITMP1, REG_ITMP1, 0);
778 if (IS_IMM(iptr->sx.val.i))
779 M_AND_IMM(REG_ITMP1, iptr->sx.val.i, d);
781 ICONST(REG_ITMP3, iptr->sx.val.i);
782 M_AND(REG_ITMP1, REG_ITMP3, d);
784 M_RSBMI_IMM(d, d, 0);
785 emit_store_dst(jd, iptr, d);
788 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
790 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
791 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
792 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
793 M_AND_IMM(s2, 0x1f, REG_ITMP2);
794 M_MOV(d, REG_LSL_REG(s1, REG_ITMP2));
795 emit_store_dst(jd, iptr, d);
798 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
800 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
801 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
802 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
803 M_AND_IMM(s2, 0x1f, REG_ITMP2);
804 M_MOV(d, REG_ASR_REG(s1, REG_ITMP2));
805 emit_store_dst(jd, iptr, d);
808 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
810 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
811 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
812 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
813 M_AND_IMM(s2, 0x1f, REG_ITMP2);
814 M_MOV(d, REG_LSR_REG(s1, REG_ITMP2));
815 emit_store_dst(jd, iptr, d);
818 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
819 /* sx.val.i = constant */
821 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
822 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
823 M_MOV(d, REG_LSL(s1, iptr->sx.val.i & 0x1f));
824 emit_store_dst(jd, iptr, d);
827 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
828 /* sx.val.i = constant */
830 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
831 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
832 /* we need to check for zero here because arm interprets it as SHR by 32 */
833 if ((iptr->sx.val.i & 0x1f) == 0) {
836 M_MOV(d, REG_ASR(s1, iptr->sx.val.i & 0x1f));
838 emit_store_dst(jd, iptr, d);
841 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
842 /* sx.val.i = constant */
844 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
845 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
846 /* we need to check for zero here because arm interprets it as SHR by 32 */
847 if ((iptr->sx.val.i & 0x1f) == 0)
850 M_MOV(d, REG_LSR(s1, iptr->sx.val.i & 0x1f));
851 emit_store_dst(jd, iptr, d);
854 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
856 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
857 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
858 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
860 emit_store_dst(jd, iptr, d);
863 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
865 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
866 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
867 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
868 M_AND(s1, s2, GET_LOW_REG(d));
869 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
870 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
871 M_AND(s1, s2, GET_HIGH_REG(d));
872 emit_store_dst(jd, iptr, d);
875 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
877 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
878 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
879 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
881 emit_store_dst(jd, iptr, d);
884 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
886 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
887 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
888 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
889 M_ORR(s1, s2, GET_LOW_REG(d));
890 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
891 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
892 M_ORR(s1, s2, GET_HIGH_REG(d));
893 emit_store_dst(jd, iptr, d);
896 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
898 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
899 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
900 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
902 emit_store_dst(jd, iptr, d);
905 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
907 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
908 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
909 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
910 M_EOR(s1, s2, GET_LOW_REG(d));
911 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
912 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
913 M_EOR(s1, s2, GET_HIGH_REG(d));
914 emit_store_dst(jd, iptr, d);
918 /* floating operations ************************************************/
920 #if !defined(ENABLE_SOFTFLOAT)
922 case ICMD_FNEG: /* ..., value ==> ..., - value */
924 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
925 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
927 emit_store_dst(jd, iptr, d);
930 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
932 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
933 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
934 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
936 emit_store_dst(jd, iptr, d);
939 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
941 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
942 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
943 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
945 emit_store_dst(jd, iptr, d);
948 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
950 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
951 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
952 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
954 emit_store_dst(jd, iptr, d);
957 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
958 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
959 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
960 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
962 emit_store_dst(jd, iptr, d);
965 /* 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);
977 case ICMD_DNEG: /* ..., value ==> ..., - value */
979 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
980 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
982 emit_store_dst(jd, iptr, d);
985 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
987 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
988 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
989 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
991 emit_store_dst(jd, iptr, d);
994 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
996 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
997 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
998 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1000 emit_store_dst(jd, iptr, d);
1003 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1005 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1006 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1007 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1009 emit_store_dst(jd, iptr, d);
1012 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1014 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1015 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1016 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1018 emit_store_dst(jd, iptr, d);
1021 /* ATTENTION: Jave does not want IEEE behaviour in DREM, do
1024 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1026 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1027 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1028 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1030 emit_store_dst(jd, iptr, d);
1033 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1035 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1036 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1038 emit_store_dst(jd, iptr, d);
1041 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1043 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1044 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1046 emit_store_dst(jd, iptr, d);
1049 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1051 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1052 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1053 /* this uses round towards zero, as Java likes it */
1055 /* this checks for NaN; to return zero as Java likes it */
1058 emit_store_dst(jd, iptr, d);
1061 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1063 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1064 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1065 /* this uses round towards zero, as Java likes it */
1067 /* this checks for NaN; to return zero as Java likes it */
1070 emit_store_dst(jd, iptr, d);
1073 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1075 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1076 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1078 emit_store_dst(jd, iptr, d);
1081 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1083 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1084 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1086 emit_store_dst(jd, iptr, d);
1089 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1091 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1092 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1093 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1096 M_SUBGT_IMM(d, d, 1);
1097 M_ADDLT_IMM(d, d, 1);
1098 emit_store_dst(jd, iptr, d);
1101 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 dcmpg val2 */
1103 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1104 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1105 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1108 M_SUBGT_IMM(d, d, 1);
1109 M_ADDLT_IMM(d, d, 1);
1110 emit_store_dst(jd, iptr, d);
1113 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1115 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1116 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1117 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1120 M_SUBLT_IMM(d, d, 1);
1121 M_ADDGT_IMM(d, d, 1);
1122 emit_store_dst(jd, iptr, d);
1125 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 dcmpl val2 */
1127 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1128 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1129 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1132 M_SUBLT_IMM(d, d, 1);
1133 M_ADDGT_IMM(d, d, 1);
1134 emit_store_dst(jd, iptr, d);
1137 #endif /* !defined(ENABLE_SOFTFLOAT) */
1140 /* memory operations **************************************************/
1142 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1144 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1145 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1146 /* implicit null-pointer check */
1147 M_ILD_INTERN(d, s1, OFFSET(java_array_t, size));
1148 emit_store_dst(jd, iptr, d);
1151 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1153 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1154 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1155 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1156 /* implicit null-pointer check */
1157 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1158 M_ADD(REG_ITMP1, s1, s2); /* REG_ITMP1 = s1 + 1 * s2 */
1159 M_LDRSB(d, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1160 emit_store_dst(jd, iptr, d);
1163 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1165 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1166 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1167 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1168 /* implicit null-pointer check */
1169 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1170 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1171 M_LDRH(d, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1172 emit_store_dst(jd, iptr, d);
1175 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1177 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1178 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1179 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1180 /* implicit null-pointer check */
1181 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1182 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1183 M_LDRSH(d, REG_ITMP1, OFFSET(java_shortarray_t, data[0]));
1184 emit_store_dst(jd, iptr, d);
1187 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1189 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1190 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1191 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1192 /* implicit null-pointer check */
1193 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1194 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1195 M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1196 emit_store_dst(jd, iptr, d);
1199 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1201 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1202 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1203 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1204 /* implicit null-pointer check */
1205 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1206 M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
1207 M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1208 emit_store_dst(jd, iptr, d);
1211 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1213 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1214 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1215 /* implicit null-pointer check */
1216 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1217 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1218 #if !defined(ENABLE_SOFTFLOAT)
1219 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1220 M_FLD_INTERN(d, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1222 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1223 M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1225 emit_store_dst(jd, iptr, d);
1228 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1230 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1231 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1232 /* implicit null-pointer check */
1233 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1234 M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
1235 #if !defined(ENABLE_SOFTFLOAT)
1236 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1237 M_DLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1239 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1240 M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1242 emit_store_dst(jd, iptr, d);
1245 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1247 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1248 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1249 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1250 /* implicit null-pointer check */
1251 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1252 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1253 M_LDR_INTERN(d, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1254 emit_store_dst(jd, iptr, d);
1257 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1259 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1260 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1261 /* implicit null-pointer check */
1262 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1263 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1264 M_ADD(REG_ITMP1, s1, s2); /* REG_ITMP1 = s1 + 1 * s2 */
1265 M_STRB(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1268 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1270 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1271 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1272 /* implicit null-pointer check */
1273 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1274 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1275 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1276 M_STRH(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1279 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1281 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1282 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1283 /* implicit null-pointer check */
1284 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1285 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1286 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1287 M_STRH(s3, REG_ITMP1, OFFSET(java_shortarray_t, data[0]));
1290 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1292 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1293 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1294 /* implicit null-pointer check */
1295 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1296 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1297 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1298 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1301 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1303 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1304 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1305 /* implicit null-pointer check */
1306 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1307 M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
1308 s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1309 M_LST_INTERN(s3, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1312 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1314 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1315 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1316 /* implicit null-pointer check */
1317 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1318 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1319 #if !defined(ENABLE_SOFTFLOAT)
1320 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1321 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1323 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1324 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1328 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1330 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1331 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1332 /* implicit null-pointer check */
1333 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1334 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 3)); /* REG_ITMP1 = s1 + 8 * s2 */
1335 #if !defined(ENABLE_SOFTFLOAT)
1336 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1337 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1339 s3 = emit_load_s3(jd, iptr, REG_ITMP23_PACKED);
1340 M_LST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1344 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1346 s1 = emit_load_s1(jd, iptr, REG_A0);
1347 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1348 s3 = emit_load_s3(jd, iptr, REG_A1);
1350 /* implicit null-pointer check */
1351 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1353 /* move arguments to argument registers */
1354 M_INTMOVE(s1, REG_A0);
1355 M_INTMOVE(s3, REG_A1);
1357 /* call builtin function */
1358 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1359 M_DSEG_BRANCH(disp);
1362 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
1365 /* check resturn value of builtin */
1366 emit_exception_check(cd, iptr);
1368 /* finally store address into array */
1369 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1370 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1371 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1372 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1373 M_STR_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1376 case ICMD_GETSTATIC: /* ... ==> ..., value */
1378 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1379 uf = iptr->sx.s23.s3.uf;
1380 fieldtype = uf->fieldref->parseddesc.fd->type;
1381 disp = dseg_add_unique_address(cd, NULL);
1383 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1385 if (opt_showdisassemble)
1389 fi = iptr->sx.s23.s3.fmiref->p.field;
1390 fieldtype = fi->type;
1391 disp = dseg_add_address(cd, fi->value);
1393 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1394 patcher_add_patch_ref(jd, PATCHER_initialize_class,
1397 if (opt_showdisassemble)
1402 M_DSEG_LOAD(REG_ITMP3, disp);
1403 switch (fieldtype) {
1405 #if defined(ENABLE_SOFTFLOAT)
1409 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1410 M_ILD_INTERN(d, REG_ITMP3, 0);
1413 #if defined(ENABLE_SOFTFLOAT)
1416 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1417 M_LLD_INTERN(d, REG_ITMP3, 0);
1419 #if !defined(ENABLE_SOFTFLOAT)
1421 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1422 M_FLD_INTERN(d, REG_ITMP3, 0);
1425 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1426 M_DLD_INTERN(d, REG_ITMP3, 0);
1432 emit_store_dst(jd, iptr, d);
1435 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1437 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1438 uf = iptr->sx.s23.s3.uf;
1439 fieldtype = uf->fieldref->parseddesc.fd->type;
1440 disp = dseg_add_unique_address(cd, NULL);
1442 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1444 if (opt_showdisassemble)
1448 fi = iptr->sx.s23.s3.fmiref->p.field;
1449 fieldtype = fi->type;
1450 disp = dseg_add_address(cd, fi->value);
1452 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1453 patcher_add_patch_ref(jd, PATCHER_initialize_class,
1456 if (opt_showdisassemble)
1461 M_DSEG_LOAD(REG_ITMP3, disp);
1462 switch (fieldtype) {
1464 #if defined(ENABLE_SOFTFLOAT)
1468 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1469 M_IST_INTERN(s1, REG_ITMP3, 0);
1472 #if defined(ENABLE_SOFTFLOAT)
1475 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
1476 M_LST_INTERN(s1, REG_ITMP3, 0);
1478 #if !defined(ENABLE_SOFTFLOAT)
1480 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1481 M_FST_INTERN(s1, REG_ITMP3, 0);
1484 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1485 M_DST_INTERN(s1, REG_ITMP3, 0);
1493 case ICMD_GETFIELD: /* ..., objectref, value ==> ... */
1495 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
1496 emit_nullpointer_check(cd, iptr, s1);
1499 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1500 uf = iptr->sx.s23.s3.uf;
1501 fieldtype = uf->fieldref->parseddesc.fd->type;
1505 fi = iptr->sx.s23.s3.fmiref->p.field;
1506 fieldtype = fi->type;
1510 #if !defined(ENABLE_SOFTFLOAT)
1511 /* HACK: softnull checks on floats */
1512 if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
1513 emit_nullpointer_check_force(cd, iptr, s1);
1516 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1518 uf = iptr->sx.s23.s3.uf;
1520 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1522 if (opt_showdisassemble)
1526 switch (fieldtype) {
1528 #if defined(ENABLE_SOFTFLOAT)
1532 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1536 #if defined(ENABLE_SOFTFLOAT)
1539 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1542 #if !defined(ENABLE_SOFTFLOAT)
1544 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1548 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1555 emit_store_dst(jd, iptr, d);
1558 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1560 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
1561 emit_nullpointer_check(cd, iptr, s1);
1563 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1564 uf = iptr->sx.s23.s3.uf;
1565 fieldtype = uf->fieldref->parseddesc.fd->type;
1569 fi = iptr->sx.s23.s3.fmiref->p.field;
1570 fieldtype = fi->type;
1574 #if !defined(ENABLE_SOFTFLOAT)
1575 /* HACK: softnull checks on floats */
1576 if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
1577 emit_nullpointer_check_force(cd, iptr, s1);
1580 switch (fieldtype) {
1582 #if defined(ENABLE_SOFTFLOAT)
1586 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1588 #if defined(ENABLE_SOFTFLOAT)
1589 case TYPE_DBL: /* fall through */
1592 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
1594 #if !defined(ENABLE_SOFTFLOAT)
1597 s2 = emit_load_s2(jd, iptr, REG_FTMP1);
1604 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1606 uf = iptr->sx.s23.s3.uf;
1608 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1610 if (opt_showdisassemble)
1614 switch (fieldtype) {
1616 #if defined(ENABLE_SOFTFLOAT)
1620 M_IST(s2, s1, disp);
1623 #if defined(ENABLE_SOFTFLOAT)
1626 M_LST(s2, s1, disp);
1628 #if !defined(ENABLE_SOFTFLOAT)
1630 M_FST(s2, s1, disp);
1633 M_DST(s2, s1, disp);
1642 /* branch operations **************************************************/
1644 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1646 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1647 M_INTMOVE(s1, REG_ITMP1_XPTR);
1648 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1649 patcher_add_patch_ref(jd, PATCHER_resolve_class,
1650 iptr->sx.s23.s2.uc, 0);
1652 if (opt_showdisassemble)
1655 disp = dseg_add_functionptr(cd, asm_handle_exception);
1656 M_DSEG_LOAD(REG_ITMP3, disp);
1657 M_MOV(REG_ITMP2_XPC, REG_PC);
1658 M_MOV(REG_PC, REG_ITMP3);
1659 M_NOP; /* nop ensures that XPC is less than the end */
1660 /* of basic block */
1663 case ICMD_GOTO: /* ... ==> ... */
1666 emit_br(cd, iptr->dst.block);
1669 case ICMD_JSR: /* ... ==> ... */
1671 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1674 case ICMD_IFNULL: /* ..., value ==> ... */
1675 case ICMD_IFNONNULL:
1677 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1679 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
1682 case ICMD_IFLT: /* ..., value ==> ... */
1683 case ICMD_IFLE: /* op1 = target JavaVM pc, val.i = constant */
1689 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1690 M_COMPARE(s1, iptr->sx.val.i);
1691 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
1694 case ICMD_IF_LEQ: /* ..., value ==> ... */
1696 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1697 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1698 if (iptr->sx.val.l == 0) {
1699 M_ORR_S(s1, s2, REG_ITMP3);
1702 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1703 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1704 M_CMP(s1, REG_ITMP3);*/
1705 ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1706 M_CMPEQ(s2, REG_ITMP3);
1708 emit_beq(cd, iptr->dst.block);
1711 case ICMD_IF_LLT: /* ..., value ==> ... */
1713 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1714 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1715 if (iptr->sx.val.l == 0) {
1716 /* if high word is less than zero, the whole long is too */
1718 emit_blt(cd, iptr->dst.block);
1721 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1722 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1723 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1724 M_CMP(s1, REG_ITMP3);*/
1725 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1726 M_MOVGT_IMM(2, REG_ITMP1);
1727 M_MOVEQ_IMM(1, REG_ITMP1);
1729 /* low compare: x=x-1(ifLO) */
1730 M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
1731 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1732 M_CMP(s2, REG_ITMP3);*/
1733 M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
1735 /* branch if (x LT 1) */
1736 M_CMP_IMM(REG_ITMP1, 1);
1737 emit_blt(cd, iptr->dst.block);
1741 case ICMD_IF_LLE: /* ..., value ==> ... */
1743 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1744 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1745 if (iptr->sx.val.l == 0) {
1746 /* if high word is less than zero, the whole long is too */
1748 emit_blt(cd, iptr->dst.block);
1750 /* ... otherwise the low word has to be zero (tricky!) */
1752 emit_beq(cd, iptr->dst.block);
1755 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1756 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1757 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1758 M_CMP(s1, REG_ITMP3);*/
1759 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1760 M_MOVGT_IMM(2, REG_ITMP1);
1761 M_MOVEQ_IMM(1, REG_ITMP1);
1763 /* low compare: x=x+1(ifHI) */
1764 M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
1765 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1766 M_CMP(s2, REG_ITMP3);*/
1767 M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
1769 /* branch if (x LE 1) */
1770 M_CMP_IMM(REG_ITMP1, 1);
1771 emit_ble(cd, iptr->dst.block);
1775 case ICMD_IF_LGE: /* ..., value ==> ... */
1777 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1778 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1779 if (iptr->sx.val.l == 0) {
1780 /* if high word is greater or equal zero, the whole long is too */
1782 emit_bge(cd, iptr->dst.block);
1785 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1786 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1787 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1788 M_CMP(s1, REG_ITMP3);*/
1789 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1790 M_MOVGT_IMM(2, REG_ITMP1);
1791 M_MOVEQ_IMM(1, REG_ITMP1);
1793 /* low compare: x=x-1(ifLO) */
1794 M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
1795 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1796 M_CMP(s2, REG_ITMP3);*/
1797 M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
1799 /* branch if (x GE 1) */
1800 M_CMP_IMM(REG_ITMP1, 1);
1801 emit_bge(cd, iptr->dst.block);
1805 case ICMD_IF_LGT: /* ..., value ==> ... */
1807 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1808 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1810 if (iptr->sx.val.l == 0) {
1811 /* if high word is greater than zero, the whole long is too */
1814 codegen_add_branch_ref(cd, iptr->dst.block);
1816 /* ... or high was zero and low is non zero (tricky!) */
1817 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1818 M_MOVLT_IMM(1, REG_ITMP3);
1819 M_ORR_S(REG_ITMP3, s2, REG_ITMP3);
1821 codegen_add_branch_ref(cd, iptr->dst.block);
1825 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1826 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1827 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1828 M_CMP(s1, REG_ITMP3);*/
1829 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1830 M_MOVGT_IMM(2, REG_ITMP1);
1831 M_MOVEQ_IMM(1, REG_ITMP1);
1833 /* low compare: x=x+1(ifHI) */
1834 M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
1835 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1836 M_CMP(s2, REG_ITMP3);*/
1837 M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
1839 /* branch if (x GT 1) */
1840 M_CMP_IMM(REG_ITMP1, 1);
1841 emit_bgt(cd, iptr->dst.block);
1847 case ICMD_IF_LNE: /* ..., value ==> ... */
1849 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1850 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1851 if (iptr->sx.val.l == 0) {
1852 M_ORR_S(s1, s2, REG_ITMP3);
1855 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1856 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1857 M_CMP(s1, REG_ITMP3);*/
1858 ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1859 M_CMPEQ(s2, REG_ITMP3);
1861 emit_bne(cd, iptr->dst.block);
1864 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1865 case ICMD_IF_ICMPNE:
1866 case ICMD_IF_ICMPLT:
1867 case ICMD_IF_ICMPLE:
1868 case ICMD_IF_ICMPGT:
1869 case ICMD_IF_ICMPGE:
1871 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1872 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1874 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
1877 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
1878 case ICMD_IF_ACMPNE:
1880 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1881 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1883 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
1886 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1887 /* op1 = target JavaVM pc */
1889 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1890 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1893 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1894 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1897 emit_beq(cd, iptr->dst.block);
1900 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
1901 /* op1 = target JavaVM pc */
1903 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1904 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1907 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1908 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1911 emit_bne(cd, iptr->dst.block);
1914 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
1915 /* op1 = target JavaVM pc */
1917 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1918 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1919 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1921 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1922 M_MOVGT_IMM(2, REG_ITMP3);
1923 M_MOVEQ_IMM(1, REG_ITMP3);
1925 /* low compare: x=x-1(ifLO) */
1926 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1927 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1929 M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1);
1931 /* branch if (x LT 1) */
1932 M_CMP_IMM(REG_ITMP3, 1);
1933 emit_blt(cd, iptr->dst.block);
1936 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
1937 /* op1 = target JavaVM pc */
1939 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1940 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1941 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1943 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1944 M_MOVGT_IMM(2, REG_ITMP3);
1945 M_MOVEQ_IMM(1, REG_ITMP3);
1947 /* low compare: x=x-1(ifLO) */
1948 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1949 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1951 M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1);
1953 /* branch if (x LE 1) */
1954 M_CMP_IMM(REG_ITMP3, 1);
1955 emit_ble(cd, iptr->dst.block);
1958 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
1959 /* op1 = target JavaVM pc */
1961 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1962 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1963 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1965 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1966 M_MOVGT_IMM(2, REG_ITMP3);
1967 M_MOVEQ_IMM(1, REG_ITMP3);
1969 /* low compare: x=x-1(ifLO) */
1970 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1971 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1973 M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1);
1975 /* branch if (x GT 1) */
1976 M_CMP_IMM(REG_ITMP3, 1);
1977 emit_bgt(cd, iptr->dst.block);
1980 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
1981 /* op1 = target JavaVM pc */
1983 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1984 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1985 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1987 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1988 M_MOVGT_IMM(2, REG_ITMP3);
1989 M_MOVEQ_IMM(1, REG_ITMP3);
1991 /* low compare: x=x-1(ifLO) */
1992 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1993 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1995 M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1);
1997 /* branch if (x GE 1) */
1998 M_CMP_IMM(REG_ITMP3, 1);
1999 emit_bge(cd, iptr->dst.block);
2002 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2005 branch_target_t *table;
2007 table = iptr->dst.table;
2009 l = iptr->sx.s23.s2.tablelow;
2010 i = iptr->sx.s23.s3.tablehigh;
2012 /* calculate new index (index - low) */
2013 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2015 M_INTMOVE(s1, REG_ITMP1);
2016 } else if (IS_IMM(l)) {
2017 M_SUB_IMM(REG_ITMP1, s1, l);
2019 ICONST(REG_ITMP2, l);
2020 M_SUB(REG_ITMP1, s1, REG_ITMP2);
2023 /* range check (index <= high-low) */
2025 M_COMPARE(REG_ITMP1, i-1);
2026 emit_bugt(cd, table[0].block);
2028 /* build jump table top down and use address of lowest entry */
2033 dseg_add_target(cd, table->block);
2038 /* length of dataseg after last dseg_add_target is used by load */
2039 /* TODO: this loads from data-segment */
2040 M_ADD(REG_ITMP2, REG_PV, REG_LSL(REG_ITMP1, 2));
2041 M_LDR(REG_PC, REG_ITMP2, -(cd->dseglen));
2044 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2047 lookup_target_t *lookup;
2049 lookup = iptr->dst.lookup;
2051 i = iptr->sx.s23.s2.lookupcount;
2054 MCODECHECK((i<<2)+8);
2055 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2058 M_COMPARE(s1, lookup->value);
2059 emit_beq(cd, lookup->target.block);
2063 /* default branch */
2064 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2068 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2070 #if !defined(ENABLE_SOFTFLOAT)
2071 REPLACEMENT_POINT_RETURN(cd, iptr);
2072 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
2073 M_CAST_FLT_TO_INT_TYPED(VAROP(iptr->s1)->type, s1, REG_RESULT);
2074 goto ICMD_RETURN_do;
2077 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2079 REPLACEMENT_POINT_RETURN(cd, iptr);
2080 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2081 M_INTMOVE(s1, REG_RESULT);
2082 goto ICMD_RETURN_do;
2084 case ICMD_DRETURN: /* ..., retvalue ==> ... */
2086 #if !defined(ENABLE_SOFTFLOAT)
2087 REPLACEMENT_POINT_RETURN(cd, iptr);
2088 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
2089 M_CAST_FLT_TO_INT_TYPED(VAROP(iptr->s1)->type, s1, REG_RESULT_PACKED);
2090 goto ICMD_RETURN_do;
2093 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2095 REPLACEMENT_POINT_RETURN(cd, iptr);
2096 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2097 M_LNGMOVE(s1, REG_RESULT_PACKED);
2098 goto ICMD_RETURN_do;
2100 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2102 REPLACEMENT_POINT_RETURN(cd, iptr);
2103 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2104 M_INTMOVE(s1, REG_RESULT);
2105 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2106 patcher_add_patch_ref(jd, PATCHER_resolve_class,
2107 iptr->sx.s23.s2.uc, 0);
2109 if (opt_showdisassemble)
2112 goto ICMD_RETURN_do;
2114 case ICMD_RETURN: /* ... ==> ... */
2116 REPLACEMENT_POINT_RETURN(cd, iptr);
2119 #if !defined(NDEBUG)
2120 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2121 emit_verbosecall_exit(jd);
2124 #if defined(ENABLE_THREADS)
2125 /* call monitorexit function */
2127 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2128 /* stack offset for monitor argument */
2130 s1 = rd->memuse * 8;
2132 /* we need to save the proper return value */
2134 switch (iptr->opc) {
2138 case ICMD_FRETURN: /* XXX TWISTI: is that correct? */
2140 M_STMFD(BITMASK_RESULT, REG_SP);
2145 M_LDR(REG_A0, REG_SP, s1);
2146 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2147 M_DSEG_BRANCH(disp);
2149 /* we no longer need PV here, no more loading */
2150 /*s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2151 M_RECOMPUTE_PV(s1);*/
2153 switch (iptr->opc) {
2157 case ICMD_FRETURN: /* XXX TWISTI: is that correct? */
2159 M_LDMFD(BITMASK_RESULT, REG_SP);
2165 /* deallocate stackframe for spilled variables */
2167 if ((cd->stackframesize / 4 - savedregs_num) > 0)
2168 M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - savedregs_num);
2170 /* restore callee saved registers + do return */
2172 if (savedregs_bitmask) {
2173 if (!jd->isleafmethod) {
2174 savedregs_bitmask &= ~(1<<REG_LR);
2175 savedregs_bitmask |= (1<<REG_PC);
2177 M_LDMFD(savedregs_bitmask, REG_SP);
2180 /* if LR was not on stack, we need to return manually */
2182 if (jd->isleafmethod)
2183 M_MOV(REG_PC, REG_LR);
2186 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
2188 bte = iptr->sx.s23.s3.bte;
2190 goto ICMD_INVOKE_do;
2192 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2193 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2194 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2195 case ICMD_INVOKEINTERFACE:
2197 REPLACEMENT_POINT_INVOKE(cd, iptr);
2199 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2201 um = iptr->sx.s23.s3.um;
2202 md = um->methodref->parseddesc.md;
2205 lm = iptr->sx.s23.s3.fmiref->p.method;
2207 md = lm->parseddesc;
2211 /* copy arguments to registers or stack location */
2213 s3 = md->paramcount;
2215 MCODECHECK((s3 << 1) + 64);
2217 for (s3 = s3 - 1; s3 >= 0; s3--) {
2218 var = VAR(iptr->sx.s23.s2.args[s3]);
2219 d = md->params[s3].regoff;
2221 if (var->flags & PREALLOC) /* argument was precolored? */
2224 /* TODO: document me */
2225 #if !defined(ENABLE_SOFTFLOAT)
2226 if (IS_INT_LNG_TYPE(var->type)) {
2227 #endif /* !defined(ENABLE_SOFTFLOAT) */
2228 if (!md->params[s3].inmemory) {
2229 s1 = emit_load(jd, iptr, var, d);
2231 if (IS_2_WORD_TYPE(var->type))
2237 if (IS_2_WORD_TYPE(var->type)) {
2238 s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2239 M_LST(s1, REG_SP, d);
2242 s1 = emit_load(jd, iptr, var, REG_ITMP1);
2243 M_IST(s1, REG_SP, d);
2246 #if !defined(ENABLE_SOFTFLOAT)
2249 if (!md->params[s3].inmemory) {
2250 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2251 M_CAST_FLT_TO_INT_TYPED(var->type, s1, d);
2254 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2255 if (IS_2_WORD_TYPE(var->type))
2256 M_DST(s1, REG_SP, d);
2258 M_FST(s1, REG_SP, d);
2261 #endif /* !defined(ENABLE_SOFTFLOAT) */
2264 switch (iptr->opc) {
2266 disp = dseg_add_functionptr(cd, bte->fp);
2268 M_DSEG_LOAD(REG_PV, disp); /* pointer to built-in-function */
2270 /* generate the actual call */
2272 M_MOV(REG_LR, REG_PC);
2273 M_MOV(REG_PC, REG_PV);
2274 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2277 emit_exception_check(cd, iptr);
2280 case ICMD_INVOKESPECIAL:
2281 emit_nullpointer_check(cd, iptr, REG_A0);
2284 case ICMD_INVOKESTATIC:
2286 disp = dseg_add_unique_address(cd, NULL);
2288 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2291 if (opt_showdisassemble)
2295 disp = dseg_add_address(cd, lm->stubroutine);
2297 M_DSEG_LOAD(REG_PV, disp); /* Pointer to method */
2299 /* generate the actual call */
2301 M_MOV(REG_LR, REG_PC);
2302 M_MOV(REG_PC, REG_PV);
2303 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2307 case ICMD_INVOKEVIRTUAL:
2309 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2311 if (opt_showdisassemble)
2317 s1 = OFFSET(vftbl_t, table[0]) +
2318 sizeof(methodptr) * lm->vftblindex;
2320 /* implicit null-pointer check */
2321 M_LDR_INTERN(REG_METHODPTR, REG_A0,
2322 OFFSET(java_object_t, vftbl));
2323 M_LDR_INTERN(REG_PV, REG_METHODPTR, s1);
2325 /* generate the actual call */
2327 M_MOV(REG_LR, REG_PC);
2328 M_MOV(REG_PC, REG_PV);
2329 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2333 case ICMD_INVOKEINTERFACE:
2335 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2337 if (opt_showdisassemble)
2344 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2345 sizeof(methodptr*) * lm->class->index;
2346 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2349 /* implicit null-pointer check */
2350 M_LDR_INTERN(REG_METHODPTR, REG_A0,
2351 OFFSET(java_object_t, vftbl));
2352 M_LDR_INTERN(REG_METHODPTR, REG_METHODPTR, s1);
2353 M_LDR_INTERN(REG_PV, REG_METHODPTR, s2);
2355 /* generate the actual call */
2357 M_MOV(REG_LR, REG_PC);
2358 M_MOV(REG_PC, REG_PV);
2359 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2364 /* store size of call code in replacement point */
2365 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2367 /* store return value */
2369 d = md->returntype.type;
2371 #if !defined(__SOFTFP__)
2372 /* TODO: this is only a hack, since we use R0/R1 for float
2373 return! this depends on gcc; it is independent from
2374 our ENABLE_SOFTFLOAT define */
2375 if (iptr->opc == ICMD_BUILTIN && d != TYPE_VOID && IS_FLT_DBL_TYPE(d)) {
2376 #if 0 && !defined(NDEBUG)
2377 dolog("BUILTIN that returns float or double (%s.%s)", m->class->name->text, m->name->text);
2379 /* we cannot use this macro, since it is not defined
2380 in ENABLE_SOFTFLOAT M_CAST_FLT_TO_INT_TYPED(d,
2381 REG_FRESULT, REG_RESULT_TYPED(d)); */
2382 if (IS_2_WORD_TYPE(d)) {
2383 DCD(0xed2d8102); /* stfd f0, [sp, #-8]! */
2384 M_LDRD_UPDATE(REG_RESULT_PACKED, REG_SP, 8);
2386 DCD(0xed2d0101); /* stfs f0, [sp, #-4]!*/
2387 M_LDR_UPDATE(REG_RESULT, REG_SP, 4);
2392 if (d != TYPE_VOID) {
2393 #if !defined(ENABLE_SOFTFLOAT)
2394 if (IS_INT_LNG_TYPE(d)) {
2395 #endif /* !defined(ENABLE_SOFTFLOAT) */
2396 if (IS_2_WORD_TYPE(d)) {
2397 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2398 M_LNGMOVE(REG_RESULT_PACKED, s1);
2401 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2402 M_INTMOVE(REG_RESULT, s1);
2405 #if !defined(ENABLE_SOFTFLOAT)
2407 s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2408 M_CAST_INT_TO_FLT_TYPED(VAROP(iptr->dst)->type, REG_RESULT_TYPED(VAROP(iptr->dst)->type), s1);
2410 #endif /* !defined(ENABLE_SOFTFLOAT) */
2412 emit_store_dst(jd, iptr, s1);
2416 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2418 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2419 /* object type cast-check */
2424 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2429 super = iptr->sx.s23.s3.c.cls;
2430 superindex = super->index;
2433 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2434 CODEGEN_CRITICAL_SECTION_NEW;
2436 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2438 /* if class is not resolved, check which code to call */
2440 if (super == NULL) {
2442 emit_label_beq(cd, BRANCH_LABEL_1);
2444 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2445 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2446 iptr->sx.s23.s3.c.ref, disp);
2448 if (opt_showdisassemble)
2451 M_DSEG_LOAD(REG_ITMP2, disp);
2452 disp = dseg_add_s4(cd, ACC_INTERFACE);
2453 M_DSEG_LOAD(REG_ITMP3, disp);
2454 M_TST(REG_ITMP2, REG_ITMP3);
2455 emit_label_beq(cd, BRANCH_LABEL_2);
2458 /* interface checkcast code */
2460 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2461 if ((super == NULL) || !IS_IMM(superindex)) {
2462 disp = dseg_add_unique_s4(cd, superindex);
2464 if (super == NULL) {
2465 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
2466 iptr->sx.s23.s3.c.ref, disp);
2468 if (opt_showdisassemble)
2473 emit_label_beq(cd, BRANCH_LABEL_3);
2476 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2477 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2479 /* we put unresolved or non-immediate superindices onto dseg */
2480 if ((super == NULL) || !IS_IMM(superindex)) {
2481 /* disp was computed before we added the patcher */
2482 M_DSEG_LOAD(REG_ITMP2, disp);
2483 M_CMP(REG_ITMP3, REG_ITMP2);
2485 assert(IS_IMM(superindex));
2486 M_CMP_IMM(REG_ITMP3, superindex);
2489 emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
2491 /* if we loaded the superindex out of the dseg above, we do
2492 things differently here! */
2493 if ((super == NULL) || !IS_IMM(superindex)) {
2495 M_LDR_INTERN(REG_ITMP3, s1, OFFSET(java_object_t, vftbl));
2497 /* this assumes something */
2498 assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
2500 /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
2501 assert(sizeof(methodptr*) == 4);
2502 M_SUB(REG_ITMP2, REG_ITMP3, REG_LSL(REG_ITMP2, 2));
2508 s2 = OFFSET(vftbl_t, interfacetable[0]) -
2509 superindex * sizeof(methodptr*);
2513 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, s2);
2514 M_TST(REG_ITMP3, REG_ITMP3);
2515 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
2518 emit_label_br(cd, BRANCH_LABEL_4);
2520 emit_label(cd, BRANCH_LABEL_3);
2523 /* class checkcast code */
2525 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2526 if (super == NULL) {
2527 emit_label(cd, BRANCH_LABEL_2);
2529 disp = dseg_add_unique_address(cd, NULL);
2531 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2532 iptr->sx.s23.s3.c.ref,
2535 if (opt_showdisassemble)
2539 disp = dseg_add_address(cd, super->vftbl);
2542 emit_label_beq(cd, BRANCH_LABEL_5);
2545 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2546 M_DSEG_LOAD(REG_ITMP3, disp);
2548 CODEGEN_CRITICAL_SECTION_START;
2550 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2551 M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2552 M_SUB(REG_ITMP2, REG_ITMP2, REG_ITMP3);
2553 M_DSEG_LOAD(REG_ITMP3, disp);
2554 M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2556 CODEGEN_CRITICAL_SECTION_END;
2558 M_CMP(REG_ITMP2, REG_ITMP3);
2559 emit_classcast_check(cd, iptr, BRANCH_UGT, 0, s1);
2562 emit_label(cd, BRANCH_LABEL_5);
2565 if (super == NULL) {
2566 emit_label(cd, BRANCH_LABEL_1);
2567 emit_label(cd, BRANCH_LABEL_4);
2570 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
2573 /* array type cast-check */
2575 s1 = emit_load_s1(jd, iptr, REG_A0);
2576 M_INTMOVE(s1, REG_A0);
2578 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2579 disp = dseg_add_unique_address(cd, NULL);
2581 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2582 iptr->sx.s23.s3.c.ref,
2585 if (opt_showdisassemble)
2589 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2591 M_DSEG_LOAD(REG_A1, disp);
2592 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2593 M_DSEG_BRANCH(disp);
2596 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2597 M_RECOMPUTE_PV(disp);
2599 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2600 M_TST(REG_RESULT, REG_RESULT);
2601 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2603 d = codegen_reg_of_dst(jd, iptr, s1);
2607 emit_store_dst(jd, iptr, d);
2610 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2616 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2621 super = iptr->sx.s23.s3.c.cls;
2622 superindex = super->index;
2625 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2626 CODEGEN_CRITICAL_SECTION_NEW;
2628 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2629 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2632 M_MOV(REG_ITMP1, s1);
2636 /* if class is not resolved, check which code to call */
2638 if (super == NULL) {
2642 emit_label_beq(cd, BRANCH_LABEL_1);
2644 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2645 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2646 iptr->sx.s23.s3.c.ref, disp);
2648 if (opt_showdisassemble)
2651 M_DSEG_LOAD(REG_ITMP2, disp);
2652 disp = dseg_add_s4(cd, ACC_INTERFACE);
2653 M_DSEG_LOAD(REG_ITMP3, disp);
2654 M_TST(REG_ITMP2, REG_ITMP3);
2655 emit_label_beq(cd, BRANCH_LABEL_2);
2658 /* interface checkcast code */
2660 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2661 if ((super == NULL) || !IS_IMM(superindex)) {
2662 disp = dseg_add_unique_s4(cd, superindex);
2664 if (super == NULL) {
2665 /* If d == REG_ITMP2, then it's destroyed in check
2670 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
2671 iptr->sx.s23.s3.c.ref, disp);
2673 if (opt_showdisassemble)
2679 emit_label_beq(cd, BRANCH_LABEL_3);
2682 M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2683 M_LDR_INTERN(REG_ITMP3,
2684 REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2686 /* we put unresolved or non-immediate superindices onto dseg
2687 and do things slightly different */
2688 if ((super == NULL) || !IS_IMM(superindex)) {
2689 /* disp was computed before we added the patcher */
2690 M_DSEG_LOAD(REG_ITMP2, disp);
2691 M_CMP(REG_ITMP3, REG_ITMP2);
2693 if (d == REG_ITMP2) {
2700 /* this assumes something */
2701 assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
2703 /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
2704 assert(sizeof(methodptr*) == 4);
2705 M_SUB(REG_ITMP1, REG_ITMP1, REG_LSL(REG_ITMP2, 2));
2707 if (d == REG_ITMP2) {
2714 assert(IS_IMM(superindex));
2715 M_CMP_IMM(REG_ITMP3, superindex);
2719 s2 = OFFSET(vftbl_t, interfacetable[0]) -
2720 superindex * sizeof(methodptr*);
2724 M_LDR_INTERN(REG_ITMP3, REG_ITMP1, s2);
2725 M_TST(REG_ITMP3, REG_ITMP3);
2729 emit_label_br(cd, BRANCH_LABEL_4);
2731 emit_label(cd, BRANCH_LABEL_3);
2734 /* class checkcast code */
2736 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2737 if (super == NULL) {
2738 emit_label(cd, BRANCH_LABEL_2);
2740 disp = dseg_add_unique_address(cd, NULL);
2742 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2743 iptr->sx.s23.s3.c.ref, disp);
2745 if (opt_showdisassemble)
2749 disp = dseg_add_address(cd, super->vftbl);
2753 emit_label_beq(cd, BRANCH_LABEL_5);
2756 M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2757 M_DSEG_LOAD(REG_ITMP2, disp);
2759 CODEGEN_CRITICAL_SECTION_START;
2761 M_LDR_INTERN(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2762 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2763 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2765 CODEGEN_CRITICAL_SECTION_END;
2767 M_SUB(REG_ITMP1, REG_ITMP1, REG_ITMP3);
2768 M_CMP(REG_ITMP1, REG_ITMP2);
2769 /* If d == REG_ITMP2, then it's destroyed */
2775 emit_label(cd, BRANCH_LABEL_5);
2778 if (super == NULL) {
2779 emit_label(cd, BRANCH_LABEL_1);
2780 emit_label(cd, BRANCH_LABEL_4);
2785 emit_store_dst(jd, iptr, d);
2788 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2790 /* copy sizes to stack if necessary */
2792 MCODECHECK((iptr->s1.argcount << 1) + 64);
2794 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2796 var = VAR(iptr->sx.s23.s2.args[s1]);
2798 /* copy SAVEDVAR sizes to stack */
2800 if (!(var->flags & PREALLOC)) {
2801 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2802 M_STR(s2, REG_SP, s1 * 4);
2806 /* a0 = dimension count */
2808 assert(IS_IMM(iptr->s1.argcount));
2809 M_MOV_IMM(REG_A0, iptr->s1.argcount);
2811 /* is patcher function set? */
2813 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2814 disp = dseg_add_unique_address(cd, NULL);
2816 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2817 iptr->sx.s23.s3.c.ref, disp);
2819 if (opt_showdisassemble)
2823 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2825 /* a1 = arraydescriptor */
2827 M_DSEG_LOAD(REG_A1, disp);
2829 /* a2 = pointer to dimensions = stack pointer */
2831 M_INTMOVE(REG_SP, REG_A2);
2833 /* call builtin_multianewarray here */
2835 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2836 M_DSEG_BRANCH(disp);
2840 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2843 /* check for exception before result assignment */
2845 emit_exception_check(cd, iptr);
2849 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2850 M_INTMOVE(REG_RESULT, d);
2851 emit_store_dst(jd, iptr, d);
2854 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
2856 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2857 emit_nullpointer_check(cd, iptr, s1);
2861 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
2864 } /* the big switch */
2866 } /* for all instructions */
2868 } /* for all basic blocks */
2870 dseg_createlinenumbertable(cd);
2873 /* generate traps */
2875 emit_patcher_traps(jd);
2877 /* everything's ok */
2883 /* codegen_emit_stub_compiler **************************************************
2885 Emits a stub routine which calls the compiler.
2887 *******************************************************************************/
2889 void codegen_emit_stub_compiler(jitdata *jd)
2894 /* get required compiler data */
2899 /* code for the stub */
2901 M_LDR_INTERN(REG_ITMP1, REG_PC, -(2 * 4 + 2 * SIZEOF_VOID_P));
2902 M_LDR_INTERN(REG_PC, REG_PC, -(3 * 4 + 3 * SIZEOF_VOID_P));
2906 /* codegen_emit_stub_native ****************************************************
2908 Emits a stub routine which calls a native method.
2910 *******************************************************************************/
2912 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
2921 s4 disp, funcdisp, s1, s2;
2923 /* get required compiler data */
2929 /* initialize variables */
2932 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
2934 /* calculate stackframe size */
2936 cd->stackframesize =
2937 4 + /* return address */
2938 sizeof(stackframeinfo) + /* stackframeinfo */
2939 sizeof(localref_table) + /* localref_table */
2940 nmd->memuse * 4; /* stack arguments */
2942 /* align stack to 8-byte */
2944 cd->stackframesize = (cd->stackframesize + 4) & ~4;
2946 /* create method header */
2948 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2949 (void) dseg_add_unique_s4(cd, cd->stackframesize); /* FrameSize */
2950 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2951 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2952 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2953 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2954 (void) dseg_addlinenumbertablesize(cd);
2955 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2957 /* generate stub code */
2959 M_STMFD(1<<REG_LR, REG_SP);
2960 M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - 1);
2962 #if !defined(NDEBUG)
2963 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2964 emit_verbosecall_enter(jd);
2967 /* get function address (this must happen before the stackframeinfo) */
2969 funcdisp = dseg_add_functionptr(cd, f);
2971 #if !defined(WITH_STATIC_CLASSPATH)
2973 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
2975 if (opt_showdisassemble)
2980 /* Save integer and float argument registers (these are 4
2981 registers, stack is 8-byte aligned). */
2983 M_STMFD(BITMASK_ARGS, REG_SP);
2984 /* TODO: floating point */
2986 /* create native stackframe info */
2988 assert(IS_IMM(4*4 + cd->stackframesize));
2989 M_ADD_IMM(REG_A0, REG_SP, 4*4 + cd->stackframesize - SIZEOF_VOID_P);
2990 M_MOV(REG_A1, REG_PV);
2991 M_ADD_IMM(REG_A2, REG_SP, 4*4 + cd->stackframesize);
2992 M_LDR_INTERN(REG_A3, REG_SP, 4*4 + cd->stackframesize - SIZEOF_VOID_P);
2993 disp = dseg_add_functionptr(cd, codegen_start_native_call);
2994 M_DSEG_BRANCH(disp);
2998 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
3001 /* Restore integer and float argument registers (these are 4
3002 registers, stack is 8-byte aligned). */
3004 M_LDMFD(BITMASK_ARGS, REG_SP);
3005 /* TODO: floating point */
3007 /* copy or spill arguments to new locations */
3008 /* ATTENTION: the ARM has only integer argument registers! */
3010 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3011 t = md->paramtypes[i].type;
3013 if (!md->params[i].inmemory) {
3014 s1 = md->params[i].regoff;
3015 s2 = nmd->params[j].regoff;
3017 if (!nmd->params[j].inmemory) {
3018 #if !defined(__ARM_EABI__)
3019 SPLIT_OPEN(t, s2, REG_ITMP1);
3022 if (IS_2_WORD_TYPE(t))
3027 #if !defined(__ARM_EABI__)
3028 SPLIT_STORE_AND_CLOSE(t, s2, 0);
3032 if (IS_2_WORD_TYPE(t))
3033 M_LST(s1, REG_SP, s2);
3035 M_IST(s1, REG_SP, s2);
3039 s1 = md->params[i].regoff + cd->stackframesize;
3040 s2 = nmd->params[j].regoff;
3042 if (IS_2_WORD_TYPE(t)) {
3043 M_LLD(REG_ITMP12_PACKED, REG_SP, s1);
3044 M_LST(REG_ITMP12_PACKED, REG_SP, s2);
3047 M_ILD(REG_ITMP1, REG_SP, s1);
3048 M_IST(REG_ITMP1, REG_SP, s2);
3053 /* put class into second argument register */
3055 if (m->flags & ACC_STATIC) {
3056 disp = dseg_add_address(cd, m->class);
3057 M_DSEG_LOAD(REG_A1, disp);
3060 /* put env into first argument register */
3062 disp = dseg_add_address(cd, _Jv_env);
3063 M_DSEG_LOAD(REG_A0, disp);
3065 /* do the native function call */
3067 M_DSEG_BRANCH(funcdisp);
3070 /* TODO: this is only needed because of the tracer ... do we
3073 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
3076 #if !defined(__SOFTFP__)
3077 /* TODO: this is only a hack, since we use R0/R1 for float return! */
3078 /* this depends on gcc; it is independent from our ENABLE_SOFTFLOAT define */
3079 if (md->returntype.type != TYPE_VOID && IS_FLT_DBL_TYPE(md->returntype.type)) {
3080 #if 0 && !defined(NDEBUG)
3081 dolog("NATIVESTUB that returns float or double (%s.%s)", m->class->name->text, m->name->text);
3083 /* we cannot use this macro, since it is not defined in ENABLE_SOFTFLOAT */
3084 /* M_CAST_FLT_TO_INT_TYPED(md->returntype.type, REG_FRESULT, REG_RESULT_TYPED(md->returntype.type)); */
3085 if (IS_2_WORD_TYPE(md->returntype.type)) {
3086 DCD(0xed2d8102); /* stfd f0, [sp, #-8]! */
3087 M_LDRD_UPDATE(REG_RESULT_PACKED, REG_SP, 8);
3089 DCD(0xed2d0101); /* stfs f0, [sp, #-4]!*/
3090 M_LDR_UPDATE(REG_RESULT, REG_SP, 4);
3095 #if !defined(NDEBUG)
3096 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3097 emit_verbosecall_exit(jd);
3100 /* remove native stackframe info */
3101 /* TODO: improve this store/load */
3103 M_STMFD(BITMASK_RESULT, REG_SP);
3105 M_ADD_IMM(REG_A0, REG_SP, 2*4 + cd->stackframesize - SIZEOF_VOID_P);
3106 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3107 M_DSEG_BRANCH(disp);
3108 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
3111 M_MOV(REG_ITMP1_XPTR, REG_RESULT);
3112 M_LDMFD(BITMASK_RESULT, REG_SP);
3114 /* finish stub code, but do not yet return to caller */
3116 M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - 1);
3117 M_LDMFD(1<<REG_LR, REG_SP);
3119 /* check for exception */
3121 M_TST(REG_ITMP1_XPTR, REG_ITMP1_XPTR);
3122 M_MOVEQ(REG_LR, REG_PC); /* if no exception, return to caller */
3124 /* handle exception here */
3126 M_SUB_IMM(REG_ITMP2_XPC, REG_LR, 4);/* move fault address into xpc */
3128 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3129 M_DSEG_LOAD(REG_ITMP3, disp); /* load asm exception handler address */
3130 M_MOV(REG_PC, REG_ITMP3); /* jump to asm exception handler */
3132 /* generate patcher stubs */
3134 emit_patcher_traps(jd);
3138 /* asm_debug *******************************************************************
3142 *******************************************************************************/
3144 void asm_debug(int a1, int a2, int a3, int a4)
3146 printf("===> i am going to exit after this debugging message!\n");
3147 printf("got asm_debug(%p, %p, %p, %p)\n",(void*)a1,(void*)a2,(void*)a3,(void*)a4);
3148 vm_abort("leave you now");
3153 * These are local overrides for various environment variables in Emacs.
3154 * Please do not remove this and leave it at the end of the file, where
3155 * Emacs will automagically detect them.
3156 * ---------------------------------------------------------------------
3159 * indent-tabs-mode: t
3163 * vim:noexpandtab:sw=4:ts=4: