1 /* src/vm/jit/s390/codegen.c - machine code generator for s390
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
32 #include "vm/jit/s390/arch.h"
33 #include "vm/jit/s390/codegen.h"
34 #include "vm/jit/s390/emit.h"
35 #include "vm/jit/s390/md-abi.h"
37 #include "native/localref.hpp"
38 #include "native/native.hpp"
40 #include "mm/memory.hpp"
42 #include "threads/lock.hpp"
44 #include "vm/jit/builtin.hpp"
45 #include "vm/exceptions.hpp"
46 #include "vm/global.h"
47 #include "vm/loader.hpp"
48 #include "vm/options.h"
49 #include "vm/statistics.h"
53 #include "vm/jit/abi.h"
54 #include "vm/jit/asmpart.h"
55 #include "vm/jit/codegen-common.hpp"
56 #include "vm/jit/dseg.h"
57 #include "vm/jit/emit-common.hpp"
58 #include "vm/jit/jit.hpp"
59 #include "vm/jit/linenumbertable.hpp"
60 #include "vm/jit/methodheader.h"
61 #include "vm/jit/parse.hpp"
62 #include "vm/jit/patcher-common.hpp"
63 #include "vm/jit/reg.h"
64 #include "vm/jit/stacktrace.hpp"
65 #include "vm/jit/trap.hpp"
68 /* DO__LOG generates a call to do__log. No registers are destroyed,
69 * so you may use it anywhere. regs is an array containing all general
74 static void do__log(u4 *regs) {
79 N_AHI(REG_SP, -200); \
80 N_STM(R0, R15, 96, REG_SP); \
81 M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
82 N_LA(R2, 96, RN, REG_SP); \
84 N_LM(R0, R15, 96, REG_SP); \
87 /* If the following macro is defined, workaround code for hercules quirks
91 /* #define SUPPORT_HERCULES 1 */
98 ===============================================================================
99 return_address (stackframesize - 1) * 8
100 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
102 saved_int_reg[rd->savintreguse]
103 saved_flt_reg[FLT_SAV_CNT - 1]
105 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
107 return_value_tmp (rd->memuse + 1) * 8
108 monitorenter_argument (rd->memuse) * 8
110 local[rd->memuse - 1] (rd->memuse - 1) * 8
120 * Generates machine code for the method prolog.
122 void codegen_emit_prolog(jitdata* jd)
131 // Get required compiler data.
132 methodinfo* m = jd->m;
133 codeinfo* code = jd->code;
134 codegendata* cd = jd->cd;
135 registerdata* rd = jd->rd;
138 * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
143 M_AADD_IMM(N_PV_OFFSET, REG_PV);
145 /* create stack frame (if necessary) */
147 if (cd->stackframesize) {
148 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
151 /* store return address */
153 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
155 /* save used callee saved registers and return address */
157 p = cd->stackframesize - 1;
159 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
160 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
162 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
163 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
166 /* take arguments out of register or stack frame */
170 for (p = 0, l = 0; p < md->paramcount; p++) {
171 t = md->paramtypes[p].type;
172 varindex = jd->local_map[l * 5 + t];
176 if (IS_2_WORD_TYPE(t))
179 if (varindex == UNUSED)
184 s1 = md->params[p].regoff;
186 if (IS_INT_LNG_TYPE(t)) { /* integer args */
187 if (IS_2_WORD_TYPE(t)) {
195 if (!md->params[p].inmemory) { /* register arguments */
196 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
197 if (IS_2_WORD_TYPE(t)) {
198 M_LNGMOVE(s2, var->vv.regoff);
200 M_INTMOVE(s2, var->vv.regoff);
202 } else { /* reg arg -> spilled */
203 if (IS_2_WORD_TYPE(t)) {
204 M_LST(s2, REG_SP, var->vv.regoff);
206 M_IST(s2, REG_SP, var->vv.regoff);
210 } else { /* stack arguments */
211 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
212 if (IS_2_WORD_TYPE(t)) {
213 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
215 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
217 } else { /* stack arg -> spilled */
218 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
222 } else { /* floating args */
223 if (!md->params[p].inmemory) { /* register arguments */
225 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
226 emit_fmove(cd, s2, var->vv.regoff);
228 } else { /* reg arg -> spilled */
229 if (IS_2_WORD_TYPE(t))
230 M_DST(s2, REG_SP, var->vv.regoff);
232 M_FST(s2, REG_SP, var->vv.regoff);
235 } else { /* stack arguments */
236 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
237 if (IS_2_WORD_TYPE(t))
238 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
241 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
243 } else { /* stack-arg -> spilled */
244 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
245 var->vv.regoff = cd->stackframesize * 8 + s1;
254 * Generates machine code for the method epilog.
256 void codegen_emit_epilog(jitdata* jd)
261 // Get required compiler data.
262 codegendata* cd = jd->cd;
263 registerdata* rd = jd->rd;
265 p = cd->stackframesize;
267 /* restore return address */
269 p--; M_ALD(REG_RA, REG_SP, p * 8);
271 /* restore saved registers */
273 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
274 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
276 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
277 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
280 /* deallocate stack */
282 if (cd->stackframesize)
283 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
290 * Generates machine code for one ICMD.
292 void codegen_emit_instruction(jitdata* jd, instruction* iptr)
295 builtintable_entry* bte;
296 methodinfo* lm; // Local methodinfo for ICMD_INVOKE*.
297 unresolved_method* um;
299 unresolved_field* uf;
301 int32_t s1, s2, s3, d;
304 // Get required compiler data.
305 codeinfo* code = jd->code;
306 codegendata* cd = jd->cd;
310 /* constant operations ************************************************/
312 case ICMD_FCONST: /* ... ==> ..., constant */
313 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
314 disp = dseg_add_float(cd, iptr->sx.val.f);
315 M_FLD_DSEG(d, disp, REG_ITMP1);
316 emit_store_dst(jd, iptr, d);
319 case ICMD_DCONST: /* ... ==> ..., constant */
320 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
321 disp = dseg_add_double(cd, iptr->sx.val.d);
322 M_DLD_DSEG(d, disp, REG_ITMP1);
323 emit_store_dst(jd, iptr, d);
326 case ICMD_ACONST: /* ... ==> ..., constant */
327 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
329 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
330 constant_classref *cr = iptr->sx.val.c.ref;
331 disp = dseg_add_unique_address(cd, cr);
333 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
338 if (iptr->sx.val.anyptr == 0) {
341 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
344 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
345 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
347 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
349 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
355 emit_store_dst(jd, iptr, d);
359 /* integer operations *************************************************/
361 case ICMD_INEG: /* ..., value ==> ..., - value */
363 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
364 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
366 emit_store_dst(jd, iptr, d);
370 case ICMD_LNEG: /* ..., value ==> ..., - value */
372 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
373 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
374 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
375 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
376 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
377 N_AHI(GET_HIGH_REG(d), -1);
378 emit_store_dst(jd, iptr, d);
381 case ICMD_I2L: /* ..., value ==> ..., value */
383 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
384 if (! N_IS_EVEN_ODD(d)) {
385 d = REG_ITMP31_PACKED;
387 assert(N_IS_EVEN_ODD(d));
389 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
391 M_INTMOVE(s1, GET_HIGH_REG(d));
392 M_SRDA_IMM(32, GET_HIGH_REG(d));
394 emit_copy_dst(jd, iptr, d);
395 emit_store_dst(jd, iptr, d);
398 case ICMD_L2I: /* ..., value ==> ..., value */
399 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
400 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
401 M_INTMOVE(GET_LOW_REG(s1), d);
402 emit_store_dst(jd, iptr, d);
405 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
406 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
407 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
411 emit_store_dst(jd, iptr, d);
414 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
415 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
416 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
420 emit_store_dst(jd, iptr, d);
423 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
425 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
426 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
430 emit_store_dst(jd, iptr, d);
433 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
435 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
436 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
437 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
444 emit_store_dst(jd, iptr, d);
449 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
450 /* sx.val.i = constant */
451 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
452 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
455 if (N_VALID_IMM(iptr->sx.val.i)) {
456 M_IADD_IMM(iptr->sx.val.i, d);
458 ICONST(REG_ITMP2, iptr->sx.val.i);
459 M_IADD(REG_ITMP2, d);
461 emit_store_dst(jd, iptr, d);
464 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
466 /* M, (r, q) -> (r, q) */
468 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
470 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
471 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
472 dd = GET_HIGH_REG(d);
481 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
482 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
492 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
493 N_AHI(GET_HIGH_REG(d), 1);
495 emit_store_dst(jd, iptr, d);
498 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
499 /* sx.val.l = constant */
501 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
502 dd = GET_HIGH_REG(d);
504 s1 = emit_load_s1_high(jd, iptr, dd);
505 s3 = iptr->sx.val.l >> 32;
509 if (N_VALID_IMM(s3)) {
512 ICONST(REG_ITMP3, s3);
513 M_IADD(REG_ITMP3, dd);
517 s1 = emit_load_s1_low(jd, iptr, dd);
518 s3 = iptr->sx.val.l & 0xffffffff;
519 ICONST(REG_ITMP3, s3);
522 N_ALR(dd, REG_ITMP3);
524 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
525 N_AHI(GET_HIGH_REG(d), 1);
527 emit_store_dst(jd, iptr, d);
530 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
532 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
533 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
534 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
536 M_INTMOVE(s1, REG_ITMP1);
537 M_ISUB(s2, REG_ITMP1);
538 M_INTMOVE(REG_ITMP1, d);
543 emit_store_dst(jd, iptr, d);
547 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
548 /* sx.val.i = constant */
550 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
551 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
554 if (N_VALID_IMM(-iptr->sx.val.i)) {
555 M_ISUB_IMM(iptr->sx.val.i, d);
557 ICONST(REG_ITMP2, iptr->sx.val.i);
558 M_ISUB(REG_ITMP2, d);
560 emit_store_dst(jd, iptr, d);
564 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
566 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
568 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
569 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
570 dd = GET_HIGH_REG(d);
573 M_INTMOVE(s2, REG_ITMP3);
580 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
581 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
585 M_INTMOVE(s2, REG_ITMP3);
592 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
593 N_AHI(GET_HIGH_REG(d), -1);
595 emit_store_dst(jd, iptr, d);
598 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
599 /* sx.val.l = constant */
601 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
603 dd = GET_HIGH_REG(d);
604 s1 = emit_load_s1_high(jd, iptr, dd);
605 s3 = iptr->sx.val.l >> 32;
609 if (N_VALID_IMM(-s3)) {
612 ICONST(REG_ITMP3, s3);
613 M_ISUB(REG_ITMP3, dd);
617 s1 = emit_load_s1_low(jd, iptr, dd);
618 s3 = iptr->sx.val.l & 0xffffffff;
619 ICONST(REG_ITMP3, s3);
622 N_SLR(dd, REG_ITMP3);
624 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
625 N_AHI(GET_HIGH_REG(d), -1);
627 emit_store_dst(jd, iptr, d);
630 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
632 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
633 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
634 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
641 emit_store_dst(jd, iptr, d);
645 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
646 /* sx.val.i = constant */
647 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
648 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
650 if (iptr->sx.val.i == 2) {
652 } else if (N_VALID_IMM(iptr->sx.val.i)) {
653 M_IMUL_IMM(iptr->sx.val.i, d);
655 disp = dseg_add_s4(cd, iptr->sx.val.i);
656 M_ILD_DSEG(REG_ITMP2, disp);
657 M_IMUL(REG_ITMP2, d);
659 emit_store_dst(jd, iptr, d);
662 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
663 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
665 /* load s1 into r0 */
667 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
668 M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
669 s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
671 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
673 /* extend s1 to long */
675 M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
679 N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
685 d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
686 M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
689 d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
690 M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
694 emit_store_dst(jd, iptr, d);
698 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
699 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
701 bte = iptr->sx.s23.s3.bte;
704 /* test s2 for zero */
706 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
707 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
708 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
709 emit_arithmetic_check(cd, iptr, REG_ITMP3);
713 disp = dseg_add_functionptr(cd, bte->fp);
717 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
719 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
720 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
724 M_ASUB_IMM(96, REG_SP);
725 M_ALD_DSEG(REG_ITMP2, disp);
726 M_JSR(REG_RA, REG_ITMP2);
727 M_AADD_IMM(96, REG_SP);
731 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
732 M_LNGMOVE(REG_RESULT_PACKED, d);
733 emit_store_dst(jd, iptr, d);
737 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
738 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
739 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
741 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
742 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
743 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
745 /* Use only 5 bits of sencond operand. */
747 M_INTMOVE(s2, REG_ITMP2);
749 ICONST(REG_ITMP3, 0x1F);
750 M_IAND(REG_ITMP3, s2);
767 emit_store_dst(jd, iptr, d);
770 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
771 /* sx.val.i = constant */
775 assert(iptr->sx.val.i <= 32);
777 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
778 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
785 s3 = (1 << iptr->sx.val.i) - 1;
787 if (N_VALID_IMM(s3)) {
790 ICONST(REG_ITMP1, -1);
791 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
792 M_IADD(REG_ITMP1, d);
795 N_BRC_BACK_PATCH(ref);
797 M_SRA_IMM(iptr->sx.val.i, d);
799 emit_store_dst(jd, iptr, d);
804 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
805 /* sx.val.i = constant */
807 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
808 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
811 M_MOV(s1, REG_ITMP1);
815 ICONST(REG_ITMP3, iptr->sx.val.i);
818 M_IAND(REG_ITMP3, d);
821 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
827 emit_store_dst(jd, iptr, d);
831 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
832 /* sx.val.i = constant */
833 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
834 /* sx.val.i = constant */
835 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
836 /* sx.val.i = constant */
837 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
838 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
842 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
851 case ICMD_IUSHRCONST:
858 emit_store_dst(jd, iptr, d);
861 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
863 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
865 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
867 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
869 /* Use only 6 bits of second operand */
871 M_INTMOVE(s2, REG_ITMP2);
873 ICONST(REG_ITMP1, 0x3F);
874 M_IAND(REG_ITMP1, s2);
876 s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
877 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
879 /* Destination must be even-odd pair */
881 if (! N_IS_EVEN_ODD(d)) {
882 d = REG_ITMP31_PACKED;
885 assert(N_IS_EVEN_ODD(d));
891 M_SLDL(s2, GET_HIGH_REG(d));
894 M_SRDA(s2, GET_HIGH_REG(d));
897 M_SRDL(s2, GET_HIGH_REG(d));
903 emit_copy_dst(jd, iptr, d);
904 emit_store_dst(jd, iptr, d);
908 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
909 /* sx.val.i = constant */
910 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
911 /* sx.val.i = constant */
912 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
913 /* sx.val.l = constant */
916 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
917 if (! N_IS_EVEN_ODD(d)) {
918 d = REG_ITMP31_PACKED;
920 assert(N_IS_EVEN_ODD(d));
922 s1 = emit_load_s1(jd, iptr, d);
926 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
930 N_SLDL(GET_HIGH_REG(d), disp, RN);
933 N_SRDA(GET_HIGH_REG(d), disp, RN);
935 case ICMD_LUSHRCONST:
936 N_SRDL(GET_HIGH_REG(d), disp, RN);
939 N_SLDL(GET_HIGH_REG(d), disp, RN);
945 emit_copy_dst(jd, iptr, d);
946 emit_store_dst(jd, iptr, d);
949 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
951 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
952 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
953 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
960 emit_store_dst(jd, iptr, d);
964 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
966 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
967 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
968 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
975 emit_store_dst(jd, iptr, d);
979 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
981 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
982 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
983 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
990 emit_store_dst(jd, iptr, d);
996 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
997 /* sx.val.i = constant */
998 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
999 /* sx.val.i = constant */
1000 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1001 /* sx.val.i = constant */
1003 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1004 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1007 ICONST(REG_ITMP2, iptr->sx.val.i);
1009 switch (iptr->opc) {
1010 case ICMD_IANDCONST:
1011 M_IAND(REG_ITMP2, d);
1013 case ICMD_IXORCONST:
1014 M_IXOR(REG_ITMP2, d);
1017 M_IOR(REG_ITMP2, d);
1023 emit_store_dst(jd, iptr, d);
1027 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1028 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1029 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1031 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1033 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1034 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1035 dd = GET_LOW_REG(d);
1037 switch (iptr->opc) {
1066 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1067 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1068 dd = GET_HIGH_REG(d);
1070 switch (iptr->opc) {
1099 emit_store_dst(jd, iptr, d);
1102 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1103 /* sx.val.l = constant */
1104 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1105 /* sx.val.l = constant */
1106 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1107 /* sx.val.l = constant */
1109 /* TODO should use memory operand to access data segment, not load */
1111 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1113 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1114 s3 = iptr->sx.val.l & 0xffffffff;
1116 M_INTMOVE(s1, GET_LOW_REG(d));
1118 ICONST(REG_ITMP3, s3);
1120 switch (iptr->opc) {
1121 case ICMD_LANDCONST:
1122 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1124 case ICMD_LXORCONST:
1125 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1128 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1134 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1135 s3 = iptr->sx.val.l >> 32;
1137 M_INTMOVE(s1, GET_HIGH_REG(d));
1139 ICONST(REG_ITMP3, s3);
1141 switch (iptr->opc) {
1142 case ICMD_LANDCONST:
1143 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1145 case ICMD_LXORCONST:
1146 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1149 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1155 emit_store_dst(jd, iptr, d);
1159 /* floating operations ************************************************/
1161 case ICMD_FNEG: /* ..., value ==> ..., - value */
1162 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1163 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1165 emit_store_dst(jd, iptr, d);
1168 case ICMD_DNEG: /* ..., value ==> ..., - value */
1169 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1170 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1172 emit_store_dst(jd, iptr, d);
1175 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1176 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1177 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1178 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1182 emit_fmove(cd, s1, d);
1185 emit_store_dst(jd, iptr, d);
1188 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1189 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1190 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1191 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1195 emit_fmove(cd, s1, d);
1198 emit_store_dst(jd, iptr, d);
1201 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1202 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1203 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1204 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1206 emit_fmove(cd, s1, d);
1208 emit_store_dst(jd, iptr, d);
1211 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1212 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1213 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1214 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1216 emit_fmove(cd, s1, d);
1218 emit_store_dst(jd, iptr, d);
1221 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1222 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1223 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1224 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1228 emit_fmove(cd, s1, d);
1231 emit_store_dst(jd, iptr, d);
1234 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1235 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1236 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1237 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1241 emit_fmove(cd, s1, d);
1244 emit_store_dst(jd, iptr, d);
1247 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1248 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1249 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1250 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1252 emit_fmove(cd, s1, d);
1254 emit_store_dst(jd, iptr, d);
1257 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1258 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1259 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1260 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1262 emit_fmove(cd, s1, d);
1264 emit_store_dst(jd, iptr, d);
1267 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1268 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1269 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1271 emit_store_dst(jd, iptr, d);
1274 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1275 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1276 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1278 emit_store_dst(jd, iptr, d);
1281 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1285 #ifdef SUPPORT_HERCULES
1289 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1290 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1294 switch (iptr->opc) {
1303 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1304 N_LHI(d, 0); /* Load 0 */
1305 ref1 = cd->mcodeptr;
1306 N_BRC(DD_ANY, 0); /* Exit */
1310 switch (iptr->opc) {
1319 #ifdef SUPPORT_HERCULES
1320 /* Hercules does the conversion using a plain C conversion.
1321 * According to manual, real hardware should *NOT* require this.
1323 * Corner case: Positive float leads to INT_MIN (overflow).
1326 switch (iptr->opc) {
1335 ref2 = cd->mcodeptr;
1336 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1340 ref3 = cd->mcodeptr;
1341 M_BGE(0); /* If integer result is negative, continue */
1343 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1344 M_ILD_DSEG(d, disp);
1346 N_BRC_BACK_PATCH(ref1);
1347 #ifdef SUPPORT_HERCULES
1348 N_BRC_BACK_PATCH(ref2);
1349 N_BRC_BACK_PATCH(ref3);
1351 emit_store_dst(jd, iptr, d);
1355 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1357 #ifdef SUPPORT_HERCULES
1360 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1361 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1362 #ifdef SUPPORT_HERCULES
1365 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1366 disp = dseg_add_double(cd, 0.0 / 0.0);
1367 M_DLD_DSEG(d, disp, REG_ITMP1);
1368 emit_label_br(cd, BRANCH_LABEL_1);
1369 N_BRC_BACK_PATCH(ref);
1372 #ifdef SUPPORT_HERCULES
1373 emit_label(cd, BRANCH_LABEL_1);
1375 emit_store_dst(jd, iptr, d);
1379 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1380 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1381 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1383 emit_store_dst(jd, iptr, d);
1386 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1387 /* == => 0, < => 1, > => -1 */
1391 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1392 /* == => 0, < => 1, > => -1 */
1395 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1396 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1397 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1399 switch (iptr->opc) {
1411 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1412 SZ_BRC + SZ_BRC + SZ_BRC
1415 N_BRC( /* load -1 */
1416 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1417 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1422 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1425 N_LHI(d, 1); /* GT */
1426 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1427 N_LHI(d, -1); /* LT */
1428 M_BR(SZ_BRC + SZ_LHI);
1429 N_LHI(d, 0); /* EQ */
1431 emit_store_dst(jd, iptr, d);
1436 /* memory operations **************************************************/
1438 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1439 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1440 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1441 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1443 /* implicit null-pointer check */
1444 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1446 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1451 emit_store_dst(jd, iptr, d);
1454 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1456 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1457 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1458 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1460 /* implicit null-pointer check */
1461 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1463 M_INTMOVE(s2, REG_ITMP2);
1464 M_SLL_IMM(1, REG_ITMP2);
1466 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1468 /* N_LH does sign extends, undo ! */
1473 emit_store_dst(jd, iptr, d);
1476 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1477 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1478 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1479 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1481 /* implicit null-pointer check */
1482 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1484 M_INTMOVE(s2, REG_ITMP2);
1485 M_SLL_IMM(1, REG_ITMP2);
1487 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1488 emit_store_dst(jd, iptr, d);
1491 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1492 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1493 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1494 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1496 /* implicit null-pointer check */
1497 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1499 M_INTMOVE(s2, REG_ITMP2);
1500 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1501 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1502 emit_store_dst(jd, iptr, d);
1505 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1507 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1508 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1510 d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1512 /* implicit null-pointer check */
1513 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1515 M_INTMOVE(s2, REG_ITMP2);
1516 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1519 GET_LOW_REG(d) /* maybe itmp3 */,
1520 OFFSET(java_longarray_t, data[0]) + 4,
1521 REG_ITMP2, s1 /* maybe itmp1 */
1525 GET_HIGH_REG(d) /* maybe itmp1 */,
1526 OFFSET(java_longarray_t, data[0]),
1527 REG_ITMP2, s1 /* maybe itmp1 */
1530 emit_store_dst(jd, iptr, d);
1534 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1536 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1537 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1538 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1540 /* implicit null-pointer check */
1541 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1543 M_INTMOVE(s2, REG_ITMP2);
1544 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1546 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1548 emit_store_dst(jd, iptr, d);
1551 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1552 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1553 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1554 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1556 /* implicit null-pointer check */
1557 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1559 M_INTMOVE(s2, REG_ITMP2);
1560 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1562 N_LD(d, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1564 emit_store_dst(jd, iptr, d);
1567 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1568 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1569 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1570 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1572 /* implicit null-pointer check */
1573 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1575 M_INTMOVE(s2, REG_ITMP2);
1576 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1577 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1578 emit_store_dst(jd, iptr, d);
1581 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1582 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1583 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1584 /* implicit null-pointer check */
1585 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1586 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1588 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1591 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1593 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1594 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1595 /* implicit null-pointer check */
1596 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1597 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1599 M_INTMOVE(s2, REG_ITMP2);
1600 M_SLL_IMM(1, REG_ITMP2);
1602 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1606 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1607 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1608 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1609 /* implicit null-pointer check */
1610 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1611 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1613 M_INTMOVE(s2, REG_ITMP2);
1614 M_SLL_IMM(1, REG_ITMP2);
1616 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1619 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1621 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1622 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1623 /* implicit null-pointer check */
1624 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1626 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1628 M_INTMOVE(s2, REG_ITMP2);
1629 M_SLL_IMM(2, REG_ITMP2);
1631 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1634 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1636 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1637 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1638 /* implicit null-pointer check */
1639 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1641 M_INTMOVE(s2, REG_ITMP2);
1642 M_SLL_IMM(3, REG_ITMP2);
1644 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1645 N_ST(s3, OFFSET(java_longarray_t, data[0]), REG_ITMP2, s1);
1646 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1647 N_ST(s3, OFFSET(java_longarray_t, data[0]) + 4, REG_ITMP2, s1);
1650 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1651 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1652 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1653 /* implicit null-pointer check */
1654 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1655 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1657 M_INTMOVE(s2, REG_ITMP2);
1658 M_SLL_IMM(2, REG_ITMP2);
1660 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1663 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1664 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1665 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1666 /* implicit null-pointer check */
1667 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1668 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1670 M_INTMOVE(s2, REG_ITMP2);
1671 M_SLL_IMM(3, REG_ITMP2);
1673 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1676 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1678 s1 = emit_load_s1(jd, iptr, REG_A0);
1679 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1680 /* implicit null-pointer check */
1681 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1682 s3 = emit_load_s3(jd, iptr, REG_A1);
1684 M_INTMOVE(s1, REG_A0);
1685 M_INTMOVE(s3, REG_A1);
1687 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1688 M_ALD_DSEG(REG_ITMP2, disp);
1689 M_ASUB_IMM(96, REG_SP);
1690 M_JSR(REG_RA, REG_ITMP2);
1691 M_AADD_IMM(96, REG_SP);
1693 emit_arraystore_check(cd, iptr);
1695 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1696 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1697 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1699 M_INTMOVE(s2, REG_ITMP2);
1700 M_SLL_IMM(2, REG_ITMP2);
1701 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1704 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1705 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1709 case ICMD_GETFIELD: /* ... ==> ..., value */
1711 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1712 emit_nullpointer_check(cd, iptr, s1);
1714 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1715 uf = iptr->sx.s23.s3.uf;
1716 fieldtype = uf->fieldref->parseddesc.fd->type;
1719 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1722 fi = iptr->sx.s23.s3.fmiref->p.field;
1723 fieldtype = fi->type;
1727 switch (fieldtype) {
1729 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1733 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
1734 if (GET_HIGH_REG(d) == s1) {
1735 M_ILD(GET_LOW_REG(d), s1, disp + 4);
1736 M_ILD(GET_HIGH_REG(d), s1, disp);
1739 M_ILD(GET_LOW_REG(d), s1, disp + 4);
1740 M_ILD(GET_HIGH_REG(d), s1, disp);
1744 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1748 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1752 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1756 emit_store_dst(jd, iptr, d);
1759 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1763 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1764 emit_nullpointer_check(cd, iptr, s1);
1766 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1767 uf = iptr->sx.s23.s3.uf;
1768 fieldtype = uf->fieldref->parseddesc.fd->type;
1772 fi = iptr->sx.s23.s3.fmiref->p.field;
1773 fieldtype = fi->type;
1777 /* We can't add a patcher ref behind this load,
1778 * because the patcher would destroy REG_ITMP3.
1780 * We pass in the disp parameter, how many bytes
1781 * to skip to the to the actual store.
1783 * XXX this relies on patcher_add_patch_ref internals
1786 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1787 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1792 if (IS_INT_LNG_TYPE(fieldtype)) {
1793 if (IS_2_WORD_TYPE(fieldtype))
1794 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
1796 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1798 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1801 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1802 ((patchref_t *)list_first(jd->code->patchers))->disp = (cd->mcodeptr - ref);
1805 switch (fieldtype) {
1807 M_IST(s2, s1, disp);
1810 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
1811 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
1814 M_AST(s2, s1, disp);
1817 M_FST(s2, s1, disp);
1820 M_DST(s2, s1, disp);
1827 /* branch operations **************************************************/
1829 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1831 disp = dseg_add_functionptr(cd, asm_handle_exception);
1832 M_ALD_DSEG(REG_ITMP1, disp);
1833 M_JMP(REG_ITMP1_XPC, REG_ITMP1);
1838 case ICMD_IF_LLT: /* ..., value ==> ... */
1839 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
1845 /* ATTENTION: compare high words signed and low words unsigned */
1847 # define LABEL_OUT BRANCH_LABEL_1
1849 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1851 if (N_VALID_IMM(iptr->sx.val.l >> 32))
1852 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
1854 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
1855 if (N_VALID_DSEG_DISP(disp)) {
1856 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
1858 ICONST(REG_ITMP2, disp);
1859 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
1866 emit_blt(cd, iptr->dst.block);
1867 /* EQ ... fall through */
1868 emit_label_bgt(cd, LABEL_OUT);
1872 emit_bgt(cd, iptr->dst.block);
1873 /* EQ ... fall through */
1874 emit_label_blt(cd, LABEL_OUT);
1877 /* EQ ... fall through */
1878 emit_label_bne(cd, LABEL_OUT);
1881 /* EQ ... fall through */
1882 emit_bne(cd, iptr->dst.block);
1888 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1890 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
1891 if (N_VALID_DSEG_DISP(disp)) {
1892 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
1894 ICONST(REG_ITMP2, disp);
1895 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
1900 emit_blt(cd, iptr->dst.block);
1901 emit_label(cd, LABEL_OUT);
1904 emit_ble(cd, iptr->dst.block);
1905 emit_label(cd, LABEL_OUT);
1908 emit_bgt(cd, iptr->dst.block);
1909 emit_label(cd, LABEL_OUT);
1912 emit_bge(cd, iptr->dst.block);
1913 emit_label(cd, LABEL_OUT);
1916 emit_beq(cd, iptr->dst.block);
1917 emit_label(cd, LABEL_OUT);
1920 emit_bne(cd, iptr->dst.block);
1929 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
1930 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
1932 /* Compare addresses as 31 bit unsigned integers */
1934 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1935 M_LDA(REG_ITMP1, s1, 0);
1937 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1938 M_LDA(REG_ITMP2, s2, 0);
1940 M_CMP(REG_ITMP1, REG_ITMP2);
1942 switch (iptr->opc) {
1943 case ICMD_IF_ACMPEQ:
1944 emit_beq(cd, iptr->dst.block);
1946 case ICMD_IF_ACMPNE:
1947 emit_bne(cd, iptr->dst.block);
1953 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
1954 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
1955 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
1956 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
1957 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
1958 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1963 /* ATTENTION: compare high words signed and low words unsigned */
1965 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1966 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1971 case ICMD_IF_LCMPLT:
1972 case ICMD_IF_LCMPLE:
1973 emit_blt(cd, iptr->dst.block);
1974 /* EQ ... fall through */
1975 out_ref = cd->mcodeptr;
1978 case ICMD_IF_LCMPGT:
1979 case ICMD_IF_LCMPGE:
1980 emit_bgt(cd, iptr->dst.block);
1981 /* EQ ... fall through */
1982 out_ref = cd->mcodeptr;
1985 case ICMD_IF_LCMPEQ:
1986 /* EQ ... fall through */
1987 out_ref = cd->mcodeptr;
1990 case ICMD_IF_LCMPNE:
1991 /* EQ ... fall through */
1992 emit_bne(cd, iptr->dst.block);
1998 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1999 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2004 case ICMD_IF_LCMPLT:
2005 emit_blt(cd, iptr->dst.block);
2007 case ICMD_IF_LCMPLE:
2008 emit_ble(cd, iptr->dst.block);
2010 case ICMD_IF_LCMPGT:
2011 emit_bgt(cd, iptr->dst.block);
2013 case ICMD_IF_LCMPGE:
2014 emit_bge(cd, iptr->dst.block);
2016 case ICMD_IF_LCMPEQ:
2017 emit_beq(cd, iptr->dst.block);
2019 case ICMD_IF_LCMPNE:
2020 emit_bne(cd, iptr->dst.block);
2026 if (out_ref != NULL) {
2027 N_BRC_BACK_PATCH(out_ref);
2033 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2036 branch_target_t *table;
2038 table = iptr->dst.table;
2040 l = iptr->sx.s23.s2.tablelow;
2041 i = iptr->sx.s23.s3.tablehigh;
2043 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2044 M_INTMOVE(s1, REG_ITMP1);
2048 } else if (N_VALID_IMM(-l)) {
2049 M_ISUB_IMM(l, REG_ITMP1);
2051 ICONST(REG_ITMP2, l);
2052 M_ISUB(REG_ITMP2, REG_ITMP1);
2055 /* number of targets */
2061 ICONST(REG_ITMP2, i);
2062 M_ICMPU(REG_ITMP1, REG_ITMP2);
2063 emit_bge(cd, table[0].block);
2065 /* build jump table top down and use address of lowest entry */
2070 dseg_add_target(cd, table->block);
2075 /* length of dataseg after last dseg_add_target is used by load */
2077 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2078 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2079 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2080 M_JMP(RN, REG_ITMP1);
2085 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2086 bte = iptr->sx.s23.s3.bte;
2087 if (bte->stub == NULL) {
2088 disp = dseg_add_functionptr(cd, bte->fp);
2089 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2091 disp = dseg_add_functionptr(cd, bte->stub);
2094 if (N_VALID_DSEG_DISP(disp)) {
2095 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2097 N_LHI(REG_ITMP1, disp);
2098 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2101 /* generate the actual call */
2104 /* post call finalization */
2105 if (bte->stub == NULL) {
2106 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2110 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2112 /* Implicit NULL pointer check */
2113 M_ILD(REG_ITMP1, REG_A0, 0);
2116 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2117 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2118 um = iptr->sx.s23.s3.um;
2119 disp = dseg_add_unique_address(cd, um);
2121 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2125 lm = iptr->sx.s23.s3.fmiref->p.method;
2126 disp = dseg_add_address(cd, lm->stubroutine);
2129 if (N_VALID_DSEG_DISP(disp)) {
2130 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2132 N_LHI(REG_ITMP1, disp);
2133 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2136 /* generate the actual call */
2140 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2141 /* TODO softnull REG_A0 */
2143 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2144 um = iptr->sx.s23.s3.um;
2145 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2150 lm = iptr->sx.s23.s3.fmiref->p.method;
2151 s1 = OFFSET(vftbl_t, table[0]) +
2152 sizeof(methodptr) * lm->vftblindex;
2155 /* implicit null-pointer check */
2157 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2158 M_ALD(REG_PV, REG_METHODPTR, s1);
2160 /* generate the actual call */
2164 case ICMD_INVOKEINTERFACE:
2165 /* TODO softnull REG_A0 */
2167 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2168 * and -0xFFF in index register (itmp1)
2171 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2172 um = iptr->sx.s23.s3.um;
2173 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2179 lm = iptr->sx.s23.s3.fmiref->p.method;
2180 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2181 sizeof(methodptr*) * lm->clazz->index;
2183 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
2186 /* Implicit null-pointer check */
2187 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2188 N_LHI(REG_ITMP2, s1);
2189 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2190 M_ALD(REG_PV, REG_METHODPTR, s2);
2192 /* generate the actual call */
2196 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2198 /* val.a: (classinfo*) superclass */
2200 /* superclass is an interface:
2202 * OK if ((sub == NULL) ||
2203 * (sub->vftbl->interfacetablelength > super->index) &&
2204 * (sub->vftbl->interfacetable[-super->index] != NULL));
2206 * superclass is a class:
2208 * OK if ((sub == NULL) || (0
2209 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2210 * super->vftbl->diffval));
2213 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2214 /* object type cast-check */
2217 vftbl_t *supervftbl;
2220 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2221 # define LABEL_CLASS BRANCH_LABEL_2
2222 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2223 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2224 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2226 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2232 super = iptr->sx.s23.s3.c.cls;
2233 superindex = super->index;
2234 supervftbl = super->vftbl;
2237 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2239 /* if class is not resolved, check which code to call */
2241 if (super == NULL) {
2243 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
2245 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2247 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2248 iptr->sx.s23.s3.c.ref,
2251 ICONST(REG_ITMP3, ACC_INTERFACE);
2253 if (N_VALID_DSEG_DISP(disp)) {
2254 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
2256 ICONST(REG_ITMP2, disp);
2257 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2259 emit_label_beq(cd, LABEL_CLASS);
2262 /* interface checkcast code */
2264 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2265 if (super == NULL) {
2266 patcher_add_patch_ref(jd,
2267 PATCHER_checkcast_instanceof_interface,
2268 iptr->sx.s23.s3.c.ref,
2272 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
2275 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2276 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2277 M_ISUB_IMM(superindex, REG_ITMP3);
2278 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
2281 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2282 superindex * sizeof(methodptr*))
2284 M_ALD(REG_ITMP2, REG_ITMP2, 0);
2285 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
2287 if (super == NULL) {
2288 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
2292 /* class checkcast code */
2294 if (super == NULL) {
2295 emit_label(cd, LABEL_CLASS);
2298 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2299 if (super == NULL) {
2300 disp = dseg_add_unique_address(cd, NULL);
2302 patcher_add_patch_ref(jd,
2303 PATCHER_resolve_classref_to_vftbl,
2304 iptr->sx.s23.s3.c.ref,
2308 disp = dseg_add_address(cd, supervftbl);
2310 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
2314 /* REG_ITMP3 := baseval(s1) */
2315 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2316 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2318 /* REG_ITMP2 := baseval(class) */
2319 M_ALD_DSEG(REG_ITMP2, disp);
2320 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2322 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
2323 M_ISUB(REG_ITMP2, REG_ITMP3);
2325 /* REG_ITMP2 := diffval(class) */
2326 M_ALD_DSEG(REG_ITMP2, disp);
2327 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2329 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
2331 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
2332 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
2333 /* Branch if greater then */
2335 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2336 M_ALD_DSEG(REG_ITMP3, disp);
2338 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2339 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2340 M_ISUB(REG_ITMP3, REG_ITMP2);
2341 M_ALD_DSEG(REG_ITMP3, disp);
2342 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2344 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
2345 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
2346 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
2347 /* Branch if greater then */
2349 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
2352 if (super == NULL) {
2353 emit_label(cd, LABEL_EXIT_CHECK_NULL);
2354 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
2355 } else if (super->flags & ACC_INTERFACE) {
2356 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
2358 emit_label(cd, LABEL_EXIT_CLASS_NULL);
2361 d = codegen_reg_of_dst(jd, iptr, s1);
2363 # undef LABEL_EXIT_CHECK_NULL
2365 # undef LABEL_EXIT_INTERFACE_NULL
2366 # undef LABEL_EXIT_INTERFACE_DONE
2367 # undef LABEL_EXIT_CLASS_NULL
2370 /* array type cast-check */
2372 s1 = emit_load_s1(jd, iptr, REG_A0);
2373 M_INTMOVE(s1, REG_A0);
2375 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2376 disp = dseg_add_unique_address(cd, NULL);
2378 patcher_add_patch_ref(jd,
2379 PATCHER_resolve_classref_to_classinfo,
2380 iptr->sx.s23.s3.c.ref,
2384 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2386 M_ALD_DSEG(REG_A1, disp);
2387 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2388 M_ALD_DSEG(REG_ITMP1, disp);
2389 M_ASUB_IMM(96, REG_SP);
2390 M_JSR(REG_RA, REG_ITMP1);
2391 M_AADD_IMM(96, REG_SP);
2393 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2394 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2396 d = codegen_reg_of_dst(jd, iptr, s1);
2400 emit_store_dst(jd, iptr, d);
2403 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2404 /* val.a: (classinfo*) superclass */
2406 /* superclass is an interface:
2408 * return (sub != NULL) &&
2409 * (sub->vftbl->interfacetablelength > super->index) &&
2410 * (sub->vftbl->interfacetable[-super->index] != NULL);
2412 * superclass is a class:
2414 * return ((sub != NULL) && (0
2415 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2416 * super->vftbl->diffvall));
2418 * If superclass is unresolved, we include both code snippets
2419 * above, a patcher resolves the class' flags and we select
2420 * the right code at runtime.
2425 vftbl_t *supervftbl;
2428 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2434 super = iptr->sx.s23.s3.c.cls;
2435 superindex = super->index;
2436 supervftbl = super->vftbl;
2439 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2440 # define LABEL_CLASS BRANCH_LABEL_2
2441 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2442 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
2443 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
2444 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
2446 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2447 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2449 M_MOV(s1, REG_ITMP1);
2453 /* if class is not resolved, check which code to call */
2455 if (super == NULL) {
2459 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
2461 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2463 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2464 iptr->sx.s23.s3.c.ref, disp);
2466 ICONST(REG_ITMP3, ACC_INTERFACE);
2468 if (N_VALID_DSEG_DISP(disp)) {
2469 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
2471 ICONST(REG_ITMP2, disp);
2472 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2475 emit_label_beq(cd, LABEL_CLASS);
2478 /* interface instanceof code */
2480 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2481 if (super == NULL) {
2482 /* If d == REG_ITMP2, then it's destroyed in check
2487 patcher_add_patch_ref(jd,
2488 PATCHER_checkcast_instanceof_interface,
2489 iptr->sx.s23.s3.c.ref, 0);
2494 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
2497 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2498 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2499 M_ISUB_IMM(superindex, REG_ITMP3);
2501 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
2505 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2506 superindex * sizeof(methodptr*))
2508 M_ALD(REG_ITMP1, REG_ITMP1, 0);
2510 /* d := (REG_ITMP1 != 0) */
2512 N_LTR(d, REG_ITMP1);
2513 M_BEQ(SZ_BRC + SZ_LHI);
2516 if (super == NULL) {
2517 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
2521 /* class instanceof code */
2523 if (super == NULL) {
2524 emit_label(cd, LABEL_CLASS);
2527 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2528 if (super == NULL) {
2529 disp = dseg_add_unique_address(cd, NULL);
2531 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2532 iptr->sx.s23.s3.c.ref,
2536 disp = dseg_add_address(cd, supervftbl);
2541 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
2544 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2545 M_ALD_DSEG(REG_ITMP2, disp);
2547 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2548 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2549 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2551 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
2553 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
2555 M_BGT(SZ_BRC + SZ_LHI);
2559 if (super == NULL) {
2560 emit_label(cd, LABEL_EXIT_CHECK_NULL);
2561 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
2562 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
2563 } else if (super->flags & ACC_INTERFACE) {
2564 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
2565 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
2567 emit_label(cd, LABEL_EXIT_CLASS_NULL);
2570 # undef LABEL_EXIT_CHECK_NULL
2572 # undef LABEL_EXIT_INTERFACE_NULL
2573 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
2574 # undef LABEL_EXIT_INTERFACE_DONE
2575 # undef LABEL_EXIT_CLASS_NULL
2577 emit_store_dst(jd, iptr, d);
2583 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2585 /* check for negative sizes and copy sizes to stack if necessary */
2587 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
2590 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2592 /* copy SAVEDVAR sizes to stack */
2593 var = VAR(iptr->sx.s23.s2.args[s1]);
2595 /* Already Preallocated? */
2596 if (!(var->flags & PREALLOC)) {
2597 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2598 M_IST(s2, REG_SP, s1 * 4);
2602 /* is a patcher function set? */
2604 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2605 disp = dseg_add_unique_address(cd, 0);
2607 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2608 iptr->sx.s23.s3.c.ref,
2612 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2614 /* a0 = dimension count */
2616 ICONST(REG_A0, iptr->s1.argcount);
2618 /* a1 = classinfo */
2620 M_ALD_DSEG(REG_A1, disp);
2622 /* a2 = pointer to dimensions = stack pointer */
2624 M_MOV(REG_SP, REG_A2);
2626 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2627 M_ALD_DSEG(REG_ITMP1, disp);
2628 M_ASUB_IMM(96, REG_SP);
2629 M_JSR(REG_RA, REG_ITMP1);
2630 M_AADD_IMM(96, REG_SP);
2632 /* check for exception before result assignment */
2634 emit_exception_check(cd, iptr);
2636 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2637 M_INTMOVE(REG_RESULT, s1);
2638 emit_store_dst(jd, iptr, s1);
2643 vm_abort("Unknown ICMD %d during code generation", iptr->opc);
2648 /* codegen_emit_stub_native ****************************************************
2650 Emits a stub routine which calls a native method.
2652 *******************************************************************************/
2655 arguments on stack \
2656 -------------------------------------------------| <- SP on nativestub entry
2658 callee saved int regs (none) |
2659 callee saved float regs (none) | stack frame like in cacao
2660 local variable slots (none) |
2661 arguments for calling methods (none) /
2662 ------------------------------------------------------------------ <- datasp
2667 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
2668 0 - 96 register save area for callee /
2669 -------------------------------------------------------- <- SP native method
2671 SP after method entry
2674 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2685 /* get required compiler data */
2691 /* set some variables */
2695 /* calculate stackframe size */
2697 cd->stackframesize =
2698 1 + /* return address */
2699 sizeof(stackframeinfo_t) / 8 +
2700 sizeof(localref_table) / 8 +
2703 (96 / 8); /* linkage area */
2705 /* keep stack 8-byte aligned */
2707 /*ALIGN_2(cd->stackframesize);*/
2709 /* create method header */
2711 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2712 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
2713 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2714 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2715 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2719 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
2720 M_AADD_IMM(N_PV_OFFSET, REG_PV);
2722 /* store return address */
2724 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
2726 #if defined(ENABLE_GC_CACAO)
2727 /* Save callee saved integer registers in stackframeinfo (GC may
2728 need to recover them during a collection). */
2730 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
2731 OFFSET(stackframeinfo_t, intregs);
2733 for (i = 0; i < INT_SAV_CNT; i++)
2734 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2737 /* save integer and float argument registers */
2739 for (i = 0; i < md->paramcount; i++) {
2740 if (!md->params[i].inmemory) {
2741 s1 = md->params[i].regoff;
2743 switch (md->paramtypes[i].type) {
2746 M_IST(s1, REG_SP, 96 + i * 8);
2749 M_LST(s1, REG_SP, 96 + i * 8);
2753 M_DST(s1, REG_SP, 96 + i * 8);
2759 /* create native stack info */
2761 M_MOV(REG_SP, REG_A0);
2762 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
2763 disp = dseg_add_functionptr(cd, codegen_start_native_call);
2764 M_ALD_DSEG(REG_ITMP2, disp);
2767 /* remember class argument */
2769 if (m->flags & ACC_STATIC)
2770 M_MOV(REG_RESULT, REG_ITMP3);
2772 /* restore integer and float argument registers */
2774 for (i = 0; i < md->paramcount; i++) {
2775 if (!md->params[i].inmemory) {
2776 s1 = md->params[i].regoff;
2778 switch (md->paramtypes[i].type) {
2781 M_ILD(s1, REG_SP, 96 + i * 8);
2784 M_LLD(s1, REG_SP, 96 + i * 8);
2788 M_DLD(s1, REG_SP, 96 + i * 8);
2794 /* copy or spill arguments to new locations */
2796 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2797 t = md->paramtypes[i].type;
2799 if (IS_INT_LNG_TYPE(t)) {
2800 if (!md->params[i].inmemory) {
2801 s1 = md->params[i].regoff;
2802 s2 = nmd->params[j].regoff;
2804 if (!nmd->params[j].inmemory) {
2805 if (IS_2_WORD_TYPE(t))
2811 if (IS_2_WORD_TYPE(t))
2812 M_LST(s1, REG_SP, s2);
2814 M_IST(s1, REG_SP, s2);
2818 s1 = md->params[i].regoff + cd->stackframesize * 8;
2819 s2 = nmd->params[j].regoff;
2821 if (IS_2_WORD_TYPE(t)) {
2822 N_MVC(s2, 8, REG_SP, s1, REG_SP);
2824 N_MVC(s2, 4, REG_SP, s1, REG_SP);
2829 /* We only copy spilled float arguments, as the float
2830 argument registers keep unchanged. */
2832 if (md->params[i].inmemory) {
2833 s1 = md->params[i].regoff + cd->stackframesize * 8;
2834 s2 = nmd->params[j].regoff;
2836 if (IS_2_WORD_TYPE(t)) {
2837 N_MVC(s2, 8, REG_SP, s1, REG_SP);
2839 N_MVC(s2, 4, REG_SP, s1, REG_SP);
2845 /* Handle native Java methods. */
2847 if (m->flags & ACC_NATIVE) {
2848 /* put class into second argument register */
2850 if (m->flags & ACC_STATIC)
2851 M_MOV(REG_ITMP3, REG_A1);
2853 /* put env into first argument register */
2855 disp = dseg_add_address(cd, VM_get_jnienv());
2856 M_ALD_DSEG(REG_A0, disp);
2859 /* Call native function. */
2861 disp = dseg_add_functionptr(cd, f);
2862 M_ALD_DSEG(REG_ITMP2, disp);
2865 /* save return value */
2867 switch (md->returntype.type) {
2870 M_IST(REG_RESULT, REG_SP, 96);
2873 M_LST(REG_RESULT_PACKED, REG_SP, 96);
2877 M_DST(REG_FRESULT, REG_SP, 96);
2883 /* remove native stackframe info */
2885 M_MOV(REG_SP, REG_A0);
2886 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
2887 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
2888 M_ALD_DSEG(REG_ITMP1, disp);
2891 M_MOV(REG_RESULT, REG_ITMP3_XPTR);
2893 /* restore return value */
2895 switch (md->returntype.type) {
2898 M_ILD(REG_RESULT, REG_SP, 96);
2901 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
2905 M_DLD(REG_FRESULT, REG_SP, 96);
2911 #if defined(ENABLE_GC_CACAO)
2912 /* Restore callee saved integer registers from stackframeinfo (GC
2913 might have modified them during a collection). */
2915 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
2916 OFFSET(stackframeinfo_t, intregs);
2918 for (i = 0; i < INT_SAV_CNT; i++)
2919 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2922 /* load return address */
2924 M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
2926 /* remove stackframe */
2928 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2930 /* check for exception */
2932 M_TEST(REG_ITMP3_XPTR);
2933 M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
2937 /* handle exception */
2939 M_MOV(REG_RA, REG_ITMP1_XPC);
2940 M_ASUB_IMM(2, REG_ITMP1_XPC);
2942 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
2943 M_ALD_DSEG(REG_ITMP2, disp);
2944 M_JMP(RN, REG_ITMP2);
2948 * These are local overrides for various environment variables in Emacs.
2949 * Please do not remove this and leave it at the end of the file, where
2950 * Emacs will automagically detect them.
2951 * ---------------------------------------------------------------------
2954 * indent-tabs-mode: t
2958 * vim:noexpandtab:sw=4:ts=4: