1 /* src/vm/jit/arm/codegen.c - machine code generator for Arm
3 Copyright (C) 1996-2011
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;
252 methodinfo* lm; // Local methodinfo for ICMD_INVOKE*.
253 unresolved_method* um;
255 unresolved_field* uf;
257 int32_t s1, s2, s3, d;
260 // Get required compiler data.
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_GETFIELD: /* ..., objectref, value ==> ... */
1214 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
1215 emit_nullpointer_check(cd, iptr, s1);
1218 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1219 uf = iptr->sx.s23.s3.uf;
1220 fieldtype = uf->fieldref->parseddesc.fd->type;
1224 fi = iptr->sx.s23.s3.fmiref->p.field;
1225 fieldtype = fi->type;
1229 #if !defined(ENABLE_SOFTFLOAT)
1230 /* HACK: softnull checks on floats */
1231 if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
1232 emit_nullpointer_check_force(cd, iptr, s1);
1235 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1237 uf = iptr->sx.s23.s3.uf;
1239 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1242 switch (fieldtype) {
1244 #if defined(ENABLE_SOFTFLOAT)
1248 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1252 #if defined(ENABLE_SOFTFLOAT)
1255 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1258 #if !defined(ENABLE_SOFTFLOAT)
1260 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1264 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1271 emit_store_dst(jd, iptr, d);
1274 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1276 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
1277 emit_nullpointer_check(cd, iptr, s1);
1279 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1280 uf = iptr->sx.s23.s3.uf;
1281 fieldtype = uf->fieldref->parseddesc.fd->type;
1285 fi = iptr->sx.s23.s3.fmiref->p.field;
1286 fieldtype = fi->type;
1290 #if !defined(ENABLE_SOFTFLOAT)
1291 /* HACK: softnull checks on floats */
1292 if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
1293 emit_nullpointer_check_force(cd, iptr, s1);
1296 switch (fieldtype) {
1298 #if defined(ENABLE_SOFTFLOAT)
1302 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1304 #if defined(ENABLE_SOFTFLOAT)
1305 case TYPE_DBL: /* fall through */
1308 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
1310 #if !defined(ENABLE_SOFTFLOAT)
1313 s2 = emit_load_s2(jd, iptr, REG_FTMP1);
1320 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1322 uf = iptr->sx.s23.s3.uf;
1324 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1327 switch (fieldtype) {
1329 #if defined(ENABLE_SOFTFLOAT)
1333 M_IST(s2, s1, disp);
1336 #if defined(ENABLE_SOFTFLOAT)
1339 M_LST(s2, s1, disp);
1341 #if !defined(ENABLE_SOFTFLOAT)
1343 M_FST(s2, s1, disp);
1346 M_DST(s2, s1, disp);
1355 /* branch operations **************************************************/
1357 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1359 disp = dseg_add_functionptr(cd, asm_handle_exception);
1360 M_DSEG_LOAD(REG_ITMP3, disp);
1361 M_MOV(REG_ITMP2_XPC, REG_PC);
1362 M_MOV(REG_PC, REG_ITMP3);
1363 M_NOP; /* nop ensures that XPC is less than the end */
1364 /* of basic block */
1367 case ICMD_IF_LEQ: /* ..., value ==> ... */
1369 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1370 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1371 if (iptr->sx.val.l == 0) {
1372 M_ORR_S(s1, s2, REG_ITMP3);
1375 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1376 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1377 M_CMP(s1, REG_ITMP3);*/
1378 ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1379 M_CMPEQ(s2, REG_ITMP3);
1381 emit_beq(cd, iptr->dst.block);
1384 case ICMD_IF_LLT: /* ..., value ==> ... */
1386 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1387 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1388 if (iptr->sx.val.l == 0) {
1389 /* if high word is less than zero, the whole long is too */
1391 emit_blt(cd, iptr->dst.block);
1394 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1395 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1396 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1397 M_CMP(s1, REG_ITMP3);*/
1398 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1399 M_MOVGT_IMM(2, REG_ITMP1);
1400 M_MOVEQ_IMM(1, REG_ITMP1);
1402 /* low compare: x=x-1(ifLO) */
1403 emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
1404 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1405 M_CMP(s2, REG_ITMP3);*/
1406 M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
1408 /* branch if (x LT 1) */
1409 M_CMP_IMM(REG_ITMP1, 1);
1410 emit_blt(cd, iptr->dst.block);
1414 case ICMD_IF_LLE: /* ..., value ==> ... */
1416 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1417 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1418 if (iptr->sx.val.l == 0) {
1419 /* if high word is less than zero, the whole long is too */
1421 emit_blt(cd, iptr->dst.block);
1423 /* ... otherwise the low word has to be zero (tricky!) */
1425 emit_beq(cd, iptr->dst.block);
1428 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1429 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1430 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1431 M_CMP(s1, REG_ITMP3);*/
1432 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1433 M_MOVGT_IMM(2, REG_ITMP1);
1434 M_MOVEQ_IMM(1, REG_ITMP1);
1436 /* low compare: x=x+1(ifHI) */
1437 emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
1438 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1439 M_CMP(s2, REG_ITMP3);*/
1440 M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
1442 /* branch if (x LE 1) */
1443 M_CMP_IMM(REG_ITMP1, 1);
1444 emit_ble(cd, iptr->dst.block);
1448 case ICMD_IF_LGE: /* ..., value ==> ... */
1450 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1451 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1452 if (iptr->sx.val.l == 0) {
1453 /* if high word is greater or equal zero, the whole long is too */
1455 emit_bge(cd, iptr->dst.block);
1458 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1459 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1460 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1461 M_CMP(s1, REG_ITMP3);*/
1462 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1463 M_MOVGT_IMM(2, REG_ITMP1);
1464 M_MOVEQ_IMM(1, REG_ITMP1);
1466 /* low compare: x=x-1(ifLO) */
1467 emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
1468 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1469 M_CMP(s2, REG_ITMP3);*/
1470 M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
1472 /* branch if (x GE 1) */
1473 M_CMP_IMM(REG_ITMP1, 1);
1474 emit_bge(cd, iptr->dst.block);
1478 case ICMD_IF_LGT: /* ..., value ==> ... */
1480 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1481 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1483 if (iptr->sx.val.l == 0) {
1484 /* if high word is greater than zero, the whole long is too */
1487 codegen_add_branch_ref(cd, iptr->dst.block);
1489 /* ... or high was zero and low is non zero (tricky!) */
1490 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1491 M_MOVLT_IMM(1, REG_ITMP3);
1492 M_ORR_S(REG_ITMP3, s2, REG_ITMP3);
1494 codegen_add_branch_ref(cd, iptr->dst.block);
1498 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1499 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1500 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1501 M_CMP(s1, REG_ITMP3);*/
1502 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1503 M_MOVGT_IMM(2, REG_ITMP1);
1504 M_MOVEQ_IMM(1, REG_ITMP1);
1506 /* low compare: x=x+1(ifHI) */
1507 emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
1508 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1509 M_CMP(s2, REG_ITMP3);*/
1510 M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
1512 /* branch if (x GT 1) */
1513 M_CMP_IMM(REG_ITMP1, 1);
1514 emit_bgt(cd, iptr->dst.block);
1520 case ICMD_IF_LNE: /* ..., value ==> ... */
1522 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1523 s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1524 if (iptr->sx.val.l == 0) {
1525 M_ORR_S(s1, s2, REG_ITMP3);
1528 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1529 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1530 M_CMP(s1, REG_ITMP3);*/
1531 ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1532 M_CMPEQ(s2, REG_ITMP3);
1534 emit_bne(cd, iptr->dst.block);
1537 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1538 /* op1 = target JavaVM pc */
1540 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1541 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1544 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1545 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1548 emit_beq(cd, iptr->dst.block);
1551 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
1552 /* op1 = target JavaVM pc */
1554 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1555 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1558 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1559 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1562 emit_bne(cd, iptr->dst.block);
1565 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
1566 /* op1 = target JavaVM pc */
1568 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1569 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1570 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1572 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1573 M_MOVGT_IMM(2, REG_ITMP3);
1574 M_MOVEQ_IMM(1, REG_ITMP3);
1576 /* low compare: x=x-1(ifLO) */
1577 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1578 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1580 M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1);
1582 /* branch if (x LT 1) */
1583 M_CMP_IMM(REG_ITMP3, 1);
1584 emit_blt(cd, iptr->dst.block);
1587 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
1588 /* op1 = target JavaVM pc */
1590 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1591 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1592 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1594 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1595 M_MOVGT_IMM(2, REG_ITMP3);
1596 M_MOVEQ_IMM(1, REG_ITMP3);
1598 /* low compare: x=x-1(ifLO) */
1599 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1600 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1602 M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1);
1604 /* branch if (x LE 1) */
1605 M_CMP_IMM(REG_ITMP3, 1);
1606 emit_ble(cd, iptr->dst.block);
1609 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
1610 /* op1 = target JavaVM pc */
1612 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1613 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1614 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1616 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1617 M_MOVGT_IMM(2, REG_ITMP3);
1618 M_MOVEQ_IMM(1, REG_ITMP3);
1620 /* low compare: x=x-1(ifLO) */
1621 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1622 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1624 M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1);
1626 /* branch if (x GT 1) */
1627 M_CMP_IMM(REG_ITMP3, 1);
1628 emit_bgt(cd, iptr->dst.block);
1631 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
1632 /* op1 = target JavaVM pc */
1634 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1635 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1636 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1638 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1639 M_MOVGT_IMM(2, REG_ITMP3);
1640 M_MOVEQ_IMM(1, REG_ITMP3);
1642 /* low compare: x=x-1(ifLO) */
1643 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1644 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1646 M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1);
1648 /* branch if (x GE 1) */
1649 M_CMP_IMM(REG_ITMP3, 1);
1650 emit_bge(cd, iptr->dst.block);
1653 case ICMD_TABLESWITCH: /* ..., index ==> ... */
1656 branch_target_t *table;
1658 table = iptr->dst.table;
1660 l = iptr->sx.s23.s2.tablelow;
1661 i = iptr->sx.s23.s3.tablehigh;
1663 /* calculate new index (index - low) */
1664 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1666 M_INTMOVE(s1, REG_ITMP1);
1667 } else if (IS_IMM(l)) {
1668 M_SUB_IMM(REG_ITMP1, s1, l);
1670 ICONST(REG_ITMP2, l);
1671 M_SUB(REG_ITMP1, s1, REG_ITMP2);
1674 /* range check (index <= high-low) */
1676 emit_icmp_imm(cd, REG_ITMP1, i-1);
1677 emit_bugt(cd, table[0].block);
1679 /* build jump table top down and use address of lowest entry */
1684 dseg_add_target(cd, table->block);
1689 /* length of dataseg after last dseg_add_target is used by load */
1690 /* TODO: this loads from data-segment */
1691 M_ADD(REG_ITMP2, REG_PV, REG_LSL(REG_ITMP1, 2));
1692 M_LDR(REG_PC, REG_ITMP2, -(cd->dseglen));
1696 bte = iptr->sx.s23.s3.bte;
1698 if (bte->stub == NULL) {
1699 disp = dseg_add_functionptr(cd, bte->fp);
1701 disp = dseg_add_functionptr(cd, bte->stub);
1704 M_DSEG_LOAD(REG_PV, disp); /* pointer to built-in-function */
1706 /* generate the actual call */
1708 M_MOV(REG_LR, REG_PC);
1709 M_MOV(REG_PC, REG_PV);
1713 case ICMD_INVOKESPECIAL:
1714 emit_nullpointer_check(cd, iptr, REG_A0);
1717 case ICMD_INVOKESTATIC:
1718 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1719 um = iptr->sx.s23.s3.um;
1720 disp = dseg_add_unique_address(cd, NULL);
1722 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
1726 lm = iptr->sx.s23.s3.fmiref->p.method;
1727 disp = dseg_add_address(cd, lm->stubroutine);
1730 M_DSEG_LOAD(REG_PV, disp); /* Pointer to method */
1732 /* generate the actual call */
1734 M_MOV(REG_LR, REG_PC);
1735 M_MOV(REG_PC, REG_PV);
1738 case ICMD_INVOKEVIRTUAL:
1739 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1740 um = iptr->sx.s23.s3.um;
1741 int32_t disp = dseg_add_unique_s4(cd, 0);
1742 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, disp);
1744 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1745 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1748 assert(REG_ITMP1 != REG_METHODPTR);
1749 assert(REG_ITMP2 == REG_METHODPTR);
1751 M_DSEG_LOAD(REG_ITMP1, disp);
1752 M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
1754 // This must be a load with displacement,
1755 // otherwise the JIT method address patching does
1756 // not work anymore (see md_jit_method_patch_address).
1757 M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
1760 lm = iptr->sx.s23.s3.fmiref->p.method;
1761 s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
1763 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1764 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1765 M_LDR(REG_PV, REG_METHODPTR, s1);
1768 // Generate the actual call.
1769 M_MOV(REG_LR, REG_PC);
1770 M_MOV(REG_PC, REG_PV);
1773 case ICMD_INVOKEINTERFACE:
1774 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1775 um = iptr->sx.s23.s3.um;
1776 int32_t disp = dseg_add_unique_s4(cd, 0);
1777 int32_t disp2 = dseg_add_unique_s4(cd, 0);
1779 // XXX We need two displacements.
1780 assert(disp2 == disp - 4);
1781 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, disp);
1783 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1784 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1787 assert(REG_ITMP1 != REG_METHODPTR);
1788 assert(REG_ITMP2 == REG_METHODPTR);
1789 assert(REG_ITMP3 != REG_METHODPTR);
1791 M_DSEG_LOAD(REG_ITMP1, disp);
1792 M_LDR_REG(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
1794 M_DSEG_LOAD(REG_ITMP3, disp2);
1795 M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP3);
1797 // This must be a load with displacement,
1798 // otherwise the JIT method address patching does
1799 // not work anymore (see md_jit_method_patch_address).
1800 M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
1803 lm = iptr->sx.s23.s3.fmiref->p.method;
1804 s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->clazz->index;
1805 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
1807 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1808 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1809 M_LDR(REG_METHODPTR, REG_METHODPTR, s1);
1810 M_LDR(REG_PV, REG_METHODPTR, s2);
1813 // Generate the actual call.
1814 M_MOV(REG_LR, REG_PC);
1815 M_MOV(REG_PC, REG_PV);
1818 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
1820 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1821 /* object type cast-check */
1826 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1831 super = iptr->sx.s23.s3.c.cls;
1832 superindex = super->index;
1835 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1837 /* if class is not resolved, check which code to call */
1839 if (super == NULL) {
1841 emit_label_beq(cd, BRANCH_LABEL_1);
1843 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
1844 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
1845 iptr->sx.s23.s3.c.ref, disp);
1847 M_DSEG_LOAD(REG_ITMP2, disp);
1848 disp = dseg_add_s4(cd, ACC_INTERFACE);
1849 M_DSEG_LOAD(REG_ITMP3, disp);
1850 M_TST(REG_ITMP2, REG_ITMP3);
1851 emit_label_beq(cd, BRANCH_LABEL_2);
1854 /* interface checkcast code */
1856 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
1857 if ((super == NULL) || !IS_IMM(superindex)) {
1858 disp = dseg_add_unique_s4(cd, superindex);
1860 if (super == NULL) {
1861 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
1862 iptr->sx.s23.s3.c.ref, disp);
1866 emit_label_beq(cd, BRANCH_LABEL_3);
1869 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
1870 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
1872 /* we put unresolved or non-immediate superindices onto dseg */
1873 if ((super == NULL) || !IS_IMM(superindex)) {
1874 /* disp was computed before we added the patcher */
1875 M_DSEG_LOAD(REG_ITMP2, disp);
1876 M_CMP(REG_ITMP3, REG_ITMP2);
1878 assert(IS_IMM(superindex));
1879 M_CMP_IMM(REG_ITMP3, superindex);
1882 emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
1884 /* if we loaded the superindex out of the dseg above, we do
1885 things differently here! */
1886 if ((super == NULL) || !IS_IMM(superindex)) {
1888 M_LDR_INTERN(REG_ITMP3, s1, OFFSET(java_object_t, vftbl));
1890 /* this assumes something */
1891 assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
1893 /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
1894 assert(sizeof(methodptr*) == 4);
1895 M_SUB(REG_ITMP2, REG_ITMP3, REG_LSL(REG_ITMP2, 2));
1901 s2 = OFFSET(vftbl_t, interfacetable[0]) -
1902 superindex * sizeof(methodptr*);
1906 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, s2);
1907 M_TST(REG_ITMP3, REG_ITMP3);
1908 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
1911 emit_label_br(cd, BRANCH_LABEL_4);
1913 emit_label(cd, BRANCH_LABEL_3);
1916 /* class checkcast code */
1918 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
1919 if (super == NULL) {
1920 emit_label(cd, BRANCH_LABEL_2);
1922 disp = dseg_add_unique_address(cd, NULL);
1924 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
1925 iptr->sx.s23.s3.c.ref,
1929 disp = dseg_add_address(cd, super->vftbl);
1932 emit_label_beq(cd, BRANCH_LABEL_5);
1935 // The following code checks whether object s is a subtype of class t.
1936 // Represents the following semantic:
1937 // if (!fast_subtype_check(s->vftbl, t->vftbl)) throw;
1939 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
1940 M_DSEG_LOAD(REG_ITMP3, disp);
1942 if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
1943 // Represents the following semantic:
1944 // if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) good;
1946 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
1947 M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
1948 M_LDR_REG(REG_ITMP1, REG_ITMP2, REG_ITMP1);
1949 M_CMP(REG_ITMP1, REG_ITMP3);
1950 emit_load_s1(jd, iptr, REG_ITMP1); /* reload s1, might have been destroyed */
1951 emit_label_beq(cd, BRANCH_LABEL_6); /* good */
1953 // Represents the following semantic:
1954 // if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) throw;
1956 // REG_ITMP3==t->vftbl;
1957 if (super == NULL) {
1958 M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
1959 M_CMP_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]));
1960 emit_load_s1(jd, iptr, REG_ITMP1); /* reload s1, might have been destroyed */
1961 emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1); /* throw */
1964 // Represents the following semantic:
1965 // if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) throw;
1967 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
1968 M_LDR_INTERN(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
1969 M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
1970 M_CMP(REG_ITMP1, REG_ITMP3);
1971 emit_load_s1(jd, iptr, REG_ITMP1); /* reload s1, might have been destroyed */
1972 emit_classcast_check(cd, iptr, BRANCH_LT, 0, s1); /* throw */
1974 // Represents the following semantic:
1975 // if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) throw;
1977 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth;
1978 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
1979 M_ADD(REG_ITMP2, REG_ITMP2, REG_LSL(REG_ITMP3, 2)); /* REG_ITMP2 = REG_ITMP2 + 4 * REG_ITMP3 */
1980 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, -DISPLAY_SIZE * SIZEOF_VOID_P);
1981 M_DSEG_LOAD(REG_ITMP3, disp); /* reload REG_ITMP3, was destroyed */
1982 M_CMP(REG_ITMP2, REG_ITMP3);
1983 emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1); /* throw */
1985 emit_label(cd, BRANCH_LABEL_6);
1988 // Represents the following semantic:
1989 // if (*(s->vftbl + t->vftbl->subtype_offset) != t->vftbl) throw;
1991 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
1992 M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
1993 M_CMP(REG_ITMP2, REG_ITMP3);
1994 emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1);
1998 emit_label(cd, BRANCH_LABEL_5);
2001 if (super == NULL) {
2002 emit_label(cd, BRANCH_LABEL_1);
2003 emit_label(cd, BRANCH_LABEL_4);
2006 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
2009 /* array type cast-check */
2011 s1 = emit_load_s1(jd, iptr, REG_A0);
2012 M_INTMOVE(s1, REG_A0);
2014 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2015 disp = dseg_add_unique_address(cd, NULL);
2017 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2018 iptr->sx.s23.s3.c.ref,
2022 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2024 M_DSEG_LOAD(REG_A1, disp);
2025 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2026 M_DSEG_BRANCH(disp);
2028 emit_recompute_pv(cd);
2030 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2031 M_TST(REG_RESULT, REG_RESULT);
2032 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2034 d = codegen_reg_of_dst(jd, iptr, s1);
2038 emit_store_dst(jd, iptr, d);
2041 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2047 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2052 super = iptr->sx.s23.s3.c.cls;
2053 superindex = super->index;
2056 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2057 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2060 M_MOV(REG_ITMP1, s1);
2064 /* if class is not resolved, check which code to call */
2066 if (super == NULL) {
2070 emit_label_beq(cd, BRANCH_LABEL_1);
2072 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2073 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2074 iptr->sx.s23.s3.c.ref, disp);
2076 M_DSEG_LOAD(REG_ITMP2, disp);
2077 disp = dseg_add_s4(cd, ACC_INTERFACE);
2078 M_DSEG_LOAD(REG_ITMP3, disp);
2079 M_TST(REG_ITMP2, REG_ITMP3);
2080 emit_label_beq(cd, BRANCH_LABEL_2);
2083 /* interface checkcast code */
2085 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2086 if ((super == NULL) || !IS_IMM(superindex)) {
2087 disp = dseg_add_unique_s4(cd, superindex);
2089 if (super == NULL) {
2090 /* If d == REG_ITMP2, then it's destroyed in check
2095 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
2096 iptr->sx.s23.s3.c.ref, disp);
2101 emit_label_beq(cd, BRANCH_LABEL_3);
2104 M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2105 M_LDR_INTERN(REG_ITMP3,
2106 REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2108 /* we put unresolved or non-immediate superindices onto dseg
2109 and do things slightly different */
2110 if ((super == NULL) || !IS_IMM(superindex)) {
2111 /* disp was computed before we added the patcher */
2112 M_DSEG_LOAD(REG_ITMP2, disp);
2113 M_CMP(REG_ITMP3, REG_ITMP2);
2115 if (d == REG_ITMP2) {
2122 /* this assumes something */
2123 assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
2125 /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
2126 assert(sizeof(methodptr*) == 4);
2127 M_SUB(REG_ITMP1, REG_ITMP1, REG_LSL(REG_ITMP2, 2));
2129 if (d == REG_ITMP2) {
2136 assert(IS_IMM(superindex));
2137 M_CMP_IMM(REG_ITMP3, superindex);
2141 s2 = OFFSET(vftbl_t, interfacetable[0]) -
2142 superindex * sizeof(methodptr*);
2146 M_LDR_INTERN(REG_ITMP3, REG_ITMP1, s2);
2147 M_TST(REG_ITMP3, REG_ITMP3);
2151 emit_label_br(cd, BRANCH_LABEL_4);
2153 emit_label(cd, BRANCH_LABEL_3);
2156 /* class checkcast code */
2158 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2159 if (super == NULL) {
2160 emit_label(cd, BRANCH_LABEL_2);
2162 disp = dseg_add_unique_address(cd, NULL);
2164 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2165 iptr->sx.s23.s3.c.ref, disp);
2168 disp = dseg_add_address(cd, super->vftbl);
2172 emit_label_beq(cd, BRANCH_LABEL_5);
2175 // The following code checks whether object s is a subtype of class t.
2176 // Represents the following semantic:
2177 // fast_subtype_check(s->vftbl, t->vftbl));
2179 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2180 M_DSEG_LOAD(REG_ITMP3, disp);
2182 if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
2183 // Represents the following semantic:
2184 // if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) true;
2186 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2187 M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
2188 M_LDR_REG(REG_ITMP1, REG_ITMP2, REG_ITMP1);
2189 M_CMP(REG_ITMP1, REG_ITMP3);
2190 emit_label_beq(cd, BRANCH_LABEL_6); /* true */
2192 // Represents the following semantic:
2193 // if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) false;
2195 // REG_ITMP3==t->vftbl;
2196 if (super == NULL) {
2197 M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
2198 M_CMP_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]));
2199 emit_label_bne(cd, BRANCH_LABEL_7); /* false */
2202 // Represents the following semantic:
2203 // if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) false;
2205 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2206 M_LDR_INTERN(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
2207 M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
2208 M_CMP(REG_ITMP1, REG_ITMP3);
2209 emit_label_blt(cd, BRANCH_LABEL_8); /* false */
2211 // Represents the following semantic:
2212 // if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) false;
2214 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth;
2215 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
2216 M_ADD(REG_ITMP2, REG_ITMP2, REG_LSL(REG_ITMP3, 2)); /* REG_ITMP2 = REG_ITMP2 + 4 * REG_ITMP3 */
2217 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, -DISPLAY_SIZE * SIZEOF_VOID_P);
2218 M_DSEG_LOAD(REG_ITMP3, disp); /* reload REG_ITMP3, was destroyed */
2219 M_CMP(REG_ITMP2, REG_ITMP3);
2221 emit_label(cd, BRANCH_LABEL_6);
2223 emit_label(cd, BRANCH_LABEL_7);
2224 emit_label(cd, BRANCH_LABEL_8);
2226 /* If d == REG_ITMP2, then it's destroyed */
2232 // Represents the following semantic:
2233 // *(s->vftbl + t->vftbl->subtype_offset) == t->vftbl;
2235 // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2236 M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
2237 M_CMP(REG_ITMP2, REG_ITMP3);
2238 /* If d == REG_ITMP2, then it's destroyed */
2245 emit_label(cd, BRANCH_LABEL_5);
2248 if (super == NULL) {
2249 emit_label(cd, BRANCH_LABEL_1);
2250 emit_label(cd, BRANCH_LABEL_4);
2255 emit_store_dst(jd, iptr, d);
2258 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2260 /* copy sizes to stack if necessary */
2262 MCODECHECK((iptr->s1.argcount << 1) + 64);
2264 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2266 var = VAR(iptr->sx.s23.s2.args[s1]);
2268 /* copy SAVEDVAR sizes to stack */
2270 if (!(var->flags & PREALLOC)) {
2271 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2272 M_STR(s2, REG_SP, s1 * 4);
2276 /* a0 = dimension count */
2278 assert(IS_IMM(iptr->s1.argcount));
2279 M_MOV_IMM(REG_A0, iptr->s1.argcount);
2281 /* is patcher function set? */
2283 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2284 disp = dseg_add_unique_address(cd, NULL);
2286 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2287 iptr->sx.s23.s3.c.ref, disp);
2290 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2292 /* a1 = arraydescriptor */
2294 M_DSEG_LOAD(REG_A1, disp);
2296 /* a2 = pointer to dimensions = stack pointer */
2298 M_INTMOVE(REG_SP, REG_A2);
2300 /* call builtin_multianewarray here */
2302 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2303 M_DSEG_BRANCH(disp);
2307 emit_recompute_pv(cd);
2309 /* check for exception before result assignment */
2311 emit_exception_check(cd, iptr);
2315 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2316 M_INTMOVE(REG_RESULT, d);
2317 emit_store_dst(jd, iptr, d);
2321 vm_abort("Unknown ICMD %d during code generation", iptr->opc);
2322 } /* the big switch */
2326 /* codegen_emit_stub_native ****************************************************
2328 Emits a stub routine which calls a native method.
2330 *******************************************************************************/
2332 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2343 /* get required compiler data */
2349 /* initialize variables */
2353 /* calculate stackframe size */
2355 cd->stackframesize =
2356 1 + /* return address */
2357 sizeof(stackframeinfo_t) / SIZEOF_VOID_P + /* stackframeinfo */
2358 sizeof(localref_table) / SIZEOF_VOID_P + /* localref_table */
2359 nmd->memuse; /* stack arguments */
2361 /* align stack to 8-byte */
2363 cd->stackframesize = (cd->stackframesize + 1) & ~1;
2365 /* create method header */
2367 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2368 (void) dseg_add_unique_s4(cd, cd->stackframesize); /* FrameSize */
2369 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2370 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2371 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2373 /* generate stub code */
2375 M_STMFD(1<<REG_LR, REG_SP);
2376 M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize * 2 - 1);
2378 #if defined(ENABLE_GC_CACAO)
2379 /* Save callee saved integer registers in stackframeinfo (GC may
2380 need to recover them during a collection). */
2382 disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
2383 OFFSET(stackframeinfo_t, intregs);
2385 for (i = 0; i < INT_SAV_CNT; i++)
2386 M_STR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2389 /* Save integer and float argument registers (these are 4
2390 registers, stack is 8-byte aligned). */
2392 M_STMFD(BITMASK_ARGS, REG_SP);
2393 /* TODO: floating point */
2395 /* create native stackframe info */
2397 M_ADD_IMM(REG_A0, REG_SP, 4*4);
2398 M_MOV(REG_A1, REG_PV);
2399 disp = dseg_add_functionptr(cd, codegen_start_native_call);
2400 M_DSEG_BRANCH(disp);
2404 emit_recompute_pv(cd);
2406 /* remember class argument */
2408 if (m->flags & ACC_STATIC)
2409 M_MOV(REG_ITMP3, REG_RESULT);
2411 /* Restore integer and float argument registers (these are 4
2412 registers, stack is 8-byte aligned). */
2414 M_LDMFD(BITMASK_ARGS, REG_SP);
2415 /* TODO: floating point */
2417 /* copy or spill arguments to new locations */
2418 /* ATTENTION: the ARM has only integer argument registers! */
2420 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2421 t = md->paramtypes[i].type;
2423 if (!md->params[i].inmemory) {
2424 s1 = md->params[i].regoff;
2425 s2 = nmd->params[j].regoff;
2427 if (!nmd->params[j].inmemory) {
2428 #if !defined(__ARM_EABI__)
2429 SPLIT_OPEN(t, s2, REG_ITMP1);
2432 if (IS_2_WORD_TYPE(t))
2437 #if !defined(__ARM_EABI__)
2438 SPLIT_STORE_AND_CLOSE(t, s2, 0);
2442 if (IS_2_WORD_TYPE(t))
2443 M_LST(s1, REG_SP, s2);
2445 M_IST(s1, REG_SP, s2);
2449 s1 = md->params[i].regoff + cd->stackframesize * 8;
2450 s2 = nmd->params[j].regoff;
2452 if (IS_2_WORD_TYPE(t)) {
2453 M_LLD(REG_ITMP12_PACKED, REG_SP, s1);
2454 M_LST(REG_ITMP12_PACKED, REG_SP, s2);
2457 M_ILD(REG_ITMP1, REG_SP, s1);
2458 M_IST(REG_ITMP1, REG_SP, s2);
2463 /* Handle native Java methods. */
2465 if (m->flags & ACC_NATIVE) {
2466 /* put class into second argument register */
2468 if (m->flags & ACC_STATIC)
2469 M_MOV(REG_A1, REG_ITMP3);
2471 /* put env into first argument register */
2473 disp = dseg_add_address(cd, VM_get_jnienv());
2474 M_DSEG_LOAD(REG_A0, disp);
2477 /* Call the native function. */
2479 disp = dseg_add_functionptr(cd, f);
2480 M_DSEG_BRANCH(disp);
2483 /* TODO: this is only needed because of the tracer ... do we
2486 emit_recompute_pv(cd);
2488 /* remove native stackframe info */
2489 /* TODO: improve this store/load */
2491 M_STMFD(BITMASK_RESULT, REG_SP);
2493 M_ADD_IMM(REG_A0, REG_SP, 2*4);
2494 M_MOV(REG_A1, REG_PV);
2495 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
2496 M_DSEG_BRANCH(disp);
2497 emit_recompute_pv(cd);
2499 M_MOV(REG_ITMP1_XPTR, REG_RESULT);
2500 M_LDMFD(BITMASK_RESULT, REG_SP);
2502 #if defined(ENABLE_GC_CACAO)
2503 /* restore callee saved int registers from stackframeinfo (GC might have */
2504 /* modified them during a collection). */
2506 disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
2507 OFFSET(stackframeinfo_t, intregs);
2509 for (i = 0; i < INT_SAV_CNT; i++)
2510 M_LDR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2513 /* finish stub code, but do not yet return to caller */
2515 M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize * 2 - 1);
2516 M_LDMFD(1<<REG_LR, REG_SP);
2518 /* check for exception */
2520 M_TST(REG_ITMP1_XPTR, REG_ITMP1_XPTR);
2521 M_MOVEQ(REG_LR, REG_PC); /* if no exception, return to caller */
2523 /* handle exception here */
2525 M_SUB_IMM(REG_ITMP2_XPC, REG_LR, 4);/* move fault address into xpc */
2527 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
2528 M_DSEG_LOAD(REG_ITMP3, disp); /* load asm exception handler address */
2529 M_MOV(REG_PC, REG_ITMP3); /* jump to asm exception handler */
2533 /* asm_debug *******************************************************************
2537 *******************************************************************************/
2539 void asm_debug(int a1, int a2, int a3, int a4)
2541 printf("===> i am going to exit after this debugging message!\n");
2542 printf("got asm_debug(%p, %p, %p, %p)\n",(void*)a1,(void*)a2,(void*)a3,(void*)a4);
2543 vm_abort("leave you now");
2548 * These are local overrides for various environment variables in Emacs.
2549 * Please do not remove this and leave it at the end of the file, where
2550 * Emacs will automagically detect them.
2551 * ---------------------------------------------------------------------
2554 * indent-tabs-mode: t
2558 * vim:noexpandtab:sw=4:ts=4: