1 /* src/vm/jit/mips/codegen.c - machine code generator for MIPS
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
30 Changes: Christian Thalinger
32 Contains the codegenerator for an MIPS (R4000 or higher) processor.
33 This module generates MIPS machine code for a sequence of
34 intermediate code commands (ICMDs).
36 $Id: codegen.c 2531 2005-05-31 10:30:31Z twisti $
48 #include "cacao/cacao.h"
49 #include "native/native.h"
50 #include "vm/builtin.h"
51 #include "vm/stringlocal.h"
52 #include "vm/jit/asmpart.h"
53 #include "vm/jit/jit.h"
55 #include "vm/jit/lsra.h"
58 #include "vm/jit/patcher.h"
59 #include "vm/jit/reg.h"
60 #include "vm/jit/mips/codegen.h"
61 #include "vm/jit/mips/arch.h"
62 #include "vm/jit/mips/types.h"
65 /* *****************************************************************************
67 Datatypes and Register Allocations:
68 -----------------------------------
70 On 64-bit-machines (like the MIPS) all operands are stored in the
71 registers in a 64-bit form, even when the correspondig JavaVM operands
72 only need 32 bits. This is done by a canonical representation:
74 32-bit integers are allways stored as sign-extended 64-bit values (this
75 approach is directly supported by the MIPS architecture and is very easy
78 32-bit-floats are stored in a 64-bit double precision register by simply
79 expanding the exponent and mantissa with zeroes. (also supported by the
85 The calling conventions and the layout of the stack is explained in detail
86 in the documention file: calling.doc
88 *******************************************************************************/
91 /* register descripton - array ************************************************/
93 /* #define REG_RES 0 reserved register for OS or code generator */
94 /* #define REG_RET 1 return value register */
95 /* #define REG_EXC 2 exception value register (only old jit) */
96 /* #define REG_SAV 3 (callee) saved register */
97 /* #define REG_TMP 4 scratch temporary register (caller saved) */
98 /* #define REG_ARG 5 argument register (caller saved) */
100 /* #define REG_END -1 last entry in tables */
102 static int nregdescint[] = {
103 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
104 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
105 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
106 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
109 /* for use of reserved registers, see comment above */
111 static int nregdescfloat[] = {
112 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
113 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
114 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
115 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
118 /* for use of reserved registers, see comment above */
121 /* Include independent code generation stuff -- include after register */
122 /* descriptions to avoid extern definitions. */
124 #include "vm/jit/codegen.inc"
125 #include "vm/jit/reg.inc"
127 #include "vm/jit/lsra.inc"
131 /* NullPointerException handlers and exception handling initialisation */
133 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
134 void thread_restartcriticalsection(ucontext_t *uc)
137 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[CTX_EPC])) != NULL)
138 uc->uc_mcontext.gregs[CTX_EPC] = (u8) critical;
142 /* NullPointerException signal handler for hardware null pointer check */
144 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
149 java_objectheader *xptr;
151 struct ucontext *_uc = (struct ucontext *) _p;
152 mcontext_t *sigctx = &_uc->uc_mcontext;
153 struct sigaction act;
155 instr = *((s4 *) (sigctx->gregs[CTX_EPC]));
156 faultaddr = sigctx->gregs[(instr >> 21) & 0x1f];
158 if (faultaddr == 0) {
159 /* Reset signal handler - necessary for SysV, does no harm for BSD */
161 act.sa_sigaction = catch_NullPointerException;
162 act.sa_flags = SA_SIGINFO;
163 sigaction(sig, &act, NULL);
166 sigaddset(&nsig, sig);
167 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
169 xptr = new_nullpointerexception();
171 sigctx->gregs[REG_ITMP1_XPTR] = (u8) xptr;
172 sigctx->gregs[REG_ITMP2_XPC] = sigctx->gregs[CTX_EPC];
173 sigctx->gregs[CTX_EPC] = (u8) asm_handle_exception;
176 faultaddr += (long) ((instr << 16) >> 16);
178 throw_cacao_exception_exit(string_java_lang_InternalError,
179 "faulting address: 0x%lx at 0x%lx\n",
181 (long) sigctx->gregs[CTX_EPC]);
188 void init_exceptions(void)
190 struct sigaction act;
192 /* The Boehm GC initialization blocks the SIGSEGV signal. So we do a
193 dummy allocation here to ensure that the GC is initialized.
195 heap_allocate(1, 0, NULL);
197 /* install signal handlers we need to convert to exceptions */
199 sigemptyset(&act.sa_mask);
202 act.sa_sigaction = catch_NullPointerException;
203 act.sa_flags = SA_SIGINFO;
206 sigaction(SIGSEGV, &act, NULL);
210 sigaction(SIGBUS, &act, NULL);
214 /* Turn off flush-to-zero */
217 n.fc_word = get_fpc_csr();
218 n.fc_struct.flush = 0;
219 set_fpc_csr(n.fc_word);
224 /* function gen_mcode **********************************************************
226 generates machine code
228 *******************************************************************************/
230 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
232 s4 len, s1, s2, s3, d;
246 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
248 /* space to save used callee saved registers */
250 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
251 savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
253 parentargs_base = rd->maxmemuse + savedregs_num;
255 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
257 if (checksync && (m->flags & ACC_SYNCHRONIZED))
262 /* adjust frame size for 16 byte alignment */
264 if (parentargs_base & 1)
267 /* create method header */
270 (void) dseg_addaddress(cd, m); /* Filler */
272 (void) dseg_addaddress(cd, m); /* MethodPointer */
273 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
275 #if defined(USE_THREADS)
277 /* IsSync contains the offset relative to the stack pointer for the
278 argument of monitor_exit used in the exception handler. Since the
279 offset could be zero and give a wrong meaning of the flag it is
283 if (checksync && (m->flags & ACC_SYNCHRONIZED))
284 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8); /* IsSync */
289 (void) dseg_adds4(cd, 0); /* IsSync */
291 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
292 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse);/* IntSave */
293 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse);/* FltSave */
294 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
296 /* create exception table */
298 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
299 dseg_addtarget(cd, ex->start);
300 dseg_addtarget(cd, ex->end);
301 dseg_addtarget(cd, ex->handler);
302 (void) dseg_addaddress(cd, ex->catchtype.cls);
305 /* initialize mcode variables */
307 mcodeptr = (s4 *) cd->mcodebase;
308 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
309 MCODECHECK(128 + m->paramcount);
311 /* create stack frame (if necessary) */
313 if (parentargs_base) {
314 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
317 /* save return address and used callee saved registers */
320 if (!m->isleafmethod) {
321 p--; M_LST(REG_RA, REG_SP, p * 8);
323 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
324 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
326 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
327 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
330 /* take arguments out of register or stack frame */
332 for (p = 0, l = 0; p < m->paramcount; p++) {
333 t = m->paramtypes[p];
334 var = &(rd->locals[l][t]);
336 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
340 if (IS_INT_LNG_TYPE(t)) { /* integer args */
341 if (p < INT_ARG_CNT) { /* register arguments */
342 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
343 M_INTMOVE(rd->argintregs[p], var->regoff);
344 } else { /* reg arg -> spilled */
345 M_LST(rd->argintregs[p], REG_SP, 8 * var->regoff);
348 } else { /* stack arguments */
349 pa = p - INT_ARG_CNT;
350 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
351 M_LLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
353 } else { /* stack arg -> spilled */
354 /* M_LLD(REG_ITMP1, REG_SP, 8 * (parentargs_base + pa)); */
355 /* M_LST(REG_ITMP1, REG_SP, 8 * var->regoff); */
356 var->regoff = parentargs_base + pa;
360 } else { /* floating args */
361 if (p < FLT_ARG_CNT) { /* register arguments */
362 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
363 M_TFLTMOVE(var->type, rd->argfltregs[p], var->regoff);
365 } else { /* reg arg -> spilled */
366 M_DST(rd->argfltregs[p], REG_SP, var->regoff * 8);
369 } else { /* stack arguments */
370 pa = p - FLT_ARG_CNT;
371 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
372 M_DLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
374 } else { /* stack-arg -> spilled */
375 /* M_DLD(REG_FTMP1, REG_SP, 8 * (parentargs_base + pa)); */
376 /* M_DST(REG_FTMP1, REG_SP, 8 * var->regoff); */
377 var->regoff = parentargs_base + pa;
383 /* call monitorenter function */
385 #if defined(USE_THREADS)
386 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
389 /* stack offset for monitor argument */
394 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
396 for (p = 0; p < INT_ARG_CNT; p++)
397 M_LST(rd->argintregs[p], REG_SP, p * 8);
399 for (p = 0; p < FLT_ARG_CNT; p++)
400 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
402 s1 += INT_ARG_CNT + FLT_ARG_CNT;
405 /* decide which monitor enter function to call */
407 if (m->flags & ACC_STATIC) {
408 p = dseg_addaddress(cd, m->class);
409 M_ALD(REG_ITMP1, REG_PV, p);
410 M_AST(REG_ITMP1, REG_SP, s1 * 8);
411 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
412 M_ALD(REG_ITMP3, REG_PV, p);
413 M_JSR(REG_RA, REG_ITMP3);
414 M_INTMOVE(REG_ITMP1, rd->argintregs[0]); /* branch delay */
415 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
416 M_LDA(REG_PV, REG_RA, disp);
419 M_BEQZ(rd->argintregs[0], 0);
420 codegen_addxnullrefs(cd, mcodeptr);
421 p = dseg_addaddress(cd, BUILTIN_monitorenter);
422 M_ALD(REG_ITMP3, REG_PV, p);
423 M_JSR(REG_RA, REG_ITMP3);
424 M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* br delay */
425 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
426 M_LDA(REG_PV, REG_RA, disp);
430 for (p = 0; p < INT_ARG_CNT; p++)
431 M_LLD(rd->argintregs[p], REG_SP, p * 8);
433 for (p = 0; p < FLT_ARG_CNT; p++)
434 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
437 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
442 /* copy argument registers to stack and call trace function */
445 M_LDA(REG_SP, REG_SP, -(2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
446 M_LST(REG_RA, REG_SP, 1 * 8);
448 /* save integer argument registers */
450 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++)
451 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
453 /* save and copy float arguments into integer registers */
455 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
456 t = m->paramtypes[p];
458 if (IS_FLT_DBL_TYPE(t)) {
459 if (IS_2_WORD_TYPE(t)) {
460 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
461 M_LLD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
464 M_FST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
465 M_ILD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
469 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
473 /* save temporary registers for leaf methods */
475 if (m->isleafmethod) {
476 for (p = 0; p < INT_TMP_CNT; p++)
477 M_LST(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
479 for (p = 0; p < FLT_TMP_CNT; p++)
480 M_DST(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
483 p = dseg_addaddress(cd, m);
484 M_ALD(REG_ITMP1, REG_PV, p);
485 M_LST(REG_ITMP1, REG_SP, 0);
486 p = dseg_addaddress(cd, (void *) builtin_trace_args);
487 M_ALD(REG_ITMP3, REG_PV, p);
488 M_JSR(REG_RA, REG_ITMP3);
491 M_LLD(REG_RA, REG_SP, 1 * 8);
493 /* restore integer argument registers */
495 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++)
496 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
498 /* restore float argument registers */
500 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
501 t = m->paramtypes[p];
503 if (IS_FLT_DBL_TYPE(t)) {
504 if (IS_2_WORD_TYPE(t)) {
505 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
508 M_FLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
512 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
516 /* restore temporary registers for leaf methods */
518 if (m->isleafmethod) {
519 for (p = 0; p < INT_TMP_CNT; p++)
520 M_LLD(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
522 for (p = 0; p < FLT_TMP_CNT; p++)
523 M_DLD(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
526 M_LDA(REG_SP, REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
531 /* end of header generation */
533 /* walk through all basic blocks */
535 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
537 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
539 if (bptr->flags >= BBREACHED) {
541 /* branch resolving */
544 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
545 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
551 /* copy interface registers to their destination */
558 while (src != NULL) {
560 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
561 /* d = reg_of_var(m, src, REG_ITMP1); */
562 if (!(src->flags & INMEMORY))
566 M_INTMOVE(REG_ITMP1, d);
567 store_reg_to_var_int(src, d);
573 while (src != NULL) {
575 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
576 d = reg_of_var(rd, src, REG_ITMP1);
577 M_INTMOVE(REG_ITMP1, d);
578 store_reg_to_var_int(src, d);
581 d = reg_of_var(rd, src, REG_IFTMP);
582 if ((src->varkind != STACKVAR)) {
584 if (IS_FLT_DBL_TYPE(s2)) {
585 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
586 s1 = rd->interfaces[len][s2].regoff;
587 M_TFLTMOVE(s2, s1, d);
590 M_DLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
592 store_reg_to_var_flt(src, d);
595 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
596 s1 = rd->interfaces[len][s2].regoff;
600 M_LLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
602 store_reg_to_var_int(src, d);
611 /* walk through all instructions */
616 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
618 MCODECHECK(64); /* an instruction usually needs < 64 words */
622 case ICMD_NOP: /* ... ==> ... */
625 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
627 var_to_reg_int(s1, src, REG_ITMP1);
629 codegen_addxnullrefs(cd, mcodeptr);
633 /* constant operations ************************************************/
635 case ICMD_ICONST: /* ... ==> ..., constant */
636 /* op1 = 0, val.i = constant */
638 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
639 ICONST(d, iptr->val.i);
640 store_reg_to_var_int(iptr->dst, d);
643 case ICMD_LCONST: /* ... ==> ..., constant */
644 /* op1 = 0, val.l = constant */
646 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
647 LCONST(d, iptr->val.l);
648 store_reg_to_var_int(iptr->dst, d);
651 case ICMD_FCONST: /* ... ==> ..., constant */
652 /* op1 = 0, val.f = constant */
654 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
655 a = dseg_addfloat(cd, iptr->val.f);
657 store_reg_to_var_flt(iptr->dst, d);
660 case ICMD_DCONST: /* ... ==> ..., constant */
661 /* op1 = 0, val.d = constant */
663 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
664 a = dseg_adddouble(cd, iptr->val.d);
666 store_reg_to_var_flt (iptr->dst, d);
669 case ICMD_ACONST: /* ... ==> ..., constant */
670 /* op1 = 0, val.a = constant */
672 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
674 a = dseg_addaddress(cd, iptr->val.a);
677 M_INTMOVE(REG_ZERO, d);
679 store_reg_to_var_int(iptr->dst, d);
683 /* load/store operations **********************************************/
685 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
686 case ICMD_LLOAD: /* op1 = local variable */
689 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
690 if ((iptr->dst->varkind == LOCALVAR) &&
691 (iptr->dst->varnum == iptr->op1))
693 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
694 if (var->flags & INMEMORY) {
695 M_LLD(d, REG_SP, 8 * var->regoff);
697 M_INTMOVE(var->regoff,d);
699 store_reg_to_var_int(iptr->dst, d);
702 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
703 case ICMD_DLOAD: /* op1 = local variable */
705 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
706 if ((iptr->dst->varkind == LOCALVAR) &&
707 (iptr->dst->varnum == iptr->op1))
709 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
711 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
712 if (var->flags & INMEMORY) {
713 M_CCFLD(var->type, t2, d, REG_SP, 8 * var->regoff);
715 M_CCFLTMOVE(var->type, t2, var->regoff, d);
718 store_reg_to_var_flt(iptr->dst, d);
722 case ICMD_ISTORE: /* ..., value ==> ... */
723 case ICMD_LSTORE: /* op1 = local variable */
726 if ((src->varkind == LOCALVAR) &&
727 (src->varnum == iptr->op1))
729 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
730 if (var->flags & INMEMORY) {
731 var_to_reg_int(s1, src, REG_ITMP1);
732 M_LST(s1, REG_SP, 8 * var->regoff);
735 var_to_reg_int(s1, src, var->regoff);
736 M_INTMOVE(s1, var->regoff);
740 case ICMD_FSTORE: /* ..., value ==> ... */
741 case ICMD_DSTORE: /* op1 = local variable */
743 if ((src->varkind == LOCALVAR) &&
744 (src->varnum == iptr->op1))
746 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
748 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
749 if (var->flags & INMEMORY) {
750 var_to_reg_flt(s1, src, REG_FTMP1);
751 M_CCFST(t1, var->type, s1, REG_SP, 8 * var->regoff);
754 var_to_reg_flt(s1, src, var->regoff);
755 M_CCFLTMOVE(t1, var->type, s1, var->regoff);
761 /* pop/dup/swap operations ********************************************/
763 /* attention: double and longs are only one entry in CACAO ICMDs */
765 case ICMD_POP: /* ..., value ==> ... */
766 case ICMD_POP2: /* ..., value, value ==> ... */
769 case ICMD_DUP: /* ..., a ==> ..., a, a */
770 M_COPY(src, iptr->dst);
773 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
775 M_COPY(src, iptr->dst);
776 M_COPY(src->prev, iptr->dst->prev);
777 M_COPY(iptr->dst, iptr->dst->prev->prev);
780 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
782 M_COPY(src, iptr->dst);
783 M_COPY(src->prev, iptr->dst->prev);
784 M_COPY(src->prev->prev, iptr->dst->prev->prev);
785 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
788 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
790 M_COPY(src, iptr->dst);
791 M_COPY(src->prev, iptr->dst->prev);
794 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
796 M_COPY(src, iptr->dst);
797 M_COPY(src->prev, iptr->dst->prev);
798 M_COPY(src->prev->prev, iptr->dst->prev->prev);
799 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
800 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
803 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
805 M_COPY(src, iptr->dst);
806 M_COPY(src->prev, iptr->dst->prev);
807 M_COPY(src->prev->prev, iptr->dst->prev->prev);
808 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
809 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
810 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
813 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
815 M_COPY(src, iptr->dst->prev);
816 M_COPY(src->prev, iptr->dst);
820 /* integer operations *************************************************/
822 case ICMD_INEG: /* ..., value ==> ..., - value */
824 var_to_reg_int(s1, src, REG_ITMP1);
825 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
826 M_ISUB(REG_ZERO, s1, d);
827 store_reg_to_var_int(iptr->dst, d);
830 case ICMD_LNEG: /* ..., value ==> ..., - value */
832 var_to_reg_int(s1, src, REG_ITMP1);
833 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
834 M_LSUB(REG_ZERO, s1, d);
835 store_reg_to_var_int(iptr->dst, d);
838 case ICMD_I2L: /* ..., value ==> ..., value */
840 var_to_reg_int(s1, src, REG_ITMP1);
841 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
843 store_reg_to_var_int(iptr->dst, d);
846 case ICMD_L2I: /* ..., value ==> ..., value */
848 var_to_reg_int(s1, src, REG_ITMP1);
849 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
850 M_ISLL_IMM(s1, 0, d );
851 store_reg_to_var_int(iptr->dst, d);
854 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
856 var_to_reg_int(s1, src, REG_ITMP1);
857 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
858 M_LSLL_IMM(s1, 56, d);
859 M_LSRA_IMM( d, 56, d);
860 store_reg_to_var_int(iptr->dst, d);
863 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
865 var_to_reg_int(s1, src, REG_ITMP1);
866 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
868 store_reg_to_var_int(iptr->dst, d);
871 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
873 var_to_reg_int(s1, src, REG_ITMP1);
874 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
875 M_LSLL_IMM(s1, 48, d);
876 M_LSRA_IMM( d, 48, d);
877 store_reg_to_var_int(iptr->dst, d);
881 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
883 var_to_reg_int(s1, src->prev, REG_ITMP1);
884 var_to_reg_int(s2, src, REG_ITMP2);
885 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
887 store_reg_to_var_int(iptr->dst, d);
890 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
891 /* val.i = constant */
893 var_to_reg_int(s1, src, REG_ITMP1);
894 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
895 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
896 M_IADD_IMM(s1, iptr->val.i, d);
899 ICONST(REG_ITMP2, iptr->val.i);
900 M_IADD(s1, REG_ITMP2, d);
902 store_reg_to_var_int(iptr->dst, d);
905 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
907 var_to_reg_int(s1, src->prev, REG_ITMP1);
908 var_to_reg_int(s2, src, REG_ITMP2);
909 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
911 store_reg_to_var_int(iptr->dst, d);
914 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
915 /* val.l = constant */
917 var_to_reg_int(s1, src, REG_ITMP1);
918 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
919 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
920 M_LADD_IMM(s1, iptr->val.l, d);
923 LCONST(REG_ITMP2, iptr->val.l);
924 M_LADD(s1, REG_ITMP2, d);
926 store_reg_to_var_int(iptr->dst, d);
929 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
931 var_to_reg_int(s1, src->prev, REG_ITMP1);
932 var_to_reg_int(s2, src, REG_ITMP2);
933 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
935 store_reg_to_var_int(iptr->dst, d);
938 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
939 /* val.i = constant */
941 var_to_reg_int(s1, src, REG_ITMP1);
942 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
943 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
944 M_IADD_IMM(s1, -iptr->val.i, d);
947 ICONST(REG_ITMP2, iptr->val.i);
948 M_ISUB(s1, REG_ITMP2, d);
950 store_reg_to_var_int(iptr->dst, d);
953 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
955 var_to_reg_int(s1, src->prev, REG_ITMP1);
956 var_to_reg_int(s2, src, REG_ITMP2);
957 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
959 store_reg_to_var_int(iptr->dst, d);
962 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
963 /* val.l = constant */
965 var_to_reg_int(s1, src, REG_ITMP1);
966 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
967 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
968 M_LADD_IMM(s1, -iptr->val.l, d);
971 LCONST(REG_ITMP2, iptr->val.l);
972 M_LSUB(s1, REG_ITMP2, d);
974 store_reg_to_var_int(iptr->dst, d);
977 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
979 var_to_reg_int(s1, src->prev, REG_ITMP1);
980 var_to_reg_int(s2, src, REG_ITMP2);
981 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
986 store_reg_to_var_int(iptr->dst, d);
989 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
990 /* val.i = constant */
992 var_to_reg_int(s1, src, REG_ITMP1);
993 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
994 ICONST(REG_ITMP2, iptr->val.i);
995 M_IMUL(s1, REG_ITMP2);
999 store_reg_to_var_int(iptr->dst, d);
1002 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1004 var_to_reg_int(s1, src->prev, REG_ITMP1);
1005 var_to_reg_int(s2, src, REG_ITMP2);
1006 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1011 store_reg_to_var_int(iptr->dst, d);
1014 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1015 /* val.l = constant */
1017 var_to_reg_int(s1, src, REG_ITMP1);
1018 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1019 LCONST(REG_ITMP2, iptr->val.l);
1020 M_LMUL(s1, REG_ITMP2);
1024 store_reg_to_var_int(iptr->dst, d);
1027 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1029 var_to_reg_int(s1, src->prev, REG_ITMP1);
1030 var_to_reg_int(s2, src, REG_ITMP2);
1031 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1036 store_reg_to_var_int(iptr->dst, d);
1039 case ICMD_IDIVCONST: /* ..., value ==> ..., value / constant */
1040 /* val.i = constant */
1042 var_to_reg_int(s1, src, REG_ITMP1);
1043 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1044 ICONST(REG_ITMP2, iptr->val.i);
1045 M_IDIV(s1, REG_ITMP2);
1049 store_reg_to_var_int(iptr->dst, d);
1052 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1054 var_to_reg_int(s1, src->prev, REG_ITMP1);
1055 var_to_reg_int(s2, src, REG_ITMP2);
1056 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1061 store_reg_to_var_int(iptr->dst, d);
1064 case ICMD_LDIVCONST: /* ..., value ==> ..., value / constant */
1065 /* val.l = constant */
1067 var_to_reg_int(s1, src, REG_ITMP1);
1068 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1069 LCONST(REG_ITMP2, iptr->val.l);
1070 M_LDIV(s1, REG_ITMP2);
1074 store_reg_to_var_int(iptr->dst, d);
1077 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1079 var_to_reg_int(s1, src->prev, REG_ITMP1);
1080 var_to_reg_int(s2, src, REG_ITMP2);
1081 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1086 store_reg_to_var_int(iptr->dst, d);
1089 case ICMD_IREMCONST: /* ..., value ==> ..., value % constant */
1090 /* val.i = constant */
1092 var_to_reg_int(s1, src, REG_ITMP1);
1093 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1094 ICONST(REG_ITMP2, iptr->val.i);
1095 M_IDIV(s1, REG_ITMP2);
1099 store_reg_to_var_int(iptr->dst, d);
1102 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1104 var_to_reg_int(s1, src->prev, REG_ITMP1);
1105 var_to_reg_int(s2, src, REG_ITMP2);
1106 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1111 store_reg_to_var_int(iptr->dst, d);
1114 case ICMD_LREMCONST: /* ..., value ==> ..., value % constant */
1115 /* val.l = constant */
1117 var_to_reg_int(s1, src, REG_ITMP1);
1118 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1119 LCONST(REG_ITMP2, iptr->val.l);
1120 M_LDIV(s1, REG_ITMP2);
1124 store_reg_to_var_int(iptr->dst, d);
1127 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1128 case ICMD_LDIVPOW2: /* val.i = constant */
1130 var_to_reg_int(s1, src, REG_ITMP1);
1131 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1132 M_LSRA_IMM(s1, 63, REG_ITMP2);
1133 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1134 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1135 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
1136 store_reg_to_var_int(iptr->dst, d);
1139 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1141 var_to_reg_int(s1, src->prev, REG_ITMP1);
1142 var_to_reg_int(s2, src, REG_ITMP2);
1143 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1145 store_reg_to_var_int(iptr->dst, d);
1148 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1149 /* val.i = constant */
1151 var_to_reg_int(s1, src, REG_ITMP1);
1152 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1153 M_ISLL_IMM(s1, iptr->val.i, d);
1154 store_reg_to_var_int(iptr->dst, d);
1157 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1159 var_to_reg_int(s1, src->prev, REG_ITMP1);
1160 var_to_reg_int(s2, src, REG_ITMP2);
1161 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1163 store_reg_to_var_int(iptr->dst, d);
1166 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1167 /* val.i = constant */
1169 var_to_reg_int(s1, src, REG_ITMP1);
1170 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1171 M_ISRA_IMM(s1, iptr->val.i, d);
1172 store_reg_to_var_int(iptr->dst, d);
1175 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1177 var_to_reg_int(s1, src->prev, REG_ITMP1);
1178 var_to_reg_int(s2, src, REG_ITMP2);
1179 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1181 store_reg_to_var_int(iptr->dst, d);
1184 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1185 /* val.i = constant */
1187 var_to_reg_int(s1, src, REG_ITMP1);
1188 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1189 M_ISRL_IMM(s1, iptr->val.i, d);
1190 store_reg_to_var_int(iptr->dst, d);
1193 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1195 var_to_reg_int(s1, src->prev, REG_ITMP1);
1196 var_to_reg_int(s2, src, REG_ITMP2);
1197 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1199 store_reg_to_var_int(iptr->dst, d);
1202 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1203 /* val.i = constant */
1205 var_to_reg_int(s1, src, REG_ITMP1);
1206 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1207 M_LSLL_IMM(s1, iptr->val.i, d);
1208 store_reg_to_var_int(iptr->dst, d);
1211 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1213 var_to_reg_int(s1, src->prev, REG_ITMP1);
1214 var_to_reg_int(s2, src, REG_ITMP2);
1215 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1217 store_reg_to_var_int(iptr->dst, d);
1220 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1221 /* val.i = constant */
1223 var_to_reg_int(s1, src, REG_ITMP1);
1224 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1225 M_LSRA_IMM(s1, iptr->val.i, d);
1226 store_reg_to_var_int(iptr->dst, d);
1229 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1231 var_to_reg_int(s1, src->prev, REG_ITMP1);
1232 var_to_reg_int(s2, src, REG_ITMP2);
1233 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1235 store_reg_to_var_int(iptr->dst, d);
1238 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1239 /* val.i = constant */
1241 var_to_reg_int(s1, src, REG_ITMP1);
1242 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1243 M_LSRL_IMM(s1, iptr->val.i, d);
1244 store_reg_to_var_int(iptr->dst, d);
1247 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1250 var_to_reg_int(s1, src->prev, REG_ITMP1);
1251 var_to_reg_int(s2, src, REG_ITMP2);
1252 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1254 store_reg_to_var_int(iptr->dst, d);
1257 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1258 /* val.i = constant */
1260 var_to_reg_int(s1, src, REG_ITMP1);
1261 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1262 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1263 M_AND_IMM(s1, iptr->val.i, d);
1266 ICONST(REG_ITMP2, iptr->val.i);
1267 M_AND(s1, REG_ITMP2, d);
1269 store_reg_to_var_int(iptr->dst, d);
1272 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1273 /* val.i = constant */
1275 var_to_reg_int(s1, src, REG_ITMP1);
1276 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1278 M_MOV(s1, REG_ITMP1);
1281 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1282 M_AND_IMM(s1, iptr->val.i, d);
1285 M_ISUB(REG_ZERO, s1, d);
1286 M_AND_IMM(d, iptr->val.i, d);
1289 ICONST(REG_ITMP2, iptr->val.i);
1290 M_AND(s1, REG_ITMP2, d);
1293 M_ISUB(REG_ZERO, s1, d);
1294 M_AND(d, REG_ITMP2, d);
1296 M_ISUB(REG_ZERO, d, d);
1297 store_reg_to_var_int(iptr->dst, d);
1300 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1301 /* val.l = constant */
1303 var_to_reg_int(s1, src, REG_ITMP1);
1304 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1305 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1306 M_AND_IMM(s1, iptr->val.l, d);
1309 LCONST(REG_ITMP2, iptr->val.l);
1310 M_AND(s1, REG_ITMP2, d);
1312 store_reg_to_var_int(iptr->dst, d);
1315 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1316 /* val.l = constant */
1318 var_to_reg_int(s1, src, REG_ITMP1);
1319 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1321 M_MOV(s1, REG_ITMP1);
1324 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1325 M_AND_IMM(s1, iptr->val.l, d);
1328 M_LSUB(REG_ZERO, s1, d);
1329 M_AND_IMM(d, iptr->val.l, d);
1332 LCONST(REG_ITMP2, iptr->val.l);
1333 M_AND(s1, REG_ITMP2, d);
1336 M_LSUB(REG_ZERO, s1, d);
1337 M_AND(d, REG_ITMP2, d);
1339 M_LSUB(REG_ZERO, d, d);
1340 store_reg_to_var_int(iptr->dst, d);
1343 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1346 var_to_reg_int(s1, src->prev, REG_ITMP1);
1347 var_to_reg_int(s2, src, REG_ITMP2);
1348 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1350 store_reg_to_var_int(iptr->dst, d);
1353 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1354 /* val.i = constant */
1356 var_to_reg_int(s1, src, REG_ITMP1);
1357 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1358 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1359 M_OR_IMM(s1, iptr->val.i, d);
1362 ICONST(REG_ITMP2, iptr->val.i);
1363 M_OR(s1, REG_ITMP2, d);
1365 store_reg_to_var_int(iptr->dst, d);
1368 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1369 /* val.l = constant */
1371 var_to_reg_int(s1, src, REG_ITMP1);
1372 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1373 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1374 M_OR_IMM(s1, iptr->val.l, d);
1377 LCONST(REG_ITMP2, iptr->val.l);
1378 M_OR(s1, REG_ITMP2, d);
1380 store_reg_to_var_int(iptr->dst, d);
1383 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1386 var_to_reg_int(s1, src->prev, REG_ITMP1);
1387 var_to_reg_int(s2, src, REG_ITMP2);
1388 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1390 store_reg_to_var_int(iptr->dst, d);
1393 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1394 /* val.i = constant */
1396 var_to_reg_int(s1, src, REG_ITMP1);
1397 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1398 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1399 M_XOR_IMM(s1, iptr->val.i, d);
1402 ICONST(REG_ITMP2, iptr->val.i);
1403 M_XOR(s1, REG_ITMP2, d);
1405 store_reg_to_var_int(iptr->dst, d);
1408 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1409 /* val.l = constant */
1411 var_to_reg_int(s1, src, REG_ITMP1);
1412 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1413 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1414 M_XOR_IMM(s1, iptr->val.l, d);
1417 LCONST(REG_ITMP2, iptr->val.l);
1418 M_XOR(s1, REG_ITMP2, d);
1420 store_reg_to_var_int(iptr->dst, d);
1424 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1426 var_to_reg_int(s1, src->prev, REG_ITMP1);
1427 var_to_reg_int(s2, src, REG_ITMP2);
1428 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1429 M_CMPLT(s1, s2, REG_ITMP3);
1430 M_CMPLT(s2, s1, REG_ITMP1);
1431 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1432 store_reg_to_var_int(iptr->dst, d);
1436 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1437 /* op1 = variable, val.i = constant */
1439 var = &(rd->locals[iptr->op1][TYPE_INT]);
1440 if (var->flags & INMEMORY) {
1442 M_LLD(s1, REG_SP, 8 * var->regoff);
1446 M_IADD_IMM(s1, iptr->val.i, s1);
1447 if (var->flags & INMEMORY)
1448 M_LST(s1, REG_SP, 8 * var->regoff);
1452 /* floating operations ************************************************/
1454 case ICMD_FNEG: /* ..., value ==> ..., - value */
1456 var_to_reg_flt(s1, src, REG_FTMP1);
1457 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1459 store_reg_to_var_flt(iptr->dst, d);
1462 case ICMD_DNEG: /* ..., value ==> ..., - value */
1464 var_to_reg_flt(s1, src, REG_FTMP1);
1465 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1467 store_reg_to_var_flt(iptr->dst, d);
1470 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1472 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1473 var_to_reg_flt(s2, src, REG_FTMP2);
1474 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1476 store_reg_to_var_flt(iptr->dst, d);
1479 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1481 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1482 var_to_reg_flt(s2, src, REG_FTMP2);
1483 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1485 store_reg_to_var_flt(iptr->dst, d);
1488 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1490 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1491 var_to_reg_flt(s2, src, REG_FTMP2);
1492 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1494 store_reg_to_var_flt(iptr->dst, d);
1497 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1499 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1500 var_to_reg_flt(s2, src, REG_FTMP2);
1501 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1503 store_reg_to_var_flt(iptr->dst, d);
1506 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1508 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1509 var_to_reg_flt(s2, src, REG_FTMP2);
1510 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1512 store_reg_to_var_flt(iptr->dst, d);
1515 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1517 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1518 var_to_reg_flt(s2, src, REG_FTMP2);
1519 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1521 store_reg_to_var_flt(iptr->dst, d);
1524 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1526 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1527 var_to_reg_flt(s2, src, REG_FTMP2);
1528 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1530 store_reg_to_var_flt(iptr->dst, d);
1533 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1535 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1536 var_to_reg_flt(s2, src, REG_FTMP2);
1537 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1539 store_reg_to_var_flt(iptr->dst, d);
1543 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1545 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1546 var_to_reg_flt(s2, src, REG_FTMP2);
1547 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1548 M_FDIV(s1,s2, REG_FTMP3);
1549 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1550 M_CVTLF(REG_FTMP3, REG_FTMP3);
1551 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1552 M_FSUB(s1, REG_FTMP3, d);
1553 store_reg_to_var_flt(iptr->dst, d);
1556 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1558 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1559 var_to_reg_flt(s2, src, REG_FTMP2);
1560 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1561 M_DDIV(s1,s2, REG_FTMP3);
1562 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1563 M_CVTLD(REG_FTMP3, REG_FTMP3);
1564 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1565 M_DSUB(s1, REG_FTMP3, d);
1566 store_reg_to_var_flt(iptr->dst, d);
1570 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1572 var_to_reg_int(s1, src, REG_ITMP1);
1573 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1576 store_reg_to_var_flt(iptr->dst, d);
1579 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1581 var_to_reg_int(s1, src, REG_ITMP1);
1582 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1585 store_reg_to_var_flt(iptr->dst, d);
1588 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1590 var_to_reg_flt(s1, src, REG_FTMP1);
1591 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1592 M_TRUNCFI(s1, REG_FTMP1);
1593 M_MOVDI(REG_FTMP1, d);
1595 store_reg_to_var_int(iptr->dst, d);
1598 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1600 var_to_reg_flt(s1, src, REG_FTMP1);
1601 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1602 M_TRUNCDI(s1, REG_FTMP1);
1603 M_MOVDI(REG_FTMP1, d);
1605 store_reg_to_var_int(iptr->dst, d);
1608 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1610 var_to_reg_flt(s1, src, REG_FTMP1);
1611 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1612 M_TRUNCFL(s1, REG_FTMP1);
1613 M_MOVDL(REG_FTMP1, d);
1615 store_reg_to_var_int(iptr->dst, d);
1618 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1620 var_to_reg_flt(s1, src, REG_FTMP1);
1621 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1622 M_TRUNCDL(s1, REG_FTMP1);
1623 M_MOVDL(REG_FTMP1, d);
1625 store_reg_to_var_int(iptr->dst, d);
1628 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1630 var_to_reg_flt(s1, src, REG_FTMP1);
1631 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1633 store_reg_to_var_flt(iptr->dst, d);
1636 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1638 var_to_reg_flt(s1, src, REG_FTMP1);
1639 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1641 store_reg_to_var_flt(iptr->dst, d);
1644 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1646 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1647 var_to_reg_flt(s2, src, REG_FTMP2);
1648 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1651 M_LADD_IMM(REG_ZERO, 1, d);
1655 M_LSUB_IMM(REG_ZERO, 1, d);
1656 M_CMOVT(REG_ZERO, d);
1657 store_reg_to_var_int(iptr->dst, d);
1660 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1662 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1663 var_to_reg_flt(s2, src, REG_FTMP2);
1664 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1667 M_LADD_IMM(REG_ZERO, 1, d);
1671 M_LSUB_IMM(REG_ZERO, 1, d);
1672 M_CMOVT(REG_ZERO, d);
1673 store_reg_to_var_int(iptr->dst, d);
1676 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1678 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1679 var_to_reg_flt(s2, src, REG_FTMP2);
1680 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1683 M_LSUB_IMM(REG_ZERO, 1, d);
1687 M_LADD_IMM(REG_ZERO, 1, d);
1688 M_CMOVT(REG_ZERO, d);
1689 store_reg_to_var_int(iptr->dst, d);
1692 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1694 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1695 var_to_reg_flt(s2, src, REG_FTMP2);
1696 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1699 M_LSUB_IMM(REG_ZERO, 1, d);
1703 M_LADD_IMM(REG_ZERO, 1, d);
1704 M_CMOVT(REG_ZERO, d);
1705 store_reg_to_var_int(iptr->dst, d);
1709 /* memory operations **************************************************/
1711 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1713 var_to_reg_int(s1, src, REG_ITMP1);
1714 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1715 gen_nullptr_check(s1);
1716 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1717 store_reg_to_var_int(iptr->dst, d);
1720 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1722 var_to_reg_int(s1, src->prev, REG_ITMP1);
1723 var_to_reg_int(s2, src, REG_ITMP2);
1724 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1725 if (iptr->op1 == 0) {
1726 gen_nullptr_check(s1);
1729 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1730 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1731 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1732 store_reg_to_var_int(iptr->dst, d);
1735 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1737 var_to_reg_int(s1, src->prev, REG_ITMP1);
1738 var_to_reg_int(s2, src, REG_ITMP2);
1739 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1740 if (iptr->op1 == 0) {
1741 gen_nullptr_check(s1);
1744 M_ASLL_IMM(s2, 2, REG_ITMP2);
1745 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1746 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1747 store_reg_to_var_int(iptr->dst, d);
1750 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1752 var_to_reg_int(s1, src->prev, REG_ITMP1);
1753 var_to_reg_int(s2, src, REG_ITMP2);
1754 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1755 if (iptr->op1 == 0) {
1756 gen_nullptr_check(s1);
1759 M_ASLL_IMM(s2, 3, REG_ITMP2);
1760 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1761 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1762 store_reg_to_var_int(iptr->dst, d);
1765 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1767 var_to_reg_int(s1, src->prev, REG_ITMP1);
1768 var_to_reg_int(s2, src, REG_ITMP2);
1769 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1770 if (iptr->op1 == 0) {
1771 gen_nullptr_check(s1);
1774 M_ASLL_IMM(s2, 2, REG_ITMP2);
1775 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1776 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1777 store_reg_to_var_flt(iptr->dst, d);
1780 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1782 var_to_reg_int(s1, src->prev, REG_ITMP1);
1783 var_to_reg_int(s2, src, REG_ITMP2);
1784 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1785 if (iptr->op1 == 0) {
1786 gen_nullptr_check(s1);
1789 M_ASLL_IMM(s2, 3, REG_ITMP2);
1790 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1791 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1792 store_reg_to_var_flt(iptr->dst, d);
1795 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1797 var_to_reg_int(s1, src->prev, REG_ITMP1);
1798 var_to_reg_int(s2, src, REG_ITMP2);
1799 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1800 if (iptr->op1 == 0) {
1801 gen_nullptr_check(s1);
1804 M_AADD(s2, s1, REG_ITMP1);
1805 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1806 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1807 store_reg_to_var_int(iptr->dst, d);
1810 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1812 var_to_reg_int(s1, src->prev, REG_ITMP1);
1813 var_to_reg_int(s2, src, REG_ITMP2);
1814 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1815 if (iptr->op1 == 0) {
1816 gen_nullptr_check(s1);
1819 M_AADD(s2, s1, REG_ITMP1);
1820 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1821 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1822 store_reg_to_var_int(iptr->dst, d);
1825 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1827 var_to_reg_int(s1, src->prev, REG_ITMP1);
1828 var_to_reg_int(s2, src, REG_ITMP2);
1829 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1830 if (iptr->op1 == 0) {
1831 gen_nullptr_check(s1);
1834 M_AADD(s2, s1, REG_ITMP1);
1835 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1836 store_reg_to_var_int(iptr->dst, d);
1840 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1842 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1843 var_to_reg_int(s2, src->prev, REG_ITMP2);
1844 if (iptr->op1 == 0) {
1845 gen_nullptr_check(s1);
1848 var_to_reg_int(s3, src, REG_ITMP3);
1849 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1850 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1851 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1854 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1856 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1857 var_to_reg_int(s2, src->prev, REG_ITMP2);
1858 if (iptr->op1 == 0) {
1859 gen_nullptr_check(s1);
1862 var_to_reg_int(s3, src, REG_ITMP3);
1863 M_ASLL_IMM(s2, 2, REG_ITMP2);
1864 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1865 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1868 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1870 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1871 var_to_reg_int(s2, src->prev, REG_ITMP2);
1872 if (iptr->op1 == 0) {
1873 gen_nullptr_check(s1);
1876 var_to_reg_int(s3, src, REG_ITMP3);
1877 M_ASLL_IMM(s2, 3, REG_ITMP2);
1878 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1879 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1882 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1884 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1885 var_to_reg_int(s2, src->prev, REG_ITMP2);
1886 if (iptr->op1 == 0) {
1887 gen_nullptr_check(s1);
1890 var_to_reg_flt(s3, src, REG_FTMP3);
1891 M_ASLL_IMM(s2, 2, REG_ITMP2);
1892 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1893 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1896 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1898 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1899 var_to_reg_int(s2, src->prev, REG_ITMP2);
1900 if (iptr->op1 == 0) {
1901 gen_nullptr_check(s1);
1904 var_to_reg_flt(s3, src, REG_FTMP3);
1905 M_ASLL_IMM(s2, 3, REG_ITMP2);
1906 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1907 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1910 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1911 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1913 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1914 var_to_reg_int(s2, src->prev, REG_ITMP2);
1915 if (iptr->op1 == 0) {
1916 gen_nullptr_check(s1);
1919 var_to_reg_int(s3, src, REG_ITMP3);
1920 M_AADD(s2, s1, REG_ITMP1);
1921 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1922 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1925 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1927 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1928 var_to_reg_int(s2, src->prev, REG_ITMP2);
1929 if (iptr->op1 == 0) {
1930 gen_nullptr_check(s1);
1933 var_to_reg_int(s3, src, REG_ITMP3);
1934 M_AADD(s2, s1, REG_ITMP1);
1935 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1939 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1941 var_to_reg_int(s1, src->prev, REG_ITMP1);
1942 var_to_reg_int(s2, src, REG_ITMP2);
1943 if (iptr->op1 == 0) {
1944 gen_nullptr_check(s1);
1947 M_ASLL_IMM(s2, 2, REG_ITMP2);
1948 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1949 M_IST(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1952 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1954 var_to_reg_int(s1, src->prev, REG_ITMP1);
1955 var_to_reg_int(s2, src, REG_ITMP2);
1956 if (iptr->op1 == 0) {
1957 gen_nullptr_check(s1);
1960 M_ASLL_IMM(s2, 3, REG_ITMP2);
1961 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1962 M_LST(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1965 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1967 var_to_reg_int(s1, src->prev, REG_ITMP1);
1968 var_to_reg_int(s2, src, REG_ITMP2);
1969 if (iptr->op1 == 0) {
1970 gen_nullptr_check(s1);
1973 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1974 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1975 M_AST(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1978 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1980 var_to_reg_int(s1, src->prev, REG_ITMP1);
1981 var_to_reg_int(s2, src, REG_ITMP2);
1982 if (iptr->op1 == 0) {
1983 gen_nullptr_check(s1);
1986 M_AADD(s2, s1, REG_ITMP1);
1987 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1990 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1991 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1993 var_to_reg_int(s1, src->prev, REG_ITMP1);
1994 var_to_reg_int(s2, src, REG_ITMP2);
1995 if (iptr->op1 == 0) {
1996 gen_nullptr_check(s1);
1999 M_AADD(s2, s1, REG_ITMP1);
2000 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2001 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
2005 case ICMD_GETSTATIC: /* ... ==> ..., value */
2006 /* op1 = type, val.a = field address */
2009 codegen_addpatchref(cd, mcodeptr,
2010 PATCHER_get_putstatic,
2011 (unresolved_field *) iptr->target);
2013 if (showdisassemble) {
2020 fieldinfo *fi = iptr->val.a;
2022 if (!fi->class->initialized) {
2023 codegen_addpatchref(cd, mcodeptr,
2024 PATCHER_clinit, fi->class);
2026 if (showdisassemble) {
2031 a = (ptrint) &(fi->value);
2034 a = dseg_addaddress(cd, a);
2035 M_ALD(REG_ITMP1, REG_PV, a);
2036 switch (iptr->op1) {
2038 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2039 M_ILD(d, REG_ITMP1, 0);
2040 store_reg_to_var_int(iptr->dst, d);
2043 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2044 M_LLD(d, REG_ITMP1, 0);
2045 store_reg_to_var_int(iptr->dst, d);
2048 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2049 M_ALD(d, REG_ITMP1, 0);
2050 store_reg_to_var_int(iptr->dst, d);
2053 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2054 M_FLD(d, REG_ITMP1, 0);
2055 store_reg_to_var_flt(iptr->dst, d);
2058 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2059 M_DLD(d, REG_ITMP1, 0);
2060 store_reg_to_var_flt(iptr->dst, d);
2065 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2066 /* op1 = type, val.a = field address */
2069 codegen_addpatchref(cd, mcodeptr,
2070 PATCHER_get_putstatic,
2071 (unresolved_field *) iptr->target);
2073 if (showdisassemble) {
2080 fieldinfo *fi = iptr->val.a;
2082 if (!fi->class->initialized) {
2083 codegen_addpatchref(cd, mcodeptr,
2084 PATCHER_clinit, fi->class);
2086 if (showdisassemble) {
2091 a = (ptrint) &(fi->value);
2094 a = dseg_addaddress(cd, a);
2095 M_ALD(REG_ITMP1, REG_PV, a);
2096 switch (iptr->op1) {
2098 var_to_reg_int(s2, src, REG_ITMP2);
2099 M_IST(s2, REG_ITMP1, 0);
2102 var_to_reg_int(s2, src, REG_ITMP2);
2103 M_LST(s2, REG_ITMP1, 0);
2106 var_to_reg_int(s2, src, REG_ITMP2);
2107 M_AST(s2, REG_ITMP1, 0);
2110 var_to_reg_flt(s2, src, REG_FTMP2);
2111 M_FST(s2, REG_ITMP1, 0);
2114 var_to_reg_flt(s2, src, REG_FTMP2);
2115 M_DST(s2, REG_ITMP1, 0);
2120 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2121 /* val = value (in current instruction) */
2122 /* op1 = type, val.a = field address (in */
2123 /* following NOP) */
2125 if (!iptr[1].val.a) {
2126 codegen_addpatchref(cd, mcodeptr,
2127 PATCHER_get_putstatic,
2128 (unresolved_field *) iptr[1].target);
2130 if (showdisassemble) {
2137 fieldinfo *fi = iptr[1].val.a;
2139 if (!fi->class->initialized) {
2140 codegen_addpatchref(cd, mcodeptr,
2141 PATCHER_clinit, fi->class);
2143 if (showdisassemble) {
2148 a = (ptrint) &(fi->value);
2151 a = dseg_addaddress(cd, a);
2152 M_ALD(REG_ITMP1, REG_PV, a);
2153 switch (iptr->op1) {
2155 M_IST(REG_ZERO, REG_ITMP1, 0);
2158 M_LST(REG_ZERO, REG_ITMP1, 0);
2161 M_AST(REG_ZERO, REG_ITMP1, 0);
2164 M_FST(REG_ZERO, REG_ITMP1, 0);
2167 M_DST(REG_ZERO, REG_ITMP1, 0);
2173 case ICMD_GETFIELD: /* ... ==> ..., value */
2174 /* op1 = type, val.i = field offset */
2176 var_to_reg_int(s1, src, REG_ITMP1);
2177 gen_nullptr_check(s1);
2180 codegen_addpatchref(cd, mcodeptr,
2181 PATCHER_get_putfield,
2182 (unresolved_field *) iptr->target);
2184 if (showdisassemble) {
2191 a = ((fieldinfo *) (iptr->val.a))->offset;
2194 switch (iptr->op1) {
2196 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2198 store_reg_to_var_int(iptr->dst, d);
2201 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2203 store_reg_to_var_int(iptr->dst, d);
2206 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2208 store_reg_to_var_int(iptr->dst, d);
2211 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2213 store_reg_to_var_flt(iptr->dst, d);
2216 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2218 store_reg_to_var_flt(iptr->dst, d);
2221 /* XXX quick hack */
2225 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2226 /* op1 = type, val.a = field address */
2228 var_to_reg_int(s1, src->prev, REG_ITMP1);
2229 gen_nullptr_check(s1);
2231 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2232 var_to_reg_int(s2, src, REG_ITMP2);
2234 var_to_reg_flt(s2, src, REG_FTMP2);
2238 codegen_addpatchref(cd, mcodeptr,
2239 PATCHER_get_putfield,
2240 (unresolved_field *) iptr->target);
2242 if (showdisassemble) {
2249 a = ((fieldinfo *) (iptr->val.a))->offset;
2252 switch (iptr->op1) {
2269 /* XXX quick hack */
2273 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2274 /* val = value (in current instruction) */
2275 /* op1 = type, val.a = field address (in */
2276 /* following NOP) */
2278 var_to_reg_int(s1, src, REG_ITMP1);
2279 gen_nullptr_check(s1);
2281 if (!iptr[1].val.a) {
2282 codegen_addpatchref(cd, mcodeptr,
2283 PATCHER_get_putfield,
2284 (unresolved_field *) iptr[1].target);
2286 if (showdisassemble) {
2293 a = ((fieldinfo *) (iptr[1].val.a))->offset;
2296 switch (iptr[1].op1) {
2298 M_IST(REG_ZERO, s1, a);
2301 M_LST(REG_ZERO, s1, a);
2304 M_AST(REG_ZERO, s1, a);
2307 M_FST(REG_ZERO, s1, a);
2310 M_DST(REG_ZERO, s1, a);
2313 /* XXX quick hack */
2318 /* branch operations **************************************************/
2320 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2322 var_to_reg_int(s1, src, REG_ITMP1);
2323 M_INTMOVE(s1, REG_ITMP1_XPTR);
2324 a = dseg_addaddress(cd, asm_handle_exception);
2325 M_ALD(REG_ITMP2, REG_PV, a);
2326 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2328 M_NOP; /* nop ensures that XPC is less than the end */
2329 /* of basic block */
2333 case ICMD_GOTO: /* ... ==> ... */
2334 /* op1 = target JavaVM pc */
2336 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2341 case ICMD_JSR: /* ... ==> ... */
2342 /* op1 = target JavaVM pc */
2344 dseg_addtarget(cd, BlockPtrOfPC(iptr->op1));
2345 M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
2346 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2350 case ICMD_RET: /* ... ==> ... */
2351 /* op1 = local variable */
2352 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2353 if (var->flags & INMEMORY) {
2354 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2363 case ICMD_IFNULL: /* ..., value ==> ... */
2364 /* op1 = target JavaVM pc */
2366 var_to_reg_int(s1, src, REG_ITMP1);
2368 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2372 case ICMD_IFNONNULL: /* ..., value ==> ... */
2373 /* op1 = target JavaVM pc */
2375 var_to_reg_int(s1, src, REG_ITMP1);
2377 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2381 case ICMD_IFEQ: /* ..., value ==> ... */
2382 /* op1 = target JavaVM pc, val.i = constant */
2384 var_to_reg_int(s1, src, REG_ITMP1);
2385 if (iptr->val.i == 0) {
2389 ICONST(REG_ITMP2, iptr->val.i);
2390 M_BEQ(s1, REG_ITMP2, 0);
2392 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2396 case ICMD_IFLT: /* ..., value ==> ... */
2397 /* op1 = target JavaVM pc, val.i = constant */
2399 var_to_reg_int(s1, src, REG_ITMP1);
2400 if (iptr->val.i == 0) {
2404 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2405 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2408 ICONST(REG_ITMP2, iptr->val.i);
2409 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2411 M_BNEZ(REG_ITMP1, 0);
2413 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2417 case ICMD_IFLE: /* ..., value ==> ... */
2418 /* op1 = target JavaVM pc, val.i = constant */
2420 var_to_reg_int(s1, src, REG_ITMP1);
2421 if (iptr->val.i == 0) {
2425 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2426 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2427 M_BNEZ(REG_ITMP1, 0);
2430 ICONST(REG_ITMP2, iptr->val.i);
2431 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2432 M_BEQZ(REG_ITMP1, 0);
2435 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2439 case ICMD_IFNE: /* ..., value ==> ... */
2440 /* op1 = target JavaVM pc, val.i = constant */
2442 var_to_reg_int(s1, src, REG_ITMP1);
2443 if (iptr->val.i == 0) {
2447 ICONST(REG_ITMP2, iptr->val.i);
2448 M_BNE(s1, REG_ITMP2, 0);
2450 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2454 case ICMD_IFGT: /* ..., value ==> ... */
2455 /* op1 = target JavaVM pc, val.i = constant */
2457 var_to_reg_int(s1, src, REG_ITMP1);
2458 if (iptr->val.i == 0) {
2462 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2463 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2464 M_BEQZ(REG_ITMP1, 0);
2467 ICONST(REG_ITMP2, iptr->val.i);
2468 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2469 M_BNEZ(REG_ITMP1, 0);
2472 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2476 case ICMD_IFGE: /* ..., value ==> ... */
2477 /* op1 = target JavaVM pc, val.i = constant */
2479 var_to_reg_int(s1, src, REG_ITMP1);
2480 if (iptr->val.i == 0) {
2484 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2485 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2488 ICONST(REG_ITMP2, iptr->val.i);
2489 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2491 M_BEQZ(REG_ITMP1, 0);
2493 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2497 case ICMD_IF_LEQ: /* ..., value ==> ... */
2498 /* op1 = target JavaVM pc, val.l = constant */
2500 var_to_reg_int(s1, src, REG_ITMP1);
2501 if (iptr->val.l == 0) {
2505 LCONST(REG_ITMP2, iptr->val.l);
2506 M_BEQ(s1, REG_ITMP2, 0);
2508 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2512 case ICMD_IF_LLT: /* ..., value ==> ... */
2513 /* op1 = target JavaVM pc, val.l = constant */
2515 var_to_reg_int(s1, src, REG_ITMP1);
2516 if (iptr->val.l == 0) {
2520 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2521 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2524 LCONST(REG_ITMP2, iptr->val.l);
2525 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2527 M_BNEZ(REG_ITMP1, 0);
2529 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2533 case ICMD_IF_LLE: /* ..., value ==> ... */
2534 /* op1 = target JavaVM pc, val.l = constant */
2536 var_to_reg_int(s1, src, REG_ITMP1);
2537 if (iptr->val.l == 0) {
2541 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2542 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2543 M_BNEZ(REG_ITMP1, 0);
2546 LCONST(REG_ITMP2, iptr->val.l);
2547 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2548 M_BEQZ(REG_ITMP1, 0);
2551 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2555 case ICMD_IF_LNE: /* ..., value ==> ... */
2556 /* op1 = target JavaVM pc, val.l = constant */
2558 var_to_reg_int(s1, src, REG_ITMP1);
2559 if (iptr->val.l == 0) {
2563 LCONST(REG_ITMP2, iptr->val.l);
2564 M_BNE(s1, REG_ITMP2, 0);
2566 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2570 case ICMD_IF_LGT: /* ..., value ==> ... */
2571 /* op1 = target JavaVM pc, val.l = constant */
2573 var_to_reg_int(s1, src, REG_ITMP1);
2574 if (iptr->val.l == 0) {
2578 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2579 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2580 M_BEQZ(REG_ITMP1, 0);
2583 LCONST(REG_ITMP2, iptr->val.l);
2584 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2585 M_BNEZ(REG_ITMP1, 0);
2588 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2592 case ICMD_IF_LGE: /* ..., value ==> ... */
2593 /* op1 = target JavaVM pc, val.l = constant */
2595 var_to_reg_int(s1, src, REG_ITMP1);
2596 if (iptr->val.l == 0) {
2600 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2601 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2604 LCONST(REG_ITMP2, iptr->val.l);
2605 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2607 M_BEQZ(REG_ITMP1, 0);
2609 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2613 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2614 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2615 case ICMD_IF_ACMPEQ:
2617 var_to_reg_int(s1, src->prev, REG_ITMP1);
2618 var_to_reg_int(s2, src, REG_ITMP2);
2620 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2624 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2625 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2626 case ICMD_IF_ACMPNE:
2628 var_to_reg_int(s1, src->prev, REG_ITMP1);
2629 var_to_reg_int(s2, src, REG_ITMP2);
2631 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2635 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2636 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2638 var_to_reg_int(s1, src->prev, REG_ITMP1);
2639 var_to_reg_int(s2, src, REG_ITMP2);
2640 M_CMPLT(s1, s2, REG_ITMP1);
2641 M_BNEZ(REG_ITMP1, 0);
2642 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2646 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2647 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2649 var_to_reg_int(s1, src->prev, REG_ITMP1);
2650 var_to_reg_int(s2, src, REG_ITMP2);
2651 M_CMPGT(s1, s2, REG_ITMP1);
2652 M_BNEZ(REG_ITMP1, 0);
2653 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2657 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2658 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2660 var_to_reg_int(s1, src->prev, REG_ITMP1);
2661 var_to_reg_int(s2, src, REG_ITMP2);
2662 M_CMPGT(s1, s2, REG_ITMP1);
2663 M_BEQZ(REG_ITMP1, 0);
2664 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2668 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2669 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2671 var_to_reg_int(s1, src->prev, REG_ITMP1);
2672 var_to_reg_int(s2, src, REG_ITMP2);
2673 M_CMPLT(s1, s2, REG_ITMP1);
2674 M_BEQZ(REG_ITMP1, 0);
2675 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2679 #ifdef CONDITIONAL_LOADCONST
2680 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2682 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2685 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2686 /* val.i = constant */
2688 var_to_reg_int(s1, src, REG_ITMP1);
2689 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2691 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2692 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2693 M_CMPEQ(s1, REG_ZERO, d);
2694 store_reg_to_var_int(iptr->dst, d);
2697 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2698 M_CMPEQ(s1, REG_ZERO, d);
2700 store_reg_to_var_int(iptr->dst, d);
2704 M_MOV(s1, REG_ITMP1);
2707 ICONST(d, iptr[1].val.i);
2709 if ((s3 >= 0) && (s3 <= 255)) {
2710 M_CMOVEQ_IMM(s1, s3, d);
2713 ICONST(REG_ITMP2, s3);
2714 M_CMOVEQ(s1, REG_ITMP2, d);
2716 store_reg_to_var_int(iptr->dst, d);
2719 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2720 /* val.i = constant */
2722 var_to_reg_int(s1, src, REG_ITMP1);
2723 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2725 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2726 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2727 M_CMPEQ(s1, REG_ZERO, d);
2728 store_reg_to_var_int(iptr->dst, d);
2731 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2732 M_CMPEQ(s1, REG_ZERO, d);
2734 store_reg_to_var_int(iptr->dst, d);
2738 M_MOV(s1, REG_ITMP1);
2741 ICONST(d, iptr[1].val.i);
2743 if ((s3 >= 0) && (s3 <= 255)) {
2744 M_CMOVNE_IMM(s1, s3, d);
2747 ICONST(REG_ITMP2, s3);
2748 M_CMOVNE(s1, REG_ITMP2, d);
2750 store_reg_to_var_int(iptr->dst, d);
2753 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2754 /* val.i = constant */
2756 var_to_reg_int(s1, src, REG_ITMP1);
2757 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2759 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2760 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2761 M_CMPLT(s1, REG_ZERO, d);
2762 store_reg_to_var_int(iptr->dst, d);
2765 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2766 M_CMPLE(REG_ZERO, s1, d);
2767 store_reg_to_var_int(iptr->dst, d);
2771 M_MOV(s1, REG_ITMP1);
2774 ICONST(d, iptr[1].val.i);
2776 if ((s3 >= 0) && (s3 <= 255)) {
2777 M_CMOVLT_IMM(s1, s3, d);
2780 ICONST(REG_ITMP2, s3);
2781 M_CMOVLT(s1, REG_ITMP2, d);
2783 store_reg_to_var_int(iptr->dst, d);
2786 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2787 /* val.i = constant */
2789 var_to_reg_int(s1, src, REG_ITMP1);
2790 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2792 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2793 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2794 M_CMPLE(REG_ZERO, s1, d);
2795 store_reg_to_var_int(iptr->dst, d);
2798 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2799 M_CMPLT(s1, REG_ZERO, d);
2800 store_reg_to_var_int(iptr->dst, d);
2804 M_MOV(s1, REG_ITMP1);
2807 ICONST(d, iptr[1].val.i);
2809 if ((s3 >= 0) && (s3 <= 255)) {
2810 M_CMOVGE_IMM(s1, s3, d);
2813 ICONST(REG_ITMP2, s3);
2814 M_CMOVGE(s1, REG_ITMP2, d);
2816 store_reg_to_var_int(iptr->dst, d);
2819 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2820 /* val.i = constant */
2822 var_to_reg_int(s1, src, REG_ITMP1);
2823 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2825 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2826 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2827 M_CMPLT(REG_ZERO, s1, d);
2828 store_reg_to_var_int(iptr->dst, d);
2831 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2832 M_CMPLE(s1, REG_ZERO, d);
2833 store_reg_to_var_int(iptr->dst, d);
2837 M_MOV(s1, REG_ITMP1);
2840 ICONST(d, iptr[1].val.i);
2842 if ((s3 >= 0) && (s3 <= 255)) {
2843 M_CMOVGT_IMM(s1, s3, d);
2846 ICONST(REG_ITMP2, s3);
2847 M_CMOVGT(s1, REG_ITMP2, d);
2849 store_reg_to_var_int(iptr->dst, d);
2852 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2853 /* val.i = constant */
2855 var_to_reg_int(s1, src, REG_ITMP1);
2856 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2858 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2859 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2860 M_CMPLE(s1, REG_ZERO, d);
2861 store_reg_to_var_int(iptr->dst, d);
2864 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2865 M_CMPLT(REG_ZERO, s1, d);
2866 store_reg_to_var_int(iptr->dst, d);
2870 M_MOV(s1, REG_ITMP1);
2873 ICONST(d, iptr[1].val.i);
2875 if ((s3 >= 0) && (s3 <= 255)) {
2876 M_CMOVLE_IMM(s1, s3, d);
2879 ICONST(REG_ITMP2, s3);
2880 M_CMOVLE(s1, REG_ITMP2, d);
2882 store_reg_to_var_int(iptr->dst, d);
2887 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2890 var_to_reg_int(s1, src, REG_RESULT);
2891 M_INTMOVE(s1, REG_RESULT);
2893 #if defined(USE_THREADS)
2894 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2896 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2897 M_ALD(REG_ITMP3, REG_PV, a);
2898 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
2899 M_JSR(REG_RA, REG_ITMP3);
2900 M_LST(REG_RESULT, REG_SP, rd->maxmemuse * 8); /* delay slot */
2902 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2903 M_LDA(REG_PV, REG_RA, disp);
2904 M_LLD(REG_RESULT, REG_SP, rd->maxmemuse * 8);
2907 goto nowperformreturn;
2909 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2911 var_to_reg_flt(s1, src, REG_FRESULT);
2913 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2914 M_TFLTMOVE(t, s1, REG_FRESULT);
2917 #if defined(USE_THREADS)
2918 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2920 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2921 M_ALD(REG_ITMP3, REG_PV, a);
2922 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
2923 M_JSR(REG_RA, REG_ITMP3);
2924 M_DST(REG_FRESULT, REG_SP, rd->maxmemuse * 8); /* delay slot */
2926 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2927 M_LDA(REG_PV, REG_RA, disp);
2928 M_DLD(REG_FRESULT, REG_SP, rd->maxmemuse * 8);
2931 goto nowperformreturn;
2933 case ICMD_RETURN: /* ... ==> ... */
2935 #if defined(USE_THREADS)
2936 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2938 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2939 M_ALD(REG_ITMP3, REG_PV, a);
2940 M_JSR(REG_RA, REG_ITMP3);
2941 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8); /* delay slot */
2942 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2943 M_LDA(REG_PV, REG_RA, disp);
2951 p = parentargs_base;
2953 /* restore return address */
2955 if (!m->isleafmethod) {
2956 p--; M_LLD(REG_RA, REG_SP, 8 * p);
2959 /* restore saved registers */
2961 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2962 p--; M_LLD(rd->savintregs[i], REG_SP, 8 * p);
2964 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2965 p--; M_DLD(rd->savfltregs[i], REG_SP, 8 * p);
2968 /* call trace function */
2971 M_LDA (REG_SP, REG_SP, -24);
2972 M_LST(REG_RA, REG_SP, 0);
2973 M_LST(REG_RESULT, REG_SP, 8);
2974 M_DST(REG_FRESULT, REG_SP,16);
2975 a = dseg_addaddress(cd, m);
2976 M_ALD(rd->argintregs[0], REG_PV, a);
2977 M_MOV(REG_RESULT, rd->argintregs[1]);
2978 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2979 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
2980 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2981 M_ALD(REG_ITMP3, REG_PV, a);
2982 M_JSR (REG_RA, REG_ITMP3);
2984 M_DLD(REG_FRESULT, REG_SP,16);
2985 M_LLD(REG_RESULT, REG_SP, 8);
2986 M_LLD(REG_RA, REG_SP, 0);
2987 M_LDA (REG_SP, REG_SP, 24);
2992 /* deallocate stack */
2994 if (parentargs_base) {
2995 M_LDA(REG_SP, REG_SP, parentargs_base * 8);
3006 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3011 tptr = (void **) iptr->target;
3013 s4ptr = iptr->val.a;
3014 l = s4ptr[1]; /* low */
3015 i = s4ptr[2]; /* high */
3017 var_to_reg_int(s1, src, REG_ITMP1);
3019 {M_INTMOVE(s1, REG_ITMP1);}
3020 else if (l <= 32768) {
3021 M_IADD_IMM(s1, -l, REG_ITMP1);
3024 ICONST(REG_ITMP2, l);
3025 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3031 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
3032 M_BEQZ(REG_ITMP2, 0);
3033 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
3034 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
3036 /* build jump table top down and use address of lowest entry */
3038 /* s4ptr += 3 + i; */
3042 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
3043 dseg_addtarget(cd, (basicblock *) tptr[0]);
3048 /* length of dataseg after last dseg_addtarget is used by load */
3050 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
3051 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
3058 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3060 s4 i, /*l, */val, *s4ptr;
3063 tptr = (void **) iptr->target;
3065 s4ptr = iptr->val.a;
3066 /*l = s4ptr[0];*/ /* default */
3067 i = s4ptr[1]; /* count */
3069 MCODECHECK((i<<2)+8);
3070 var_to_reg_int(s1, src, REG_ITMP1);
3076 ICONST(REG_ITMP2, val);
3077 M_BEQ(s1, REG_ITMP2, 0);
3078 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
3083 tptr = (void **) iptr->target;
3084 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
3091 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3092 /* op1 = return type, val.a = function pointer*/
3096 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3097 /* op1 = return type, val.a = function pointer*/
3101 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3102 /* op1 = return type, val.a = function pointer*/
3106 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3107 /* op1 = arg count, val.a = method pointer */
3109 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3110 /* op1 = arg count, val.a = method pointer */
3112 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3113 /* op1 = arg count, val.a = method pointer */
3115 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3116 /* op1 = arg count, val.a = method pointer */
3123 MCODECHECK((s3 << 1) + 64);
3125 /* copy arguments to registers or stack location */
3127 for (; --s3 >= 0; src = src->prev) {
3128 if (src->varkind == ARGVAR)
3130 if (IS_INT_LNG_TYPE(src->type)) {
3131 if (s3 < INT_ARG_CNT) {
3132 s1 = rd->argintregs[s3];
3133 var_to_reg_int(d, src, s1);
3137 var_to_reg_int(d, src, REG_ITMP1);
3138 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3142 if (s3 < FLT_ARG_CNT) {
3143 s1 = rd->argfltregs[s3];
3144 var_to_reg_flt(d, src, s1);
3145 M_TFLTMOVE(src->type, d, s1);
3148 var_to_reg_flt(d, src, REG_FTMP1);
3149 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3155 switch (iptr->opc) {
3160 codegen_addpatchref(cd, mcodeptr,
3161 (functionptr) lm, iptr->target);
3163 if (showdisassemble) {
3173 a = dseg_addaddress(cd, a);
3174 d = iptr->op1; /* return type */
3176 M_ALD(REG_ITMP3, REG_PV, a); /* built-in-function pointer */
3177 M_JSR(REG_RA, REG_ITMP3);
3179 goto afteractualcall;
3181 case ICMD_INVOKESPECIAL:
3182 gen_nullptr_check(rd->argintregs[0]);
3183 M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr */
3186 case ICMD_INVOKESTATIC:
3188 unresolved_method *um = iptr->target;
3190 codegen_addpatchref(cd, mcodeptr,
3191 PATCHER_invokestatic_special, um);
3193 if (showdisassemble) {
3198 d = um->methodref->parseddesc.md->returntype.type;
3201 a = (ptrint) lm->stubroutine;
3202 d = lm->parseddesc->returntype.type;
3205 a = dseg_addaddress(cd, a);
3206 M_ALD(REG_PV, REG_PV, a); /* method pointer in pv */
3209 case ICMD_INVOKEVIRTUAL:
3210 gen_nullptr_check(rd->argintregs[0]);
3213 unresolved_method *um = iptr->target;
3215 codegen_addpatchref(cd, mcodeptr,
3216 PATCHER_invokevirtual, um);
3218 if (showdisassemble) {
3223 d = um->methodref->parseddesc.md->returntype.type;
3226 s1 = OFFSET(vftbl_t, table[0]) +
3227 sizeof(methodptr) * lm->vftblindex;
3228 d = lm->parseddesc->returntype.type;
3231 M_ALD(REG_METHODPTR, rd->argintregs[0],
3232 OFFSET(java_objectheader, vftbl));
3233 M_ALD(REG_PV, REG_METHODPTR, s1);
3236 case ICMD_INVOKEINTERFACE:
3237 gen_nullptr_check(rd->argintregs[0]);
3240 unresolved_method *um = iptr->target;
3242 codegen_addpatchref(cd, mcodeptr,
3243 PATCHER_invokeinterface, um);
3245 if (showdisassemble) {
3251 d = um->methodref->parseddesc.md->returntype.type;
3254 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3255 sizeof(methodptr*) * lm->class->index;
3257 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3259 d = lm->parseddesc->returntype.type;
3262 M_ALD(REG_METHODPTR, rd->argintregs[0],
3263 OFFSET(java_objectheader, vftbl));
3264 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3265 M_ALD(REG_PV, REG_METHODPTR, s2);
3269 M_JSR(REG_RA, REG_PV);
3276 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3277 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3279 s4 ml = -s1, mh = 0;
3280 while (ml < -32768) { ml += 65536; mh--; }
3282 M_IADD_IMM(REG_PV, ml, REG_PV);
3283 M_LADD(REG_PV, REG_RA, REG_PV);
3286 /* d contains return type */
3288 if (d != TYPE_VOID) {
3289 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3290 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3291 M_INTMOVE(REG_RESULT, s1);
3292 store_reg_to_var_int(iptr->dst, s1);
3295 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3296 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3297 store_reg_to_var_flt(iptr->dst, s1);
3304 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3305 /* op1: 0 == array, 1 == class */
3306 /* val.a: (classinfo*) superclass */
3308 /* superclass is an interface:
3310 * OK if ((sub == NULL) ||
3311 * (sub->vftbl->interfacetablelength > super->index) &&
3312 * (sub->vftbl->interfacetable[-super->index] != NULL));
3314 * superclass is a class:
3316 * OK if ((sub == NULL) || (0
3317 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3318 * super->vftbl->diffvall));
3323 vftbl_t *supervftbl;
3326 super = (classinfo *) iptr->val.a;
3333 superindex = super->index;
3334 supervftbl = super->vftbl;
3337 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3338 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3341 var_to_reg_int(s1, src, REG_ITMP1);
3343 /* calculate interface checkcast code size */
3347 s2 += (showdisassemble ? 2 : 0);
3349 /* calculate class checkcast code size */
3351 s3 = 10 /* 10 + (s1 == REG_ITMP1) */;
3353 s3 += (showdisassemble ? 2 : 0);
3355 /* if class is not resolved, check which code to call */
3358 M_BEQZ(s1, 5 + (showdisassemble ? 2 : 0) + s2 + 2 + s3);
3361 codegen_addpatchref(cd, mcodeptr,
3362 PATCHER_checkcast_instanceof_flags,
3363 (constant_classref *) iptr->target);
3365 if (showdisassemble) {
3369 a = dseg_adds4(cd, 0); /* super->flags */
3370 M_ILD(REG_ITMP2, REG_PV, a);
3371 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3372 M_BEQZ(REG_ITMP2, 1 + s2 + 2);
3376 /* interface checkcast code */
3378 if (!super || super->flags & ACC_INTERFACE) {
3384 codegen_addpatchref(cd, mcodeptr,
3385 PATCHER_checkcast_instanceof_interface,
3386 (constant_classref *) iptr->target);
3388 if (showdisassemble) {
3393 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3394 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3395 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3396 M_BLEZ(REG_ITMP3, 0);
3397 codegen_addxcastrefs(cd, mcodeptr);
3399 M_ALD(REG_ITMP3, REG_ITMP2,
3400 OFFSET(vftbl_t, interfacetable[0]) -
3401 superindex * sizeof(methodptr*));
3402 M_BEQZ(REG_ITMP3, 0);
3403 codegen_addxcastrefs(cd, mcodeptr);
3412 /* class checkcast code */
3414 if (!super || !(super->flags & ACC_INTERFACE)) {
3420 codegen_addpatchref(cd, mcodeptr,
3421 PATCHER_checkcast_instanceof_class,
3422 (constant_classref *) iptr->target);
3424 if (showdisassemble) {
3429 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3430 a = dseg_addaddress(cd, (void *) supervftbl);
3431 M_ALD(REG_ITMP3, REG_PV, a);
3432 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3433 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3435 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3436 /* if (s1 != REG_ITMP1) { */
3437 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3438 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3439 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3440 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3442 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3444 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3445 M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3446 M_ALD(REG_ITMP3, REG_PV, a);
3447 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3448 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3449 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3452 M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3453 M_BNEZ(REG_ITMP3, 0);
3454 codegen_addxcastrefs(cd, mcodeptr);
3457 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3459 store_reg_to_var_int(iptr->dst, d);
3463 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3464 /* op1: 0 == array, 1 == class */
3465 /* val.a: (classinfo*) superclass */
3467 /* superclass is an interface:
3469 * return (sub != NULL) &&
3470 * (sub->vftbl->interfacetablelength > super->index) &&
3471 * (sub->vftbl->interfacetable[-super->index] != NULL);
3473 * superclass is a class:
3475 * return ((sub != NULL) && (0
3476 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3477 * super->vftbl->diffvall));
3482 vftbl_t *supervftbl;
3485 super = (classinfo *) iptr->val.a;
3492 superindex = super->index;
3493 supervftbl = super->vftbl;
3496 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3497 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3500 var_to_reg_int(s1, src, REG_ITMP1);
3501 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3503 M_MOV(s1, REG_ITMP1);
3507 /* calculate interface instanceof code size */
3511 s2 += (showdisassemble ? 2 : 0);
3513 /* calculate class instanceof code size */
3517 s3 += (showdisassemble ? 2 : 0);
3521 /* if class is not resolved, check which code to call */
3524 M_BEQZ(s1, 5 + (showdisassemble ? 2 : 0) + s2 + 2 + s3);
3527 codegen_addpatchref(cd, mcodeptr,
3528 PATCHER_checkcast_instanceof_flags,
3529 (constant_classref *) iptr->target);
3531 if (showdisassemble) {
3535 a = dseg_adds4(cd, 0); /* super->flags */
3536 M_ILD(REG_ITMP3, REG_PV, a);
3537 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
3538 M_BEQZ(REG_ITMP3, 1 + s2 + 2);
3542 /* interface instanceof code */
3544 if (!super || (super->flags & ACC_INTERFACE)) {
3550 codegen_addpatchref(cd, mcodeptr,
3551 PATCHER_checkcast_instanceof_interface,
3552 (constant_classref *) iptr->target);
3554 if (showdisassemble) {
3559 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3560 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3561 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3562 M_BLEZ(REG_ITMP3, 3);
3564 M_ALD(REG_ITMP1, REG_ITMP1,
3565 OFFSET(vftbl_t, interfacetable[0]) -
3566 superindex * sizeof(methodptr*));
3567 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3575 /* class instanceof code */
3577 if (!super || !(super->flags & ACC_INTERFACE)) {
3583 codegen_addpatchref(cd, mcodeptr,
3584 PATCHER_checkcast_instanceof_class,
3585 (constant_classref *) iptr->target);
3587 if (showdisassemble) {
3592 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3593 a = dseg_addaddress(cd, supervftbl);
3594 M_ALD(REG_ITMP2, REG_PV, a);
3595 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3596 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3598 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3599 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3600 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3601 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3602 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3604 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3605 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3608 store_reg_to_var_int(iptr->dst, d);
3612 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3614 var_to_reg_int(s1, src, REG_ITMP1);
3616 codegen_addxcheckarefs(cd, mcodeptr);
3620 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3622 M_BEQZ(REG_RESULT, 0);
3623 codegen_addxexceptionrefs(cd, mcodeptr);
3627 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3628 /* op1 = dimension, val.a = array descriptor */
3630 /* check for negative sizes and copy sizes to stack if necessary */
3632 MCODECHECK((iptr->op1 << 1) + 64);
3634 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3635 var_to_reg_int(s2, src, REG_ITMP1);
3637 codegen_addxcheckarefs(cd, mcodeptr);
3640 /* copy SAVEDVAR sizes to stack */
3642 if (src->varkind != ARGVAR) {
3643 M_LST(s2, REG_SP, s1 * 8);
3647 /* is patcher function set? */
3650 codegen_addpatchref(cd, mcodeptr,
3651 (functionptr) iptr->target, iptr->val.a);
3653 if (showdisassemble) {
3660 a = (ptrint) iptr->val.a;
3663 /* a0 = dimension count */
3665 ICONST(rd->argintregs[0], iptr->op1);
3667 /* a1 = arraydescriptor */
3669 a = dseg_addaddress(cd, a);
3670 M_ALD(rd->argintregs[1], REG_PV, a);
3672 /* a2 = pointer to dimensions = stack pointer */
3674 M_INTMOVE(REG_SP, rd->argintregs[2]);
3676 a = dseg_addaddress(cd, BUILTIN_multianewarray);
3677 M_ALD(REG_ITMP3, REG_PV, a);
3678 M_JSR(REG_RA, REG_ITMP3);
3680 s1 = (s4)((u1 *) mcodeptr - cd->mcodebase);
3682 M_LDA (REG_PV, REG_RA, -s1);
3686 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3687 M_INTMOVE(REG_RESULT, s1);
3688 store_reg_to_var_int(iptr->dst, s1);
3692 throw_cacao_exception_exit(string_java_lang_InternalError,
3693 "Unknown ICMD %d", iptr->opc);
3696 } /* for instruction */
3698 /* copy values to interface registers */
3700 src = bptr->outstack;
3701 len = bptr->outdepth;
3708 if ((src->varkind != STACKVAR)) {
3710 if (IS_FLT_DBL_TYPE(s2)) {
3711 var_to_reg_flt(s1, src, REG_FTMP1);
3712 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3713 M_TFLTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3716 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3720 var_to_reg_int(s1, src, REG_ITMP1);
3721 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3722 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3725 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3731 } /* if (bptr -> flags >= BBREACHED) */
3732 } /* for basic block */
3735 /* generate bound check stubs */
3737 s4 *xcodeptr = NULL;
3740 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3741 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3743 (u1 *) mcodeptr - cd->mcodebase);
3747 M_MOV(bref->reg, REG_ITMP1);
3748 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3750 if (xcodeptr != NULL) {
3751 M_BR(xcodeptr - mcodeptr);
3755 xcodeptr = mcodeptr;
3757 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3758 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3760 M_MOV(REG_ITMP1, rd->argintregs[0]);
3761 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3762 M_ALD(REG_ITMP3, REG_PV, a);
3763 M_JSR(REG_RA, REG_ITMP3);
3765 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3767 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3768 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3770 a = dseg_addaddress(cd, asm_handle_exception);
3771 M_ALD(REG_ITMP3, REG_PV, a);
3777 /* generate negative array size check stubs */
3781 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3782 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3783 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3785 (u1 *) xcodeptr - cd->mcodebase - 4);
3789 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3791 (u1 *) mcodeptr - cd->mcodebase);
3795 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3797 if (xcodeptr != NULL) {
3798 M_BR(xcodeptr - mcodeptr);
3802 xcodeptr = mcodeptr;
3804 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3805 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3807 a = dseg_addaddress(cd, new_negativearraysizeexception);
3808 M_ALD(REG_ITMP3, REG_PV, a);
3809 M_JSR(REG_RA, REG_ITMP3);
3811 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3813 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3814 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3816 a = dseg_addaddress(cd, asm_handle_exception);
3817 M_ALD(REG_ITMP3, REG_PV, a);
3823 /* generate cast check stubs */
3827 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3828 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3829 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3831 (u1 *) xcodeptr - cd->mcodebase - 4);
3835 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3837 (u1 *) mcodeptr - cd->mcodebase);
3841 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3843 if (xcodeptr != NULL) {
3844 M_BR(xcodeptr - mcodeptr);
3848 xcodeptr = mcodeptr;
3850 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3851 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3853 a = dseg_addaddress(cd, new_classcastexception);
3854 M_ALD(REG_ITMP3, REG_PV, a);
3855 M_JSR(REG_RA, REG_ITMP3);
3857 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3859 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3860 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3862 a = dseg_addaddress(cd, asm_handle_exception);
3863 M_ALD(REG_ITMP3, REG_PV, a);
3869 /* generate exception check stubs */
3873 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3874 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3875 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3877 (u1 *) xcodeptr - cd->mcodebase - 4);
3881 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3883 (u1 *) mcodeptr - cd->mcodebase);
3887 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3889 if (xcodeptr != NULL) {
3890 M_BR(xcodeptr - mcodeptr);
3894 xcodeptr = mcodeptr;
3896 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3897 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3898 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3900 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3901 M_ALD(REG_ITMP3, REG_PV, a);
3902 M_JSR(REG_RA, REG_ITMP3);
3905 /* get the exceptionptr from the ptrprt and clear it */
3906 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3907 M_AST(REG_ZERO, REG_RESULT, 0);
3909 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3910 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3912 a = dseg_addaddress(cd, &_exceptionptr);
3913 M_ALD(REG_ITMP3, REG_PV, a);
3914 M_ALD(REG_ITMP1_XPTR, REG_ITMP3, 0);
3915 M_AST(REG_ZERO, REG_ITMP3, 0);
3918 a = dseg_addaddress(cd, asm_handle_exception);
3919 M_ALD(REG_ITMP3, REG_PV, a);
3925 /* generate null pointer check stubs */
3929 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3930 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3931 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3933 (u1 *) xcodeptr - cd->mcodebase - 4);
3937 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3939 (u1 *) mcodeptr - cd->mcodebase);
3943 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3945 if (xcodeptr != NULL) {
3946 M_BR(xcodeptr - mcodeptr);
3950 xcodeptr = mcodeptr;
3952 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3953 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3955 a = dseg_addaddress(cd, new_nullpointerexception);
3956 M_ALD(REG_ITMP3, REG_PV, a);
3957 M_JSR(REG_RA, REG_ITMP3);
3959 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3961 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3962 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3964 a = dseg_addaddress(cd, asm_handle_exception);
3965 M_ALD(REG_ITMP3, REG_PV, a);
3972 /* generate put/getstatic stub call code */
3979 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3980 /* check code segment size */
3982 MCODECHECK(22 + 4 + 1);
3984 /* Get machine code which is patched back in later. The call is */
3985 /* 2 instruction words long. */
3987 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3989 /* We need to split this, because an unaligned 8 byte read causes */
3992 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3994 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3995 /* create a virtual java_objectheader */
3997 /* align data structure to 8-byte */
4001 *((ptrint *) (mcodeptr + 0)) = 0; /* vftbl */
4002 *((ptrint *) (mcodeptr + 2)) = (ptrint) get_dummyLR(); /* monitorPtr */
4004 mcodeptr += 2 * 2; /* mcodeptr is a `u4*' pointer */
4007 /* patch in the call to call the following code (done at compile */
4010 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4011 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4013 M_BRS(tmpmcodeptr - (xcodeptr + 1));
4014 M_MOV(REG_RA, REG_ITMP3); /* branch delay slot */
4016 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4018 /* create stack frame */
4020 M_LSUB_IMM(REG_SP, 5 * 8, REG_SP);
4022 /* move return address onto stack */
4024 M_AST(REG_RA, REG_SP, 4 * 8);
4025 M_MOV(REG_ITMP3, REG_RA); /* restore return address */
4027 /* move pointer to java_objectheader onto stack */
4029 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4030 M_MOV(REG_RA, REG_ITMP3); /* save return address */
4033 M_LSUB_IMM(REG_RA, 6 * 4 + 2 * 8, REG_RA);
4034 M_AST(REG_RA, REG_SP, 3 * 8);
4035 M_MOV(REG_ITMP3, REG_RA); /* restore return address */
4037 M_AST(REG_ZERO, REG_SP, 3 * 8);
4040 /* move machine code onto stack */
4042 a = dseg_adds8(cd, mcode);
4043 M_LLD(REG_ITMP3, REG_PV, a);
4044 M_LST(REG_ITMP3, REG_SP, 2 * 8);
4046 /* move class/method/field reference onto stack */
4048 a = dseg_addaddress(cd, pref->ref);
4049 M_ALD(REG_ITMP3, REG_PV, a);
4050 M_AST(REG_ITMP3, REG_SP, 1 * 8);
4052 /* move patcher function pointer onto stack */
4054 a = dseg_addaddress(cd, pref->patcher);
4055 M_ALD(REG_ITMP3, REG_PV, a);
4056 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4058 a = dseg_addaddress(cd, asm_wrapper_patcher);
4059 M_ALD(REG_ITMP3, REG_PV, a);
4066 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4068 docacheflush((void*) m->entrypoint, ((u1*) mcodeptr - cd->mcodebase));
4072 /* createcompilerstub **********************************************************
4074 Creates a stub routine which calls the compiler.
4076 *******************************************************************************/
4078 #define COMPSTUB_SIZE 4
4080 u1 *createcompilerstub(methodinfo *m)
4082 u8 *s = CNEW(u8, COMPSTUB_SIZE); /* memory to hold the stub */
4083 s4 *mcodeptr = (s4 *) s; /* code generation pointer */
4085 /* code for the stub */
4086 M_ALD(REG_PV, REG_PV, 24); /* load pointer to the compiler */
4088 M_JSR(REG_ITMP1, REG_PV); /* jump to the compiler, return address
4089 in itmp1 is used as method pointer */
4092 s[2] = (u8) m; /* literals to be adressed */
4093 s[3] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
4095 (void) docacheflush((void*) s, (char*) mcodeptr - (char*) s);
4097 #if defined(STATISTICS)
4099 count_cstub_len += COMPSTUB_SIZE * 8;
4106 /* function removecompilerstub *************************************************
4108 deletes a compilerstub from memory (simply by freeing it)
4110 *******************************************************************************/
4112 void removecompilerstub(u1 *stub)
4114 CFREE(stub, COMPSTUB_SIZE * 8);
4118 /* function: createnativestub **************************************************
4120 creates a stub routine which calls a native method
4122 *******************************************************************************/
4124 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4125 #define NATIVESTUB_STACK 2
4126 #define NATIVESTUB_THREAD_EXTRA 5
4128 #define NATIVESTUB_STACK 1
4129 #define NATIVESTUB_THREAD_EXTRA 1
4132 #define NATIVESTUB_SIZE (54 + 4 + NATIVESTUB_THREAD_EXTRA - 1)
4133 #define NATIVESTUB_STATIC_SIZE (18 + 4 + 1)
4134 #define NATIVESTUB_VERBOSE_SIZE (50 + 17)
4135 #define NATIVESTUB_OFFSET 11
4138 u1 *createnativestub(functionptr f, methodinfo *m)
4140 u8 *s; /* memory to hold the stub */
4142 s4 *mcodeptr; /* code generation pointer */
4143 s4 stackframesize = 0; /* size of stackframe if needed */
4148 t_inlining_globals *id;
4151 /* mark start of dump memory area */
4153 dumpsize = dump_size();
4155 /* setup registers before using it */
4157 cd = DNEW(codegendata);
4158 rd = DNEW(registerdata);
4159 id = DNEW(t_inlining_globals);
4161 inlining_setup(m, id);
4162 reg_setup(m, rd, id);
4164 method_descriptor2types(m); /* set paramcount and paramtypes */
4166 stubsize = NATIVESTUB_SIZE; /* calculate nativestub size */
4168 if ((m->flags & ACC_STATIC) && !m->class->initialized)
4169 stubsize += NATIVESTUB_STATIC_SIZE;
4172 stubsize += NATIVESTUB_VERBOSE_SIZE;
4174 s = CNEW(u8, stubsize); /* memory to hold the stub */
4175 cs = s + NATIVESTUB_OFFSET;
4176 mcodeptr = (s4 *) (cs); /* code generation pointer */
4178 /* set some required varibles which are normally set by codegen_setup */
4179 cd->mcodebase = (u1 *) mcodeptr;
4180 cd->patchrefs = NULL;
4182 *(cs-1) = (u8) f; /* address of native method */
4183 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4184 *(cs-2) = (u8) &builtin_get_exceptionptrptr;
4186 *(cs-2) = (u8) (&_exceptionptr); /* address of exceptionptr */
4188 *(cs-3) = (u8) asm_handle_nat_exception;/* addr of asm exception handler */
4189 *(cs-4) = (u8) (&env); /* addr of jni_environement */
4190 *(cs-5) = (u8) builtin_trace_args;
4192 *(cs-7) = (u8) builtin_displaymethodstop;
4193 *(cs-8) = (u8) m->class;
4194 *(cs-9) = (u8) asm_wrapper_patcher;
4195 *(cs-10) = (u8) NULL; /* filled with machine code */
4196 *(cs-11) = (u8) PATCHER_clinit;
4198 M_LDA(REG_SP, REG_SP, -NATIVESTUB_STACK * 8); /* build up stackframe */
4199 M_LST(REG_RA, REG_SP, 0); /* store return address */
4201 /* if function is static, check for initialized */
4203 if ((m->flags & ACC_STATIC) && !m->class->initialized) {
4204 codegen_addpatchref(cd, mcodeptr, NULL, NULL);
4207 /* max. 50 instructions */
4213 M_LDA(REG_SP, REG_SP, -(18 * 8));
4214 M_AST(REG_RA, REG_SP, 1 * 8);
4216 /* save integer argument registers */
4217 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
4218 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
4221 /* save and copy float arguments into integer registers */
4222 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
4223 t = m->paramtypes[p];
4225 if (IS_FLT_DBL_TYPE(t)) {
4226 if (IS_2_WORD_TYPE(t)) {
4227 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
4228 M_LLD(rd->argintregs[p], REG_SP, (10 + p) * 8);
4231 M_FST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
4232 M_ILD(rd->argintregs[p], REG_SP, (10 + p) * 8);
4236 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
4240 M_ALD(REG_ITMP1, REG_PV, -6 * 8); /* method address */
4241 M_AST(REG_ITMP1, REG_SP, 0);
4242 M_ALD(REG_ITMP3, REG_PV, -5 * 8); /* builtin_trace_args */
4243 M_JSR(REG_RA, REG_ITMP3);
4245 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4246 M_LDA(REG_PV, REG_RA, disp);
4248 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
4249 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
4252 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
4253 t = m->paramtypes[p];
4255 if (IS_FLT_DBL_TYPE(t)) {
4256 if (IS_2_WORD_TYPE(t)) {
4257 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
4260 M_FLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
4264 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
4268 M_ALD(REG_RA, REG_SP, 1 * 8);
4269 M_LDA(REG_SP, REG_SP, 18 * 8);
4272 /* save argument registers on stack -- if we have to */
4274 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
4276 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
4277 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
4279 stackframesize = stackparamcnt + paramshiftcnt;
4281 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
4283 /* copy stack arguments into new stack frame -- if any */
4284 for (i = 0; i < stackparamcnt; i++) {
4285 M_LLD(REG_ITMP1, REG_SP, (stackparamcnt + 1 + i) * 8);
4286 M_LST(REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
4289 if (m->flags & ACC_STATIC) {
4290 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4291 M_DST(rd->argfltregs[5], REG_SP, 1 * 8);
4293 M_LST(rd->argintregs[5], REG_SP, 1 * 8);
4296 if (IS_FLT_DBL_TYPE(m->paramtypes[4])) {
4297 M_DST(rd->argfltregs[4], REG_SP, 0 * 8);
4299 M_LST(rd->argintregs[4], REG_SP, 0 * 8);
4303 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4304 M_DST(rd->argfltregs[5], REG_SP, 0 * 8);
4306 M_LST(rd->argintregs[5], REG_SP, 0 * 8);
4311 if (m->flags & ACC_STATIC) {
4312 M_MOV(rd->argintregs[5], rd->argintregs[7]);
4314 M_DMFC1(REG_ITMP1, rd->argfltregs[5]);
4315 M_DMTC1(REG_ITMP1, rd->argfltregs[7]);
4317 M_MOV(rd->argintregs[4], rd->argintregs[6]);
4319 M_DMFC1(REG_ITMP1, rd->argfltregs[4]);
4320 M_DMTC1(REG_ITMP1, rd->argfltregs[6]);
4322 M_MOV(rd->argintregs[3], rd->argintregs[5]);
4323 M_DMFC1(REG_ITMP1, rd->argfltregs[3]);
4325 M_MOV(rd->argintregs[2], rd->argintregs[4]);
4326 M_DMTC1(REG_ITMP1, rd->argfltregs[5]);
4328 M_MOV(rd->argintregs[1], rd->argintregs[3]);
4329 M_DMFC1(REG_ITMP1, rd->argfltregs[2]);
4331 M_MOV(rd->argintregs[0], rd->argintregs[2]);
4332 M_DMTC1(REG_ITMP1, rd->argfltregs[4]);
4334 M_DMFC1(REG_ITMP1, rd->argfltregs[1]);
4335 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4337 M_DMFC1(REG_ITMP1, rd->argfltregs[0]);
4338 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4340 M_ALD(rd->argintregs[1], REG_PV, -8 * 8);
4343 M_MOV(rd->argintregs[6], rd->argintregs[7]);
4345 M_DMFC1(REG_ITMP1, rd->argfltregs[6]);
4346 M_DMTC1(REG_ITMP1, rd->argfltregs[7]);
4348 M_MOV(rd->argintregs[5], rd->argintregs[6]);
4350 M_DMFC1(REG_ITMP1, rd->argfltregs[5]);
4351 M_DMTC1(REG_ITMP1, rd->argfltregs[6]);
4353 M_MOV(rd->argintregs[4], rd->argintregs[5]);
4354 M_DMFC1(REG_ITMP1, rd->argfltregs[4]);
4356 M_MOV(rd->argintregs[3], rd->argintregs[4]);
4357 M_DMTC1(REG_ITMP1, rd->argfltregs[5]);
4359 M_MOV(rd->argintregs[2], rd->argintregs[3]);
4360 M_DMFC1(REG_ITMP1, rd->argfltregs[3]);
4362 M_MOV(rd->argintregs[1], rd->argintregs[2]);
4363 M_DMTC1(REG_ITMP1, rd->argfltregs[4]);
4365 M_MOV(rd->argintregs[0], rd->argintregs[1]);
4366 M_DMFC1(REG_ITMP1, rd->argfltregs[2]);
4368 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4370 M_DMFC1(REG_ITMP1, rd->argfltregs[1]);
4371 M_DMFC1(REG_ITMP2, rd->argfltregs[0]);
4373 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4374 M_DMTC1(REG_ITMP2, rd->argfltregs[1]);
4377 M_ALD(rd->argintregs[0], REG_PV, -4 * 8); /* jni environement */
4378 M_ALD(REG_ITMP3, REG_PV, -1 * 8); /* load adress of native method */
4379 M_JSR(REG_RA, REG_ITMP3); /* call native method */
4380 M_NOP; /* delay slot */
4382 /* remove stackframe if there is one */
4383 if (stackframesize) {
4384 M_LDA(REG_SP, REG_SP, stackframesize * 8);
4387 /* 17 instructions */
4389 M_LDA(REG_SP, REG_SP, -(3 * 8));
4390 M_AST(REG_RA, REG_SP, 0 * 8);
4391 M_LST(REG_RESULT, REG_SP, 1 * 8);
4392 M_DST(REG_FRESULT, REG_SP, 2 * 8);
4393 M_ALD(rd->argintregs[0], REG_PV, -6 * 8);
4394 M_MOV(REG_RESULT, rd->argintregs[1]);
4395 M_DMFC1(REG_ITMP1, REG_FRESULT);
4396 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4397 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4398 M_ALD(REG_ITMP3, REG_PV, -7 * 8);/* builtin_displaymethodstop */
4399 M_JSR(REG_RA, REG_ITMP3);
4401 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4402 M_LDA(REG_PV, REG_RA, disp);
4403 M_ALD(REG_RA, REG_SP, 0 * 8);
4404 M_LLD(REG_RESULT, REG_SP, 1 * 8);
4405 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
4406 M_LDA(REG_SP, REG_SP, 3 * 8);
4409 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4410 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* builtin_get_exceptionptrptr */
4411 M_JSR(REG_RA, REG_ITMP3);
4414 if (IS_FLT_DBL_TYPE(m->returntype)) {
4415 M_DST(REG_FRESULT, REG_SP, 1 * 8);
4418 M_AST(REG_RESULT, REG_SP, 1 * 8);
4421 M_MOV(REG_RESULT, REG_ITMP3);
4423 if (IS_FLT_DBL_TYPE(m->returntype)) {
4424 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
4427 M_ALD(REG_RESULT, REG_SP, 1 * 8);
4430 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* get address of exceptionptr */
4433 M_LLD(REG_RA, REG_SP, 0); /* load return address */
4434 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4436 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
4437 M_LDA(REG_SP, REG_SP, NATIVESTUB_STACK * 8);/*remove stackframe, delay slot*/
4439 M_RET(REG_RA); /* return to caller */
4440 M_NOP; /* delay slot */
4442 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4443 M_ALD(REG_ITMP3, REG_PV, -3 * 8); /* load asm exception handler address */
4445 M_JMP(REG_ITMP3); /* jump to asm exception handler */
4446 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4449 /* generate static stub call code */
4456 /* there can only be one clinit ref entry */
4457 pref = cd->patchrefs;
4460 /* Get machine code which is patched back in later. The call is */
4461 /* 2 instruction words long. */
4463 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4465 /* We need to split this, because an unaligned 8 byte read causes */
4468 *(cs-10) = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
4470 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4471 /* create a virtual java_objectheader */
4473 /* align data structure to 8-byte */
4477 *((ptrint *) (mcodeptr + 0)) = 0; /* vftbl */
4478 *((ptrint *) (mcodeptr + 2)) = (ptrint) get_dummyLR(); /* monitorPtr */
4480 mcodeptr += 2 * 2; /* mcodeptr is a `u4*' pointer */
4483 /* patch in the call to call the following code (done at compile */
4486 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4487 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4489 M_BRS(tmpmcodeptr - (xcodeptr + 1));
4490 M_MOV(REG_RA, REG_ITMP3); /* branch delay slot */
4492 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4494 /* create stack frame */
4496 M_LSUB_IMM(REG_SP, 5 * 8, REG_SP);
4498 /* move return address onto stack */
4500 M_AST(REG_RA, REG_SP, 4 * 8);
4501 M_MOV(REG_ITMP3, REG_RA); /* restore return address */
4503 /* move pointer to java_objectheader onto stack */
4505 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4506 M_MOV(REG_RA, REG_ITMP3); /* save return address */
4509 M_LSUB_IMM(REG_RA, 6 * 4 + 2 * 8, REG_RA);
4510 M_AST(REG_RA, REG_SP, 3 * 8);
4511 M_MOV(REG_ITMP3, REG_RA); /* restore return address */
4513 M_AST(REG_ZERO, REG_SP, 3 * 8);
4516 /* move machine code onto stack */
4518 M_LLD(REG_ITMP3, REG_PV, -10 * 8); /* machine code */
4519 M_LST(REG_ITMP3, REG_SP, 2 * 8);
4521 /* move class reference onto stack */
4523 M_ALD(REG_ITMP3, REG_PV, -8 * 8); /* class */
4524 M_AST(REG_ITMP3, REG_SP, 1 * 8);
4526 /* move patcher function pointer onto stack */
4528 M_ALD(REG_ITMP3, REG_PV, -11 * 8); /* patcher function */
4529 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4531 M_ALD(REG_ITMP3, REG_PV, -9 * 8); /* asm_wrapper_patcher */
4537 (void) docacheflush((void*) cs, (char*) mcodeptr - (char*) cs);
4539 /* Check if the stub size is big enough to hold the whole stub generated. */
4540 /* If not, this can lead into unpredictable crashes, because of heap */
4543 if ((s4) ((ptrint) mcodeptr - (ptrint) s) > stubsize * sizeof(u8)) {
4544 throw_cacao_exception_exit(string_java_lang_InternalError,
4545 "Native stub size %d is to small for current stub size %d",
4546 stubsize, (s4) ((ptrint) mcodeptr - (ptrint) s));
4549 #if defined(STATISTICS)
4551 count_nstub_len += NATIVESTUB_SIZE * 8;
4554 /* release dump area */
4556 dump_release(dumpsize);
4558 return (u1 *) (s + NATIVESTUB_OFFSET);
4562 /* function: removenativestub **************************************************
4564 removes a previously created native-stub from memory
4566 *******************************************************************************/
4568 void removenativestub(u1 *stub)
4570 CFREE((u8 *) stub - NATIVESTUB_OFFSET, NATIVESTUB_SIZE * 8);
4574 void docacheflush(u1 *p, long bytelen)
4576 u1 *e = p + bytelen;
4577 long psize = sysconf(_SC_PAGESIZE);
4578 p -= (long) p & (psize - 1);
4579 e += psize - ((((long) e - 1) & (psize - 1)) + 1);
4581 mprotect(p, bytelen, PROT_READ | PROT_WRITE | PROT_EXEC);
4586 * These are local overrides for various environment variables in Emacs.
4587 * Please do not remove this and leave it at the end of the file, where
4588 * Emacs will automagically detect them.
4589 * ---------------------------------------------------------------------
4592 * indent-tabs-mode: t