1 /* src/vm/jit/arm/codegen.c - machine code generator for Arm
3 Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
35 #include "vm/jit/arm/arch.h"
36 #include "vm/jit/arm/codegen.h"
38 #include "mm/memory.hpp"
40 #include "native/localref.hpp"
41 #include "native/native.hpp"
43 #include "threads/lock.hpp"
45 #include "vm/jit/builtin.hpp"
46 #include "vm/exceptions.hpp"
47 #include "vm/global.h"
48 #include "vm/loader.hpp"
49 #include "vm/options.h"
52 #include "vm/jit/abi.h"
53 #include "vm/jit/asmpart.h"
54 #include "vm/jit/codegen-common.hpp"
55 #include "vm/jit/dseg.h"
56 #include "vm/jit/emit-common.hpp"
57 #include "vm/jit/jit.hpp"
58 #include "vm/jit/linenumbertable.hpp"
59 #include "vm/jit/methodheader.h"
60 #include "vm/jit/parse.hpp"
61 #include "vm/jit/patcher-common.hpp"
62 #include "vm/jit/reg.h"
66 * Generates machine code for the method prolog.
68 void codegen_emit_prolog(jitdata* jd)
77 // Get required compiler data.
78 methodinfo* m = jd->m;
79 codeinfo* code = jd->code;
80 codegendata* cd = jd->cd;
81 registerdata* rd = jd->rd;
83 int32_t savedregs_num = 0;
84 uint32_t savedregs_bitmask = 0;
86 if (!code_is_leafmethod(code)) {
88 savedregs_bitmask = (1<<REG_LR);
91 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
93 savedregs_bitmask |= (1<<(rd->savintregs[i]));
97 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
98 vm_abort("codegen_emit_prolog: Floating-point callee saved registers are not saved to stack");
102 /* save return address and used callee saved registers */
104 if (savedregs_bitmask != 0)
105 M_STMFD(savedregs_bitmask, REG_SP);
107 /* create additional stack frame for spilled variables (if necessary) */
109 int32_t additional_bytes = (cd->stackframesize * 8 - savedregs_num * 4);
111 if (additional_bytes > 0)
112 M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, additional_bytes / 4);
114 /* take arguments out of register or stack frame */
117 for (i = 0, len = 0; i < md->paramcount; i++) {
118 s1 = md->params[i].regoff;
119 t = md->paramtypes[i].type;
121 varindex = jd->local_map[len * 5 + t];
123 len += (IS_2_WORD_TYPE(t)) ? 2 : 1; /* 2 word type arguments */
125 if (varindex == UNUSED)
130 /* ATTENTION: we use interger registers for all arguments (even float) */
131 #if !defined(ENABLE_SOFTFLOAT)
132 if (IS_INT_LNG_TYPE(t)) {
134 if (!md->params[i].inmemory) {
135 if (!(var->flags & INMEMORY)) {
136 if (IS_2_WORD_TYPE(t))
137 M_LNGMOVE(s1, var->vv.regoff);
139 M_INTMOVE(s1, var->vv.regoff);
142 if (IS_2_WORD_TYPE(t))
143 M_LST(s1, REG_SP, var->vv.regoff);
145 M_IST(s1, REG_SP, var->vv.regoff);
148 else { /* stack arguments */
149 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
150 if (IS_2_WORD_TYPE(t))
151 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
153 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
155 else { /* stack arg -> spilled */
156 /* Reuse Memory Position on Caller Stack */
157 var->vv.regoff = cd->stackframesize * 8 + s1;
160 #if !defined(ENABLE_SOFTFLOAT)
163 if (!md->params[i].inmemory) {
164 if (!(var->flags & INMEMORY)) {
165 if (IS_2_WORD_TYPE(t))
166 M_CAST_L2D(s1, var->vv.regoff);
168 M_CAST_I2F(s1, var->vv.regoff);
171 if (IS_2_WORD_TYPE(t))
172 M_LST(s1, REG_SP, var->vv.regoff);
174 M_IST(s1, REG_SP, var->vv.regoff);
178 if (!(var->flags & INMEMORY)) {
179 if (IS_2_WORD_TYPE(t))
180 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
182 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
185 /* Reuse Memory Position on Caller Stack */
186 var->vv.regoff = cd->stackframesize * 8 + s1;
190 #endif /* !defined(ENABLE_SOFTFLOAT) */
196 * Generates machine code for the method epilog.
198 void codegen_emit_epilog(jitdata* jd)
202 // Get required compiler data.
203 codeinfo* code = jd->code;
204 codegendata* cd = jd->cd;
205 registerdata* rd = jd->rd;
207 int32_t savedregs_num = 0;
208 uint32_t savedregs_bitmask = 0;
210 if (!code_is_leafmethod(code)) {
212 savedregs_bitmask = (1<<REG_LR);
215 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
217 savedregs_bitmask |= (1<<(rd->savintregs[i]));
220 /* deallocate stackframe for spilled variables */
222 int32_t additional_bytes = (cd->stackframesize * 8 - savedregs_num * 4);
224 if (additional_bytes > 0)
225 M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, additional_bytes / 4);
227 /* restore callee saved registers + do return */
229 if (savedregs_bitmask) {
230 if (!code_is_leafmethod(code)) {
231 savedregs_bitmask &= ~(1<<REG_LR);
232 savedregs_bitmask |= (1<<REG_PC);
234 M_LDMFD(savedregs_bitmask, REG_SP);
237 /* if LR was not on stack, we need to return manually */
239 if (code_is_leafmethod(code))
240 M_MOV(REG_PC, REG_LR);
245 * Generates machine code for one ICMD.
247 void codegen_emit_instruction(jitdata* jd, instruction* iptr)
250 builtintable_entry* bte;
251 methodinfo* lm; // Local methodinfo for ICMD_INVOKE*.
252 unresolved_method* um;
254 unresolved_field* uf;
256 int32_t s1, s2, s3, d;
259 // Get required compiler data.
260 codeinfo* code = jd->code;
261 codegendata* cd = jd->cd;
266 /* constant operations ************************************************/
268 case ICMD_ACONST: /* ... ==> ..., constant */
270 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
271 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
272 disp = dseg_add_unique_address(cd, NULL);
274 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
275 iptr->sx.val.c.ref, disp);
277 M_DSEG_LOAD(d, disp);
280 ICONST(d, (u4) iptr->sx.val.anyptr);
282 emit_store_dst(jd, iptr, d);
285 case ICMD_FCONST: /* ... ==> ..., constant */
287 #if defined(ENABLE_SOFTFLOAT)
288 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
289 ICONST(d, iptr->sx.val.i);
290 emit_store_dst(jd, iptr, d);
292 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
293 FCONST(d, iptr->sx.val.f);
294 emit_store_dst(jd, iptr, d);
298 case ICMD_DCONST: /* ... ==> ..., constant */
300 #if defined(ENABLE_SOFTFLOAT)
301 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
302 LCONST(d, iptr->sx.val.l);
303 emit_store_dst(jd, iptr, d);
305 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
306 DCONST(d, iptr->sx.val.d);
307 emit_store_dst(jd, iptr, d);
312 /* integer operations *************************************************/
314 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
316 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
317 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
318 M_MOV(d, REG_LSL(s1, 24));
319 M_MOV(d, REG_ASR(d, 24));
320 emit_store_dst(jd, iptr, d);
323 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
325 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
326 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
327 M_MOV(d, REG_LSL(s1, 16));
328 M_MOV(d, REG_LSR(d, 16)); /* ATTENTION: char is unsigned */
329 emit_store_dst(jd, iptr, d);
332 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
334 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
335 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
336 M_MOV(d, REG_LSL(s1, 16));
337 M_MOV(d, REG_ASR(d, 16));
338 emit_store_dst(jd, iptr, d);
341 case ICMD_I2L: /* ..., value ==> ..., value */
343 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
344 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
345 M_INTMOVE(s1, GET_LOW_REG(d));
346 M_MOV(GET_HIGH_REG(d), REG_ASR(s1, 31));
347 emit_store_dst(jd, iptr, d);
350 case ICMD_L2I: /* ..., value ==> ..., value */
352 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
353 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
355 emit_store_dst(jd, iptr, d);
358 case ICMD_INEG: /* ..., value ==> ..., - value */
360 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
361 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
363 emit_store_dst(jd, iptr, d);
366 case ICMD_LNEG: /* ..., value ==> ..., - value */
368 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
369 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
370 M_RSB_IMMS(GET_LOW_REG(d), GET_LOW_REG(s1), 0);
371 M_RSC_IMM(GET_HIGH_REG(d), GET_HIGH_REG(s1), 0);
372 emit_store_dst(jd, iptr, d);
375 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
377 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
378 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
379 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
381 emit_store_dst(jd, iptr, d);
384 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
386 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
387 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
388 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
389 M_ADD_S(GET_LOW_REG(d), s1, s2);
390 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
391 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
392 M_ADC(GET_HIGH_REG(d), s1, s2);
393 emit_store_dst(jd, iptr, d);
399 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
400 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
402 if (IS_IMM(iptr->sx.val.i)) {
403 M_ADD_IMM(d, s1, iptr->sx.val.i);
404 } else if (IS_IMM(-iptr->sx.val.i)) {
405 M_SUB_IMM(d, s1, (-iptr->sx.val.i));
407 ICONST(REG_ITMP3, iptr->sx.val.i);
408 M_ADD(d, s1, REG_ITMP3);
411 emit_store_dst(jd, iptr, d);
414 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
415 /* sx.val.l = constant */
417 s3 = iptr->sx.val.l & 0xffffffff;
418 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
419 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
421 M_ADD_IMMS(GET_LOW_REG(d), s1, s3);
423 ICONST(REG_ITMP3, s3);
424 M_ADD_S(GET_LOW_REG(d), s1, REG_ITMP3);
426 s3 = iptr->sx.val.l >> 32;
427 s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
429 M_ADC_IMM(GET_HIGH_REG(d), s1, s3);
431 ICONST(REG_ITMP3, s3);
432 M_ADC(GET_HIGH_REG(d), s1, REG_ITMP3);
434 emit_store_dst(jd, iptr, d);
437 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
439 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
440 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
441 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
443 emit_store_dst(jd, iptr, d);
446 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
448 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
449 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
450 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
451 M_SUB_S(GET_LOW_REG(d), s1, s2);
452 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
453 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
454 M_SBC(GET_HIGH_REG(d), s1, s2);
455 emit_store_dst(jd, iptr, d);
458 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
459 /* sx.val.i = constant */
461 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
462 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
463 if (IS_IMM(iptr->sx.val.i))
464 M_SUB_IMM(d, s1, iptr->sx.val.i);
466 ICONST(REG_ITMP3, iptr->sx.val.i);
467 M_SUB(d, s1, REG_ITMP3);
469 emit_store_dst(jd, iptr, d);
472 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
473 /* sx.val.l = constant */
475 s3 = iptr->sx.val.l & 0xffffffff;
476 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
477 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
479 M_SUB_IMMS(GET_LOW_REG(d), s1, s3);
481 ICONST(REG_ITMP3, s3);
482 M_SUB_S(GET_LOW_REG(d), s1, REG_ITMP3);
484 s3 = iptr->sx.val.l >> 32;
485 s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
487 M_SBC_IMM(GET_HIGH_REG(d), s1, s3);
489 ICONST(REG_ITMP3, s3);
490 M_SBC(GET_HIGH_REG(d), s1, REG_ITMP3);
492 emit_store_dst(jd, iptr, d);
495 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
497 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
498 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
499 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
501 emit_store_dst(jd, iptr, d);
504 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
505 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
507 s1 = emit_load_s1(jd, iptr, REG_A0);
508 s2 = emit_load_s2(jd, iptr, REG_A1);
509 emit_arithmetic_check(cd, iptr, s2);
511 /* move arguments into argument registers */
512 M_INTMOVE(s1, REG_A0);
513 M_INTMOVE(s2, REG_A1);
515 /* call builtin function */
516 bte = iptr->sx.s23.s3.bte;
517 disp = dseg_add_functionptr(cd, bte->fp);
521 emit_recompute_pv(cd);
523 /* move result into destination register */
524 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
525 M_INTMOVE(REG_RESULT, d);
526 emit_store_dst(jd, iptr, d);
529 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
530 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
532 /* move arguments into argument registers */
534 s1 = emit_load_s1(jd, iptr, REG_A0_A1_PACKED);
535 s2 = emit_load_s2(jd, iptr, REG_A2_A3_PACKED);
536 /* XXX TODO: only do this if arithmetic check is really done! */
537 M_ORR(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
538 emit_arithmetic_check(cd, iptr, REG_ITMP3);
540 M_LNGMOVE(s1, REG_A0_A1_PACKED);
541 M_LNGMOVE(s2, REG_A2_A3_PACKED);
543 /* call builtin function */
544 bte = iptr->sx.s23.s3.bte;
545 disp = dseg_add_functionptr(cd, bte->fp);
549 emit_recompute_pv(cd);
551 /* move result into destination register */
552 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
553 M_LNGMOVE(REG_RESULT_PACKED, d);
554 emit_store_dst(jd, iptr, d);
557 case ICMD_IMULPOW2: /* ..., value ==> ..., value * (2 ^ constant) */
558 /* sx.val.i = constant */
560 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
561 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
562 M_MOV(d, REG_LSL(s1, iptr->sx.val.i));
563 emit_store_dst(jd, iptr, d);
566 case ICMD_IDIVPOW2: /* ..., value ==> ..., value / (2 ^ constant) */
567 /* sx.val.i = constant */
569 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
570 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
571 /* this rounds towards 0 as java likes it */
572 M_MOV(REG_ITMP3, REG_ASR(s1, 31));
573 M_ADD(REG_ITMP3, s1, REG_LSR(REG_ITMP3, 32 - iptr->sx.val.i));
574 M_MOV(d, REG_ASR(REG_ITMP3, iptr->sx.val.i));
575 /* this rounds towards nearest, not java style */
576 /*M_MOV_S(d, REG_ASR(s1, iptr->sx.val.i));
577 M_ADCMI_IMM(d, d, 0);*/
578 emit_store_dst(jd, iptr, d);
581 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
582 /* sx.val.i = constant [ (2 ^ x) - 1 ] */
584 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
585 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
586 M_MOV_S(REG_ITMP1, s1);
587 M_RSBMI_IMM(REG_ITMP1, REG_ITMP1, 0);
588 if (IS_IMM(iptr->sx.val.i))
589 M_AND_IMM(REG_ITMP1, iptr->sx.val.i, d);
591 ICONST(REG_ITMP3, iptr->sx.val.i);
592 M_AND(REG_ITMP1, REG_ITMP3, d);
594 M_RSBMI_IMM(d, d, 0);
595 emit_store_dst(jd, iptr, d);
598 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
600 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
601 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
602 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
603 M_AND_IMM(s2, 0x1f, REG_ITMP2);
604 M_MOV(d, REG_LSL_REG(s1, REG_ITMP2));
605 emit_store_dst(jd, iptr, d);
608 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
610 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
611 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
612 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
613 M_AND_IMM(s2, 0x1f, REG_ITMP2);
614 M_MOV(d, REG_ASR_REG(s1, REG_ITMP2));
615 emit_store_dst(jd, iptr, d);
618 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
620 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
621 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
622 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
623 M_AND_IMM(s2, 0x1f, REG_ITMP2);
624 M_MOV(d, REG_LSR_REG(s1, REG_ITMP2));
625 emit_store_dst(jd, iptr, d);
628 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
629 /* sx.val.i = constant */
631 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
632 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
633 M_MOV(d, REG_LSL(s1, iptr->sx.val.i & 0x1f));
634 emit_store_dst(jd, iptr, d);
637 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
638 /* sx.val.i = constant */
640 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
641 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
642 /* we need to check for zero here because arm interprets it as SHR by 32 */
643 if ((iptr->sx.val.i & 0x1f) == 0) {
646 M_MOV(d, REG_ASR(s1, iptr->sx.val.i & 0x1f));
648 emit_store_dst(jd, iptr, d);
651 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
652 /* sx.val.i = constant */
654 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
655 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
656 /* we need to check for zero here because arm interprets it as SHR by 32 */
657 if ((iptr->sx.val.i & 0x1f) == 0)
660 M_MOV(d, REG_LSR(s1, iptr->sx.val.i & 0x1f));
661 emit_store_dst(jd, iptr, d);
664 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
666 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
667 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
668 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
670 emit_store_dst(jd, iptr, d);
673 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
675 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
676 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
677 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
678 M_AND(s1, s2, GET_LOW_REG(d));
679 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
680 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
681 M_AND(s1, s2, GET_HIGH_REG(d));
682 emit_store_dst(jd, iptr, d);
685 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
687 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
688 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
689 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
691 emit_store_dst(jd, iptr, d);
694 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
696 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
697 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
698 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
699 M_ORR(s1, s2, GET_LOW_REG(d));
700 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
701 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
702 M_ORR(s1, s2, GET_HIGH_REG(d));
703 emit_store_dst(jd, iptr, d);
706 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
708 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
709 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
710 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
712 emit_store_dst(jd, iptr, d);
715 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
717 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
718 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
719 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
720 M_EOR(s1, s2, GET_LOW_REG(d));
721 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
722 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
723 M_EOR(s1, s2, GET_HIGH_REG(d));
724 emit_store_dst(jd, iptr, d);
728 /* floating operations ************************************************/
730 #if !defined(ENABLE_SOFTFLOAT)
732 case ICMD_FNEG: /* ..., value ==> ..., - value */
734 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
735 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
737 emit_store_dst(jd, iptr, d);
740 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
742 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
743 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
744 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
746 emit_store_dst(jd, iptr, d);
749 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
751 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
752 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
753 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
755 emit_store_dst(jd, iptr, d);
758 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
760 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
761 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
762 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
764 emit_store_dst(jd, iptr, d);
767 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
768 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
769 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
770 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
772 emit_store_dst(jd, iptr, d);
775 /* ATTENTION: Jave does not want IEEE behaviour in FREM, do
779 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
781 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
782 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
783 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
785 emit_store_dst(jd, iptr, d);
789 case ICMD_DNEG: /* ..., value ==> ..., - value */
791 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
792 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
794 emit_store_dst(jd, iptr, d);
797 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
799 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
800 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
801 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
803 emit_store_dst(jd, iptr, d);
806 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
808 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
809 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
810 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
812 emit_store_dst(jd, iptr, d);
815 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
817 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
818 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
819 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
821 emit_store_dst(jd, iptr, d);
824 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
826 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
827 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
828 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
830 emit_store_dst(jd, iptr, d);
833 /* ATTENTION: Jave does not want IEEE behaviour in DREM, do
837 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
839 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
840 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
841 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
843 emit_store_dst(jd, iptr, d);
847 case ICMD_I2F: /* ..., value ==> ..., (float) value */
849 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
850 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
851 #if defined(__VFP_FP__)
857 emit_store_dst(jd, iptr, d);
860 case ICMD_I2D: /* ..., value ==> ..., (double) value */
862 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
863 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
864 #if defined(__VFP_FP__)
870 emit_store_dst(jd, iptr, d);
873 case ICMD_F2I: /* ..., value ==> ..., (int) value */
875 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
876 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
877 #if defined(__VFP_FP__)
878 M_CVTFI(s1, REG_FTMP2);
879 M_FMRS(REG_FTMP2, d);
881 /* this uses round towards zero, as Java likes it */
883 /* this checks for NaN; to return zero as Java likes it */
887 emit_store_dst(jd, iptr, d);
890 case ICMD_D2I: /* ..., value ==> ..., (int) value */
892 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
893 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
894 #if defined(__VFP_FP__)
895 M_CVTDI(s1, REG_FTMP2);
896 M_FMRS(REG_FTMP2, d);
898 /* this uses round towards zero, as Java likes it */
900 /* this checks for NaN; to return zero as Java likes it */
904 emit_store_dst(jd, iptr, d);
907 case ICMD_D2F: /* ..., value ==> ..., (float) value */
909 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
910 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
912 emit_store_dst(jd, iptr, d);
915 case ICMD_F2D: /* ..., value ==> ..., (double) value */
917 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
918 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
920 emit_store_dst(jd, iptr, d);
923 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
925 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
926 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
927 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
930 #if defined(__VFP_FP__)
931 M_FMSTAT; /* on VFP we need to transfer the flags */
933 M_SUBGT_IMM(d, d, 1);
934 M_ADDLT_IMM(d, d, 1);
935 emit_store_dst(jd, iptr, d);
938 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 dcmpg 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_ITMP1);
945 #if defined(__VFP_FP__)
946 M_FMSTAT; /* on VFP we need to transfer the flags */
948 M_SUBGT_IMM(d, d, 1);
949 M_ADDLT_IMM(d, d, 1);
950 emit_store_dst(jd, iptr, d);
953 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
955 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
956 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
957 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
960 #if defined(__VFP_FP__)
961 M_FMSTAT; /* on VFP we need to transfer the flags */
963 M_SUBLT_IMM(d, d, 1);
964 M_ADDGT_IMM(d, d, 1);
965 emit_store_dst(jd, iptr, d);
968 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 dcmpl 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_ITMP1);
975 #if defined(__VFP_FP__)
976 M_FMSTAT; /* on VFP we need to transfer the flags */
978 M_SUBLT_IMM(d, d, 1);
979 M_ADDGT_IMM(d, d, 1);
980 emit_store_dst(jd, iptr, d);
983 #endif /* !defined(ENABLE_SOFTFLOAT) */
986 /* memory operations **************************************************/
988 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
990 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
991 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
992 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
993 /* implicit null-pointer check */
994 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
995 M_ADD(REG_ITMP1, s1, s2); /* REG_ITMP1 = s1 + 1 * s2 */
996 M_LDRSB(d, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
997 emit_store_dst(jd, iptr, d);
1000 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1002 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1003 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1004 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1005 /* implicit null-pointer check */
1006 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1007 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1008 M_LDRH(d, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1009 emit_store_dst(jd, iptr, d);
1012 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1014 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1015 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1016 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1017 /* implicit null-pointer check */
1018 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1019 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1020 M_LDRSH(d, REG_ITMP1, OFFSET(java_shortarray_t, data[0]));
1021 emit_store_dst(jd, iptr, d);
1024 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1026 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1027 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1028 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1029 /* implicit null-pointer check */
1030 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1031 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1032 M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1033 emit_store_dst(jd, iptr, d);
1036 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1038 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1039 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1040 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1041 /* implicit null-pointer check */
1042 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1043 M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
1044 M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1045 emit_store_dst(jd, iptr, d);
1048 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1050 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1051 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1052 /* implicit null-pointer check */
1053 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1054 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1055 #if !defined(ENABLE_SOFTFLOAT)
1056 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1057 M_FLD_INTERN(d, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1059 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1060 M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1062 emit_store_dst(jd, iptr, d);
1065 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1067 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1068 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1069 /* implicit null-pointer check */
1070 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1071 M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
1072 #if !defined(ENABLE_SOFTFLOAT)
1073 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1074 M_DLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1076 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1077 M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1079 emit_store_dst(jd, iptr, d);
1082 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1084 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1085 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1086 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1087 /* implicit null-pointer check */
1088 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1089 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1090 M_LDR_INTERN(d, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1091 emit_store_dst(jd, iptr, d);
1094 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1096 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1097 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1098 /* implicit null-pointer check */
1099 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1100 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1101 M_ADD(REG_ITMP1, s1, s2); /* REG_ITMP1 = s1 + 1 * s2 */
1102 M_STRB(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1105 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1107 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1108 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1109 /* implicit null-pointer check */
1110 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1111 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1112 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1113 M_STRH(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1116 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1118 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1119 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1120 /* implicit null-pointer check */
1121 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1122 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1123 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1124 M_STRH(s3, REG_ITMP1, OFFSET(java_shortarray_t, data[0]));
1127 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1129 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1130 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1131 /* implicit null-pointer check */
1132 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1133 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1134 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1135 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1138 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1140 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1141 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1142 /* implicit null-pointer check */
1143 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1144 M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
1145 s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1146 M_LST_INTERN(s3, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1149 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1151 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1152 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1153 /* implicit null-pointer check */
1154 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1155 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1156 #if !defined(ENABLE_SOFTFLOAT)
1157 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1158 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1160 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1161 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1165 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1167 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1168 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1169 /* implicit null-pointer check */
1170 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1171 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 3)); /* REG_ITMP1 = s1 + 8 * s2 */
1172 #if !defined(ENABLE_SOFTFLOAT)
1173 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1174 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1176 s3 = emit_load_s3(jd, iptr, REG_ITMP23_PACKED);
1177 M_LST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1181 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1183 s1 = emit_load_s1(jd, iptr, REG_A0);
1184 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1185 s3 = emit_load_s3(jd, iptr, REG_A1);
1187 /* implicit null-pointer check */
1188 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1190 /* move arguments to argument registers */
1191 M_INTMOVE(s1, REG_A0);
1192 M_INTMOVE(s3, REG_A1);
1194 /* call builtin function */
1195 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1196 M_DSEG_BRANCH(disp);
1199 emit_recompute_pv(cd);
1201 /* check resturn value of builtin */
1202 emit_arraystore_check(cd, iptr);
1204 /* finally store address into array */
1205 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1206 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1207 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1208 M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1209 M_STR_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1212 case ICMD_GETSTATIC: /* ... ==> ..., value */
1213 switch (fieldtype) {
1215 #if defined(ENABLE_SOFTFLOAT)
1219 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1220 M_ILD_INTERN(d, REG_ITMP3, 0);
1223 #if defined(ENABLE_SOFTFLOAT)
1226 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1227 M_LLD_INTERN(d, REG_ITMP3, 0);
1229 #if !defined(ENABLE_SOFTFLOAT)
1231 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1232 M_FLD_INTERN(d, REG_ITMP3, 0);
1235 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1236 M_DLD_INTERN(d, REG_ITMP3, 0);
1242 emit_store_dst(jd, iptr, d);
1245 case ICMD_GETFIELD: /* ..., objectref, value ==> ... */
1247 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
1248 emit_nullpointer_check(cd, iptr, s1);
1251 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1252 uf = iptr->sx.s23.s3.uf;
1253 fieldtype = uf->fieldref->parseddesc.fd->type;
1257 fi = iptr->sx.s23.s3.fmiref->p.field;
1258 fieldtype = fi->type;
1262 #if !defined(ENABLE_SOFTFLOAT)
1263 /* HACK: softnull checks on floats */
1264 if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
1265 emit_nullpointer_check_force(cd, iptr, s1);
1268 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1270 uf = iptr->sx.s23.s3.uf;
1272 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1275 switch (fieldtype) {
1277 #if defined(ENABLE_SOFTFLOAT)
1281 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1285 #if defined(ENABLE_SOFTFLOAT)
1288 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1291 #if !defined(ENABLE_SOFTFLOAT)
1293 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1297 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1304 emit_store_dst(jd, iptr, d);
1307 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1309 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
1310 emit_nullpointer_check(cd, iptr, s1);
1312 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1313 uf = iptr->sx.s23.s3.uf;
1314 fieldtype = uf->fieldref->parseddesc.fd->type;
1318 fi = iptr->sx.s23.s3.fmiref->p.field;
1319 fieldtype = fi->type;
1323 #if !defined(ENABLE_SOFTFLOAT)
1324 /* HACK: softnull checks on floats */
1325 if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
1326 emit_nullpointer_check_force(cd, iptr, s1);
1329 switch (fieldtype) {
1331 #if defined(ENABLE_SOFTFLOAT)
1335 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1337 #if defined(ENABLE_SOFTFLOAT)
1338 case TYPE_DBL: /* fall through */
1341 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
1343 #if !defined(ENABLE_SOFTFLOAT)
1346 s2 = emit_load_s2(jd, iptr, REG_FTMP1);
1353 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1355 uf = iptr->sx.s23.s3.uf;
1357 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1360 switch (fieldtype) {
1362 #if defined(ENABLE_SOFTFLOAT)
1366 M_IST(s2, s1, disp);
1369 #if defined(ENABLE_SOFTFLOAT)
1372 M_LST(s2, s1, disp);
1374 #if !defined(ENABLE_SOFTFLOAT)
1376 M_FST(s2, s1, disp);
1379 M_DST(s2, s1, disp);
1388 /* branch operations **************************************************/
1390 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1392 disp = dseg_add_functionptr(cd, asm_handle_exception);
1393 M_DSEG_LOAD(REG_ITMP3, disp);
1394 M_MOV(REG_ITMP2_XPC, REG_PC);
1395 M_MOV(REG_PC, REG_ITMP3);
1396 M_NOP; /* nop ensures that XPC is less than the end */
1397 /* of basic block */
1400 case ICMD_IF_LEQ: /* ..., value ==> ... */
1402 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1403 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1404 if (iptr->sx.val.l == 0) {
1405 M_ORR_S(s1, s2, REG_ITMP3);
1408 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1409 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1410 M_CMP(s1, REG_ITMP3);*/
1411 ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1412 M_CMPEQ(s2, REG_ITMP3);
1414 emit_beq(cd, iptr->dst.block);
1417 case ICMD_IF_LLT: /* ..., value ==> ... */
1419 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1420 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1421 if (iptr->sx.val.l == 0) {
1422 /* if high word is less than zero, the whole long is too */
1424 emit_blt(cd, iptr->dst.block);
1427 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1428 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1429 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1430 M_CMP(s1, REG_ITMP3);*/
1431 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1432 M_MOVGT_IMM(2, REG_ITMP1);
1433 M_MOVEQ_IMM(1, REG_ITMP1);
1435 /* low compare: x=x-1(ifLO) */
1436 emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
1437 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1438 M_CMP(s2, REG_ITMP3);*/
1439 M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
1441 /* branch if (x LT 1) */
1442 M_CMP_IMM(REG_ITMP1, 1);
1443 emit_blt(cd, iptr->dst.block);
1447 case ICMD_IF_LLE: /* ..., value ==> ... */
1449 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1450 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1451 if (iptr->sx.val.l == 0) {
1452 /* if high word is less than zero, the whole long is too */
1454 emit_blt(cd, iptr->dst.block);
1456 /* ... otherwise the low word has to be zero (tricky!) */
1458 emit_beq(cd, iptr->dst.block);
1461 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1462 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1463 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1464 M_CMP(s1, REG_ITMP3);*/
1465 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1466 M_MOVGT_IMM(2, REG_ITMP1);
1467 M_MOVEQ_IMM(1, REG_ITMP1);
1469 /* low compare: x=x+1(ifHI) */
1470 emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
1471 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1472 M_CMP(s2, REG_ITMP3);*/
1473 M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
1475 /* branch if (x LE 1) */
1476 M_CMP_IMM(REG_ITMP1, 1);
1477 emit_ble(cd, iptr->dst.block);
1481 case ICMD_IF_LGE: /* ..., value ==> ... */
1483 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1484 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1485 if (iptr->sx.val.l == 0) {
1486 /* if high word is greater or equal zero, the whole long is too */
1488 emit_bge(cd, iptr->dst.block);
1491 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1492 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1493 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1494 M_CMP(s1, REG_ITMP3);*/
1495 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1496 M_MOVGT_IMM(2, REG_ITMP1);
1497 M_MOVEQ_IMM(1, REG_ITMP1);
1499 /* low compare: x=x-1(ifLO) */
1500 emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
1501 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1502 M_CMP(s2, REG_ITMP3);*/
1503 M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
1505 /* branch if (x GE 1) */
1506 M_CMP_IMM(REG_ITMP1, 1);
1507 emit_bge(cd, iptr->dst.block);
1511 case ICMD_IF_LGT: /* ..., value ==> ... */
1513 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1514 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1516 if (iptr->sx.val.l == 0) {
1517 /* if high word is greater than zero, the whole long is too */
1520 codegen_add_branch_ref(cd, iptr->dst.block);
1522 /* ... or high was zero and low is non zero (tricky!) */
1523 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1524 M_MOVLT_IMM(1, REG_ITMP3);
1525 M_ORR_S(REG_ITMP3, s2, REG_ITMP3);
1527 codegen_add_branch_ref(cd, iptr->dst.block);
1531 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1532 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1533 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1534 M_CMP(s1, REG_ITMP3);*/
1535 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1536 M_MOVGT_IMM(2, REG_ITMP1);
1537 M_MOVEQ_IMM(1, REG_ITMP1);
1539 /* low compare: x=x+1(ifHI) */
1540 emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
1541 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1542 M_CMP(s2, REG_ITMP3);*/
1543 M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
1545 /* branch if (x GT 1) */
1546 M_CMP_IMM(REG_ITMP1, 1);
1547 emit_bgt(cd, iptr->dst.block);
1553 case ICMD_IF_LNE: /* ..., value ==> ... */
1555 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1556 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1557 if (iptr->sx.val.l == 0) {
1558 M_ORR_S(s1, s2, REG_ITMP3);
1561 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1562 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1563 M_CMP(s1, REG_ITMP3);*/
1564 ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1565 M_CMPEQ(s2, REG_ITMP3);
1567 emit_bne(cd, iptr->dst.block);
1570 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1571 /* op1 = target JavaVM pc */
1573 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1574 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1577 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1578 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1581 emit_beq(cd, iptr->dst.block);
1584 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
1585 /* op1 = target JavaVM pc */
1587 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1588 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1591 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1592 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1595 emit_bne(cd, iptr->dst.block);
1598 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
1599 /* op1 = target JavaVM pc */
1601 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1602 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1603 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1605 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1606 M_MOVGT_IMM(2, REG_ITMP3);
1607 M_MOVEQ_IMM(1, REG_ITMP3);
1609 /* low compare: x=x-1(ifLO) */
1610 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1611 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1613 M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1);
1615 /* branch if (x LT 1) */
1616 M_CMP_IMM(REG_ITMP3, 1);
1617 emit_blt(cd, iptr->dst.block);
1620 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
1621 /* op1 = target JavaVM pc */
1623 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1624 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1625 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1627 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1628 M_MOVGT_IMM(2, REG_ITMP3);
1629 M_MOVEQ_IMM(1, REG_ITMP3);
1631 /* low compare: x=x-1(ifLO) */
1632 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1633 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1635 M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1);
1637 /* branch if (x LE 1) */
1638 M_CMP_IMM(REG_ITMP3, 1);
1639 emit_ble(cd, iptr->dst.block);
1642 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
1643 /* op1 = target JavaVM pc */
1645 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1646 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1647 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1649 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1650 M_MOVGT_IMM(2, REG_ITMP3);
1651 M_MOVEQ_IMM(1, REG_ITMP3);
1653 /* low compare: x=x-1(ifLO) */
1654 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1655 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1657 M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1);
1659 /* branch if (x GT 1) */
1660 M_CMP_IMM(REG_ITMP3, 1);
1661 emit_bgt(cd, iptr->dst.block);
1664 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
1665 /* op1 = target JavaVM pc */
1667 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1668 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1669 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1671 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1672 M_MOVGT_IMM(2, REG_ITMP3);
1673 M_MOVEQ_IMM(1, REG_ITMP3);
1675 /* low compare: x=x-1(ifLO) */
1676 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1677 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1679 M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1);
1681 /* branch if (x GE 1) */
1682 M_CMP_IMM(REG_ITMP3, 1);
1683 emit_bge(cd, iptr->dst.block);
1686 case ICMD_TABLESWITCH: /* ..., index ==> ... */
1689 branch_target_t *table;
1691 table = iptr->dst.table;
1693 l = iptr->sx.s23.s2.tablelow;
1694 i = iptr->sx.s23.s3.tablehigh;
1696 /* calculate new index (index - low) */
1697 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1699 M_INTMOVE(s1, REG_ITMP1);
1700 } else if (IS_IMM(l)) {
1701 M_SUB_IMM(REG_ITMP1, s1, l);
1703 ICONST(REG_ITMP2, l);
1704 M_SUB(REG_ITMP1, s1, REG_ITMP2);
1707 /* range check (index <= high-low) */
1709 emit_icmp_imm(cd, REG_ITMP1, i-1);
1710 emit_bugt(cd, table[0].block);
1712 /* build jump table top down and use address of lowest entry */
1717 dseg_add_target(cd, table->block);
1722 /* length of dataseg after last dseg_add_target is used by load */
1723 /* TODO: this loads from data-segment */
1724 M_ADD(REG_ITMP2, REG_PV, REG_LSL(REG_ITMP1, 2));
1725 M_LDR(REG_PC, REG_ITMP2, -(cd->dseglen));
1729 bte = iptr->sx.s23.s3.bte;
1730 if (bte->stub == NULL) {
1731 disp = dseg_add_functionptr(cd, bte->fp);
1733 disp = dseg_add_functionptr(cd, bte->stub);
1736 M_DSEG_LOAD(REG_PV, disp); /* pointer to built-in-function */
1738 /* generate the actual call */
1740 M_MOV(REG_LR, REG_PC);
1741 M_MOV(REG_PC, REG_PV);
1743 #if !defined(__SOFTFP__)
1744 /* TODO: this is only a hack, since we use R0/R1 for float
1745 return! this depends on gcc; it is independent from
1746 our ENABLE_SOFTFLOAT define */
1747 if (d != TYPE_VOID && IS_FLT_DBL_TYPE(d)) {
1748 #if 0 && !defined(NDEBUG)
1749 dolog("BUILTIN that returns float or double (%s.%s)", m->clazz->name->text, m->name->text);
1751 /* we cannot use this macro, since it is not defined
1752 in ENABLE_SOFTFLOAT M_CAST_FLT_TO_INT_TYPED(d,
1753 REG_FRESULT, REG_RESULT_TYPED(d)); */
1754 if (IS_2_WORD_TYPE(d)) {
1755 DCD(0xed2d8102); /* stfd f0, [sp, #-8]! */
1756 M_LDRD_UPDATE(REG_RESULT_PACKED, REG_SP, 8);
1758 DCD(0xed2d0101); /* stfs f0, [sp, #-4]!*/
1759 M_LDR_UPDATE(REG_RESULT, REG_SP, 4);
1765 case ICMD_INVOKESPECIAL:
1766 emit_nullpointer_check(cd, iptr, REG_A0);
1769 case ICMD_INVOKESTATIC:
1770 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1771 um = iptr->sx.s23.s3.um;
1772 disp = dseg_add_unique_address(cd, NULL);
1774 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
1778 lm = iptr->sx.s23.s3.fmiref->p.method;
1779 disp = dseg_add_address(cd, lm->stubroutine);
1782 M_DSEG_LOAD(REG_PV, disp); /* Pointer to method */
1784 /* generate the actual call */
1786 M_MOV(REG_LR, REG_PC);
1787 M_MOV(REG_PC, REG_PV);
1790 case ICMD_INVOKEVIRTUAL:
1791 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1792 um = iptr->sx.s23.s3.um;
1793 int32_t disp = dseg_add_unique_s4(cd, 0);
1794 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, disp);
1796 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1797 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1800 assert(REG_ITMP1 != REG_METHODPTR);
1801 assert(REG_ITMP2 == REG_METHODPTR);
1803 M_DSEG_LOAD(REG_ITMP1, disp);
1804 M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
1806 // This must be a load with displacement,
1807 // otherwise the JIT method address patching does
1808 // not work anymore (see md_jit_method_patch_address).
1809 M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
1812 lm = iptr->sx.s23.s3.fmiref->p.method;
1813 s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
1815 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1816 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1817 M_LDR(REG_PV, REG_METHODPTR, s1);
1820 // Generate the actual call.
1821 M_MOV(REG_LR, REG_PC);
1822 M_MOV(REG_PC, REG_PV);
1825 case ICMD_INVOKEINTERFACE:
1826 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1827 um = iptr->sx.s23.s3.um;
1828 int32_t disp = dseg_add_unique_s4(cd, 0);
1829 int32_t disp2 = dseg_add_unique_s4(cd, 0);
1831 // XXX We need two displacements.
1832 assert(disp2 == disp - 4);
1833 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, disp);
1835 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1836 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1839 assert(REG_ITMP1 != REG_METHODPTR);
1840 assert(REG_ITMP2 == REG_METHODPTR);
1841 assert(REG_ITMP3 != REG_METHODPTR);
1843 M_DSEG_LOAD(REG_ITMP1, disp);
1844 M_LDR_REG(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
1846 M_DSEG_LOAD(REG_ITMP3, disp2);
1847 M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP3);
1849 // This must be a load with displacement,
1850 // otherwise the JIT method address patching does
1851 // not work anymore (see md_jit_method_patch_address).
1852 M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
1855 lm = iptr->sx.s23.s3.fmiref->p.method;
1856 s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->clazz->index;
1857 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
1859 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1860 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1861 M_LDR(REG_METHODPTR, REG_METHODPTR, s1);
1862 M_LDR(REG_PV, REG_METHODPTR, s2);
1865 // Generate the actual call.
1866 M_MOV(REG_LR, REG_PC);
1867 M_MOV(REG_PC, REG_PV);
1870 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
1872 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1873 /* object type cast-check */
1878 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1883 super = iptr->sx.s23.s3.c.cls;
1884 superindex = super->index;
1887 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1889 /* if class is not resolved, check which code to call */
1891 if (super == NULL) {
1893 emit_label_beq(cd, BRANCH_LABEL_1);
1895 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
1896 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
1897 iptr->sx.s23.s3.c.ref, disp);
1899 M_DSEG_LOAD(REG_ITMP2, disp);
1900 disp = dseg_add_s4(cd, ACC_INTERFACE);
1901 M_DSEG_LOAD(REG_ITMP3, disp);
1902 M_TST(REG_ITMP2, REG_ITMP3);
1903 emit_label_beq(cd, BRANCH_LABEL_2);
1906 /* interface checkcast code */
1908 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
1909 if ((super == NULL) || !IS_IMM(superindex)) {
1910 disp = dseg_add_unique_s4(cd, superindex);
1912 if (super == NULL) {
1913 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
1914 iptr->sx.s23.s3.c.ref, disp);
1918 emit_label_beq(cd, BRANCH_LABEL_3);
1921 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
1922 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
1924 /* we put unresolved or non-immediate superindices onto dseg */
1925 if ((super == NULL) || !IS_IMM(superindex)) {
1926 /* disp was computed before we added the patcher */
1927 M_DSEG_LOAD(REG_ITMP2, disp);
1928 M_CMP(REG_ITMP3, REG_ITMP2);
1930 assert(IS_IMM(superindex));
1931 M_CMP_IMM(REG_ITMP3, superindex);
1934 emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
1936 /* if we loaded the superindex out of the dseg above, we do
1937 things differently here! */
1938 if ((super == NULL) || !IS_IMM(superindex)) {
1940 M_LDR_INTERN(REG_ITMP3, s1, OFFSET(java_object_t, vftbl));
1942 /* this assumes something */
1943 assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
1945 /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
1946 assert(sizeof(methodptr*) == 4);
1947 M_SUB(REG_ITMP2, REG_ITMP3, REG_LSL(REG_ITMP2, 2));
1953 s2 = OFFSET(vftbl_t, interfacetable[0]) -
1954 superindex * sizeof(methodptr*);
1958 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, s2);
1959 M_TST(REG_ITMP3, REG_ITMP3);
1960 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
1963 emit_label_br(cd, BRANCH_LABEL_4);
1965 emit_label(cd, BRANCH_LABEL_3);
1968 /* class checkcast code */
1970 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
1971 if (super == NULL) {
1972 emit_label(cd, BRANCH_LABEL_2);
1974 disp = dseg_add_unique_address(cd, NULL);
1976 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
1977 iptr->sx.s23.s3.c.ref,
1981 disp = dseg_add_address(cd, super->vftbl);
1984 emit_label_beq(cd, BRANCH_LABEL_5);
1987 // The following code checks whether object s is a subtype of class t.
1988 // Represents the following semantic:
1989 // if (!fast_subtype_check(s->vftbl, t->vftbl)) throw;
1991 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
1992 M_DSEG_LOAD(REG_ITMP3, disp);
1994 if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
1995 // Represents the following semantic:
1996 // if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) good;
1998 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
1999 M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
2000 M_LDR_REG(REG_ITMP1, REG_ITMP2, REG_ITMP1);
2001 M_CMP(REG_ITMP1, REG_ITMP3);
2002 emit_load_s1(jd, iptr, REG_ITMP1); /* reload s1, might have been destroyed */
2003 emit_label_beq(cd, BRANCH_LABEL_6); /* good */
2005 // Represents the following semantic:
2006 // if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) throw;
2008 // REG_ITMP3==t->vftbl;
2009 if (super == NULL) {
2010 M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
2011 M_CMP_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]));
2012 emit_load_s1(jd, iptr, REG_ITMP1); /* reload s1, might have been destroyed */
2013 emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1); /* throw */
2016 // Represents the following semantic:
2017 // if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) throw;
2019 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2020 M_LDR_INTERN(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
2021 M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
2022 M_CMP(REG_ITMP1, REG_ITMP3);
2023 emit_load_s1(jd, iptr, REG_ITMP1); /* reload s1, might have been destroyed */
2024 emit_classcast_check(cd, iptr, BRANCH_LT, 0, s1); /* throw */
2026 // Represents the following semantic:
2027 // if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) throw;
2029 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth;
2030 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
2031 M_ADD(REG_ITMP2, REG_ITMP2, REG_LSL(REG_ITMP3, 2)); /* REG_ITMP2 = REG_ITMP2 + 4 * REG_ITMP3 */
2032 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, -DISPLAY_SIZE * SIZEOF_VOID_P);
2033 M_DSEG_LOAD(REG_ITMP3, disp); /* reload REG_ITMP3, was destroyed */
2034 M_CMP(REG_ITMP2, REG_ITMP3);
2035 emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1); /* throw */
2037 emit_label(cd, BRANCH_LABEL_6);
2040 // Represents the following semantic:
2041 // if (*(s->vftbl + t->vftbl->subtype_offset) != t->vftbl) throw;
2043 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2044 M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
2045 M_CMP(REG_ITMP2, REG_ITMP3);
2046 emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1);
2050 emit_label(cd, BRANCH_LABEL_5);
2053 if (super == NULL) {
2054 emit_label(cd, BRANCH_LABEL_1);
2055 emit_label(cd, BRANCH_LABEL_4);
2058 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
2061 /* array type cast-check */
2063 s1 = emit_load_s1(jd, iptr, REG_A0);
2064 M_INTMOVE(s1, REG_A0);
2066 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2067 disp = dseg_add_unique_address(cd, NULL);
2069 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2070 iptr->sx.s23.s3.c.ref,
2074 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2076 M_DSEG_LOAD(REG_A1, disp);
2077 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2078 M_DSEG_BRANCH(disp);
2080 emit_recompute_pv(cd);
2082 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2083 M_TST(REG_RESULT, REG_RESULT);
2084 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2086 d = codegen_reg_of_dst(jd, iptr, s1);
2090 emit_store_dst(jd, iptr, d);
2093 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2099 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2104 super = iptr->sx.s23.s3.c.cls;
2105 superindex = super->index;
2108 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2109 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2112 M_MOV(REG_ITMP1, s1);
2116 /* if class is not resolved, check which code to call */
2118 if (super == NULL) {
2122 emit_label_beq(cd, BRANCH_LABEL_1);
2124 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2125 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2126 iptr->sx.s23.s3.c.ref, disp);
2128 M_DSEG_LOAD(REG_ITMP2, disp);
2129 disp = dseg_add_s4(cd, ACC_INTERFACE);
2130 M_DSEG_LOAD(REG_ITMP3, disp);
2131 M_TST(REG_ITMP2, REG_ITMP3);
2132 emit_label_beq(cd, BRANCH_LABEL_2);
2135 /* interface checkcast code */
2137 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2138 if ((super == NULL) || !IS_IMM(superindex)) {
2139 disp = dseg_add_unique_s4(cd, superindex);
2141 if (super == NULL) {
2142 /* If d == REG_ITMP2, then it's destroyed in check
2147 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
2148 iptr->sx.s23.s3.c.ref, disp);
2153 emit_label_beq(cd, BRANCH_LABEL_3);
2156 M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2157 M_LDR_INTERN(REG_ITMP3,
2158 REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2160 /* we put unresolved or non-immediate superindices onto dseg
2161 and do things slightly different */
2162 if ((super == NULL) || !IS_IMM(superindex)) {
2163 /* disp was computed before we added the patcher */
2164 M_DSEG_LOAD(REG_ITMP2, disp);
2165 M_CMP(REG_ITMP3, REG_ITMP2);
2167 if (d == REG_ITMP2) {
2174 /* this assumes something */
2175 assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
2177 /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
2178 assert(sizeof(methodptr*) == 4);
2179 M_SUB(REG_ITMP1, REG_ITMP1, REG_LSL(REG_ITMP2, 2));
2181 if (d == REG_ITMP2) {
2188 assert(IS_IMM(superindex));
2189 M_CMP_IMM(REG_ITMP3, superindex);
2193 s2 = OFFSET(vftbl_t, interfacetable[0]) -
2194 superindex * sizeof(methodptr*);
2198 M_LDR_INTERN(REG_ITMP3, REG_ITMP1, s2);
2199 M_TST(REG_ITMP3, REG_ITMP3);
2203 emit_label_br(cd, BRANCH_LABEL_4);
2205 emit_label(cd, BRANCH_LABEL_3);
2208 /* class checkcast code */
2210 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2211 if (super == NULL) {
2212 emit_label(cd, BRANCH_LABEL_2);
2214 disp = dseg_add_unique_address(cd, NULL);
2216 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2217 iptr->sx.s23.s3.c.ref, disp);
2220 disp = dseg_add_address(cd, super->vftbl);
2224 emit_label_beq(cd, BRANCH_LABEL_5);
2227 // The following code checks whether object s is a subtype of class t.
2228 // Represents the following semantic:
2229 // fast_subtype_check(s->vftbl, t->vftbl));
2231 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2232 M_DSEG_LOAD(REG_ITMP3, disp);
2234 if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
2235 // Represents the following semantic:
2236 // if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) true;
2238 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2239 M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
2240 M_LDR_REG(REG_ITMP1, REG_ITMP2, REG_ITMP1);
2241 M_CMP(REG_ITMP1, REG_ITMP3);
2242 emit_label_beq(cd, BRANCH_LABEL_6); /* true */
2244 // Represents the following semantic:
2245 // if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) false;
2247 // REG_ITMP3==t->vftbl;
2248 if (super == NULL) {
2249 M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
2250 M_CMP_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]));
2251 emit_label_bne(cd, BRANCH_LABEL_7); /* false */
2254 // Represents the following semantic:
2255 // if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) false;
2257 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2258 M_LDR_INTERN(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
2259 M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
2260 M_CMP(REG_ITMP1, REG_ITMP3);
2261 emit_label_blt(cd, BRANCH_LABEL_8); /* false */
2263 // Represents the following semantic:
2264 // if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) false;
2266 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth;
2267 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
2268 M_ADD(REG_ITMP2, REG_ITMP2, REG_LSL(REG_ITMP3, 2)); /* REG_ITMP2 = REG_ITMP2 + 4 * REG_ITMP3 */
2269 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, -DISPLAY_SIZE * SIZEOF_VOID_P);
2270 M_DSEG_LOAD(REG_ITMP3, disp); /* reload REG_ITMP3, was destroyed */
2271 M_CMP(REG_ITMP2, REG_ITMP3);
2273 emit_label(cd, BRANCH_LABEL_6);
2275 emit_label(cd, BRANCH_LABEL_7);
2276 emit_label(cd, BRANCH_LABEL_8);
2278 /* If d == REG_ITMP2, then it's destroyed */
2284 // Represents the following semantic:
2285 // *(s->vftbl + t->vftbl->subtype_offset) == t->vftbl;
2287 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2288 M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
2289 M_CMP(REG_ITMP2, REG_ITMP3);
2290 /* If d == REG_ITMP2, then it's destroyed */
2297 emit_label(cd, BRANCH_LABEL_5);
2300 if (super == NULL) {
2301 emit_label(cd, BRANCH_LABEL_1);
2302 emit_label(cd, BRANCH_LABEL_4);
2307 emit_store_dst(jd, iptr, d);
2310 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2312 /* copy sizes to stack if necessary */
2314 MCODECHECK((iptr->s1.argcount << 1) + 64);
2316 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2318 var = VAR(iptr->sx.s23.s2.args[s1]);
2320 /* copy SAVEDVAR sizes to stack */
2322 if (!(var->flags & PREALLOC)) {
2323 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2324 M_STR(s2, REG_SP, s1 * 4);
2328 /* a0 = dimension count */
2330 assert(IS_IMM(iptr->s1.argcount));
2331 M_MOV_IMM(REG_A0, iptr->s1.argcount);
2333 /* is patcher function set? */
2335 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2336 disp = dseg_add_unique_address(cd, NULL);
2338 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2339 iptr->sx.s23.s3.c.ref, disp);
2342 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2344 /* a1 = arraydescriptor */
2346 M_DSEG_LOAD(REG_A1, disp);
2348 /* a2 = pointer to dimensions = stack pointer */
2350 M_INTMOVE(REG_SP, REG_A2);
2352 /* call builtin_multianewarray here */
2354 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2355 M_DSEG_BRANCH(disp);
2359 emit_recompute_pv(cd);
2361 /* check for exception before result assignment */
2363 emit_exception_check(cd, iptr);
2367 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2368 M_INTMOVE(REG_RESULT, d);
2369 emit_store_dst(jd, iptr, d);
2373 vm_abort("Unknown ICMD %d during code generation", iptr->opc);
2374 } /* the big switch */
2378 /* codegen_emit_stub_native ****************************************************
2380 Emits a stub routine which calls a native method.
2382 *******************************************************************************/
2384 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2395 /* get required compiler data */
2401 /* initialize variables */
2405 /* calculate stackframe size */
2407 cd->stackframesize =
2408 4 + /* return address */
2409 sizeof(stackframeinfo_t) + /* stackframeinfo */
2410 sizeof(localref_table) + /* localref_table */
2411 nmd->memuse * 4; /* stack arguments */
2413 /* align stack to 8-byte */
2415 cd->stackframesize = (cd->stackframesize + 4) & ~4;
2417 /* create method header */
2419 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2420 (void) dseg_add_unique_s4(cd, cd->stackframesize); /* FrameSize */
2421 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2422 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2423 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2425 /* generate stub code */
2427 M_STMFD(1<<REG_LR, REG_SP);
2428 M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - 1);
2430 #if defined(ENABLE_GC_CACAO)
2431 /* Save callee saved integer registers in stackframeinfo (GC may
2432 need to recover them during a collection). */
2434 disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
2435 OFFSET(stackframeinfo_t, intregs);
2437 for (i = 0; i < INT_SAV_CNT; i++)
2438 M_STR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2441 /* Save integer and float argument registers (these are 4
2442 registers, stack is 8-byte aligned). */
2444 M_STMFD(BITMASK_ARGS, REG_SP);
2445 /* TODO: floating point */
2447 /* create native stackframe info */
2449 M_ADD_IMM(REG_A0, REG_SP, 4*4);
2450 M_MOV(REG_A1, REG_PV);
2451 disp = dseg_add_functionptr(cd, codegen_start_native_call);
2452 M_DSEG_BRANCH(disp);
2456 emit_recompute_pv(cd);
2458 /* remember class argument */
2460 if (m->flags & ACC_STATIC)
2461 M_MOV(REG_ITMP3, REG_RESULT);
2463 /* Restore integer and float argument registers (these are 4
2464 registers, stack is 8-byte aligned). */
2466 M_LDMFD(BITMASK_ARGS, REG_SP);
2467 /* TODO: floating point */
2469 /* copy or spill arguments to new locations */
2470 /* ATTENTION: the ARM has only integer argument registers! */
2472 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2473 t = md->paramtypes[i].type;
2475 if (!md->params[i].inmemory) {
2476 s1 = md->params[i].regoff;
2477 s2 = nmd->params[j].regoff;
2479 if (!nmd->params[j].inmemory) {
2480 #if !defined(__ARM_EABI__)
2481 SPLIT_OPEN(t, s2, REG_ITMP1);
2484 if (IS_2_WORD_TYPE(t))
2489 #if !defined(__ARM_EABI__)
2490 SPLIT_STORE_AND_CLOSE(t, s2, 0);
2494 if (IS_2_WORD_TYPE(t))
2495 M_LST(s1, REG_SP, s2);
2497 M_IST(s1, REG_SP, s2);
2501 s1 = md->params[i].regoff + cd->stackframesize;
2502 s2 = nmd->params[j].regoff;
2504 if (IS_2_WORD_TYPE(t)) {
2505 M_LLD(REG_ITMP12_PACKED, REG_SP, s1);
2506 M_LST(REG_ITMP12_PACKED, REG_SP, s2);
2509 M_ILD(REG_ITMP1, REG_SP, s1);
2510 M_IST(REG_ITMP1, REG_SP, s2);
2515 /* Handle native Java methods. */
2517 if (m->flags & ACC_NATIVE) {
2518 /* put class into second argument register */
2520 if (m->flags & ACC_STATIC)
2521 M_MOV(REG_A1, REG_ITMP3);
2523 /* put env into first argument register */
2525 disp = dseg_add_address(cd, VM_get_jnienv());
2526 M_DSEG_LOAD(REG_A0, disp);
2529 /* Call the native function. */
2531 disp = dseg_add_functionptr(cd, f);
2532 M_DSEG_BRANCH(disp);
2535 /* TODO: this is only needed because of the tracer ... do we
2538 emit_recompute_pv(cd);
2540 #if !defined(__SOFTFP__)
2541 /* TODO: this is only a hack, since we use R0/R1 for float return! */
2542 /* this depends on gcc; it is independent from our ENABLE_SOFTFLOAT define */
2543 if (md->returntype.type != TYPE_VOID && IS_FLT_DBL_TYPE(md->returntype.type)) {
2544 #if 0 && !defined(NDEBUG)
2545 dolog("NATIVESTUB that returns float or double (%s.%s)", m->clazz->name->text, m->name->text);
2547 /* we cannot use this macro, since it is not defined in ENABLE_SOFTFLOAT */
2548 /* M_CAST_FLT_TO_INT_TYPED(md->returntype.type, REG_FRESULT, REG_RESULT_TYPED(md->returntype.type)); */
2549 if (IS_2_WORD_TYPE(md->returntype.type)) {
2550 DCD(0xed2d8102); /* stfd f0, [sp, #-8]! */
2551 M_LDRD_UPDATE(REG_RESULT_PACKED, REG_SP, 8);
2553 DCD(0xed2d0101); /* stfs f0, [sp, #-4]!*/
2554 M_LDR_UPDATE(REG_RESULT, REG_SP, 4);
2559 /* remove native stackframe info */
2560 /* TODO: improve this store/load */
2562 M_STMFD(BITMASK_RESULT, REG_SP);
2564 M_ADD_IMM(REG_A0, REG_SP, 2*4);
2565 M_MOV(REG_A1, REG_PV);
2566 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
2567 M_DSEG_BRANCH(disp);
2568 emit_recompute_pv(cd);
2570 M_MOV(REG_ITMP1_XPTR, REG_RESULT);
2571 M_LDMFD(BITMASK_RESULT, REG_SP);
2573 #if defined(ENABLE_GC_CACAO)
2574 /* restore callee saved int registers from stackframeinfo (GC might have */
2575 /* modified them during a collection). */
2577 disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
2578 OFFSET(stackframeinfo_t, intregs);
2580 for (i = 0; i < INT_SAV_CNT; i++)
2581 M_LDR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2584 /* finish stub code, but do not yet return to caller */
2586 M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - 1);
2587 M_LDMFD(1<<REG_LR, REG_SP);
2589 /* check for exception */
2591 M_TST(REG_ITMP1_XPTR, REG_ITMP1_XPTR);
2592 M_MOVEQ(REG_LR, REG_PC); /* if no exception, return to caller */
2594 /* handle exception here */
2596 M_SUB_IMM(REG_ITMP2_XPC, REG_LR, 4);/* move fault address into xpc */
2598 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
2599 M_DSEG_LOAD(REG_ITMP3, disp); /* load asm exception handler address */
2600 M_MOV(REG_PC, REG_ITMP3); /* jump to asm exception handler */
2604 /* asm_debug *******************************************************************
2608 *******************************************************************************/
2610 void asm_debug(int a1, int a2, int a3, int a4)
2612 printf("===> i am going to exit after this debugging message!\n");
2613 printf("got asm_debug(%p, %p, %p, %p)\n",(void*)a1,(void*)a2,(void*)a3,(void*)a4);
2614 vm_abort("leave you now");
2619 * These are local overrides for various environment variables in Emacs.
2620 * Please do not remove this and leave it at the end of the file, where
2621 * Emacs will automagically detect them.
2622 * ---------------------------------------------------------------------
2625 * indent-tabs-mode: t
2629 * vim:noexpandtab:sw=4:ts=4: