1 /* src/vm/jit/powerpc64/codegen.c - machine code generator for 64-bit PowerPC
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
39 #include "vm/jit/powerpc64/arch.h"
40 #include "vm/jit/powerpc64/codegen.h"
42 #include "mm/memory.h"
44 #include "native/localref.h"
45 #include "native/native.h"
47 #include "threads/lock-common.h"
49 #include "vm/builtin.h"
50 #include "vm/exceptions.h"
51 #include "vm/global.h"
52 #include "vm/stringlocal.h"
55 #include "vm/jit/abi.h"
56 #include "vm/jit/abi-asm.h"
57 #include "vm/jit/md.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/codegen-common.h"
60 #include "vm/jit/dseg.h"
61 #include "vm/jit/emit-common.h"
62 #include "vm/jit/jit.h"
63 #include "vm/jit/parse.h"
64 #include "vm/jit/patcher-common.h"
65 #include "vm/jit/reg.h"
66 #include "vm/jit/replace.h"
67 #include "vm/jit/stacktrace.h"
69 #include "vmcore/loader.h"
70 #include "vmcore/options.h"
72 #if defined(ENABLE_LSRA)
73 # include "vm/jit/allocator/lsra.h"
77 /* codegen_emit ****************************************************************
79 Generates machine code.
81 *******************************************************************************/
83 bool codegen_emit(jitdata *jd)
89 s4 len, s1, s2, s3, d, disp;
96 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
97 unresolved_method *um;
98 builtintable_entry *bte;
102 unresolved_field *uf;
105 /* get required compiler data */
112 /* prevent compiler warnings */
126 /* space to save used callee saved registers */
128 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
129 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
131 cd->stackframesize = rd->memuse + savedregs_num;
133 #if defined(ENABLE_THREADS)
134 /* space to save argument of monitor_enter and Return Values to survive */
135 /* monitor_exit. The stack position for the argument can not be shared */
136 /* with place to save the return register on PPC64, since both values */
138 if (checksync && code_is_synchronized(code)) {
139 /* reserve 2 slots for long/double return values for monitorexit */
140 cd->stackframesize += 2;
145 /* create method header */
147 /* align stack to 16-bytes */
150 /* if (!m->isleafmethod || opt_verbosecall) */
151 /* stackframesize = (stackframesize + 3) & ~3;
153 /* else if (m->isleafmethod && (stackframesize == LA_WORD_SIZE)) */
154 /* stackframesize = 0; */
156 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
157 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
159 /* IsSync contains the offset relative to the stack pointer for the
160 argument of monitor_exit used in the exception handler. Since the
161 offset could be zero and give a wrong meaning of the flag it is
164 /* XXX Remove this "offset by one". */
166 code->synchronizedoffset = (rd->memuse + 1) * 8;
168 /* REMOVEME: We still need it for exception handling in assembler. */
170 if (code_is_leafmethod(code))
171 (void) dseg_add_unique_s4(cd, 1);
173 (void) dseg_add_unique_s4(cd, 0);
175 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
176 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
178 dseg_addlinenumbertablesize(cd);
180 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
182 /* create exception table */
184 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
185 dseg_add_target(cd, ex->start);
186 dseg_add_target(cd, ex->end);
187 dseg_add_target(cd, ex->handler);
188 (void) dseg_add_unique_address(cd, ex->catchtype.any);
191 /* create stack frame (if necessary) */
193 if (!code_is_leafmethod(code)) {
195 M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
198 if (cd->stackframesize)
199 M_STDU(REG_SP, REG_SP, -cd->stackframesize * 8);
201 /* save return address and used callee saved registers */
203 p = cd->stackframesize;
204 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
205 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
207 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
208 p --; M_DST(rd->savfltregs[i], REG_SP, p * 8);
211 /* take arguments out of register or stack frame */
215 for (p = 0, l = 0; p < md->paramcount; p++) {
216 t = md->paramtypes[p].type;
217 varindex = jd->local_map[l*5 + t];
219 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
221 if (varindex == UNUSED)
225 s1 = md->params[p].regoff;
227 if (IS_INT_LNG_TYPE(t)) {
228 if (!md->params[p].inmemory) {
229 if (!IS_INMEMORY(var->flags))
230 M_INTMOVE(s1, var->vv.regoff);
232 M_LST(s1, REG_SP, var->vv.regoff);
235 if (!IS_INMEMORY(var->flags))
236 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
238 var->vv.regoff = cd->stackframesize * 8 + s1;
242 if (!md->params[p].inmemory) {
243 if (!IS_INMEMORY(var->flags))
244 M_FLTMOVE(s1, var->vv.regoff);
246 M_DST(s1, REG_SP, var->vv.regoff);
249 if (!(var->flags & INMEMORY)) {
250 if (IS_2_WORD_TYPE(t))
251 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
253 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
256 var->vv.regoff = cd->stackframesize * 8 + s1;
261 /* save monitorenter argument */
263 #if defined(ENABLE_THREADS)
265 if (checksync && code_is_synchronized(code)) {
267 /* stackoffset for argument used for LOCK_monitor_exit */
270 #if !defined (NDEBUG)
271 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
272 M_AADD_IMM(REG_SP, -((LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT) * 8), REG_SP);
274 for (p = 0; p < INT_ARG_CNT; p++)
275 M_LST(abi_registers_integer_argument[p], REG_SP, LA_SIZE + PA_SIZE + p * 8);
277 for (p = 0; p < FLT_ARG_CNT; p++)
278 M_DST(abi_registers_float_argument[p], REG_SP, LA_SIZE + PA_SIZE + (INT_ARG_CNT + p) * 8);
280 /* used for LOCK_monitor_exit, adopt size because we created another stackframe */
281 s1 += (LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT);
285 p = dseg_add_functionptr(cd, LOCK_monitor_enter);
286 M_ALD(REG_ITMP3, REG_PV, p);
287 M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
290 /* get or test the lock object */
292 if (m->flags & ACC_STATIC) {
293 p = dseg_add_address(cd, &m->class->object.header);
294 M_ALD(REG_A0, REG_PV, p);
299 M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
302 M_AST(REG_A0, REG_SP, s1 * 8); /* rd->memuse * 8 */
306 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
307 for (p = 0; p < INT_ARG_CNT; p++)
308 M_LLD(abi_registers_integer_argument[p], REG_SP, LA_SIZE + PA_SIZE + p * 8);
310 for (p = 0; p < FLT_ARG_CNT; p++)
311 M_DLD(abi_registers_float_argument[p], REG_SP, LA_SIZE + PA_SIZE + (INT_ARG_CNT + p) * 8);
313 M_AADD_IMM(REG_SP, (LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT) * 8, REG_SP);
319 /* call trace function */
320 #if !defined (NDEBUG)
321 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
322 emit_verbosecall_enter(jd);
327 /* end of header generation */
329 /* create replacement points */
331 REPLACEMENT_POINTS_INIT(cd, jd);
333 /* walk through all basic blocks */
335 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
337 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
339 if (bptr->flags >= BBREACHED) {
341 /* branch resolving */
342 codegen_resolve_branchrefs(cd, bptr);
344 /* handle replacement points */
346 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
348 /* copy interface registers to their destination */
353 #if defined(ENABLE_LSRA)
357 var = VAR(bptr->invars[len]);
358 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
359 /* d = reg_of_var(m, var, REG_ITMP1); */
360 if (!(var->flags & INMEMORY))
364 M_INTMOVE(REG_ITMP1, d);
365 emit_store(jd, NULL, var, d);
372 var = VAR(bptr->invars[len]);
373 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
374 d = codegen_reg_of_var(0, var, REG_ITMP1);
375 M_INTMOVE(REG_ITMP1, d);
376 emit_store(jd, NULL, var, d);
379 assert((var->flags & INOUT));
383 #if defined(ENABLE_LSRA)
386 /* walk through all instructions */
391 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
392 if (iptr->line != currentline) {
393 dseg_addlinenumber(cd, iptr->line);
394 currentline = iptr->line;
397 MCODECHECK(128); /* an instruction usually needs < 64 words */
400 case ICMD_NOP: /* ... ==> ... */
401 case ICMD_POP: /* ..., value ==> ... */
402 case ICMD_POP2: /* ..., value, value ==> ... */
405 case ICMD_INLINE_START:
407 REPLACEMENT_POINT_INLINE_START(cd, iptr);
410 case ICMD_INLINE_BODY:
412 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
413 dseg_addlinenumber_inline_start(cd, iptr);
414 dseg_addlinenumber(cd, iptr->line);
417 case ICMD_INLINE_END:
419 dseg_addlinenumber_inline_end(cd, iptr);
420 dseg_addlinenumber(cd, iptr->line);
423 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
425 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
428 emit_nullpointer_check(cd, iptr, s1);
431 /* constant operations ************************************************/
433 case ICMD_ICONST: /* ... ==> ..., constant */
435 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
436 ICONST(d, iptr->sx.val.i);
437 emit_store_dst(jd, iptr, d);
440 case ICMD_LCONST: /* ... ==> ..., constant */
442 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
443 LCONST(d, iptr->sx.val.l);
444 emit_store_dst(jd, iptr, d);
447 case ICMD_FCONST: /* ... ==> ..., constant */
449 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
450 a = dseg_add_float(cd, iptr->sx.val.f);
452 emit_store_dst(jd, iptr, d);
455 case ICMD_DCONST: /* ... ==> ..., constant */
457 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
458 a = dseg_add_double(cd, iptr->sx.val.d);
460 emit_store_dst(jd, iptr, d);
463 case ICMD_ACONST: /* ... ==> ..., constant */
465 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
467 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
468 disp = dseg_add_unique_address(cd, iptr->sx.val.c.ref);
469 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
473 disp = dseg_add_address(cd, iptr->sx.val.anyptr);
475 M_ALD(d, REG_PV, disp);
476 emit_store_dst(jd, iptr, d);
480 /* load/store/copy/move operations ************************************/
482 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
483 case ICMD_ALOAD: /* s1.localindex = local variable */
487 case ICMD_ISTORE: /* ..., value ==> ... */
498 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
503 /* integer operations *************************************************/
505 case ICMD_INEG: /* ..., value ==> ..., - value */
506 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
507 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
510 emit_store_dst(jd, iptr, d);
514 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
515 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
517 emit_store_dst(jd, iptr, d);
521 case ICMD_I2L: /* ..., value ==> ..., value */
523 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
524 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
526 emit_store_dst(jd, iptr, d);
529 case ICMD_L2I: /* ..., value ==> ..., value */
531 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
532 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
534 emit_store_dst(jd, iptr, d);
537 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
539 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
540 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
542 emit_store_dst(jd, iptr, d);
545 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
547 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
548 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
550 emit_store_dst(jd, iptr, d);
553 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
555 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
556 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
558 emit_store_dst(jd, iptr, d);
562 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
564 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
565 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
566 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
569 emit_store_dst(jd, iptr, d);
575 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
576 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
577 if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) {
578 M_IADD_IMM(s1, iptr->sx.val.i, d);
580 ICONST(REG_ITMP2, iptr->sx.val.i);
581 M_IADD(s1, REG_ITMP2, d);
584 emit_store_dst(jd, iptr, d);
587 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
589 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
590 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
591 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
593 emit_store_dst(jd, iptr, d);
596 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
597 /* sx.val.l = constant */
599 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
600 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
602 if ((iptr->sx.val.l >= -32768) && (iptr->sx.val.l <= 32767)) {
603 M_LADD_IMM(s1, iptr->sx.val.l, d);
605 LCONST(REG_ITMP2, iptr->sx.val.l);
606 M_LADD(s1, REG_ITMP2, d);
608 emit_store_dst(jd, iptr, d);
611 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
613 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
614 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
615 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
618 emit_store_dst(jd, iptr, d);
621 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
622 /* sx.val.i = constant */
624 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
625 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
626 if ((iptr->sx.val.i >= -32767) && (iptr->sx.val.i <= 32768)) {
627 M_IADD_IMM(s1, -iptr->sx.val.i, d);
629 ICONST(REG_ITMP2, iptr->sx.val.i);
630 M_SUB(s1, REG_ITMP2, d);
633 emit_store_dst(jd, iptr, d);
636 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
638 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
639 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
640 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
642 emit_store_dst(jd, iptr, d);
645 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
646 /* sx.val.l = constant */
648 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
649 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
651 if ((iptr->sx.val.l >= -32767) && (iptr->sx.val.l <= 32767)) {
652 M_LADD_IMM(s1, -iptr->sx.val.l, d);
654 LCONST(REG_ITMP2, iptr->sx.val.l);
655 M_SUB(s1, REG_ITMP2, d);
657 emit_store_dst(jd, iptr, d);
661 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
662 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
663 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
664 emit_arithmetic_check(cd, iptr, s2);
668 emit_store_dst(jd, iptr, d);
671 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
673 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
674 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
675 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
676 emit_arithmetic_check(cd, iptr, s2);
679 /* we need to test if divident was 0x8000000000000, bit OV is set in XER in this case */
680 /* we only need to check this if we did a LDIV, not for IDIV */
682 M_ANDIS(REG_ITMP2, 0x4000, REG_ITMP2); /* test OV */
684 M_MOV(s1, d); /* java specs says result == dividend */
685 emit_store_dst(jd, iptr, d);
689 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
690 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
691 emit_arithmetic_check(cd, iptr, s2);
693 M_DIV(s1, s2, REG_ITMP3);
694 M_MUL(REG_ITMP3, s2, REG_ITMP2);
695 M_SUB(s1, REG_ITMP2, REG_ITMP3);
696 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
699 emit_store_dst(jd, iptr, d);
703 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
704 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
705 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
706 emit_arithmetic_check(cd, iptr, s2);
708 M_DIV(s1, s2, REG_ITMP3);
709 /* we need to test if divident was 0x8000000000000, bit OV is set in XER in this case */
710 /* we only need to check this if we did a LDIV, not for IDIV */
712 M_ANDIS(REG_ITMP2, 0x4000, REG_ITMP2); /* test OV */
714 LCONST(REG_ITMP3, 0); /* result == 0 in this case */
716 M_MUL(REG_ITMP3, s2, REG_ITMP2);
717 M_SUB(s1, REG_ITMP2, REG_ITMP3);
718 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
721 emit_store_dst(jd, iptr, d);
725 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
726 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
727 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
728 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
731 emit_store_dst(jd, iptr, d);
735 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
736 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
737 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
739 emit_store_dst(jd, iptr, d);
742 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
743 /* sx.val.i = constant */
745 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
746 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
747 if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
748 M_MUL_IMM(s1, iptr->sx.val.i, d);
750 ICONST(REG_ITMP3, iptr->sx.val.i);
751 M_MUL(s1, REG_ITMP3, d);
754 emit_store_dst(jd, iptr, d);
757 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
758 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
759 if ((iptr->sx.val.l >= -32767) && (iptr->sx.val.l <= 32767))
760 M_MUL_IMM(s1, iptr->sx.val.l, d);
762 LCONST(REG_ITMP3, iptr->sx.val.l);
763 M_MUL(s1, REG_ITMP3, d);
765 emit_store_dst(jd, iptr, d);
768 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
770 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
771 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
772 M_SRA_IMM(s1, iptr->sx.val.i, d);
775 emit_store_dst(jd, iptr, d);
778 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
780 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
781 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
782 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
783 M_AND_IMM(s2, 0x1f, REG_ITMP3);
784 M_SLL(s1, REG_ITMP3, d);
786 emit_store_dst(jd, iptr, d);
789 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
790 /* sx.val.i = constant */
792 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
793 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
794 M_SLL_IMM(s1, iptr->sx.val.i & 0x1f, d);
796 emit_store_dst(jd, iptr, d);
799 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
801 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
802 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
803 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
804 M_AND_IMM(s2, 0x1f, REG_ITMP3);
805 M_SRA(s1, REG_ITMP3, d);
806 emit_store_dst(jd, iptr, d);
809 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
810 /* sx.val.i = constant */
812 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
813 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
814 M_SRA_IMM(s1, iptr->sx.val.i & 0x1f, d);
815 emit_store_dst(jd, iptr, d);
818 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
820 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
821 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
822 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
823 M_AND_IMM(s2, 0x1f, REG_ITMP2);
824 M_MOV(s1, REG_ITMP1);
825 M_CLR_HIGH(REG_ITMP1);
826 M_SRL(REG_ITMP1, REG_ITMP2, d);
827 M_EXTSW(d,d); /* for the case it was shift 0 bits */
828 emit_store_dst(jd, iptr, d);
831 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
832 /* sx.val.i = constant */
834 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
835 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
836 if (iptr->sx.val.i & 0x1f) {
837 M_MOV(s1, REG_ITMP1);
838 M_CLR_HIGH(REG_ITMP1);
839 M_SRA_IMM(REG_ITMP1, iptr->sx.val.i & 0x1f, d);
843 emit_store_dst(jd, iptr, d);
847 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
848 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
849 M_SLL_IMM(s1, iptr->sx.val.i & 0x3f, d);
850 emit_store_dst(jd, iptr, d);
853 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
854 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
855 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
856 M_AND_IMM(s2, 0x3f, REG_ITMP2);
857 M_SLL(s1, REG_ITMP2, d);
858 emit_store_dst(jd, iptr, d);
861 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
862 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
863 M_SRA_IMM(s1, iptr->sx.val.i & 0x3f, d);
864 emit_store_dst(jd, iptr, d);
867 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
868 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
869 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
870 M_AND_IMM(s2, 0x3f, REG_ITMP2);
871 M_SRA(s1, REG_ITMP2, d);
872 emit_store_dst(jd, iptr, d);
874 case ICMD_LUSHRCONST:
875 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
876 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
877 M_SRL_IMM(s1, iptr->sx.val.i & 0x3f, d);
878 emit_store_dst(jd, iptr, d);
881 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
882 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
883 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
884 M_AND_IMM(s2, 0x3f, REG_ITMP2);
885 M_SRL(s1, REG_ITMP2, d);
886 emit_store_dst(jd, iptr, d);
889 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
890 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
891 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
892 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
895 emit_store_dst(jd, iptr, d);
899 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
900 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
901 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
903 emit_store_dst(jd, iptr, d);
906 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
907 /* sx.val.i = constant */
909 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
910 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
911 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535)) {
912 M_AND_IMM(s1, iptr->sx.val.i, d);
915 else if (iptr->sx.val.i == 0xffffff) {
916 M_RLWINM(s1, 0, 8, 31, d);
920 ICONST(REG_ITMP3, iptr->sx.val.i);
921 M_AND(s1, REG_ITMP3, d);
923 emit_store_dst(jd, iptr, d);
926 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
927 /* sx.val.l = constant */
929 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
930 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
931 if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 65535))
932 M_AND_IMM(s1, iptr->sx.val.l, d);
934 else if (iptr->sx.val.l == 0xffffff) {
935 M_RLWINM(s1, 0, 8, 31, d);
939 LCONST(REG_ITMP3, iptr->sx.val.l);
940 M_AND(s1, REG_ITMP3, d);
942 emit_store_dst(jd, iptr, d);
945 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
946 /* sx.val.i = constant */
947 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
948 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
950 /* fast division, result in REG_ITMP3) */
951 M_SRA_IMM(s1, iptr->sx.val.i, REG_ITMP3);
952 M_ADDZE(REG_ITMP3, REG_ITMP3);
954 M_SUB(s1, REG_ITMP3, d);
956 emit_store_dst(jd, iptr, d);
960 M_MOV(s1, REG_ITMP2);
962 M_BGE(1 + 3*(iptr->sx.val.i >= 32768));
963 if (iptr->sx.val.i >= 32768) {
964 M_ADDIS(REG_ZERO, iptr->sx.val.i >> 16, REG_ITMP2);
965 M_EXTSW(REG_ITMP2, REG_ITMP2);
966 M_OR_IMM(REG_ITMP2, iptr->sx.val.i, REG_ITMP2);
967 M_IADD(s1, REG_ITMP2, REG_ITMP2);
969 M_IADD_IMM(s1, iptr->sx.val.i, REG_ITMP2);
972 int b=0, m = iptr->sx.val.i;
975 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
977 M_SUB(s1, REG_ITMP2, d);
979 emit_store_dst(jd, iptr, d);
983 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
984 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
985 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
986 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
989 emit_store_dst(jd, iptr, d);
994 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
995 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
996 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
998 emit_store_dst(jd, iptr, d);
1001 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1002 /* sx.val.i = constant */
1004 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1005 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1006 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535))
1007 M_OR_IMM(s1, iptr->sx.val.i, d);
1009 ICONST(REG_ITMP3, iptr->sx.val.i);
1010 M_OR(s1, REG_ITMP3, d);
1012 emit_store_dst(jd, iptr, d);
1015 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1016 /* sx.val.l = constant */
1018 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1019 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1020 if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 65535))
1021 M_OR_IMM(s1, iptr->sx.val.l, d);
1023 LCONST(REG_ITMP3, iptr->sx.val.l);
1024 M_OR(s1, REG_ITMP3, d);
1026 emit_store_dst(jd, iptr, d);
1030 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1033 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1034 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1035 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1037 emit_store_dst(jd, iptr, d);
1040 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1041 /* sx.val.i = constant */
1043 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1044 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1045 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535))
1046 M_XOR_IMM(s1, iptr->sx.val.i, d);
1048 ICONST(REG_ITMP3, iptr->sx.val.i);
1049 M_XOR(s1, REG_ITMP3, d);
1051 emit_store_dst(jd, iptr, d);
1054 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1055 /* sx.val.l = constant */
1057 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1058 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1059 if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 65535))
1060 M_XOR_IMM(s1, iptr->sx.val.l, d);
1062 LCONST(REG_ITMP3, iptr->sx.val.l);
1063 M_XOR(s1, REG_ITMP3, d);
1065 emit_store_dst(jd, iptr, d);
1068 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1070 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1071 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1072 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1073 /* XXX implement me!!! */
1074 vm_abort("codegen: implement ICMD_LCMP!");
1075 emit_store_dst(jd, iptr, d);
1080 /* floating operations ************************************************/
1082 case ICMD_FNEG: /* ..., value ==> ..., - value */
1084 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1085 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1087 emit_store_dst(jd, iptr, d);
1090 case ICMD_DNEG: /* ..., value ==> ..., - value */
1092 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1093 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1095 emit_store_dst(jd, iptr, d);
1098 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1100 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1101 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1102 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1104 emit_store_dst(jd, iptr, d);
1107 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1109 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1110 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1111 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1113 emit_store_dst(jd, iptr, d);
1116 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1118 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1119 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1120 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1122 emit_store_dst(jd, iptr, d);
1125 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1127 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1128 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1129 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1131 emit_store_dst(jd, iptr, d);
1134 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1136 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1137 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1138 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1140 emit_store_dst(jd, iptr, d);
1143 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1145 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1146 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1147 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1149 emit_store_dst(jd, iptr, d);
1152 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1154 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1155 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1156 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1158 emit_store_dst(jd, iptr, d);
1161 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1163 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1164 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1165 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1167 emit_store_dst(jd, iptr, d);
1170 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1173 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1174 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1176 disp = dseg_add_float(cd, 0.0);
1177 M_FLD(REG_FTMP2, REG_PV, disp);
1178 M_FCMPU(s1, REG_FTMP2);
1180 disp = dseg_add_unique_s4(cd, 0);
1181 M_CVTDL_C(s1, REG_FTMP1);
1182 M_LDA(REG_ITMP1, REG_PV, disp);
1183 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1184 M_ILD(d, REG_PV, disp);
1185 emit_store_dst(jd, iptr, d);
1188 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1190 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1191 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1193 emit_store_dst(jd, iptr, d);
1196 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1198 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1199 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1201 emit_store_dst(jd, iptr, d);
1204 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1205 case ICMD_DCMPL: /* == => 0, < => 1, > => -1 */
1207 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1208 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1209 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1211 M_IADD_IMM(REG_ZERO, -1, d);
1214 M_IADD_IMM(REG_ZERO, 0, d);
1216 M_IADD_IMM(REG_ZERO, 1, d);
1217 emit_store_dst(jd, iptr, d);
1220 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1221 case ICMD_DCMPG: /* == => 0, < => 1, > => -1 */
1223 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1224 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1225 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1227 M_IADD_IMM(REG_ZERO, 1, d);
1230 M_IADD_IMM(REG_ZERO, 0, d);
1232 M_IADD_IMM(REG_ZERO, -1, d);
1233 emit_store_dst(jd, iptr, d);
1237 /* memory operations **************************************************/
1239 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1241 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1242 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1243 emit_nullpointer_check(cd, iptr, s1);
1244 M_ILD(d, s1, OFFSET(java_array_t, size));
1245 emit_store_dst(jd, iptr, d);
1248 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1250 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1251 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1252 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1253 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1254 M_IADD_IMM(s2, OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
1255 /* implicit null-pointer check */
1256 M_LBZX(d, s1, REG_ITMP2);
1258 emit_store_dst(jd, iptr, d);
1261 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1263 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1264 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1265 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1266 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1267 M_SLL_IMM(s2, 1, REG_ITMP2);
1268 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray_t, data[0]), REG_ITMP2);
1269 /* implicit null-pointer check */
1270 M_LHZX(d, s1, REG_ITMP2);
1271 emit_store_dst(jd, iptr, d);
1274 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1276 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1277 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1278 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1279 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1280 M_SLL_IMM(s2, 1, REG_ITMP2);
1281 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
1282 /* implicit null-pointer check */
1283 M_LHAX(d, s1, REG_ITMP2);
1284 emit_store_dst(jd, iptr, d);
1287 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1289 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1290 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1291 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1292 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1293 M_SLL_IMM(s2, 2, REG_ITMP2);
1294 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray_t, data[0]), REG_ITMP2);
1295 /* implicit null-pointer check */
1296 M_LWAX(d, s1, REG_ITMP2);
1297 emit_store_dst(jd, iptr, d);
1300 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1302 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1303 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1304 d = codegen_reg_of_dst(jd, iptr, PACK_REGS(REG_ITMP2, REG_ITMP1));
1305 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1306 M_SLL_IMM(s2, 3, REG_ITMP2);
1307 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1308 /* implicit null-pointer check */
1309 M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray_t, data[0]));
1310 emit_store_dst(jd, iptr, d);
1313 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1315 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1316 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1317 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1318 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1319 M_SLL_IMM(s2, 2, REG_ITMP2);
1320 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
1321 /* implicit null-pointer check */
1322 M_LFSX(d, s1, REG_ITMP2);
1323 emit_store_dst(jd, iptr, d);
1326 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1328 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1329 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1330 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1331 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1332 M_SLL_IMM(s2, 3, REG_ITMP2);
1333 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
1334 /* implicit null-pointer check */
1335 M_LFDX(d, s1, REG_ITMP2);
1336 emit_store_dst(jd, iptr, d);
1339 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1341 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1342 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1343 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1344 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1345 M_SLL_IMM(s2, 3, REG_ITMP2);
1346 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray_t, data[0]), REG_ITMP2);
1347 /* implicit null-pointer check */
1348 M_ALDX(d, s1, REG_ITMP2);
1349 emit_store_dst(jd, iptr, d);
1353 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1355 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1356 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1357 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1358 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1359 M_IADD_IMM(s2, OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
1360 /* implicit null-pointer check */
1361 M_STBX(s3, s1, REG_ITMP2);
1364 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1366 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1367 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1368 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1369 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1370 M_SLL_IMM(s2, 1, REG_ITMP2);
1371 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray_t, data[0]), REG_ITMP2);
1372 /* implicit null-pointer check */
1373 M_STHX(s3, s1, REG_ITMP2);
1376 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1378 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1379 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1380 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1381 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1382 M_SLL_IMM(s2, 1, REG_ITMP2);
1383 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
1384 M_STHX(s3, s1, REG_ITMP2);
1387 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1389 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1390 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1391 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1392 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1393 M_SLL_IMM(s2, 2, REG_ITMP2);
1394 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray_t, data[0]), REG_ITMP2);
1395 /* implicit null-pointer check */
1396 M_STWX(s3, s1, REG_ITMP2);
1399 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1401 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1402 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1403 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1404 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1405 M_SLL_IMM(s2, 3, REG_ITMP2);
1406 M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray_t, data[0]), REG_ITMP2);
1407 /* implicit null-pointer check */
1408 M_LSTX(s3, s1, REG_ITMP2);
1411 case ICMD_FASTORE: /* ..., 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_FTMP3);
1417 M_SLL_IMM(s2, 2, REG_ITMP2);
1418 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
1419 /* implicit null-pointer check */
1420 M_STFSX(s3, s1, REG_ITMP2);
1423 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1425 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1426 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1427 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1428 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1429 M_SLL_IMM(s2, 3, REG_ITMP2);
1430 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
1431 /* implicit null-pointer check */
1432 M_STFDX(s3, s1, REG_ITMP2);
1435 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1437 s1 = emit_load_s1(jd, iptr, REG_A0);
1438 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1439 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1440 s3 = emit_load_s3(jd, iptr, REG_A1);
1442 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1443 M_ALD(REG_ITMP3, REG_PV, disp);
1444 M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
1447 M_INTMOVE(s1, REG_A0);
1448 M_INTMOVE(s3, REG_A1);
1451 emit_arraystore_check(cd, iptr);
1453 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1454 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1455 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1456 M_SLL_IMM(s2, 3, REG_ITMP2);
1457 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray_t, data[0]), REG_ITMP2);
1458 /* implicit null-pointer check */
1459 M_ASTX(s3, s1, REG_ITMP2);
1463 case ICMD_GETSTATIC: /* ... ==> ..., value */
1465 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1466 uf = iptr->sx.s23.s3.uf;
1467 fieldtype = uf->fieldref->parseddesc.fd->type;
1468 disp = dseg_add_unique_address(cd, NULL);
1470 patcher_add_patch_ref(jd, PATCHER_get_putstatic,
1471 iptr->sx.s23.s3.uf, disp);
1475 fi = iptr->sx.s23.s3.fmiref->p.field;
1476 fieldtype = fi->type;
1477 disp = dseg_add_address(cd, fi->value);
1479 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1480 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
1484 M_ALD(REG_ITMP1, REG_PV, disp);
1485 switch (fieldtype) {
1487 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1488 M_ILD_INTERN(d, REG_ITMP1, 0);
1491 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1492 M_LLD(d, REG_ITMP1, 0);
1495 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1496 M_ALD_INTERN(d, REG_ITMP1, 0);
1499 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1500 M_FLD_INTERN(d, REG_ITMP1, 0);
1503 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1504 M_DLD_INTERN(d, REG_ITMP1, 0);
1507 emit_store_dst(jd, iptr, d);
1510 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1513 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1514 uf = iptr->sx.s23.s3.uf;
1515 fieldtype = uf->fieldref->parseddesc.fd->type;
1516 disp = dseg_add_unique_address(cd, NULL);
1518 patcher_add_patch_ref(jd, PATCHER_get_putstatic,
1519 iptr->sx.s23.s3.uf, disp);
1522 fi = iptr->sx.s23.s3.fmiref->p.field;
1523 fieldtype = fi->type;
1524 disp = dseg_add_address(cd, fi->value);
1526 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1527 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
1531 M_ALD(REG_ITMP1, REG_PV, disp);
1532 switch (fieldtype) {
1534 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1535 M_IST_INTERN(s1, REG_ITMP1, 0);
1538 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1539 M_LST_INTERN(s1, REG_ITMP1, 0);
1542 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1543 M_AST_INTERN(s1, REG_ITMP1, 0);
1546 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1547 M_FST_INTERN(s1, REG_ITMP1, 0);
1550 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1551 M_DST_INTERN(s1, REG_ITMP1, 0);
1557 case ICMD_GETFIELD: /* ... ==> ..., value */
1559 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1561 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1562 uf = iptr->sx.s23.s3.uf;
1563 fieldtype = uf->fieldref->parseddesc.fd->type;
1566 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1569 fi = iptr->sx.s23.s3.fmiref->p.field;
1570 fieldtype = fi->type;
1574 /* implicit null-pointer check */
1575 switch (fieldtype) {
1577 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1581 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1585 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1589 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1593 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1597 emit_store_dst(jd, iptr, d);
1600 case ICMD_PUTFIELD: /* ..., value ==> ... */
1602 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1604 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1605 uf = iptr->sx.s23.s3.uf;
1606 fieldtype = uf->fieldref->parseddesc.fd->type;
1610 fi = iptr->sx.s23.s3.fmiref->p.field;
1611 fieldtype = fi->type;
1615 if (IS_INT_LNG_TYPE(fieldtype)) {
1616 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1619 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1621 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1622 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1626 /* implicit null-pointer check */
1627 switch (fieldtype) {
1629 M_IST(s2, s1, disp);
1632 M_LST(s2, s1, disp);
1635 M_AST(s2, s1, disp);
1638 M_FST(s2, s1, disp);
1641 M_DST(s2, s1, disp);
1647 /* branch operations **************************************************/
1649 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1651 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1652 M_LNGMOVE(s1, REG_ITMP1_XPTR);
1654 #ifdef ENABLE_VERIFIER
1655 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1656 patcher_add_patch_ref(jd, PATCHER_resolve_class,
1657 iptr->sx.s23.s2.uc, 0);
1659 #endif /* ENABLE_VERIFIER */
1661 disp = dseg_add_functionptr(cd, asm_handle_exception);
1662 M_ALD(REG_ITMP2, REG_PV, disp);
1665 if (code_is_leafmethod(code))
1666 M_MFLR(REG_ITMP3); /* save LR */
1668 M_BL(0); /* get current PC */
1669 M_MFLR(REG_ITMP2_XPC);
1671 if (code_is_leafmethod(code))
1672 M_MTLR(REG_ITMP3); /* restore LR */
1674 M_RTS; /* jump to CTR */
1678 case ICMD_GOTO: /* ... ==> ... */
1679 case ICMD_RET: /* ... ==> ... */
1681 emit_br(cd, iptr->dst.block);
1685 case ICMD_JSR: /* ... ==> ... */
1687 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1691 case ICMD_IFNULL: /* ..., value ==> ... */
1693 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1695 emit_beq(cd, iptr->dst.block);
1698 case ICMD_IFNONNULL: /* ..., value ==> ... */
1700 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1702 emit_bne(cd, iptr->dst.block);
1710 case ICMD_IFEQ: /* ..., value ==> ... */
1712 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1713 if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
1714 M_CMPI(s1, iptr->sx.val.i);
1716 ICONST(REG_ITMP2, iptr->sx.val.i);
1717 M_CMP(s1, REG_ITMP2);
1719 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
1722 case ICMD_IF_LEQ: /* ..., value ==> ... */
1723 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1724 LCONST(REG_ITMP2, iptr->sx.val.l);
1725 M_CMP(s1, REG_ITMP2);
1726 emit_beq(cd, iptr->dst.block);
1728 case ICMD_IF_LLT: /* ..., value ==> ... */
1729 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1730 LCONST(REG_ITMP2, iptr->sx.val.l);
1731 M_CMP(s1, REG_ITMP2);
1732 emit_blt(cd, iptr->dst.block);
1734 case ICMD_IF_LLE: /* ..., value ==> ... */
1735 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1736 LCONST(REG_ITMP2, iptr->sx.val.l);
1737 M_CMP(s1, REG_ITMP2);
1738 emit_ble(cd, iptr->dst.block);
1741 case ICMD_IF_LNE: /* ..., value ==> ... */
1742 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1743 LCONST(REG_ITMP2, iptr->sx.val.l);
1744 M_CMP(s1, REG_ITMP2);
1745 emit_bne(cd, iptr->dst.block);
1747 case ICMD_IF_LGE: /* ..., value ==> ... */
1748 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1749 LCONST(REG_ITMP2, iptr->sx.val.l);
1750 M_CMP(s1, REG_ITMP2);
1751 emit_bge(cd, iptr->dst.block);
1753 case ICMD_IF_LGT: /* ..., value ==> ... */
1754 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1755 LCONST(REG_ITMP2, iptr->sx.val.l);
1756 M_CMP(s1, REG_ITMP2);
1757 emit_bgt(cd, iptr->dst.block);
1759 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1760 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
1761 case ICMD_IF_LCMPEQ:
1763 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1764 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1766 emit_beq(cd, iptr->dst.block);
1769 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
1770 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
1771 case ICMD_IF_LCMPNE:
1773 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1774 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1776 emit_bne(cd, iptr->dst.block);
1780 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
1781 case ICMD_IF_LCMPLT:
1783 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1784 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1786 emit_blt(cd, iptr->dst.block);
1789 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
1790 case ICMD_IF_LCMPGT:
1792 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1793 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1795 emit_bgt(cd, iptr->dst.block);
1798 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
1799 case ICMD_IF_LCMPLE:
1801 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1802 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1804 emit_ble(cd, iptr->dst.block);
1807 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
1808 case ICMD_IF_LCMPGE:
1810 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1811 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1813 emit_bge(cd, iptr->dst.block);
1817 case ICMD_LRETURN: /* ..., retvalue ==> ... */
1818 case ICMD_IRETURN: /* ..., retvalue ==> ... */
1820 REPLACEMENT_POINT_RETURN(cd, iptr);
1821 s1 = emit_load_s1(jd, iptr, REG_RESULT);
1822 M_LNGMOVE(s1, REG_RESULT);
1823 goto nowperformreturn;
1825 case ICMD_ARETURN: /* ..., retvalue ==> ... */
1827 REPLACEMENT_POINT_RETURN(cd, iptr);
1828 s1 = emit_load_s1(jd, iptr, REG_RESULT);
1829 M_LNGMOVE(s1, REG_RESULT);
1831 #ifdef ENABLE_VERIFIER
1832 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1833 patcher_add_patch_ref(jd, PATCHER_resolve_class,
1834 iptr->sx.s23.s2.uc, 0);
1836 #endif /* ENABLE_VERIFIER */
1838 goto nowperformreturn;
1840 case ICMD_FRETURN: /* ..., retvalue ==> ... */
1843 REPLACEMENT_POINT_RETURN(cd, iptr);
1844 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
1845 M_FLTMOVE(s1, REG_FRESULT);
1846 goto nowperformreturn;
1848 case ICMD_RETURN: /* ... ==> ... */
1850 REPLACEMENT_POINT_RETURN(cd, iptr);
1856 p = cd->stackframesize;
1858 /* call trace function */
1860 #if !defined(NDEBUG)
1861 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
1862 emit_verbosecall_exit(jd);
1865 #if defined(ENABLE_THREADS)
1866 if (checksync && code_is_synchronized(code)) {
1867 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
1868 M_ALD(REG_ITMP3, REG_PV, disp);
1869 M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
1872 /* we need to save the proper return value */
1874 switch (iptr->opc) {
1879 M_LST(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
1882 M_FST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1885 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1889 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
1892 /* and now restore the proper return value */
1894 switch (iptr->opc) {
1899 M_LLD(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
1902 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1905 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1911 /* restore return address */
1913 if (!code_is_leafmethod(code)) {
1914 /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
1915 may have a displacement overflow. */
1917 M_ALD(REG_ITMP1, REG_SP, p * 8 + LA_LR_OFFSET);
1921 /* restore saved registers */
1923 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
1924 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
1926 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
1927 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
1930 /* deallocate stack */
1932 if (cd->stackframesize)
1933 M_LDA(REG_SP, REG_SP, cd->stackframesize * 8);
1941 case ICMD_TABLESWITCH: /* ..., index ==> ... */
1944 branch_target_t *table;
1946 table = iptr->dst.table;
1948 l = iptr->sx.s23.s2.tablelow;
1949 i = iptr->sx.s23.s3.tablehigh;
1951 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1953 M_INTMOVE(s1, REG_ITMP1);
1954 } else if (l <= 32768) {
1955 M_LDA(REG_ITMP1, s1, -l);
1957 ICONST(REG_ITMP2, l);
1958 M_SUB(s1, REG_ITMP2, REG_ITMP1);
1961 /* number of targets */
1966 M_CMPUI(REG_ITMP1, i - 1);
1967 emit_bgt(cd, table[0].block);
1969 /* build jump table top down and use address of lowest entry */
1974 dseg_add_target(cd, table->block);
1978 /* length of dataseg after last dseg_add_unique_target is used by load */
1980 M_SLL_IMM(REG_ITMP1, 3, REG_ITMP1);
1981 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
1982 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
1990 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
1993 lookup_target_t *lookup;
1995 lookup = iptr->dst.lookup;
1997 i = iptr->sx.s23.s2.lookupcount;
1999 MCODECHECK((i<<3)+8);
2000 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2002 val = lookup->value;
2003 if ((val >= -32768) && (val <= 32767)) {
2007 a = dseg_add_s4(cd, val);
2008 M_ILD(REG_ITMP2, REG_PV, a);
2009 M_CMP(s1, REG_ITMP2);
2011 emit_beq(cd, lookup->target.block);
2015 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2022 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2024 bte = iptr->sx.s23.s3.bte;
2028 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2029 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2030 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2031 case ICMD_INVOKEINTERFACE:
2033 REPLACEMENT_POINT_INVOKE(cd, iptr);
2035 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2037 um = iptr->sx.s23.s3.um;
2038 md = um->methodref->parseddesc.md;
2041 lm = iptr->sx.s23.s3.fmiref->p.method;
2043 md = lm->parseddesc;
2047 s3 = md->paramcount;
2049 MCODECHECK((s3 << 2) + 128);
2051 /* copy arguments to registers or stack location */
2053 for (s3 = s3 - 1; s3 >= 0; s3--) {
2054 var = VAR(iptr->sx.s23.s2.args[s3]);
2055 d = md->params[s3].regoff;
2057 if (var->flags & PREALLOC)
2060 if (IS_INT_LNG_TYPE(var->type)) {
2061 if (!md->params[s3].inmemory) {
2062 s1 = emit_load(jd, iptr, var, d);
2066 s1 = emit_load(jd, iptr, var, REG_ITMP1);
2067 M_LST(s1, REG_SP, d);
2071 if (!md->params[s3].inmemory) {
2072 s1 = emit_load(jd, iptr, var, d);
2076 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2077 M_DST(s1, REG_SP, d);
2082 switch (iptr->opc) {
2084 if (bte->stub == NULL) {
2085 disp = dseg_add_functionptr(cd, bte->fp);
2086 M_ALD(REG_PV, REG_PV, disp);
2087 M_ALD(REG_PV, REG_PV, 0); /* TOC */
2090 disp = dseg_add_functionptr(cd, bte->stub);
2091 M_ALD(REG_PV, REG_PV, disp);
2094 /* generate the actual call */
2097 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2098 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2100 M_LDA(REG_PV, REG_ITMP1, -disp);
2103 case ICMD_INVOKESPECIAL:
2104 emit_nullpointer_check(cd, iptr, REG_A0);
2107 case ICMD_INVOKESTATIC:
2109 disp = dseg_add_unique_address(cd, um);
2111 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2114 disp = dseg_add_address(cd, lm->stubroutine);
2116 M_ALD(REG_PV, REG_PV, disp);
2118 /* generate the actual call */
2122 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2123 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2125 M_LDA(REG_PV, REG_ITMP1, -disp);
2128 case ICMD_INVOKEVIRTUAL:
2130 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2133 s1 = OFFSET(vftbl_t, table[0]) +
2134 sizeof(methodptr) * lm->vftblindex;
2137 /* implicit null-pointer check */
2138 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2139 M_ALD(REG_PV, REG_METHODPTR, s1);
2141 /* generate the actual call */
2145 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2146 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2148 M_LDA(REG_PV, REG_ITMP1, -disp);
2151 case ICMD_INVOKEINTERFACE:
2153 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2159 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2160 sizeof(methodptr*) * lm->class->index;
2162 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2165 /* implicit null-pointer check */
2166 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2167 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2168 M_ALD(REG_PV, REG_METHODPTR, s2);
2170 /* generate the actual call */
2174 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2175 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2177 M_LDA(REG_PV, REG_ITMP1, -disp);
2181 /* store return value */
2183 d = md->returntype.type;
2185 if (d != TYPE_VOID) {
2186 if (IS_INT_LNG_TYPE(d)) {
2187 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2188 M_MOV(REG_RESULT, s1);
2191 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2192 M_FLTMOVE(REG_FRESULT, s1);
2194 emit_store_dst(jd, iptr, s1);
2198 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2199 /* val.a: (classinfo*) superclass */
2201 /* superclass is an interface:
2203 * OK if ((sub == NULL) ||
2204 * (sub->vftbl->interfacetablelength > super->index) &&
2205 * (sub->vftbl->interfacetable[-super->index] != NULL));
2207 * superclass is a class:
2209 * OK if ((sub == NULL) || (0
2210 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2211 * super->vftbl->diffvall));
2214 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2215 /* object type cast-check */
2220 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2225 super = iptr->sx.s23.s3.c.cls;
2226 superindex = super->index;
2229 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2230 CODEGEN_CRITICAL_SECTION_NEW;
2233 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2235 /* if class is not resolved, check which code to call */
2237 if (super == NULL) {
2239 emit_label_beq(cd, BRANCH_LABEL_1);
2240 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2242 patcher_add_patch_ref(jd,
2243 PATCHER_resolve_classref_to_flags,
2244 iptr->sx.s23.s3.c.ref,
2247 M_ILD(REG_ITMP2, REG_PV, disp);
2248 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2250 emit_label_beq(cd, BRANCH_LABEL_2);
2253 /* interface checkcast code */
2255 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2256 if (super == NULL) {
2257 patcher_add_patch_ref(jd,
2258 PATCHER_checkcast_interface,
2259 iptr->sx.s23.s3.c.ref,
2263 emit_label_beq(cd, BRANCH_LABEL_3);
2266 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2267 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2268 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2269 emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
2270 M_ALD(REG_ITMP3, REG_ITMP2,
2271 OFFSET(vftbl_t, interfacetable[0]) -
2272 superindex * sizeof(methodptr*));
2274 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
2276 if (super == NULL) {
2277 emit_label_br(cd, BRANCH_LABEL_4);
2279 emit_label(cd, BRANCH_LABEL_3);
2283 /* class checkcast code */
2285 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2286 if (super == NULL) {
2287 emit_label(cd, BRANCH_LABEL_2);
2289 disp = dseg_add_unique_address(cd, NULL);
2290 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2291 iptr->sx.s23.s3.c.ref,
2294 disp = dseg_add_address(cd, super->vftbl);
2296 emit_label_beq(cd, BRANCH_LABEL_5);
2299 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2301 CODEGEN_CRITICAL_SECTION_START;
2303 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2304 M_ALD(REG_ITMP2, REG_PV, disp);
2305 if (s1 != REG_ITMP1) {
2306 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2307 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2309 CODEGEN_CRITICAL_SECTION_END;
2311 M_SUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2312 M_EXTSW(REG_ITMP3, REG_ITMP3);
2314 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2315 M_SUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2316 M_EXTSW(REG_ITMP3, REG_ITMP3);
2317 M_ALD(REG_ITMP2, REG_PV, disp);
2318 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2320 CODEGEN_CRITICAL_SECTION_END;
2323 M_CMPU(REG_ITMP3, REG_ITMP2);
2324 emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1);
2327 emit_label(cd, BRANCH_LABEL_5);
2330 if (super == NULL) {
2331 emit_label(cd, BRANCH_LABEL_1);
2332 emit_label(cd, BRANCH_LABEL_4);
2334 d = codegen_reg_of_dst(jd, iptr, s1);
2337 /* array type cast-check */
2339 s1 = emit_load_s1(jd, iptr, REG_A0);
2340 M_INTMOVE(s1, REG_A0);
2343 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2344 disp = dseg_add_unique_address(cd, NULL);
2345 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2346 iptr->sx.s23.s3.c.ref,
2349 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2352 M_ALD(REG_A1, REG_PV, disp);
2353 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2354 M_ALD(REG_ITMP2, REG_PV, disp);
2355 M_ALD(REG_ITMP2, REG_ITMP2, 0); /* TOC */
2359 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2361 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2362 d = codegen_reg_of_dst(jd, iptr, s1);
2365 emit_store_dst(jd, iptr, d);
2369 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2370 /* val.a: (classinfo*) superclass */
2372 /* superclass is an interface:
2374 * return (sub != NULL) &&
2375 * (sub->vftbl->interfacetablelength > super->index) &&
2376 * (sub->vftbl->interfacetable[-super->index] != NULL);
2378 * superclass is a class:
2380 * return ((sub != NULL) && (0
2381 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2382 * super->vftbl->diffvall));
2389 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2394 super = iptr->sx.s23.s3.c.cls;
2395 superindex = super->index;
2398 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2399 CODEGEN_CRITICAL_SECTION_NEW;
2402 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2403 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2405 M_MOV(s1, REG_ITMP1);
2411 /* if class is not resolved, check which code to call */
2413 if (super == NULL) {
2415 emit_label_beq(cd, BRANCH_LABEL_1);
2416 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2418 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2419 iptr->sx.s23.s3.c.ref, disp);
2421 M_ILD(REG_ITMP3, REG_PV, disp);
2422 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
2423 emit_label_beq(cd, BRANCH_LABEL_2);
2426 /* interface instanceof code */
2428 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2429 if (super == NULL) {
2430 patcher_add_patch_ref(jd,
2431 PATCHER_instanceof_interface,
2432 iptr->sx.s23.s3.c.ref, 0);
2436 emit_label_beq(cd, BRANCH_LABEL_3);
2439 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2440 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2441 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2443 M_ALD(REG_ITMP1, REG_ITMP1,
2444 OFFSET(vftbl_t, interfacetable[0]) -
2445 superindex * sizeof(methodptr*));
2448 M_IADD_IMM(REG_ZERO, 1, d);
2450 if (super == NULL) {
2451 emit_label_br(cd, BRANCH_LABEL_4);
2453 emit_label(cd, BRANCH_LABEL_3);
2457 /* class instanceof code */
2459 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2461 if (super == NULL) {
2462 emit_label(cd, BRANCH_LABEL_2);
2464 disp = dseg_add_unique_address(cd, NULL);
2465 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2466 iptr->sx.s23.s3.c.ref,
2470 disp = dseg_add_address(cd, super->vftbl);
2472 emit_label_beq(cd, BRANCH_LABEL_5);
2475 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2476 M_ALD(REG_ITMP2, REG_PV, disp);
2478 CODEGEN_CRITICAL_SECTION_START;
2480 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2481 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2482 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2484 CODEGEN_CRITICAL_SECTION_END;
2486 M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2487 M_EXTSW(REG_ITMP1, REG_ITMP1);
2488 M_CMPU(REG_ITMP1, REG_ITMP2);
2491 M_IADD_IMM(REG_ZERO, 1, d);
2494 emit_label(cd, BRANCH_LABEL_5);
2497 if (super == NULL) {
2498 emit_label(cd, BRANCH_LABEL_1);
2499 emit_label(cd, BRANCH_LABEL_4);
2502 emit_store_dst(jd, iptr, d);
2506 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2508 /* check for negative sizes and copy sizes to stack if necessary */
2510 MCODECHECK((iptr->s1.argcount << 2) + 128);
2512 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2514 var = VAR(iptr->sx.s23.s2.args[s1]);
2516 /* copy SAVEDVAR sizes to stack */
2518 if (!(var->flags & PREALLOC)) {
2519 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2520 #if defined(__DARWIN__)
2521 M_LST(s2, REG_SP, LA_SIZE + (s1 + INT_ARG_CNT) * 8);
2523 M_LST(s2, REG_SP, LA_SIZE + (s1 + 3) * 8);
2528 /* a0 = dimension count */
2530 ICONST(REG_A0, iptr->s1.argcount);
2532 /* is patcher function set? */
2534 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2535 disp = dseg_add_unique_address(cd, NULL);
2537 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2538 iptr->sx.s23.s3.c.ref, disp);
2540 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2543 /* a1 = arraydescriptor */
2545 M_ALD(REG_A1, REG_PV, disp);
2547 /* a2 = pointer to dimensions = stack pointer */
2549 #if defined(__DARWIN__)
2550 M_LDA(REG_A2, REG_SP, LA_SIZE + INT_ARG_CNT * 8);
2552 M_LDA(REG_A2, REG_SP, LA_SIZE + 3 * 8);
2555 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2556 M_ALD(REG_ITMP3, REG_PV, disp);
2557 M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
2561 /* check for exception before result assignment */
2562 emit_exception_check(cd, iptr);
2564 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2565 M_INTMOVE(REG_RESULT, d);
2566 emit_store_dst(jd, iptr, d);
2570 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
2575 } /* for instruction */
2577 } /* if (bptr -> flags >= BBREACHED) */
2578 } /* for basic block */
2580 dseg_createlinenumbertable(cd);
2582 /* generate traps */
2584 emit_patcher_traps(jd);
2586 /* everything's ok */
2592 /* codegen_emit_stub_native ****************************************************
2594 Emits a stub routine which calls a native method.
2596 *******************************************************************************/
2598 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2609 /* get required compiler data */
2615 /* set some variables */
2619 /* calculate stackframe size */
2621 cd->stackframesize =
2622 sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
2623 sizeof(localref_table) / SIZEOF_VOID_P +
2624 4 + /* 4 stackframeinfo arguments (darwin)*/
2628 /* cd->stackframesize = (cd->stackframesize + 3) & ~3;*/ /* keep stack 16-byte aligned */
2630 /* create method header */
2632 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2633 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
2634 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2635 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2636 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2637 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2638 (void) dseg_addlinenumbertablesize(cd);
2639 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2644 M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET);
2645 M_STDU(REG_SP, REG_SP, -(cd->stackframesize * 8));
2647 /* save integer and float argument registers */
2649 for (i = 0; i < md->paramcount; i++) {
2650 if (!md->params[i].inmemory) {
2651 s1 = md->params[i].regoff;
2653 switch (md->paramtypes[i].type) {
2657 M_LST(s1, REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + i * 8);
2661 M_DST(s1, REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + i * 8);
2667 /* create native stack info */
2669 M_MOV(REG_SP, REG_A0);
2670 M_MOV(REG_PV, REG_A1);
2671 disp = dseg_add_functionptr(cd, codegen_start_native_call);
2672 M_ALD(REG_ITMP1, REG_PV, disp);
2673 M_ALD(REG_ITMP1, REG_ITMP1, 0); /* TOC */
2677 /* remember class argument */
2679 if (m->flags & ACC_STATIC)
2680 M_MOV(REG_RESULT, REG_ITMP3);
2682 /* restore integer and float argument registers */
2684 for (i = 0; i < md->paramcount; i++) {
2685 if (!md->params[i].inmemory) {
2686 s1 = md->params[i].regoff;
2688 switch (md->paramtypes[i].type) {
2692 M_LLD(s1, REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + i * 8);
2696 M_DLD(s1, REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + i * 8);
2702 /* copy or spill arguments to new locations */
2704 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2705 t = md->paramtypes[i].type;
2707 if (IS_INT_LNG_TYPE(t)) {
2708 if (!md->params[i].inmemory) {
2709 s1 = md->params[i].regoff;
2710 s2 = nmd->params[j].regoff;
2712 if (!nmd->params[j].inmemory)
2715 M_LST(s1, REG_SP, s2);
2718 s1 = md->params[i].regoff + cd->stackframesize * 8;
2719 s2 = nmd->params[j].regoff;
2721 M_LLD(REG_ITMP1, REG_SP, s1);
2722 M_LST(REG_ITMP1, REG_SP, s2);
2726 /* We only copy spilled float arguments, as the float
2727 argument registers keep unchanged. */
2729 if (md->params[i].inmemory) {
2730 s1 = md->params[i].regoff + cd->stackframesize * 8;
2731 s2 = nmd->params[j].regoff;
2733 M_DLD(REG_FTMP1, REG_SP, s1);
2735 if (IS_2_WORD_TYPE(t))
2736 M_DST(REG_FTMP1, REG_SP, s2);
2738 M_FST(REG_FTMP1, REG_SP, s2 + 4);
2743 /* Handle native Java methods. */
2745 if (m->flags & ACC_NATIVE) {
2746 /* put class into second argument register */
2748 if (m->flags & ACC_STATIC)
2749 M_MOV(REG_ITMP3, REG_A1);
2751 /* put env into first argument register */
2753 disp = dseg_add_unique_address(cd, _Jv_env);
2754 M_ALD(REG_A0, REG_PV, disp);
2757 /* Call the native function. */
2758 /* native functions have a different TOC for sure */
2760 M_AST(REG_TOC, REG_SP, 40); /* save old TOC */
2761 disp = dseg_add_functionptr(cd, f);
2762 M_ALD(REG_ITMP3, REG_PV, disp);
2763 M_ALD(REG_TOC, REG_ITMP3, 8); /* load TOC from func. descriptor */
2764 M_ALD(REG_ITMP3, REG_ITMP3, 0);
2767 M_ALD(REG_TOC, REG_SP, 40); /* restore TOC */
2769 /* save return value */
2771 if (md->returntype.type != TYPE_VOID) {
2772 if (IS_INT_LNG_TYPE(md->returntype.type)) {
2773 M_LST(REG_RESULT, REG_SP, LA_SIZE + PA_SIZE + 2 * 8);
2776 M_DST(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 2 * 8);
2780 /* remove native stackframe info */
2782 M_MOV(REG_SP, REG_A0);
2783 M_MOV(REG_PV, REG_A1);
2784 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
2785 M_ALD(REG_ITMP1, REG_PV, disp);
2786 M_ALD(REG_ITMP1, REG_ITMP1, 0); /* XXX what about TOC? */
2789 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
2791 /* restore return value */
2793 if (md->returntype.type != TYPE_VOID) {
2794 if (IS_INT_LNG_TYPE(md->returntype.type)) {
2795 M_LLD(REG_RESULT, REG_SP, LA_SIZE + PA_SIZE + 2 * 8);
2798 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 2 * 8);
2802 M_ALD(REG_ITMP2_XPC, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
2803 M_MTLR(REG_ITMP2_XPC);
2804 M_LDA(REG_SP, REG_SP, cd->stackframesize * 8); /* remove stackframe */
2806 /* check for exception */
2808 M_TST(REG_ITMP1_XPTR);
2809 M_BNE(1); /* if no exception then return */
2813 /* handle exception */
2815 M_LADD_IMM(REG_ITMP2_XPC, -4, REG_ITMP2_XPC); /* exception address */
2817 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
2818 M_ALD(REG_ITMP3, REG_PV, disp);
2827 * These are local overrides for various environment variables in Emacs.
2828 * Please do not remove this and leave it at the end of the file, where
2829 * Emacs will automagically detect them.
2830 * ---------------------------------------------------------------------
2833 * indent-tabs-mode: t
2837 * vim:noexpandtab:sw=4:ts=4: