1 /* src/vm/jit/m68k/codegen.c
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 $Id: codegen.c 7564 2007-03-23 23:36:17Z twisti $
38 #include "vm/jit/m68k/codegen.h"
39 #include "vm/jit/m68k/emit.h"
41 #include "mm/memory.h"
42 #include "native/jni.h"
43 #include "native/native.h"
45 #include "threads/lock-common.h"
47 #include "vm/builtin.h"
48 #include "vm/exceptions.h"
49 #include "vm/global.h"
50 #include "vm/stringlocal.h"
53 #include "vm/jit/asmpart.h"
54 #include "vm/jit/codegen-common.h"
55 #include "vm/jit/dseg.h"
56 #include "vm/jit/emit-common.h"
57 #include "vm/jit/jit.h"
58 #include "vm/jit/parse.h"
59 #include "vm/jit/patcher.h"
60 #include "vm/jit/reg.h"
61 #include "vm/jit/replace.h"
62 #include "vm/jit/stacktrace.h"
63 #include "vm/jit/md.h"
65 #include "vmcore/loader.h"
66 #include "vmcore/options.h"
67 #include "vmcore/utf8.h"
70 bool codegen_emit(jitdata *jd)
76 s4 len, s1, s2, s3, d, disp;
83 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
84 unresolved_method *um;
85 builtintable_entry *bte;
92 /* get required compiler data */
99 /* prevent compiler warnings */
107 /* save calle saved registers */
108 s4 savedregs_num = 0;
110 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
111 savedregs_num += (ADR_SAV_CNT - rd->savadrreguse);
112 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
114 cd->stackframesize = rd->memuse + savedregs_num;
116 /* FIXME: we could need 2 words to move a double result, which gets
117 * passed in %d0, %d1 into a floating point register, this is of
118 * course onyl true when not using ENABLE_SOFTFLOAT, so this could be
119 * optimized away, for now always use 2 more words. When optimizing watch
120 * the threading code, which stores the lock word, the offset would change */
121 cd->stackframesize += 2;
123 #if defined(ENABLE_THREADS)
124 /* we need additional space to save argument of monitor_enter */
125 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
126 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type)) {
127 cd->stackframesize += 2;
129 cd->stackframesize ++;
135 /* create method header */
136 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
137 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
138 #if defined(ENABLE_THREADS)
139 if (checksync && (m->flags & ACC_SYNCHRONIZED))
140 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4);/* IsSync */
143 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
144 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
146 /* XXX we use the IntSAce a split field for the adr now */
147 (void) dseg_add_unique_s4(cd, (ADR_SAV_CNT - rd->savadrreguse) << 16 | (INT_SAV_CNT - rd->savintreguse)); /* IntSave */
148 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
150 dseg_addlinenumbertablesize(cd);
152 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
154 /* create exception table */
155 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
156 dseg_add_target(cd, ex->start);
157 dseg_add_target(cd, ex->end);
158 dseg_add_target(cd, ex->handler);
159 (void) dseg_add_unique_address(cd, ex->catchtype.any);
162 #if defined(ENABLE_PROFILING)
167 emit_verbosecall_enter(jd);
169 /* create stack frame */
170 M_AADD_IMM(-(cd->stackframesize*4), REG_SP);
172 /* save used callee saved registers */
173 p = cd->stackframesize;
174 for (i=INT_SAV_CNT-1; i>=rd->savintreguse; --i) {
175 p--; M_IST(rd->savintregs[i], REG_SP, p*4);
177 for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
178 p--; M_AST(rd->savadrregs[i], REG_SP, p*4);
180 #if !defined(ENABLE_SOFTFLOAT)
181 for (i=FLT_SAV_CNT-1; i>=rd->savfltreguse; --i) {
182 p-=2; M_DST(rd->savfltregs[i], REG_SP, p*4);
185 assert(FLT_SAV_CNT == 0);
186 assert(rd->savfltreguse == 0);
188 /* take arguments out of stack frame */
190 for (p = 0, l = 0; p < md->paramcount; p++) {
191 t = md->paramtypes[p].type;
192 varindex = jd->local_map[l * 5 + t];
195 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
198 if (varindex == UNUSED)
203 s1 = md->params[p].regoff;
204 assert(md->params[p].inmemory); /* all args are on stack */
207 #if defined(ENABLE_SOFTFLOAT)
213 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
214 if (IS_2_WORD_TYPE(t)) {
215 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
217 M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
219 } else { /* stack arg -> spilled */
221 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
222 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
223 if (IS_2_WORD_TYPE(t)) {
224 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4 + 4);
225 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
228 /* Reuse Memory Position on Caller Stack */
229 var->vv.regoff = cd->stackframesize + s1;
233 #if !defined(ENABLE_SOFTFLOAT)
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 + s1 + 1) * 4);
240 M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
242 } else { /* stack-arg -> spilled */
244 if (IS_2_WORD_TYPE(t)) {
245 M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
246 M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
248 M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
249 M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
252 /* Reuse Memory Position on Caller Stack */
253 var->vv.regoff = cd->stackframesize + s1;
257 #endif /* SOFTFLOAT */
259 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
260 M_ALD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
261 } else { /* stack-arg -> spilled */
263 M_ALD(REG_ATMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
264 M_AST(REG_ATMP1, REG_SP, var->vv.regoff * 4);
266 /* Reuse Memory Position on Caller Stack */
267 var->vv.regoff = cd->stackframesize + s1;
273 } /* end for argument out of stack*/
275 #if defined(ENABLE_THREADS)
276 /* call monitor_enter function */
277 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
278 if (m->flags & ACC_STATIC) {
279 M_AMOV_IMM((&m->class->object.header), REG_ATMP1);
281 /* for non-static case the first arg is the object */
282 M_ALD(REG_ATMP1, REG_SP, cd->stackframesize*4 + 4);
285 M_TRAP(M68K_EXCEPTION_HARDWARE_NULLPOINTER);
288 M_AST(REG_ATMP1, REG_SP, rd->memuse * 4 + 2*4);
289 M_AST(REG_ATMP1, REG_SP, 0 * 4);
290 M_JSR_IMM(LOCK_monitor_enter);
296 /* create replacement points */
297 REPLACEMENT_POINTS_INIT(cd, jd);
299 /* foreach basic block */
300 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
302 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
304 if (bptr->flags >= BBREACHED) {
306 /* branch resolving */
307 codegen_resolve_branchrefs(cd, bptr);
309 /* FIXME there are still some constrcuts to copy in here */
311 /* walk through all instructions */
315 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
316 if (iptr->line != currentline) {
317 dseg_addlinenumber(cd, iptr->line);
318 currentline = iptr->line;
321 MCODECHECK(1024); /* 1kB should be enough */
324 case ICMD_NOP: /* ... ==> ... */
325 case ICMD_POP: /* ..., value ==> ... */
326 case ICMD_POP2: /* ..., value, value ==> ... */
329 case ICMD_INLINE_START:
331 REPLACEMENT_POINT_INLINE_START(cd, iptr);
334 case ICMD_INLINE_BODY:
336 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
337 dseg_addlinenumber_inline_start(cd, iptr);
338 dseg_addlinenumber(cd, iptr->line);
341 case ICMD_INLINE_END:
343 dseg_addlinenumber_inline_end(cd, iptr);
344 dseg_addlinenumber(cd, iptr->line);
347 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
349 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
350 assert(VAROP(iptr->s1)->type == TYPE_ADR);
351 emit_nullpointer_check(cd, iptr, s1);
355 /* CONST **************************************************************/
356 case ICMD_ICONST: /* ... ==> ..., constant */
357 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
358 M_IMOV_IMM(iptr->sx.val.i, d);
359 emit_store_dst(jd, iptr, d);
362 case ICMD_LCONST: /* ... ==> ..., constant */
364 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
365 LCONST(iptr->sx.val.l, d);
366 emit_store_dst(jd, iptr, d);
369 case ICMD_FCONST: /* ... ==> ..., constant */
371 #if defined(ENABLE_SOFTFLOAT)
372 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
373 M_IMOV_IMM(iptr->sx.val.i, d);
374 emit_store_dst(jd, iptr, d);
376 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
377 FCONST(iptr->sx.val.i, d);
378 emit_store_dst(jd, iptr, d);
382 case ICMD_DCONST: /* ... ==> ..., constant */
384 #if defined(ENABLE_SOFTFLOAT)
385 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
386 LCONST(iptr->sx.val.l, d);
387 emit_store_dst(jd, iptr, d);
389 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
390 disp = dseg_add_double(cd, iptr->sx.val.d);
391 M_AMOV_IMM(0, REG_ATMP1);
393 M_DLD(d, REG_ATMP1, disp);
394 emit_store_dst(jd, iptr, d);
400 /* integer operations ************************************************/
401 case ICMD_INEG: /* ..., value ==> ..., - value */
403 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
404 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
405 M_INTMOVE(s1, REG_ITMP1);
407 M_INTMOVE(REG_ITMP1, d);
408 emit_store_dst(jd, iptr, d);
412 case ICMD_LNEG: /* ..., value ==> ..., - value */
414 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
415 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
416 M_SUBFIC(GET_LOW_REG(s1), 0, GET_LOW_REG(d));
417 M_SUBFZE(GET_HIGH_REG(s1), GET_HIGH_REG(d));
418 emit_store_dst(jd, iptr, d);
421 case ICMD_I2L: /* ..., value ==> ..., value */
423 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
424 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
425 M_IMOV(s1, GET_LOW_REG(d)); /* sets negativ bit */
427 M_ISET(GET_HIGH_REG(d));
429 M_ICLR(GET_HIGH_REG(d));
431 emit_store_dst(jd, iptr, d);
434 case ICMD_L2I: /* ..., value ==> ..., value */
436 s1 = emit_load_s1_low(jd, iptr, REG_ITMP2);
437 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
439 emit_store_dst(jd, iptr, d);
441 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
443 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
444 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
446 emit_store_dst(jd, iptr, d);
449 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
451 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
452 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
454 emit_store_dst(jd, iptr, d);
457 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
459 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
460 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
462 emit_store_dst(jd, iptr, d);
467 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
469 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
470 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
471 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
472 M_INTMOVE(s2, REG_ITMP2);
473 M_IADD(s1, REG_ITMP2);
474 M_INTMOVE(REG_ITMP2, d);
475 emit_store_dst(jd, iptr, d);
478 /* s1.localindex = variable, sx.val.i = constant*/
483 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
484 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
485 M_INTMOVE(s1, REG_ITMP1);
486 M_IADD_IMM(iptr->sx.val.i, REG_ITMP1);
487 M_INTMOVE(REG_ITMP1, d);
488 emit_store_dst(jd, iptr, d);
491 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
493 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
494 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
495 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
496 M_INTMOVE(s1, REG_ITMP1);
497 M_ISUB(s2, REG_ITMP1);
498 M_INTMOVE(REG_ITMP1, d);
499 emit_store_dst(jd, iptr, d);
502 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
503 /* sx.val.i = constant */
505 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
506 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
507 M_INTMOVE(s1, REG_ITMP1);
508 M_IADD_IMM(-iptr->sx.val.i, REG_ITMP1);
509 M_INTMOVE(REG_ITMP1, d);
510 emit_store_dst(jd, iptr, d);
513 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
514 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
515 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
516 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
517 emit_arithmetic_check(cd, iptr, s2);
518 M_INTMOVE(s1, REG_ITMP1);
519 M_IDIV(s2, REG_ITMP1);
520 M_INTMOVE(REG_ITMP1, d);
521 emit_store_dst(jd, iptr, d);
524 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
525 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
526 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
527 M_INTMOVE(s1, REG_ITMP1);
531 M_IADD_IMM((1 << iptr->sx.val.i) - 1, REG_ITMP1);
533 M_IMOV_IMM(iptr->sx.val.i, REG_ITMP2);
534 M_ISSR(REG_ITMP2, REG_ITMP1);
535 M_INTMOVE(REG_ITMP1, d);
536 emit_store_dst(jd, iptr, d);
539 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
540 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
541 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
542 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
543 emit_arithmetic_check(cd, iptr, s2);
545 M_ICMP_IMM(0x80000000, s1);
550 M_TPFL; /* hides the next instruction */
551 M_IREM(s2, s1, REG_ITMP3);
553 M_INTMOVE(REG_ITMP3, d);
555 emit_store_dst(jd, iptr, d);
558 case ICMD_IREMPOW2: /* ..., value ==> ..., value << constant */
559 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
560 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
562 M_IMOV(s1, REG_ITMP1);
566 M_IAND_IMM(iptr->sx.val.i, d);
568 M_BGE(2 + 2 + 6 + 2);
569 M_IMOV(s1, d); /* don't use M_INTMOVE, so we know the jump offset */
571 M_IAND_IMM(iptr->sx.val.i, d); /* use 32-bit for jump offset */
574 emit_store_dst(jd, iptr, d);
578 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
579 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
581 bte = iptr->sx.s23.s3.bte;
584 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
585 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
586 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
587 /* XXX could be optimized */
588 emit_arithmetic_check(cd, iptr, REG_ITMP3);
590 M_LST(s2, REG_SP, 2 * 4);
591 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
592 M_LST(s1, REG_SP, 0 * 4);
596 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
597 M_LNGMOVE(REG_RESULT_PACKED, d);
598 emit_store_dst(jd, iptr, d);
601 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
603 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
604 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
605 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
606 M_INTMOVE(s2, REG_ITMP2);
607 M_IMUL(s1, REG_ITMP2);
608 M_INTMOVE(REG_ITMP2, d);
609 emit_store_dst(jd, iptr, d);
612 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
613 /* sx.val.i = constant */
614 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
615 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
616 M_IMOV_IMM(iptr->sx.val.i, REG_ITMP2);
617 M_IMUL(s1, REG_ITMP2);
618 M_INTMOVE(REG_ITMP2, d);
619 emit_store_dst(jd, iptr, d);
622 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
624 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
625 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
626 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
627 M_INTMOVE(s1, REG_ITMP1);
628 M_INTMOVE(s2, REG_ITMP2);
629 M_IAND_IMM(0x1f, REG_ITMP2);
630 M_ISSL(REG_ITMP2, REG_ITMP1);
631 M_INTMOVE(REG_ITMP1, d);
632 emit_store_dst(jd, iptr, d);
635 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
636 /* sx.val.i = constant */
638 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
639 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
640 if (iptr->sx.val.i & 0x1f) {
641 M_INTMOVE(s1, REG_ITMP1)
642 if ((iptr->sx.val.i & 0x1f) <= 7) {
643 M_ISSL_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
645 M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
646 M_ISSL(REG_ITMP2, REG_ITMP1);
648 M_INTMOVE(REG_ITMP1, d);
652 emit_store_dst(jd, iptr, d);
655 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
657 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
658 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
659 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
660 M_INTMOVE(s1, REG_ITMP1);
661 M_INTMOVE(s2, REG_ITMP2);
662 M_IAND_IMM(0x1f, REG_ITMP2);
663 M_ISSR(REG_ITMP2, REG_ITMP1);
664 M_INTMOVE(REG_ITMP1, d);
665 emit_store_dst(jd, iptr, d);
668 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
669 /* sx.val.i = constant */
671 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
672 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
673 if (iptr->sx.val.i & 0x1f) {
674 M_INTMOVE(s1, REG_ITMP1)
675 if ((iptr->sx.val.i & 0x1f) <= 7) {
676 M_ISSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
678 M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
679 M_ISSR(REG_ITMP2, REG_ITMP1);
681 M_INTMOVE(REG_ITMP1, d);
685 emit_store_dst(jd, iptr, d);
688 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
690 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
691 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
692 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
693 M_INTMOVE(s1, REG_ITMP1);
694 M_INTMOVE(s2, REG_ITMP2);
695 M_IAND_IMM(0x1f, REG_ITMP2);
696 M_IUSR(REG_ITMP2, REG_ITMP1);
697 M_INTMOVE(REG_ITMP1, d);
698 emit_store_dst(jd, iptr, d);
701 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
702 /* sx.val.i = constant */
703 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
704 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
705 if (iptr->sx.val.i & 0x1f) {
706 M_INTMOVE(s1, REG_ITMP1)
707 if ((iptr->sx.val.i & 0x1f) <= 7) {
708 M_IUSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
710 M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
711 M_IUSR(REG_ITMP2, REG_ITMP1);
713 M_INTMOVE(REG_ITMP1, d);
717 emit_store_dst(jd, iptr, d);
720 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
722 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
723 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
724 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
725 M_INTMOVE(s2, REG_ITMP2);
726 M_IAND(s1, REG_ITMP2);
727 M_INTMOVE(REG_ITMP2, d);
728 emit_store_dst(jd, iptr, d);
731 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
732 /* sx.val.i = constant */
734 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
735 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
736 M_INTMOVE(s1, REG_ITMP1);
737 M_IAND_IMM(iptr->sx.val.i, REG_ITMP1);
738 M_INTMOVE(REG_ITMP1, d);
739 emit_store_dst(jd, iptr, d);
742 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
743 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
744 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
745 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
746 M_INTMOVE(s2, REG_ITMP2);
747 M_IOR(s1, REG_ITMP2);
748 M_INTMOVE(REG_ITMP2, d);
749 emit_store_dst(jd, iptr, d);
752 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
753 /* sx.val.i = constant */
754 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
755 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
756 M_INTMOVE(s1, REG_ITMP1);
757 M_IOR_IMM(iptr->sx.val.i, REG_ITMP1);
758 M_INTMOVE(REG_ITMP1, d);
759 emit_store_dst(jd, iptr, d);
762 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 | val2 */
763 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
764 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
765 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
766 M_INTMOVE(s2, REG_ITMP2);
767 M_IXOR(s1, REG_ITMP2);
768 M_INTMOVE(REG_ITMP2, d);
769 emit_store_dst(jd, iptr, d);
772 case ICMD_IXORCONST: /* ..., value ==> ..., value | constant */
773 /* sx.val.i = constant */
774 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
775 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
776 M_INTMOVE(s1, REG_ITMP1);
777 M_IXOR_IMM(iptr->sx.val.i, REG_ITMP1);
778 M_INTMOVE(REG_ITMP1, d);
779 emit_store_dst(jd, iptr, d);
782 /* floating point operations ******************************************/
783 #if !defined(ENABLE_SOFTFLOAT)
784 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
786 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
787 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
788 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
791 M_BFUN(14); /* result is -1, branch to end */
792 M_BFLT(10); /* result is -1, branch to end */
794 M_BFEQ(4) /* result is 0, branch to end */
796 emit_store_dst(jd, iptr, d);
799 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
801 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
802 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
803 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
806 M_BFUN(16); /* result is +1, branch to end */
807 M_BFGT(14); /* result is +1, branch to end */
809 M_BFEQ(8) /* result is 0, branch to end */
811 emit_store_dst(jd, iptr, d);
814 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
815 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
816 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
817 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
818 M_FLTMOVE(s2, REG_FTMP2);
819 M_FMUL(s1, REG_FTMP2);
820 M_FLTMOVE(REG_FTMP2, d);
821 emit_store_dst(jd, iptr, d);
824 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
825 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
826 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
827 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
828 M_DBLMOVE(s2, REG_FTMP2);
829 M_DMUL(s1, REG_FTMP2);
830 M_DBLMOVE(REG_FTMP2, d);
831 emit_store_dst(jd, iptr, d);
834 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
835 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
836 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
837 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
838 M_FLTMOVE(s1, REG_FTMP1);
839 M_FDIV(s2, REG_FTMP1);
840 M_FLTMOVE(REG_FTMP1, d);
841 emit_store_dst(jd, iptr, d);
844 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
845 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
846 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
847 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
848 M_DBLMOVE(s1, REG_FTMP1);
849 M_DDIV(s2, REG_FTMP1);
850 M_DBLMOVE(REG_FTMP1, d);
851 emit_store_dst(jd, iptr, d);
854 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
855 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
856 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
857 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
858 M_FLTMOVE(s2, REG_FTMP2);
859 M_FADD(s1, REG_FTMP2);
860 M_FLTMOVE(REG_FTMP2, d);
861 emit_store_dst(jd, iptr, d);
864 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
865 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
866 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
867 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
868 M_DBLMOVE(s2, REG_FTMP2);
869 M_DADD(s1, REG_FTMP2);
870 M_DBLMOVE(REG_FTMP2, d);
871 emit_store_dst(jd, iptr, d);
874 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
875 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
876 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
877 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
878 M_FLTMOVE(s1, REG_FTMP1);
879 M_FSUB(s2, REG_FTMP1);
880 M_FLTMOVE(REG_FTMP1, d);
881 emit_store_dst(jd, iptr, d);
884 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
885 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
886 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
887 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
888 M_DBLMOVE(s1, REG_FTMP1);
889 M_DSUB(s2, REG_FTMP1);
890 M_DBLMOVE(REG_FTMP1, d);
891 emit_store_dst(jd, iptr, d);
894 case ICMD_F2D: /* ..., value ==> ..., (double) value */
895 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
896 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
898 emit_store_dst(jd, iptr, d);
900 case ICMD_D2F: /* ..., value ==> ..., (float) value */
901 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
902 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
904 emit_store_dst(jd, iptr, d);
911 /* load/store/copy/move operations ************************************/
913 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
914 case ICMD_ALOAD: /* s1 = local variable */
918 case ICMD_ISTORE: /* ..., value ==> ... */
930 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
935 case ICMD_ACONST: /* ... ==> ..., constant */
936 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
938 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
939 constant_classref *cr = iptr->sx.val.c.ref;;
940 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, cr, 0);
943 M_AMOV_IMM(iptr->sx.val.anyptr, d);
945 emit_store_dst(jd, iptr, d);
947 /* BRANCH *************************************************************/
949 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
951 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
952 M_ADRMOVE(s1, REG_ATMP1_XPTR);
954 #ifdef ENABLE_VERIFIER
955 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
956 unresolved_class *uc = iptr->sx.s23.s2.uc;
958 codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
960 #endif /* ENABLE_VERIFIER */
961 M_JSR_PCREL(2); /* get current PC */
964 M_AMOV_IMM(asm_handle_exception, REG_ATMP3);
969 case ICMD_GOTO: /* ... ==> ... */
970 case ICMD_RET: /* ... ==> ... */
972 emit_br(cd, iptr->dst.block);
976 case ICMD_JSR: /* ... ==> ... */
978 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
984 case ICMD_IFNULL: /* ..., value ==> ... */
986 assert(IS_ADR_TYPE(VAROP(iptr->s1)->type));
987 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
989 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
997 case ICMD_IFEQ: /* ..., value ==> ... */
999 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1000 assert (VAROP(iptr->s1)->type == TYPE_INT);
1001 M_ICMP_IMM(iptr->sx.val.i, s1);
1002 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
1005 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1006 case ICMD_IF_ICMPNE:
1007 case ICMD_IF_ICMPLT:
1008 case ICMD_IF_ICMPGT:
1009 case ICMD_IF_ICMPLE:
1010 case ICMD_IF_ICMPGE:
1012 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1013 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1015 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
1018 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
1019 case ICMD_IF_ACMPNE:
1021 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1022 s2 = emit_load_s2(jd, iptr, REG_ATMP2);
1024 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
1028 /* MEMORY *************************************************************/
1029 case ICMD_GETSTATIC:
1030 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1031 uf = iptr->sx.s23.s3.uf;
1032 fieldtype = uf->fieldref->parseddesc.fd->type;
1033 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
1035 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
1037 fieldtype = fi->type;
1038 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1039 codegen_addpatchref(cd, PATCHER_initialize_class, fi->class, 0);
1042 disp = (ptrint) &(fi->value);
1044 M_AMOV_IMM(disp, REG_ATMP1);
1045 switch (fieldtype) {
1046 #if defined(ENABLE_SOFTFLOAT)
1050 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1051 M_ILD(d, REG_ATMP1, 0);
1054 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1055 M_ALD(d, REG_ATMP1, 0);
1057 #if defined(ENABLE_SOFTFLOAT)
1061 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
1062 M_LLD(d, REG_ATMP1, 0);
1064 #if !defined(ENABLE_SOFTFLOAT)
1066 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1067 M_FLD(d, REG_ATMP1, 0);
1070 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1071 M_DLD(d, REG_ATMP1, 0);
1075 emit_store_dst(jd, iptr, d);
1078 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1080 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1081 uf = iptr->sx.s23.s3.uf;
1082 fieldtype = uf->fieldref->parseddesc.fd->type;
1084 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
1086 fi = iptr->sx.s23.s3.fmiref->p.field;
1087 fieldtype = fi->type;
1088 disp = &(fi->value);
1090 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1091 codegen_addpatchref(cd, PATCHER_initialize_class, fi->class, 0);
1094 M_AMOV_IMM(disp, REG_ATMP1);
1095 switch (fieldtype) {
1096 #if defined(ENABLE_SOFTFLOAT)
1100 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1101 M_IST(s1, REG_ATMP1, 0);
1103 #if defined(ENABLE_SOFTFLOAT)
1107 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
1108 M_LST(s1, REG_ATMP1, 0);
1111 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1112 M_AST(s1, REG_ATMP1, 0);
1114 #if !defined(ENABLE_SOFTFLOAT)
1116 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1117 M_FST(s1, REG_ATMP1, 0);
1120 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1121 M_DST(s1, REG_ATMP1, 0);
1128 case ICMD_GETFIELD: /* ... ==> ..., value */
1130 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1132 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1133 uf = iptr->sx.s23.s3.uf;
1134 fieldtype = uf->fieldref->parseddesc.fd->type;
1137 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1140 fi = iptr->sx.s23.s3.fmiref->p.field;
1141 fieldtype = fi->type;
1145 /* implicit null-pointer check */
1146 switch (fieldtype) {
1147 #if defined(ENABLE_SOFTFLOAT)
1151 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1154 #if defined(ENABLE_SOFTFLOAT)
1158 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1162 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1165 #if !defined(ENABLE_SOFTFLOAT)
1167 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1171 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1176 emit_store_dst(jd, iptr, d);
1179 case ICMD_PUTFIELD: /* ..., value ==> ... */
1181 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1183 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1184 uf = iptr->sx.s23.s3.uf;
1185 fieldtype = uf->fieldref->parseddesc.fd->type;
1189 fi = iptr->sx.s23.s3.fmiref->p.field;
1190 fieldtype = fi->type;
1194 if (IS_INT_LNG_TYPE(fieldtype)) {
1195 if (IS_2_WORD_TYPE(fieldtype)) {
1196 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
1198 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1201 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1204 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1205 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1207 /* implicit null-pointer check */
1208 switch (fieldtype) {
1209 #if defined(ENABLE_SOFTFLOAT)
1213 M_IST(s2, s1, disp);
1216 #if defined(ENABLE_SOFTFLOAT)
1220 M_LST(s2, s1, disp);
1223 M_AST(s2, s1, disp);
1225 #if !defined(ENABLE_SOFTFLOAT)
1227 M_FST(s2, s1, disp);
1230 M_DST(s2, s1, disp);
1236 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1238 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1239 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1240 /* implicit null-pointer check */
1241 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1242 emit_store_dst(jd, iptr, d);
1245 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1247 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1248 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1249 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1250 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1251 M_INTMOVE(s2, REG_ITMP2);
1252 M_IADD_IMM(OFFSET(java_bytearray, data[0]), REG_ITMP2);
1253 M_ADRMOVE(s1, REG_ATMP1);
1254 M_AADDINT(REG_ITMP2, REG_ATMP1);
1255 /* implicit null-pointer check */
1256 M_LBZX(REG_ATMP1, d);
1258 emit_store_dst(jd, iptr, d);
1261 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1263 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1264 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1265 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1266 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1267 M_INTMOVE(s2, REG_ITMP2);
1268 M_ISSL_IMM(1, REG_ITMP2);
1269 M_IADD_IMM(OFFSET(java_chararray, data[0]), REG_ITMP2);
1270 M_ADRMOVE(s1, REG_ATMP1);
1271 M_AADDINT(REG_ITMP2, REG_ATMP1);
1272 /* implicit null-pointer check */
1273 M_LHZX(REG_ATMP1, d);
1275 emit_store_dst(jd, iptr, d);
1278 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1280 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1281 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1282 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1283 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1284 M_INTMOVE(s2, REG_ITMP2);
1285 M_ISSL_IMM(1, REG_ITMP2);
1286 M_IADD_IMM(OFFSET(java_shortarray, data[0]), REG_ITMP2);
1287 M_ADRMOVE(s1, REG_ATMP1);
1288 M_AADDINT(REG_ITMP2, REG_ATMP1);
1290 /* implicit null-pointer check */
1291 M_LHZX(REG_ATMP1, d);
1293 emit_store_dst(jd, iptr, d);
1296 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1298 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1299 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1300 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1301 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1302 M_INTMOVE(s2, REG_ITMP2);
1303 M_ISSL_IMM(2, REG_ITMP2);
1304 M_IADD_IMM(OFFSET(java_intarray, data[0]), REG_ITMP2);
1305 M_ADRMOVE(s1, REG_ATMP1);
1306 M_AADDINT(REG_ITMP2, REG_ATMP1);
1307 /* implicit null-pointer check */
1308 M_LWZX(REG_ATMP1, d);
1309 emit_store_dst(jd, iptr, d);
1312 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1313 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1314 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1315 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1316 /* implicit null-pointer check */
1317 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1318 M_INTMOVE(s2, REG_ITMP1);
1319 M_ISSL_IMM(3, REG_ITMP1);
1320 M_IADD_IMM(OFFSET(java_longarray, data[0]), REG_ITMP1);
1321 M_ADRMOVE(s1, REG_ATMP1);
1322 M_AADDINT(REG_ITMP1, REG_ATMP1);
1323 /* implicit null-pointer check */
1324 M_LLD(d, REG_ATMP1, 0);
1325 emit_store_dst(jd, iptr, d);
1328 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1329 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1330 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1331 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1332 M_INTMOVE(s2, REG_ITMP2);
1333 M_ISSL_IMM(2, REG_ITMP2);
1334 M_IADD_IMM(OFFSET(java_floatarray, data[0]), REG_ITMP2);
1335 M_ADRMOVE(s1, REG_ATMP1);
1336 M_AADDINT(REG_ITMP2, REG_ATMP1);
1337 /* implicit null-pointer check */
1338 #if !defined(ENABLE_SOFTFLOAT)
1339 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1340 M_FLD(d, REG_ATMP1, 0);
1342 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1343 M_LWZX(REG_ATMP1, d);
1345 emit_store_dst(jd, iptr, d);
1348 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1349 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1350 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1351 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1352 M_INTMOVE(s2, REG_ITMP2);
1353 M_ISSL_IMM(3, REG_ITMP2);
1354 M_IADD_IMM(OFFSET(java_doublearray, data[0]), REG_ITMP2);
1355 M_ADRMOVE(s1, REG_ATMP1);
1356 M_AADDINT(REG_ITMP2, REG_ATMP1);
1357 /* implicit null-pointer check */
1358 #if !defined(ENABLE_SOFTFLOAT)
1359 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1360 M_DLD(d, REG_ATMP1, 0);
1362 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1363 M_LLD(d, REG_ATMP1, 0);
1365 emit_store_dst(jd, iptr, d);
1368 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1369 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1370 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1371 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1372 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1373 M_INTMOVE(s2, REG_ITMP2);
1374 M_ISSL_IMM(2, REG_ITMP2);
1375 M_IADD_IMM(OFFSET(java_objectarray, data[0]), REG_ITMP2);
1376 M_ADRMOVE(s1, REG_ATMP1);
1377 M_AADDINT(REG_ITMP2, REG_ATMP1);
1379 /* implicit null-pointer check */
1380 M_LAX(REG_ATMP1, d);
1381 emit_store_dst(jd, iptr, d);
1385 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1386 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1387 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1388 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1389 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1390 M_INTMOVE(s2, REG_ITMP2);
1391 M_IADD_IMM(OFFSET(java_bytearray, data[0]), REG_ITMP2);
1392 M_ADRMOVE(s1, REG_ATMP1);
1393 M_AADDINT(REG_ITMP2, REG_ATMP1);
1394 /* implicit null-pointer check */
1395 M_STBX(REG_ATMP1, s3);
1398 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1399 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1400 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1401 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1402 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1403 M_INTMOVE(s2, REG_ITMP2);
1404 M_ISSL_IMM(1, REG_ITMP2);
1405 M_IADD_IMM(OFFSET(java_chararray, data[0]), REG_ITMP2);
1406 M_ADRMOVE(s1, REG_ATMP1);
1407 M_AADDINT(REG_ITMP2, REG_ATMP1);
1408 /* implicit null-pointer check */
1409 M_STHX(REG_ATMP1, s3);
1412 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1413 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1414 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1415 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1416 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1417 M_INTMOVE(s2, REG_ITMP2);
1418 M_ISSL_IMM(1, REG_ITMP2);
1419 M_IADD_IMM(OFFSET(java_shortarray, data[0]), REG_ITMP2);
1420 M_ADRMOVE(s1, REG_ATMP1);
1421 M_AADDINT(REG_ITMP2, REG_ATMP1);
1422 /* implicit null-pointer check */
1423 M_STHX(REG_ATMP1, s3);
1426 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1427 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1428 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1429 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1430 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1431 M_INTMOVE(s2, REG_ITMP2);
1432 M_ISSL_IMM(2, REG_ITMP2);
1433 M_IADD_IMM(OFFSET(java_intarray, data[0]), REG_ITMP2);
1434 M_ADRMOVE(s1, REG_ATMP1);
1435 M_AADDINT(REG_ITMP2, REG_ATMP1);
1436 /* implicit null-pointer check */
1437 M_STWX(REG_ATMP1, s3);
1440 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1441 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1442 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1443 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1445 M_INTMOVE(s2, REG_ITMP1);
1446 M_ISSL_IMM(3, REG_ITMP1);
1447 M_IADD_IMM(OFFSET(java_longarray, data[0]), REG_ITMP1);
1448 M_ADRMOVE(s1, REG_ATMP1);
1449 M_AADDINT(REG_ITMP1, REG_ATMP1);
1450 /* implicit null-pointer check */
1451 s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1452 M_LST(s3, REG_ATMP1, 0);
1455 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1456 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1457 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1458 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1459 M_INTMOVE(s2, REG_ITMP2);
1460 M_ISSL_IMM(2, REG_ITMP2);
1461 M_IADD_IMM(OFFSET(java_floatarray, data[0]), REG_ITMP2);
1462 M_ADRMOVE(s1, REG_ATMP1);
1463 M_AADDINT(REG_ITMP2, REG_ATMP1);
1464 /* implicit null-pointer check */
1465 #if !defined(ENABLE_SOFTFLOAT)
1466 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1467 M_FST(s3, REG_ATMP1, 0);
1469 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1470 M_STWX(REG_ATMP1, s3);
1474 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1475 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1476 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1477 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1478 M_INTMOVE(s2, REG_ITMP2);
1479 M_ISSL_IMM(3, REG_ITMP2);
1480 M_IADD_IMM(OFFSET(java_doublearray, data[0]), REG_ITMP2);
1481 M_ADRMOVE(s1, REG_ATMP1);
1482 M_AADDINT(REG_ITMP2, REG_ATMP1);
1483 /* implicit null-pointer check */
1484 #if !defined(ENABLE_SOFTFLOAT)
1485 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1486 M_DST(s3, REG_ATMP1, 0);
1488 s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1489 /* implicit null-pointer check */
1490 M_LST(s3, REG_ATMP1, 0);
1494 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1496 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1497 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1498 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1499 s3 = emit_load_s3(jd, iptr, REG_ATMP2);
1501 /* XXX what if array is NULL */
1502 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1504 M_AST(s1, REG_SP, 0*4);
1505 M_AST(s3, REG_SP, 1*4);
1506 M_JSR_IMM(BUILTIN_canstore);
1507 emit_exception_check(cd, iptr);
1509 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1510 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1511 s3 = emit_load_s3(jd, iptr, REG_ATMP2);
1512 M_INTMOVE(s2, REG_ITMP1);
1513 M_ISSL_IMM(2, REG_ITMP1);
1514 M_IADD_IMM(OFFSET(java_objectarray, data[0]), REG_ITMP1);
1515 M_ADRMOVE(s1, REG_ATMP1);
1516 M_AADDINT(REG_ITMP1, REG_ATMP1);
1517 /* implicit null-pointer check */
1518 M_STAX(REG_ATMP1, s3);
1523 /* METHOD INVOCATION *********************************************************/
1524 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
1525 bte = iptr->sx.s23.s3.bte;
1529 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
1530 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1531 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
1532 case ICMD_INVOKEINTERFACE:
1533 REPLACEMENT_POINT_INVOKE(cd, iptr);
1535 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1537 um = iptr->sx.s23.s3.um;
1538 md = um->methodref->parseddesc.md;
1541 lm = iptr->sx.s23.s3.fmiref->p.method;
1543 md = lm->parseddesc;
1546 s3 = md->paramcount;
1548 MCODECHECK((s3 << 1) + 64);
1550 /* copy arguments to stack */
1551 for (s3 = s3 - 1; s3 >= 0; s3--) {
1552 var = VAR(iptr->sx.s23.s2.args[s3]);
1553 /* already preallocated */
1554 if (var->flags & PREALLOC) continue;
1556 if (!md->params[s3].inmemory) assert(0);
1558 switch (var->type) {
1559 #if defined(ENABLE_SOFTFLOAT)
1563 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
1564 M_LST(d, REG_SP, md->params[s3].regoff*4);
1566 #if defined(ENABLE_SOFTFLOAT)
1570 d = emit_load(jd, iptr, var, REG_ITMP1);
1571 M_IST(d, REG_SP, md->params[s3].regoff*4);
1574 d = emit_load(jd, iptr, var, REG_ATMP1);
1575 M_AST(d, REG_SP, md->params[s3].regoff*4);
1577 #if !defined(ENABLE_SOFTFLOAT)
1579 d = emit_load(jd, iptr, var, REG_FTMP1);
1580 M_FST(d, REG_SP, md->params[s3].regoff*4);
1583 d = emit_load(jd, iptr, var, REG_FTMP1);
1584 M_DST(d, REG_SP, md->params[s3].regoff*4);
1592 /* arguments in place now */
1595 disp = (ptrint) bte->fp;
1596 d = md->returntype.type;
1599 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1600 emit_exception_check(cd, iptr);
1603 case ICMD_INVOKESPECIAL:
1604 /* adress register for sure */
1605 M_ALD(REG_ATMP1, REG_SP, 0);
1606 emit_nullpointer_check(cd, iptr, REG_ATMP1);
1608 case ICMD_INVOKESTATIC:
1610 codegen_addpatchref(cd, PATCHER_invokestatic_special, um, 0);
1612 M_AMOV_IMM(disp, REG_ATMP1);
1614 disp = lm->stubroutine;
1615 M_AMOV_IMM(disp, REG_ATMP1);
1618 /* generate the actual call */
1620 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1624 case ICMD_INVOKEVIRTUAL:
1626 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
1629 s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
1631 /* load object pointer (==argument 0) */
1632 M_ALD(REG_ATMP1, REG_SP, 0);
1633 /* implicit null-pointer check */
1634 M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_objectheader, vftbl));
1635 M_ALD(REG_ATMP3, REG_METHODPTR, s1);
1636 /* generate the actual call */
1639 case ICMD_INVOKEINTERFACE:
1641 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
1646 s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->class->index;
1647 s2 = sizeof(methodptr) * (lm - lm->class->methods);
1649 /* load object pointer (==argument 0) */
1650 M_ALD(REG_ATMP1, REG_SP, 0);
1652 /* implicit null-pointer check */
1653 M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_objectheader, vftbl));
1654 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
1655 M_ALD(REG_ATMP3, REG_METHODPTR, s2);
1657 /* generate the actual call */
1659 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1663 } /* switch (iptr->opc) */
1665 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1667 /* store return value */
1668 d = md->returntype.type;
1671 case TYPE_VOID: break;
1672 #if defined(ENABLE_SOFTFLOAT)
1676 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
1677 M_INTMOVE(REG_RESULT, s1);
1679 #if defined(ENABLE_SOFTFLOAT)
1683 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1684 M_LNGMOVE(REG_RESULT_PACKED, s1);
1687 s1 = codegen_reg_of_dst(jd, iptr, REG_ATMP1);
1688 /* all stuff is returned in %d0 */
1689 M_INT2ADRMOVE(REG_RESULT, s1);
1691 #if !defined(ENABLE_SOFTFLOAT)
1693 * for BUILTINS float values are returned in %d0,%d1
1694 * within cacao we use %fp0 for that.
1697 s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1698 if (iptr->opc == ICMD_BUILTIN) {
1699 M_INT2FLTMOVE(REG_FRESULT, s1);
1701 M_FLTMOVE(REG_FRESULT, s1);
1705 s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1706 if (iptr->opc == ICMD_BUILTIN) {
1707 M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 4);
1708 M_DLD(s1, REG_SP, rd->memuse * 4);
1710 M_DBLMOVE(REG_FRESULT, s1);
1717 if (d != TYPE_VOID) emit_store_dst(jd, iptr, s1);
1718 break; /* ICMD_INVOKE* */
1720 #if defined(ENABLE_SOFTFLOAT)
1723 case ICMD_IRETURN: /* ..., retvalue ==> ... */
1725 REPLACEMENT_POINT_RETURN(cd, iptr);
1726 s1 = emit_load_s1(jd, iptr, REG_RESULT);
1727 M_INTMOVE(s1, REG_RESULT);
1728 goto nowperformreturn;
1730 case ICMD_ARETURN: /* ..., retvalue ==> ... */
1732 REPLACEMENT_POINT_RETURN(cd, iptr);
1733 s1 = emit_load_s1(jd, iptr, REG_RESULT);
1734 assert(VAROP(iptr->s1)->type == TYPE_ADR);
1735 M_ADR2INTMOVE(s1, REG_RESULT);
1737 #ifdef ENABLE_VERIFIER
1738 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1739 unresolved_class *uc = iptr->sx.s23.s2.uc;
1741 codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
1743 #endif /* ENABLE_VERIFIER */
1744 goto nowperformreturn;
1746 #if defined(ENABLE_SOFTFLOAT)
1749 case ICMD_LRETURN: /* ..., retvalue ==> ... */
1750 REPLACEMENT_POINT_RETURN(cd, iptr);
1751 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
1752 M_LNGMOVE(s1, REG_RESULT_PACKED);
1753 goto nowperformreturn;
1755 #if !defined(ENABLE_SOFTFLOAT)
1756 case ICMD_FRETURN: /* ..., retvalue ==> ... */
1757 REPLACEMENT_POINT_RETURN(cd, iptr);
1758 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
1759 M_FLTMOVE(s1, REG_FRESULT);
1760 goto nowperformreturn;
1763 REPLACEMENT_POINT_RETURN(cd, iptr);
1764 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
1765 M_DBLMOVE(s1, REG_FRESULT);
1766 goto nowperformreturn;
1770 case ICMD_RETURN: /* ... ==> ... */
1772 REPLACEMENT_POINT_RETURN(cd, iptr);
1778 p = cd->stackframesize;
1780 /* call trace function */
1781 #if !defined(NDEBUG)
1782 emit_verbosecall_exit(jd);
1785 #if defined(ENABLE_THREADS)
1786 /* call lock_monitor_exit */
1787 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1788 M_ILD(REG_ITMP3, REG_SP, rd->memuse * 4 + 2*4);
1790 /* we need to save the proper return value */
1791 /* we do not care for the long -> doubel convert space here */
1792 switch (iptr->opc) {
1793 #if defined(ENABLE_SOFTFLOAT)
1797 M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 4);
1799 #if defined(ENABLE_SOFTFLOAT)
1804 M_IST(REG_RESULT , REG_SP, rd->memuse * 4);
1806 #if !defined(ENABLE_SOFTFLOAT)
1808 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4);
1811 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4);
1816 M_IST(REG_ITMP3, REG_SP, 0 * 4);
1817 M_JSR_IMM(LOCK_monitor_exit);
1819 /* and now restore the proper return value */
1820 switch (iptr->opc) {
1822 #if defined(ENABLE_SOFTFLOAT)
1826 M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 4);
1828 #if defined(ENABLE_SOFTFLOAT)
1833 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4);
1835 #if !defined(ENABLE_SOFTFLOAT)
1837 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4);
1840 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4);
1848 /* restore return address */
1850 if (!jd->isleafmethod) {
1851 /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
1852 may have a displacement overflow. */
1854 M_ALD(REG_ITMP1, REG_SP, p * 4 + LA_LR_OFFSET);
1858 /* restore saved registers */
1860 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
1861 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
1863 for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
1864 p--; M_ALD(rd->savadrregs[i], REG_SP, p*4);
1866 #if !defined(ENABLE_SOFTFLOAT)
1867 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
1868 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
1871 /* deallocate stack */
1872 M_AADD_IMM(cd->stackframesize*4, REG_SP);
1878 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
1879 /* val.a: (classinfo*) superclass */
1881 /* superclass is an interface:
1883 * return (sub != NULL) &&
1884 * (sub->vftbl->interfacetablelength > super->index) &&
1885 * (sub->vftbl->interfacetable[-super->index] != NULL);
1887 * superclass is a class:
1889 * return ((sub != NULL) && (0
1890 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
1891 * super->vftbl->diffvall));
1898 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1903 super = iptr->sx.s23.s3.c.cls;
1904 superindex = super->index;
1907 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
1908 CODEGEN_CRITICAL_SECTION_NEW;
1910 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1911 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1913 assert(VAROP(iptr->s1 )->type == TYPE_ADR);
1914 assert(VAROP(iptr->dst)->type == TYPE_INT);
1918 /* if class is not resolved, check which code to call */
1920 if (super == NULL) {
1922 emit_label_beq(cd, BRANCH_LABEL_1);
1924 codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
1926 M_IMOV_IMM32(0, REG_ITMP3);
1927 M_IAND_IMM(ACC_INTERFACE, REG_ITMP3);
1928 emit_label_beq(cd, BRANCH_LABEL_2);
1931 /* interface instanceof code */
1933 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
1934 if (super == NULL) {
1935 codegen_addpatchref(cd, PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0);
1938 emit_label_beq(cd, BRANCH_LABEL_3);
1941 M_ALD(REG_ATMP1, s1, OFFSET(java_objectheader, vftbl));
1942 M_ILD(REG_ITMP3, REG_ATMP1, OFFSET(vftbl_t, interfacetablelength));
1943 M_IADD_IMM(-superindex, REG_ITMP3); /* -superindex may be patched patched */
1946 M_ALD(REG_ATMP1, REG_ATMP1, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); /* patch here too! */
1952 emit_label_br(cd, BRANCH_LABEL_4);
1954 emit_label(cd, BRANCH_LABEL_3);
1957 /* class instanceof code */
1959 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
1960 if (super == NULL) {
1961 emit_label(cd, BRANCH_LABEL_2);
1963 codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
1964 M_AMOV_IMM(0, REG_ATMP2);
1966 M_AMOV_IMM(super->vftbl, REG_ATMP2);
1968 emit_label_beq(cd, BRANCH_LABEL_5);
1971 M_ALD(REG_ATMP1, s1, OFFSET(java_objectheader, vftbl));
1973 CODEGEN_CRITICAL_SECTION_START;
1975 M_ILD(REG_ITMP1, REG_ATMP1, OFFSET(vftbl_t, baseval));
1976 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval));
1977 M_ILD(REG_ITMP2, REG_ATMP2, OFFSET(vftbl_t, diffval));
1979 CODEGEN_CRITICAL_SECTION_END;
1981 M_ISUB(REG_ITMP3, REG_ITMP1);
1982 M_ICMP(REG_ITMP2, REG_ITMP1);
1985 M_TPFW; /* overlaps next instruction */
1989 emit_label(cd, BRANCH_LABEL_5);
1992 if (super == NULL) {
1993 emit_label(cd, BRANCH_LABEL_1);
1994 emit_label(cd, BRANCH_LABEL_4);
1997 emit_store_dst(jd, iptr, d);
2001 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2002 /* val.a: (classinfo*) superclass */
2004 /* superclass is an interface:
2006 * OK if ((sub == NULL) ||
2007 * (sub->vftbl->interfacetablelength > super->index) &&
2008 * (sub->vftbl->interfacetable[-super->index] != NULL));
2010 * superclass is a class:
2012 * OK if ((sub == NULL) || (0
2013 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2014 * super->vftbl->diffvall));
2017 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2018 /* object type cast-check */
2023 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2028 super = iptr->sx.s23.s3.c.cls;
2029 superindex = super->index;
2032 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2033 CODEGEN_CRITICAL_SECTION_NEW;
2035 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
2036 assert(VAROP(iptr->s1)->type == TYPE_ADR);
2038 /* if class is not resolved, check which code to call */
2040 if (super == NULL) {
2042 emit_label_beq(cd, BRANCH_LABEL_1);
2044 codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
2046 M_IMOV_IMM32(0, REG_ITMP2);
2047 M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
2048 emit_label_beq(cd, BRANCH_LABEL_2);
2051 /* interface checkcast code */
2053 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2054 if (super == NULL) {
2055 codegen_addpatchref(cd, PATCHER_checkcast_interface, iptr->sx.s23.s3.c.ref, 0);
2058 emit_label_beq(cd, BRANCH_LABEL_3);
2061 M_ALD(REG_ATMP2, s1, OFFSET(java_objectheader, vftbl));
2062 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetablelength));
2064 M_IADD_IMM(-superindex, REG_ITMP3); /* superindex patched */
2066 emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
2068 M_ALD(REG_ATMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); /* patched*/
2070 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ATMP3, s1);
2073 emit_label_br(cd, BRANCH_LABEL_4);
2075 emit_label(cd, BRANCH_LABEL_3);
2078 /* class checkcast code */
2080 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2081 if (super == NULL) {
2082 emit_label(cd, BRANCH_LABEL_2);
2084 codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
2085 M_AMOV_IMM(0, REG_ATMP3);
2087 M_AMOV_IMM(super->vftbl, REG_ATMP3);
2089 emit_label_beq(cd, BRANCH_LABEL_5);
2092 M_ALD(REG_ATMP2, s1, OFFSET(java_objectheader, vftbl));
2094 CODEGEN_CRITICAL_SECTION_START;
2096 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval)); /* REG_ITMP3 == sub->vftbl->baseval */
2097 M_ILD(REG_ITMP1, REG_ATMP3, OFFSET(vftbl_t, baseval));
2098 M_ILD(REG_ITMP2, REG_ATMP3, OFFSET(vftbl_t, diffval));
2100 CODEGEN_CRITICAL_SECTION_END;
2102 M_ISUB(REG_ITMP1, REG_ITMP3);
2103 M_ICMP(REG_ITMP2, REG_ITMP3); /* XXX was CMPU */
2105 emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1); /* XXX was BRANCH_GT */
2108 emit_label(cd, BRANCH_LABEL_5);
2111 if (super == NULL) {
2112 emit_label(cd, BRANCH_LABEL_1);
2113 emit_label(cd, BRANCH_LABEL_4);
2116 d = codegen_reg_of_dst(jd, iptr, s1);
2118 /* array type cast-check */
2120 s1 = emit_load_s1(jd, iptr, REG_ATMP2);
2122 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2123 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
2124 M_AMOV_IMM(0, REG_ATMP1);
2126 M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
2131 M_JSR_IMM(BUILTIN_arraycheckcast);
2132 M_AADD_IMM(2*4, REG_SP); /* pop arguments off stack */
2134 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2136 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2137 d = codegen_reg_of_dst(jd, iptr, s1);
2139 assert(VAROP(iptr->dst)->type == TYPE_ADR);
2141 emit_store_dst(jd, iptr, d);
2144 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2147 branch_target_t *table;
2149 table = iptr->dst.table;
2151 l = iptr->sx.s23.s2.tablelow;
2152 i = iptr->sx.s23.s3.tablehigh;
2154 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2155 M_INTMOVE(s1, REG_ITMP1);
2156 if (l != 0) M_ISUB_IMM(l, REG_ITMP1);
2161 M_ICMP_IMM(i - 1, REG_ITMP1);
2162 emit_bugt(cd, table[0].block);
2164 /* build jump table top down and use address of lowest entry */
2168 dseg_add_target(cd, table->block);
2172 /* length of dataseg after last dseg_add_target is used by load */
2173 M_AMOV_IMM(0, REG_ATMP2);
2176 M_ISSL_IMM(2, REG_ITMP1); /* index * 4 == offset in table */
2177 M_AADDINT(REG_ITMP1, REG_ATMP2); /* offset in table */
2178 M_AADD_IMM(-(cd->dseglen), REG_ATMP2); /* start of table in dseg */
2179 M_ALD(REG_ATMP1, REG_ATMP2, 0);
2186 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2189 lookup_target_t *lookup;
2191 lookup = iptr->dst.lookup;
2193 i = iptr->sx.s23.s2.lookupcount;
2195 MCODECHECK((i<<2)+8);
2196 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2199 M_ICMP_IMM(lookup->value, s1);
2200 emit_beq(cd, lookup->target.block);
2204 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2209 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2211 /* check for negative sizes and copy sizes to stack if necessary */
2212 MCODECHECK((iptr->s1.argcount << 1) + 64);
2214 for (s1 = iptr->s1.argcount; --s1 >= 0;) {
2215 var = VAR(iptr->sx.s23.s2.args[s1]);
2217 /* Already Preallocated? */
2218 if (!(var->flags & PREALLOC)) {
2219 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2220 M_IST(s2, REG_SP, (s1 + 3) * 4);
2224 /* a0 = dimension count */
2225 M_IMOV_IMM(iptr->s1.argcount, REG_ITMP1);
2226 M_IST(REG_ITMP1, REG_SP, 0*4);
2228 /* a1 = arraydescriptor */
2229 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2230 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
2231 M_AMOV_IMM(0, REG_ATMP1);
2233 M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
2235 M_AST(REG_ATMP1, REG_SP, 1*4);
2237 /* a2 = pointer to dimensions = stack pointer */
2238 M_AMOV(REG_SP, REG_ATMP1);
2239 M_AADD_IMM(3*4, REG_ATMP1);
2240 M_AST(REG_ATMP1, REG_SP, 2*4);
2242 M_JSR_IMM(BUILTIN_multianewarray);
2244 /* check for exception before result assignment */
2245 emit_exception_check(cd, iptr);
2247 assert(VAROP(iptr->dst)->type == TYPE_ADR);
2248 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2249 M_INT2ADRMOVE(REG_RESULT, d);
2250 emit_store_dst(jd, iptr, d);
2256 printf("UNKNOWN OPCODE %d\n", iptr->opc);
2257 exceptions_throw_internalerror("Unknown ICMD %d during code generation", iptr->opc);
2261 } /* for each instruction */
2262 } /* if (btpre->flags >= BBREACHED) */
2263 } /* for each basic block */
2265 dseg_createlinenumbertable(cd);
2267 /* generate stubs */
2268 emit_patcher_stubs(jd);
2269 REPLACEMENT_EMIT_STUBS(jd);
2275 /* codegen_emit_stub_compiler **************************************************
2277 Emits a stub routine which calls the compiler.
2279 *******************************************************************************/
2281 void codegen_emit_stub_compiler(jitdata *jd)
2286 /* get required compiler data */
2291 /* code for the stub */
2293 M_AMOV_IMM(m, REG_ATMP1);
2294 M_AMOV_IMM(asm_call_jit_compiler, REG_ATMP3);
2299 /* codegen_emit_stub_native ****************************************************
2301 Emits a stub routine which calls a native method.
2303 *******************************************************************************/
2305 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
2312 s4 nativeparams, i, j, t, s1, s2;
2314 /* get required compiler data */
2322 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
2324 /* calc stackframe size */
2325 cd->stackframesize = sizeof(stackframeinfo) / SIZEOF_VOID_P +
2326 sizeof(localref_table) / SIZEOF_VOID_P +
2328 1 + /* functionptr */
2329 4; /* args for codegen_start_native_call */
2331 /* create method header */
2332 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2333 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
2334 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2335 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2336 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2337 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2338 (void) dseg_addlinenumbertablesize(cd);
2339 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2341 /* print call trace */
2342 #if !defined(NDEBUG)
2343 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
2344 emit_verbosecall_enter(jd);
2349 M_AADD_IMM(-(cd->stackframesize*4), REG_SP);
2351 /* get function address (this must happen before the stackframeinfo) */
2352 #if !defined(WITH_STATIC_CLASSPATH)
2354 codegen_addpatchref(cd, PATCHER_resolve_native_function, m, 0);
2357 M_AMOV_IMM(f, REG_ATMP2); /* do not move this line, the patcher is needed */
2359 M_AST(REG_ATMP2, REG_SP, 4 * 4);
2361 /* put arguments for codegen_start_native_call onto stack */
2362 /* void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra) */
2364 M_AMOV(REG_SP, REG_ATMP1);
2365 M_AADD_IMM(cd->stackframesize * 4, REG_ATMP1);
2367 M_ALD(REG_ATMP3, REG_ATMP1, 0 * 4);
2368 M_AST(REG_ATMP3, REG_SP, 3 * 4); /* ra */
2370 M_AST(REG_ATMP1, REG_SP, 0 * 4); /* datasp */
2372 M_AADD_IMM(1 * 4 , REG_ATMP1);
2373 M_AST(REG_ATMP1, REG_SP, 2 * 4); /* sp */
2375 M_AMOV_IMM(0, REG_ATMP2); /* 0 needs to patched */
2376 dseg_adddata(cd); /* this patches it */
2378 M_AST(REG_ATMP2, REG_SP, 1 * 4); /* pv */
2380 M_JSR_IMM(codegen_start_native_call);
2382 /* load function pointer */
2383 M_ALD(REG_ATMP2, REG_SP, 4 * 4);
2385 /* copy arguments into stackframe */
2386 for (i = md->paramcount -1, j = i + nativeparams; i >= 0; --i, --j) {
2387 t = md->paramtypes[i].type;
2388 /* all arguments via stack */
2389 assert(md->params[i].inmemory);
2391 s1 = (md->params[i].regoff + cd->stackframesize + 1) * 4;
2392 s2 = nmd->params[j].regoff * 4;
2394 /* simply copy argument stack */
2395 M_ILD(REG_ITMP1, REG_SP, s1);
2396 M_IST(REG_ITMP1, REG_SP, s2);
2397 if (IS_2_WORD_TYPE(t)) {
2398 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
2399 M_IST(REG_ITMP1, REG_SP, s2 + 4);
2403 /* for static function class as second arg */
2404 if (m->flags & ACC_STATIC) {
2405 M_AMOV_IMM(m->class, REG_ATMP1);
2406 M_AST(REG_ATMP1, REG_SP, 1 * 4);
2408 /* env ist first argument */
2409 M_AMOV_IMM(_Jv_env, REG_ATMP1);
2410 M_AST(REG_ATMP1, REG_SP, 0 * 4);
2412 /* call the native function */
2415 /* save return value */
2416 switch (md->returntype.type) {
2417 case TYPE_VOID: break;
2419 #if defined(ENABLE_SOFTFLOAT)
2423 M_IST(REG_D1, REG_SP, 2 * 4);
2426 #if defined(ENABLE_SOFTFLOAT)
2431 M_IST(REG_D0, REG_SP, 1 * 4);
2434 #if !defined(ENABLE_SOFTFLOAT)
2435 /* natives return float arguments in %d0, %d1, cacao expects them in %fp0 */
2437 M_INT2FLTMOVE(REG_D0, REG_D0);
2438 M_FST(REG_D0, REG_SP, 1 * 4);
2441 /* to convert %d0, %d1 to dbl we need 2 memory slots
2442 * it is safe reuse argument stack slots here */
2443 M_IST(REG_D0, REG_SP, 1 * 4);
2444 M_IST(REG_D1, REG_SP, 2 * 4);
2445 /*M_DST(REG_D0, REG_SP, 1 * 4);*/
2451 /* print call trace */
2452 #if ! defined(NDEBUG)
2453 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
2454 emit_verbosecall_exit(jd);
2457 /* remove native stackframe info */
2458 /* therefore we call: java_objectheader *codegen_finish_native_call(u1 *datasp) */
2460 M_AMOV(REG_SP, REG_ATMP3);
2461 M_AADD_IMM(cd->stackframesize * 4, REG_ATMP3);
2462 M_AST(REG_ATMP3, REG_SP, 0 * 4); /* datasp */
2463 M_JSR_IMM(codegen_finish_native_call);
2465 M_INT2ADRMOVE(REG_RESULT, REG_ATMP1);
2466 /* restore return value */
2467 switch (md->returntype.type) {
2468 case TYPE_VOID: break;
2470 #if defined(ENABLE_SOFTFLOAT)
2474 M_ILD(REG_D1, REG_SP, 2 * 4);
2476 #if defined(ENABLE_SOFTFLOAT)
2481 M_ILD(REG_D0, REG_SP, 1 * 4);
2484 #if !defined(ENABLE_SOFTFLOAT)
2486 M_FLD(REG_D0, REG_SP, 1 * 4);
2489 M_DLD(REG_D0, REG_SP, 1 * 4);
2494 /* restore saved registers */
2496 M_AADD_IMM(cd->stackframesize*4, REG_SP);
2497 /* check for exception */
2502 /* handle exception, REG_ATMP1 already contains exception object, REG_ATMP2 holds address */
2504 M_ALD(REG_ATMP2_XPC, REG_SP, 0); /* take return address as faulting instruction */
2505 M_AADD_IMM(-2, REG_ATMP2_XPC); /* which is off by 2 */
2506 M_JMP_IMM(asm_handle_nat_exception);
2508 /* should never be reached from within jit code*/
2511 /* generate patcher stub call code */
2512 emit_patcher_stubs(jd);
2517 * These are local overrides for various environment variables in Emacs.
2518 * Please do not remove this and leave it at the end of the file, where
2519 * Emacs will automagically detect them.
2520 * ---------------------------------------------------------------------
2523 * indent-tabs-mode: t
2527 * vim:noexpandtab:sw=4:ts=4: