1 /* 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 Contains the codegenerator for an MIPS (R4000 or higher) processor.
31 This module generates MIPS machine code for a sequence of
32 intermediate code commands (ICMDs).
34 $Id: codegen.c 1862 2005-01-05 10:48:23Z twisti $
45 #include "cacao/cacao.h"
46 #include "native/native.h"
47 #include "vm/builtin.h"
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/jit.h"
50 #include "vm/jit/reg.h"
51 #include "vm/jit/mips/codegen.h"
52 #include "vm/jit/mips/types.h"
55 /* *****************************************************************************
57 Datatypes and Register Allocations:
58 -----------------------------------
60 On 64-bit-machines (like the MIPS) all operands are stored in the
61 registers in a 64-bit form, even when the correspondig JavaVM operands
62 only need 32 bits. This is done by a canonical representation:
64 32-bit integers are allways stored as sign-extended 64-bit values (this
65 approach is directly supported by the MIPS architecture and is very easy
68 32-bit-floats are stored in a 64-bit double precision register by simply
69 expanding the exponent and mantissa with zeroes. (also supported by the
75 The calling conventions and the layout of the stack is explained in detail
76 in the documention file: calling.doc
78 *******************************************************************************/
81 /* register descripton - array ************************************************/
83 /* #define REG_RES 0 reserved register for OS or code generator */
84 /* #define REG_RET 1 return value register */
85 /* #define REG_EXC 2 exception value register (only old jit) */
86 /* #define REG_SAV 3 (callee) saved register */
87 /* #define REG_TMP 4 scratch temporary register (caller saved) */
88 /* #define REG_ARG 5 argument register (caller saved) */
90 /* #define REG_END -1 last entry in tables */
92 static int nregdescint[] = {
93 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
94 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
95 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
96 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
99 /* for use of reserved registers, see comment above */
101 static int nregdescfloat[] = {
102 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
103 REG_TMP, REG_TMP, REG_TMP, REG_TMP, 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_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
108 /* for use of reserved registers, see comment above */
111 /* Include independent code generation stuff -- include after register */
112 /* descriptions to avoid extern definitions. */
114 #include "vm/jit/codegen.inc"
115 #include "vm/jit/reg.inc"
117 #include "vm/jit/lsra.inc"
121 /* NullPointerException handlers and exception handling initialisation */
123 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
124 void thread_restartcriticalsection(ucontext_t *uc)
127 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[CTX_EPC])) != NULL)
128 uc->uc_mcontext.gregs[CTX_EPC] = (u8) critical;
132 /* NullPointerException signal handler for hardware null pointer check */
134 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
139 java_objectheader *xptr;
141 struct ucontext *_uc = (struct ucontext *) _p;
142 mcontext_t *sigctx = &_uc->uc_mcontext;
143 struct sigaction act;
145 instr = *((s4 *) (sigctx->gregs[CTX_EPC]));
146 faultaddr = sigctx->gregs[(instr >> 21) & 0x1f];
148 if (faultaddr == 0) {
149 /* Reset signal handler - necessary for SysV, does no harm for BSD */
151 act.sa_sigaction = catch_NullPointerException;
152 act.sa_flags = SA_SIGINFO;
153 sigaction(sig, &act, NULL);
156 sigaddset(&nsig, sig);
157 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
159 xptr = new_nullpointerexception();
161 sigctx->gregs[REG_ITMP1_XPTR] = (u8) xptr;
162 sigctx->gregs[REG_ITMP2_XPC] = sigctx->gregs[CTX_EPC];
163 sigctx->gregs[CTX_EPC] = (u8) asm_handle_exception;
166 faultaddr += (long) ((instr << 16) >> 16);
167 fprintf(stderr, "faulting address: 0x%lx at 0x%lx\n", (long) faultaddr, (long) sigctx->gregs[CTX_EPC]);
168 panic("Stack overflow");
175 void init_exceptions(void)
177 struct sigaction act;
179 /* The Boehm GC initialization blocks the SIGSEGV signal. So we do a
180 dummy allocation here to ensure that the GC is initialized.
182 heap_allocate(1, 0, NULL);
184 /* install signal handlers we need to convert to exceptions */
186 sigemptyset(&act.sa_mask);
189 act.sa_sigaction = catch_NullPointerException;
190 act.sa_flags = SA_SIGINFO;
193 sigaction(SIGSEGV, &act, NULL);
197 sigaction(SIGBUS, &act, NULL);
201 /* Turn off flush-to-zero */
204 n.fc_word = get_fpc_csr();
205 n.fc_struct.flush = 0;
206 set_fpc_csr(n.fc_word);
211 /* function gen_mcode **********************************************************
213 generates machine code
215 *******************************************************************************/
217 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
219 s4 len, s1, s2, s3, d;
233 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
235 /* space to save used callee saved registers */
237 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
238 savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
240 parentargs_base = rd->maxmemuse + savedregs_num;
242 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
244 if (checksync && (m->flags & ACC_SYNCHRONIZED))
249 /* adjust frame size for 16 byte alignment */
251 if (parentargs_base & 1)
254 /* create method header */
257 (void) dseg_addaddress(cd, m); /* Filler */
259 (void) dseg_addaddress(cd, m); /* MethodPointer */
260 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
262 #if defined(USE_THREADS)
264 /* IsSync contains the offset relative to the stack pointer for the
265 argument of monitor_exit used in the exception handler. Since the
266 offset could be zero and give a wrong meaning of the flag it is
270 if (checksync && (m->flags & ACC_SYNCHRONIZED))
271 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8); /* IsSync */
276 (void) dseg_adds4(cd, 0); /* IsSync */
278 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
279 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse);/* IntSave */
280 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse);/* FltSave */
281 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
283 /* create exception table */
285 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
286 dseg_addtarget(cd, ex->start);
287 dseg_addtarget(cd, ex->end);
288 dseg_addtarget(cd, ex->handler);
289 (void) dseg_addaddress(cd, ex->catchtype);
292 /* initialize mcode variables */
294 mcodeptr = (s4 *) cd->mcodebase;
295 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
296 MCODECHECK(128 + m->paramcount);
298 /* create stack frame (if necessary) */
300 if (parentargs_base) {
301 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
304 /* save return address and used callee saved registers */
307 if (!m->isleafmethod) {
308 p--; M_LST(REG_RA, REG_SP, 8 * p);
310 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
311 p--; M_LST(rd->savintregs[i], REG_SP, 8 * p);
313 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
314 p--; M_DST(rd->savfltregs[i], REG_SP, 8 * p);
317 /* save monitorenter argument */
319 #if defined(USE_THREADS)
320 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
321 if (m->flags & ACC_STATIC) {
322 p = dseg_addaddress(cd, m->class);
323 M_ALD(REG_ITMP1, REG_PV, p);
324 M_AST(REG_ITMP1, REG_SP, rd->maxmemuse * 8);
327 M_AST(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
332 /* copy argument registers to stack and call trace function with pointer
333 to arguments on stack. ToDo: save floating point registers !!!!!!!!!
337 M_LDA(REG_SP, REG_SP, -(18 * 8));
338 M_LST(REG_RA, REG_SP, 1 * 8);
340 /* save integer argument registers */
341 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
342 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
345 /* save and copy float arguments into integer registers */
346 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
347 t = m->paramtypes[p];
349 if (IS_FLT_DBL_TYPE(t)) {
350 if (IS_2_WORD_TYPE(t)) {
351 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
352 M_LLD(rd->argintregs[p], REG_SP, (10 + p) * 8);
355 M_FST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
356 M_ILD(rd->argintregs[p], REG_SP, (10 + p) * 8);
360 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
364 p = dseg_addaddress(cd, m);
365 M_ALD(REG_ITMP1, REG_PV, p);
366 M_LST(REG_ITMP1, REG_SP, 0);
367 p = dseg_addaddress(cd, (void *) builtin_trace_args);
368 M_ALD(REG_ITMP3, REG_PV, p);
369 M_JSR(REG_RA, REG_ITMP3);
372 M_LLD(REG_RA, REG_SP, 1 * 8);
374 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
375 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
378 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
379 t = m->paramtypes[p];
381 if (IS_FLT_DBL_TYPE(t)) {
382 if (IS_2_WORD_TYPE(t)) {
383 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
386 M_FLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
390 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
394 M_LDA(REG_SP, REG_SP, 18 * 8);
397 /* take arguments out of register or stack frame */
399 for (p = 0, l = 0; p < m->paramcount; p++) {
400 t = m->paramtypes[p];
401 var = &(rd->locals[l][t]);
403 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
407 if (IS_INT_LNG_TYPE(t)) { /* integer args */
408 if (p < INT_ARG_CNT) { /* register arguments */
409 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
410 M_INTMOVE(rd->argintregs[p], var->regoff);
411 } else { /* reg arg -> spilled */
412 M_LST(rd->argintregs[p], REG_SP, 8 * var->regoff);
415 } else { /* stack arguments */
416 pa = p - INT_ARG_CNT;
417 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
418 M_LLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
420 } else { /* stack arg -> spilled */
421 M_LLD(REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
422 M_LST(REG_ITMP1, REG_SP, 8 * var->regoff);
426 } else { /* floating args */
427 if (p < FLT_ARG_CNT) { /* register arguments */
428 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
429 M_TFLTMOVE(var->type, rd->argfltregs[p], var->regoff);
431 } else { /* reg arg -> spilled */
432 M_DST(rd->argfltregs[p], REG_SP, var->regoff * 8);
435 } else { /* stack arguments */
436 pa = p - FLT_ARG_CNT;
437 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
438 M_DLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
440 } else { /* stack-arg -> spilled */
441 M_DLD(REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
442 M_DST(REG_FTMP1, REG_SP, 8 * var->regoff);
448 /* call monitorenter function */
450 #if defined(USE_THREADS)
451 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
453 s8 func_enter = (m->flags & ACC_STATIC) ?
454 (s8) builtin_staticmonitorenter : (s8) builtin_monitorenter;
455 p = dseg_addaddress(cd, (void *) func_enter);
456 M_ALD(REG_ITMP3, REG_PV, p);
457 M_JSR(REG_RA, REG_ITMP3);
458 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
459 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
460 M_LDA(REG_PV, REG_RA, disp);
465 /* end of header generation */
467 /* walk through all basic blocks */
468 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
470 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
472 if (bptr->flags >= BBREACHED) {
474 /* branch resolving */
477 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
478 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
484 /* copy interface registers to their destination */
489 while (src != NULL) {
491 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
492 d = reg_of_var(rd, src, REG_ITMP1);
493 M_INTMOVE(REG_ITMP1, d);
494 store_reg_to_var_int(src, d);
497 d = reg_of_var(rd, src, REG_IFTMP);
498 if ((src->varkind != STACKVAR)) {
500 if (IS_FLT_DBL_TYPE(s2)) {
501 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
502 s1 = rd->interfaces[len][s2].regoff;
503 M_TFLTMOVE(s2, s1, d);
506 M_DLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
508 store_reg_to_var_flt(src, d);
511 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
512 s1 = rd->interfaces[len][s2].regoff;
516 M_LLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
518 store_reg_to_var_int(src, d);
525 /* walk through all instructions */
529 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
531 MCODECHECK(64); /* an instruction usually needs < 64 words */
534 case ICMD_NOP: /* ... ==> ... */
537 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
539 var_to_reg_int(s1, src, REG_ITMP1);
541 codegen_addxnullrefs(cd, mcodeptr);
545 /* constant operations ************************************************/
547 case ICMD_ICONST: /* ... ==> ..., constant */
548 /* op1 = 0, val.i = constant */
550 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
551 ICONST(d, iptr->val.i);
552 store_reg_to_var_int(iptr->dst, d);
555 case ICMD_LCONST: /* ... ==> ..., constant */
556 /* op1 = 0, val.l = constant */
558 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
559 LCONST(d, iptr->val.l);
560 store_reg_to_var_int(iptr->dst, d);
563 case ICMD_FCONST: /* ... ==> ..., constant */
564 /* op1 = 0, val.f = constant */
566 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
567 a = dseg_addfloat(cd, iptr->val.f);
569 store_reg_to_var_flt(iptr->dst, d);
572 case ICMD_DCONST: /* ... ==> ..., constant */
573 /* op1 = 0, val.d = constant */
575 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
576 a = dseg_adddouble(cd, iptr->val.d);
578 store_reg_to_var_flt (iptr->dst, d);
581 case ICMD_ACONST: /* ... ==> ..., constant */
582 /* op1 = 0, val.a = constant */
584 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
586 a = dseg_addaddress(cd, iptr->val.a);
589 M_INTMOVE(REG_ZERO, d);
591 store_reg_to_var_int(iptr->dst, d);
595 /* load/store operations **********************************************/
597 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
598 case ICMD_LLOAD: /* op1 = local variable */
601 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
602 if ((iptr->dst->varkind == LOCALVAR) &&
603 (iptr->dst->varnum == iptr->op1))
605 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
606 if (var->flags & INMEMORY) {
607 M_LLD(d, REG_SP, 8 * var->regoff);
609 M_INTMOVE(var->regoff,d);
611 store_reg_to_var_int(iptr->dst, d);
614 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
615 case ICMD_DLOAD: /* op1 = local variable */
617 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
618 if ((iptr->dst->varkind == LOCALVAR) &&
619 (iptr->dst->varnum == iptr->op1))
621 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
623 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
624 if (var->flags & INMEMORY) {
625 M_CCFLD(var->type, t2, d, REG_SP, 8 * var->regoff);
627 M_CCFLTMOVE(var->type, t2, var->regoff, d);
630 store_reg_to_var_flt(iptr->dst, d);
634 case ICMD_ISTORE: /* ..., value ==> ... */
635 case ICMD_LSTORE: /* op1 = local variable */
638 if ((src->varkind == LOCALVAR) &&
639 (src->varnum == iptr->op1))
641 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
642 if (var->flags & INMEMORY) {
643 var_to_reg_int(s1, src, REG_ITMP1);
644 M_LST(s1, REG_SP, 8 * var->regoff);
647 var_to_reg_int(s1, src, var->regoff);
648 M_INTMOVE(s1, var->regoff);
652 case ICMD_FSTORE: /* ..., value ==> ... */
653 case ICMD_DSTORE: /* op1 = local variable */
655 if ((src->varkind == LOCALVAR) &&
656 (src->varnum == iptr->op1))
658 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
660 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
661 if (var->flags & INMEMORY) {
662 var_to_reg_flt(s1, src, REG_FTMP1);
663 M_CCFST(t1, var->type, s1, REG_SP, 8 * var->regoff);
666 var_to_reg_flt(s1, src, var->regoff);
667 M_CCFLTMOVE(t1, var->type, s1, var->regoff);
673 /* pop/dup/swap operations ********************************************/
675 /* attention: double and longs are only one entry in CACAO ICMDs */
677 case ICMD_POP: /* ..., value ==> ... */
678 case ICMD_POP2: /* ..., value, value ==> ... */
681 case ICMD_DUP: /* ..., a ==> ..., a, a */
682 M_COPY(src, iptr->dst);
685 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
687 M_COPY(src, iptr->dst);
688 M_COPY(src->prev, iptr->dst->prev);
689 M_COPY(iptr->dst, iptr->dst->prev->prev);
692 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
694 M_COPY(src, iptr->dst);
695 M_COPY(src->prev, iptr->dst->prev);
696 M_COPY(src->prev->prev, iptr->dst->prev->prev);
697 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
700 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
702 M_COPY(src, iptr->dst);
703 M_COPY(src->prev, iptr->dst->prev);
706 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
708 M_COPY(src, iptr->dst);
709 M_COPY(src->prev, iptr->dst->prev);
710 M_COPY(src->prev->prev, iptr->dst->prev->prev);
711 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
712 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
715 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
717 M_COPY(src, iptr->dst);
718 M_COPY(src->prev, iptr->dst->prev);
719 M_COPY(src->prev->prev, iptr->dst->prev->prev);
720 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
721 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
722 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
725 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
727 M_COPY(src, iptr->dst->prev);
728 M_COPY(src->prev, iptr->dst);
732 /* integer operations *************************************************/
734 case ICMD_INEG: /* ..., value ==> ..., - value */
736 var_to_reg_int(s1, src, REG_ITMP1);
737 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
738 M_ISUB(REG_ZERO, s1, d);
739 store_reg_to_var_int(iptr->dst, d);
742 case ICMD_LNEG: /* ..., value ==> ..., - value */
744 var_to_reg_int(s1, src, REG_ITMP1);
745 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
746 M_LSUB(REG_ZERO, s1, d);
747 store_reg_to_var_int(iptr->dst, d);
750 case ICMD_I2L: /* ..., value ==> ..., value */
752 var_to_reg_int(s1, src, REG_ITMP1);
753 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
755 store_reg_to_var_int(iptr->dst, d);
758 case ICMD_L2I: /* ..., value ==> ..., value */
760 var_to_reg_int(s1, src, REG_ITMP1);
761 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
762 M_ISLL_IMM(s1, 0, d );
763 store_reg_to_var_int(iptr->dst, d);
766 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
768 var_to_reg_int(s1, src, REG_ITMP1);
769 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
770 M_LSLL_IMM(s1, 56, d);
771 M_LSRA_IMM( d, 56, d);
772 store_reg_to_var_int(iptr->dst, d);
775 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
777 var_to_reg_int(s1, src, REG_ITMP1);
778 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
780 store_reg_to_var_int(iptr->dst, d);
783 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
785 var_to_reg_int(s1, src, REG_ITMP1);
786 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
787 M_LSLL_IMM(s1, 48, d);
788 M_LSRA_IMM( d, 48, d);
789 store_reg_to_var_int(iptr->dst, d);
793 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
795 var_to_reg_int(s1, src->prev, REG_ITMP1);
796 var_to_reg_int(s2, src, REG_ITMP2);
797 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
799 store_reg_to_var_int(iptr->dst, d);
802 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
803 /* val.i = constant */
805 var_to_reg_int(s1, src, REG_ITMP1);
806 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
807 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
808 M_IADD_IMM(s1, iptr->val.i, d);
811 ICONST(REG_ITMP2, iptr->val.i);
812 M_IADD(s1, REG_ITMP2, d);
814 store_reg_to_var_int(iptr->dst, d);
817 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
819 var_to_reg_int(s1, src->prev, REG_ITMP1);
820 var_to_reg_int(s2, src, REG_ITMP2);
821 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
823 store_reg_to_var_int(iptr->dst, d);
826 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
827 /* val.l = constant */
829 var_to_reg_int(s1, src, REG_ITMP1);
830 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
831 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
832 M_LADD_IMM(s1, iptr->val.l, d);
835 LCONST(REG_ITMP2, iptr->val.l);
836 M_LADD(s1, REG_ITMP2, d);
838 store_reg_to_var_int(iptr->dst, d);
841 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
843 var_to_reg_int(s1, src->prev, REG_ITMP1);
844 var_to_reg_int(s2, src, REG_ITMP2);
845 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
847 store_reg_to_var_int(iptr->dst, d);
850 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
851 /* val.i = constant */
853 var_to_reg_int(s1, src, REG_ITMP1);
854 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
855 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
856 M_IADD_IMM(s1, -iptr->val.i, d);
859 ICONST(REG_ITMP2, iptr->val.i);
860 M_ISUB(s1, REG_ITMP2, d);
862 store_reg_to_var_int(iptr->dst, d);
865 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
867 var_to_reg_int(s1, src->prev, REG_ITMP1);
868 var_to_reg_int(s2, src, REG_ITMP2);
869 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
871 store_reg_to_var_int(iptr->dst, d);
874 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
875 /* val.l = constant */
877 var_to_reg_int(s1, src, REG_ITMP1);
878 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
879 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
880 M_LADD_IMM(s1, -iptr->val.l, d);
883 LCONST(REG_ITMP2, iptr->val.l);
884 M_LSUB(s1, REG_ITMP2, d);
886 store_reg_to_var_int(iptr->dst, d);
889 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
891 var_to_reg_int(s1, src->prev, REG_ITMP1);
892 var_to_reg_int(s2, src, REG_ITMP2);
893 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
898 store_reg_to_var_int(iptr->dst, d);
901 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
902 /* val.i = constant */
904 var_to_reg_int(s1, src, REG_ITMP1);
905 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
906 ICONST(REG_ITMP2, iptr->val.i);
907 M_IMUL(s1, REG_ITMP2);
911 store_reg_to_var_int(iptr->dst, d);
914 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
916 var_to_reg_int(s1, src->prev, REG_ITMP1);
917 var_to_reg_int(s2, src, REG_ITMP2);
918 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
923 store_reg_to_var_int(iptr->dst, d);
926 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
927 /* val.l = constant */
929 var_to_reg_int(s1, src, REG_ITMP1);
930 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
931 LCONST(REG_ITMP2, iptr->val.l);
932 M_LMUL(s1, REG_ITMP2);
936 store_reg_to_var_int(iptr->dst, d);
939 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
941 var_to_reg_int(s1, src->prev, REG_ITMP1);
942 var_to_reg_int(s2, src, REG_ITMP2);
943 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
948 store_reg_to_var_int(iptr->dst, d);
951 case ICMD_IDIVCONST: /* ..., value ==> ..., value / constant */
952 /* val.i = constant */
954 var_to_reg_int(s1, src, REG_ITMP1);
955 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
956 ICONST(REG_ITMP2, iptr->val.i);
957 M_IDIV(s1, REG_ITMP2);
961 store_reg_to_var_int(iptr->dst, d);
964 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
966 var_to_reg_int(s1, src->prev, REG_ITMP1);
967 var_to_reg_int(s2, src, REG_ITMP2);
968 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
973 store_reg_to_var_int(iptr->dst, d);
976 case ICMD_LDIVCONST: /* ..., value ==> ..., value / constant */
977 /* val.l = constant */
979 var_to_reg_int(s1, src, REG_ITMP1);
980 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
981 LCONST(REG_ITMP2, iptr->val.l);
982 M_LDIV(s1, REG_ITMP2);
986 store_reg_to_var_int(iptr->dst, d);
989 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
991 var_to_reg_int(s1, src->prev, REG_ITMP1);
992 var_to_reg_int(s2, src, REG_ITMP2);
993 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
998 store_reg_to_var_int(iptr->dst, d);
1001 case ICMD_IREMCONST: /* ..., value ==> ..., value % constant */
1002 /* val.i = constant */
1004 var_to_reg_int(s1, src, REG_ITMP1);
1005 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1006 ICONST(REG_ITMP2, iptr->val.i);
1007 M_IDIV(s1, REG_ITMP2);
1011 store_reg_to_var_int(iptr->dst, d);
1014 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1016 var_to_reg_int(s1, src->prev, REG_ITMP1);
1017 var_to_reg_int(s2, src, REG_ITMP2);
1018 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1023 store_reg_to_var_int(iptr->dst, d);
1026 case ICMD_LREMCONST: /* ..., value ==> ..., value % constant */
1027 /* val.l = constant */
1029 var_to_reg_int(s1, src, REG_ITMP1);
1030 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1031 LCONST(REG_ITMP2, iptr->val.l);
1032 M_LDIV(s1, REG_ITMP2);
1036 store_reg_to_var_int(iptr->dst, d);
1039 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1040 case ICMD_LDIVPOW2: /* val.i = constant */
1042 var_to_reg_int(s1, src, REG_ITMP1);
1043 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1044 M_LSRA_IMM(s1, 63, REG_ITMP2);
1045 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1046 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1047 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
1048 store_reg_to_var_int(iptr->dst, d);
1051 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1053 var_to_reg_int(s1, src->prev, REG_ITMP1);
1054 var_to_reg_int(s2, src, REG_ITMP2);
1055 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1057 store_reg_to_var_int(iptr->dst, d);
1060 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1061 /* val.i = constant */
1063 var_to_reg_int(s1, src, REG_ITMP1);
1064 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1065 M_ISLL_IMM(s1, iptr->val.i, d);
1066 store_reg_to_var_int(iptr->dst, d);
1069 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1071 var_to_reg_int(s1, src->prev, REG_ITMP1);
1072 var_to_reg_int(s2, src, REG_ITMP2);
1073 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1075 store_reg_to_var_int(iptr->dst, d);
1078 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1079 /* val.i = constant */
1081 var_to_reg_int(s1, src, REG_ITMP1);
1082 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1083 M_ISRA_IMM(s1, iptr->val.i, d);
1084 store_reg_to_var_int(iptr->dst, d);
1087 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1089 var_to_reg_int(s1, src->prev, REG_ITMP1);
1090 var_to_reg_int(s2, src, REG_ITMP2);
1091 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1093 store_reg_to_var_int(iptr->dst, d);
1096 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1097 /* val.i = constant */
1099 var_to_reg_int(s1, src, REG_ITMP1);
1100 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1101 M_ISRL_IMM(s1, iptr->val.i, d);
1102 store_reg_to_var_int(iptr->dst, d);
1105 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1107 var_to_reg_int(s1, src->prev, REG_ITMP1);
1108 var_to_reg_int(s2, src, REG_ITMP2);
1109 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1111 store_reg_to_var_int(iptr->dst, d);
1114 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1115 /* val.i = constant */
1117 var_to_reg_int(s1, src, REG_ITMP1);
1118 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1119 M_LSLL_IMM(s1, iptr->val.i, d);
1120 store_reg_to_var_int(iptr->dst, d);
1123 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1125 var_to_reg_int(s1, src->prev, REG_ITMP1);
1126 var_to_reg_int(s2, src, REG_ITMP2);
1127 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1129 store_reg_to_var_int(iptr->dst, d);
1132 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1133 /* val.i = constant */
1135 var_to_reg_int(s1, src, REG_ITMP1);
1136 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1137 M_LSRA_IMM(s1, iptr->val.i, d);
1138 store_reg_to_var_int(iptr->dst, d);
1141 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1143 var_to_reg_int(s1, src->prev, REG_ITMP1);
1144 var_to_reg_int(s2, src, REG_ITMP2);
1145 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1147 store_reg_to_var_int(iptr->dst, d);
1150 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1151 /* val.i = constant */
1153 var_to_reg_int(s1, src, REG_ITMP1);
1154 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1155 M_LSRL_IMM(s1, iptr->val.i, d);
1156 store_reg_to_var_int(iptr->dst, d);
1159 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1162 var_to_reg_int(s1, src->prev, REG_ITMP1);
1163 var_to_reg_int(s2, src, REG_ITMP2);
1164 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1166 store_reg_to_var_int(iptr->dst, d);
1169 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1170 /* val.i = constant */
1172 var_to_reg_int(s1, src, REG_ITMP1);
1173 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1174 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1175 M_AND_IMM(s1, iptr->val.i, d);
1178 ICONST(REG_ITMP2, iptr->val.i);
1179 M_AND(s1, REG_ITMP2, d);
1181 store_reg_to_var_int(iptr->dst, d);
1184 case ICMD_IREMPOW2: /* ..., 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);
1190 M_MOV(s1, REG_ITMP1);
1193 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1194 M_AND_IMM(s1, iptr->val.i, d);
1197 M_ISUB(REG_ZERO, s1, d);
1198 M_AND_IMM(d, iptr->val.i, d);
1201 ICONST(REG_ITMP2, iptr->val.i);
1202 M_AND(s1, REG_ITMP2, d);
1205 M_ISUB(REG_ZERO, s1, d);
1206 M_AND(d, REG_ITMP2, d);
1208 M_ISUB(REG_ZERO, d, d);
1209 store_reg_to_var_int(iptr->dst, d);
1212 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1213 /* val.l = constant */
1215 var_to_reg_int(s1, src, REG_ITMP1);
1216 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1217 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1218 M_AND_IMM(s1, iptr->val.l, d);
1221 LCONST(REG_ITMP2, iptr->val.l);
1222 M_AND(s1, REG_ITMP2, d);
1224 store_reg_to_var_int(iptr->dst, d);
1227 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1228 /* val.l = constant */
1230 var_to_reg_int(s1, src, REG_ITMP1);
1231 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1233 M_MOV(s1, REG_ITMP1);
1236 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1237 M_AND_IMM(s1, iptr->val.l, d);
1240 M_LSUB(REG_ZERO, s1, d);
1241 M_AND_IMM(d, iptr->val.l, d);
1244 LCONST(REG_ITMP2, iptr->val.l);
1245 M_AND(s1, REG_ITMP2, d);
1248 M_LSUB(REG_ZERO, s1, d);
1249 M_AND(d, REG_ITMP2, d);
1251 M_LSUB(REG_ZERO, d, d);
1252 store_reg_to_var_int(iptr->dst, d);
1255 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1258 var_to_reg_int(s1, src->prev, REG_ITMP1);
1259 var_to_reg_int(s2, src, REG_ITMP2);
1260 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1262 store_reg_to_var_int(iptr->dst, d);
1265 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1266 /* val.i = constant */
1268 var_to_reg_int(s1, src, REG_ITMP1);
1269 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1270 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1271 M_OR_IMM(s1, iptr->val.i, d);
1274 ICONST(REG_ITMP2, iptr->val.i);
1275 M_OR(s1, REG_ITMP2, d);
1277 store_reg_to_var_int(iptr->dst, d);
1280 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1281 /* val.l = constant */
1283 var_to_reg_int(s1, src, REG_ITMP1);
1284 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1285 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1286 M_OR_IMM(s1, iptr->val.l, d);
1289 LCONST(REG_ITMP2, iptr->val.l);
1290 M_OR(s1, REG_ITMP2, d);
1292 store_reg_to_var_int(iptr->dst, d);
1295 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1298 var_to_reg_int(s1, src->prev, REG_ITMP1);
1299 var_to_reg_int(s2, src, REG_ITMP2);
1300 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1302 store_reg_to_var_int(iptr->dst, d);
1305 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1306 /* val.i = constant */
1308 var_to_reg_int(s1, src, REG_ITMP1);
1309 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1310 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1311 M_XOR_IMM(s1, iptr->val.i, d);
1314 ICONST(REG_ITMP2, iptr->val.i);
1315 M_XOR(s1, REG_ITMP2, d);
1317 store_reg_to_var_int(iptr->dst, d);
1320 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1321 /* val.l = constant */
1323 var_to_reg_int(s1, src, REG_ITMP1);
1324 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1325 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1326 M_XOR_IMM(s1, iptr->val.l, d);
1329 LCONST(REG_ITMP2, iptr->val.l);
1330 M_XOR(s1, REG_ITMP2, d);
1332 store_reg_to_var_int(iptr->dst, d);
1336 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1338 var_to_reg_int(s1, src->prev, REG_ITMP1);
1339 var_to_reg_int(s2, src, REG_ITMP2);
1340 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1341 M_CMPLT(s1, s2, REG_ITMP3);
1342 M_CMPLT(s2, s1, REG_ITMP1);
1343 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1344 store_reg_to_var_int(iptr->dst, d);
1348 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1349 /* op1 = variable, val.i = constant */
1351 var = &(rd->locals[iptr->op1][TYPE_INT]);
1352 if (var->flags & INMEMORY) {
1354 M_LLD(s1, REG_SP, 8 * var->regoff);
1358 M_IADD_IMM(s1, iptr->val.i, s1);
1359 if (var->flags & INMEMORY)
1360 M_LST(s1, REG_SP, 8 * var->regoff);
1364 /* floating operations ************************************************/
1366 case ICMD_FNEG: /* ..., value ==> ..., - value */
1368 var_to_reg_flt(s1, src, REG_FTMP1);
1369 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1371 store_reg_to_var_flt(iptr->dst, d);
1374 case ICMD_DNEG: /* ..., value ==> ..., - value */
1376 var_to_reg_flt(s1, src, REG_FTMP1);
1377 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1379 store_reg_to_var_flt(iptr->dst, d);
1382 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1384 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1385 var_to_reg_flt(s2, src, REG_FTMP2);
1386 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1388 store_reg_to_var_flt(iptr->dst, d);
1391 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1393 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1394 var_to_reg_flt(s2, src, REG_FTMP2);
1395 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1397 store_reg_to_var_flt(iptr->dst, d);
1400 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1402 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1403 var_to_reg_flt(s2, src, REG_FTMP2);
1404 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1406 store_reg_to_var_flt(iptr->dst, d);
1409 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1411 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1412 var_to_reg_flt(s2, src, REG_FTMP2);
1413 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1415 store_reg_to_var_flt(iptr->dst, d);
1418 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1420 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1421 var_to_reg_flt(s2, src, REG_FTMP2);
1422 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1424 store_reg_to_var_flt(iptr->dst, d);
1427 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1429 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1430 var_to_reg_flt(s2, src, REG_FTMP2);
1431 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1433 store_reg_to_var_flt(iptr->dst, d);
1436 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1438 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1439 var_to_reg_flt(s2, src, REG_FTMP2);
1440 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1442 store_reg_to_var_flt(iptr->dst, d);
1445 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1447 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1448 var_to_reg_flt(s2, src, REG_FTMP2);
1449 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1451 store_reg_to_var_flt(iptr->dst, d);
1454 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1457 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1458 var_to_reg_flt(s2, src, REG_FTMP2);
1459 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1460 M_FDIV(s1,s2, REG_FTMP3);
1461 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1462 M_CVTLF(REG_FTMP3, REG_FTMP3);
1463 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1464 M_FSUB(s1, REG_FTMP3, d);
1465 store_reg_to_var_flt(iptr->dst, d);
1468 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1470 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1471 var_to_reg_flt(s2, src, REG_FTMP2);
1472 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1473 M_DDIV(s1,s2, REG_FTMP3);
1474 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1475 M_CVTLD(REG_FTMP3, REG_FTMP3);
1476 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1477 M_DSUB(s1, REG_FTMP3, d);
1478 store_reg_to_var_flt(iptr->dst, d);
1481 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1483 var_to_reg_int(s1, src, REG_ITMP1);
1484 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1487 store_reg_to_var_flt(iptr->dst, d);
1490 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1492 var_to_reg_int(s1, src, REG_ITMP1);
1493 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1496 store_reg_to_var_flt(iptr->dst, d);
1499 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1501 var_to_reg_flt(s1, src, REG_FTMP1);
1502 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1503 M_TRUNCFI(s1, REG_FTMP1);
1504 M_MOVDI(REG_FTMP1, d);
1506 store_reg_to_var_int(iptr->dst, d);
1509 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1511 var_to_reg_flt(s1, src, REG_FTMP1);
1512 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1513 M_TRUNCDI(s1, REG_FTMP1);
1514 M_MOVDI(REG_FTMP1, d);
1516 store_reg_to_var_int(iptr->dst, d);
1519 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1521 var_to_reg_flt(s1, src, REG_FTMP1);
1522 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1523 M_TRUNCFL(s1, REG_FTMP1);
1524 M_MOVDL(REG_FTMP1, d);
1526 store_reg_to_var_int(iptr->dst, d);
1529 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1531 var_to_reg_flt(s1, src, REG_FTMP1);
1532 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1533 M_TRUNCDL(s1, REG_FTMP1);
1534 M_MOVDL(REG_FTMP1, d);
1536 store_reg_to_var_int(iptr->dst, d);
1539 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1541 var_to_reg_flt(s1, src, REG_FTMP1);
1542 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1544 store_reg_to_var_flt(iptr->dst, d);
1547 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1549 var_to_reg_flt(s1, src, REG_FTMP1);
1550 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1552 store_reg_to_var_flt(iptr->dst, d);
1555 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1557 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1558 var_to_reg_flt(s2, src, REG_FTMP2);
1559 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1562 M_LADD_IMM(REG_ZERO, 1, d);
1566 M_LSUB_IMM(REG_ZERO, 1, d);
1567 M_CMOVT(REG_ZERO, d);
1568 store_reg_to_var_int(iptr->dst, d);
1571 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1573 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1574 var_to_reg_flt(s2, src, REG_FTMP2);
1575 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1578 M_LADD_IMM(REG_ZERO, 1, d);
1582 M_LSUB_IMM(REG_ZERO, 1, d);
1583 M_CMOVT(REG_ZERO, d);
1584 store_reg_to_var_int(iptr->dst, d);
1587 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1589 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1590 var_to_reg_flt(s2, src, REG_FTMP2);
1591 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1594 M_LSUB_IMM(REG_ZERO, 1, d);
1598 M_LADD_IMM(REG_ZERO, 1, d);
1599 M_CMOVT(REG_ZERO, d);
1600 store_reg_to_var_int(iptr->dst, d);
1603 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1605 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1606 var_to_reg_flt(s2, src, REG_FTMP2);
1607 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1610 M_LSUB_IMM(REG_ZERO, 1, d);
1614 M_LADD_IMM(REG_ZERO, 1, d);
1615 M_CMOVT(REG_ZERO, d);
1616 store_reg_to_var_int(iptr->dst, d);
1620 /* memory operations **************************************************/
1622 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1624 var_to_reg_int(s1, src, REG_ITMP1);
1625 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1626 gen_nullptr_check(s1);
1627 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1628 store_reg_to_var_int(iptr->dst, d);
1631 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1633 var_to_reg_int(s1, src->prev, REG_ITMP1);
1634 var_to_reg_int(s2, src, REG_ITMP2);
1635 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1636 if (iptr->op1 == 0) {
1637 gen_nullptr_check(s1);
1640 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1641 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1642 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1643 store_reg_to_var_int(iptr->dst, d);
1646 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1648 var_to_reg_int(s1, src->prev, REG_ITMP1);
1649 var_to_reg_int(s2, src, REG_ITMP2);
1650 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1651 if (iptr->op1 == 0) {
1652 gen_nullptr_check(s1);
1655 M_ASLL_IMM(s2, 2, REG_ITMP2);
1656 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1657 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1658 store_reg_to_var_int(iptr->dst, d);
1661 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1663 var_to_reg_int(s1, src->prev, REG_ITMP1);
1664 var_to_reg_int(s2, src, REG_ITMP2);
1665 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1666 if (iptr->op1 == 0) {
1667 gen_nullptr_check(s1);
1670 M_ASLL_IMM(s2, 3, REG_ITMP2);
1671 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1672 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1673 store_reg_to_var_int(iptr->dst, d);
1676 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1678 var_to_reg_int(s1, src->prev, REG_ITMP1);
1679 var_to_reg_int(s2, src, REG_ITMP2);
1680 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1681 if (iptr->op1 == 0) {
1682 gen_nullptr_check(s1);
1685 M_ASLL_IMM(s2, 2, REG_ITMP2);
1686 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1687 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1688 store_reg_to_var_flt(iptr->dst, d);
1691 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1693 var_to_reg_int(s1, src->prev, REG_ITMP1);
1694 var_to_reg_int(s2, src, REG_ITMP2);
1695 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1696 if (iptr->op1 == 0) {
1697 gen_nullptr_check(s1);
1700 M_ASLL_IMM(s2, 3, REG_ITMP2);
1701 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1702 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1703 store_reg_to_var_flt(iptr->dst, d);
1706 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1708 var_to_reg_int(s1, src->prev, REG_ITMP1);
1709 var_to_reg_int(s2, src, REG_ITMP2);
1710 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1711 if (iptr->op1 == 0) {
1712 gen_nullptr_check(s1);
1715 M_AADD(s2, s1, REG_ITMP1);
1716 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1717 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1718 store_reg_to_var_int(iptr->dst, d);
1721 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1723 var_to_reg_int(s1, src->prev, REG_ITMP1);
1724 var_to_reg_int(s2, src, REG_ITMP2);
1725 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1726 if (iptr->op1 == 0) {
1727 gen_nullptr_check(s1);
1730 M_AADD(s2, s1, REG_ITMP1);
1731 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1732 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1733 store_reg_to_var_int(iptr->dst, d);
1736 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1738 var_to_reg_int(s1, src->prev, REG_ITMP1);
1739 var_to_reg_int(s2, src, REG_ITMP2);
1740 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1741 if (iptr->op1 == 0) {
1742 gen_nullptr_check(s1);
1745 M_AADD(s2, s1, REG_ITMP1);
1746 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1747 store_reg_to_var_int(iptr->dst, d);
1751 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1753 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1754 var_to_reg_int(s2, src->prev, REG_ITMP2);
1755 if (iptr->op1 == 0) {
1756 gen_nullptr_check(s1);
1759 var_to_reg_int(s3, src, REG_ITMP3);
1760 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1761 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1762 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1765 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1767 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1768 var_to_reg_int(s2, src->prev, REG_ITMP2);
1769 if (iptr->op1 == 0) {
1770 gen_nullptr_check(s1);
1773 var_to_reg_int(s3, src, REG_ITMP3);
1774 M_ASLL_IMM(s2, 2, REG_ITMP2);
1775 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1776 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1779 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1781 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1782 var_to_reg_int(s2, src->prev, REG_ITMP2);
1783 if (iptr->op1 == 0) {
1784 gen_nullptr_check(s1);
1787 var_to_reg_int(s3, src, REG_ITMP3);
1788 M_ASLL_IMM(s2, 3, REG_ITMP2);
1789 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1790 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1793 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1795 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1796 var_to_reg_int(s2, src->prev, REG_ITMP2);
1797 if (iptr->op1 == 0) {
1798 gen_nullptr_check(s1);
1801 var_to_reg_flt(s3, src, REG_FTMP3);
1802 M_ASLL_IMM(s2, 2, REG_ITMP2);
1803 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1804 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1807 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1809 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1810 var_to_reg_int(s2, src->prev, REG_ITMP2);
1811 if (iptr->op1 == 0) {
1812 gen_nullptr_check(s1);
1815 var_to_reg_flt(s3, src, REG_FTMP3);
1816 M_ASLL_IMM(s2, 3, REG_ITMP2);
1817 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1818 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1821 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1822 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1824 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1825 var_to_reg_int(s2, src->prev, REG_ITMP2);
1826 if (iptr->op1 == 0) {
1827 gen_nullptr_check(s1);
1830 var_to_reg_int(s3, src, REG_ITMP3);
1831 M_AADD(s2, s1, REG_ITMP1);
1832 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1833 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1836 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1838 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1839 var_to_reg_int(s2, src->prev, REG_ITMP2);
1840 if (iptr->op1 == 0) {
1841 gen_nullptr_check(s1);
1844 var_to_reg_int(s3, src, REG_ITMP3);
1845 M_AADD(s2, s1, REG_ITMP1);
1846 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1850 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1851 /* op1 = type, val.a = field address */
1853 /* If the static fields' class is not yet initialized, we do it */
1854 /* now. The call code is generated later. */
1855 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1856 codegen_addclinitref(cd, mcodeptr, ((fieldinfo *) iptr->val.a)->class);
1858 /* This is just for debugging purposes. Is very difficult to */
1859 /* read patched code. Here we patch the following 2 nop's */
1860 /* so that the real code keeps untouched. */
1861 if (showdisassemble) {
1867 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1868 M_ALD(REG_ITMP1, REG_PV, a);
1869 switch (iptr->op1) {
1871 var_to_reg_int(s2, src, REG_ITMP2);
1872 M_IST(s2, REG_ITMP1, 0);
1875 var_to_reg_int(s2, src, REG_ITMP2);
1876 M_LST(s2, REG_ITMP1, 0);
1879 var_to_reg_int(s2, src, REG_ITMP2);
1880 M_AST(s2, REG_ITMP1, 0);
1883 var_to_reg_flt(s2, src, REG_FTMP2);
1884 M_FST(s2, REG_ITMP1, 0);
1887 var_to_reg_flt(s2, src, REG_FTMP2);
1888 M_DST(s2, REG_ITMP1, 0);
1891 throw_cacao_exception_exit(string_java_lang_InternalError,
1892 "Unknown PUTSTATIC operand type %d",
1897 case ICMD_GETSTATIC: /* ... ==> ..., value */
1898 /* op1 = type, val.a = field address */
1900 /* If the static fields' class is not yet initialized, we do it */
1901 /* now. The call code is generated later. */
1902 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1903 codegen_addclinitref(cd, mcodeptr, ((fieldinfo *) iptr->val.a)->class);
1905 /* This is just for debugging purposes. Is very difficult to */
1906 /* read patched code. Here we patch the following 2 nop's */
1907 /* so that the real code keeps untouched. */
1908 if (showdisassemble) {
1914 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1915 M_ALD(REG_ITMP1, REG_PV, a);
1916 switch (iptr->op1) {
1918 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1919 M_ILD(d, REG_ITMP1, 0);
1920 store_reg_to_var_int(iptr->dst, d);
1923 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1924 M_LLD(d, REG_ITMP1, 0);
1925 store_reg_to_var_int(iptr->dst, d);
1928 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1929 M_ALD(d, REG_ITMP1, 0);
1930 store_reg_to_var_int(iptr->dst, d);
1933 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1934 M_FLD(d, REG_ITMP1, 0);
1935 store_reg_to_var_flt(iptr->dst, d);
1938 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1939 M_DLD(d, REG_ITMP1, 0);
1940 store_reg_to_var_flt(iptr->dst, d);
1943 throw_cacao_exception_exit(string_java_lang_InternalError,
1944 "Unknown GETSTATIC operand type %d",
1950 case ICMD_PUTFIELD: /* ..., value ==> ... */
1951 /* op1 = type, val.i = field offset */
1953 a = ((fieldinfo *)(iptr->val.a))->offset;
1954 switch (iptr->op1) {
1956 var_to_reg_int(s1, src->prev, REG_ITMP1);
1957 var_to_reg_int(s2, src, REG_ITMP2);
1958 gen_nullptr_check(s1);
1962 var_to_reg_int(s1, src->prev, REG_ITMP1);
1963 var_to_reg_int(s2, src, REG_ITMP2);
1964 gen_nullptr_check(s1);
1968 var_to_reg_int(s1, src->prev, REG_ITMP1);
1969 var_to_reg_int(s2, src, REG_ITMP2);
1970 gen_nullptr_check(s1);
1974 var_to_reg_int(s1, src->prev, REG_ITMP1);
1975 var_to_reg_flt(s2, src, REG_FTMP2);
1976 gen_nullptr_check(s1);
1980 var_to_reg_int(s1, src->prev, REG_ITMP1);
1981 var_to_reg_flt(s2, src, REG_FTMP2);
1982 gen_nullptr_check(s1);
1986 throw_cacao_exception_exit(string_java_lang_InternalError,
1987 "Unknown PUTFIELD operand type %d",
1992 case ICMD_GETFIELD: /* ... ==> ..., value */
1993 /* op1 = type, val.i = field offset */
1995 a = ((fieldinfo *)(iptr->val.a))->offset;
1996 switch (iptr->op1) {
1998 var_to_reg_int(s1, src, REG_ITMP1);
1999 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2000 gen_nullptr_check(s1);
2002 store_reg_to_var_int(iptr->dst, d);
2005 var_to_reg_int(s1, src, REG_ITMP1);
2006 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2007 gen_nullptr_check(s1);
2009 store_reg_to_var_int(iptr->dst, d);
2012 var_to_reg_int(s1, src, REG_ITMP1);
2013 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2014 gen_nullptr_check(s1);
2016 store_reg_to_var_int(iptr->dst, d);
2019 var_to_reg_int(s1, src, REG_ITMP1);
2020 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2021 gen_nullptr_check(s1);
2023 store_reg_to_var_flt(iptr->dst, d);
2026 var_to_reg_int(s1, src, REG_ITMP1);
2027 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2028 gen_nullptr_check(s1);
2030 store_reg_to_var_flt(iptr->dst, d);
2033 throw_cacao_exception_exit(string_java_lang_InternalError,
2034 "Unknown GETFIELD operand type %d",
2040 /* branch operations **************************************************/
2042 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2044 var_to_reg_int(s1, src, REG_ITMP1);
2045 M_INTMOVE(s1, REG_ITMP1_XPTR);
2046 a = dseg_addaddress(cd, asm_handle_exception);
2047 M_ALD(REG_ITMP2, REG_PV, a);
2048 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2050 M_NOP; /* nop ensures that XPC is less than the end */
2051 /* of basic block */
2055 case ICMD_GOTO: /* ... ==> ... */
2056 /* op1 = target JavaVM pc */
2058 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2063 case ICMD_JSR: /* ... ==> ... */
2064 /* op1 = target JavaVM pc */
2066 dseg_addtarget(cd, BlockPtrOfPC(iptr->op1));
2067 M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
2068 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2072 case ICMD_RET: /* ... ==> ... */
2073 /* op1 = local variable */
2074 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2075 if (var->flags & INMEMORY) {
2076 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2085 case ICMD_IFNULL: /* ..., value ==> ... */
2086 /* op1 = target JavaVM pc */
2088 var_to_reg_int(s1, src, REG_ITMP1);
2090 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2094 case ICMD_IFNONNULL: /* ..., value ==> ... */
2095 /* op1 = target JavaVM pc */
2097 var_to_reg_int(s1, src, REG_ITMP1);
2099 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2103 case ICMD_IFEQ: /* ..., value ==> ... */
2104 /* op1 = target JavaVM pc, val.i = constant */
2106 var_to_reg_int(s1, src, REG_ITMP1);
2107 if (iptr->val.i == 0) {
2111 ICONST(REG_ITMP2, iptr->val.i);
2112 M_BEQ(s1, REG_ITMP2, 0);
2114 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2118 case ICMD_IFLT: /* ..., value ==> ... */
2119 /* op1 = target JavaVM pc, val.i = constant */
2121 var_to_reg_int(s1, src, REG_ITMP1);
2122 if (iptr->val.i == 0) {
2126 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2127 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2130 ICONST(REG_ITMP2, iptr->val.i);
2131 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2133 M_BNEZ(REG_ITMP1, 0);
2135 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2139 case ICMD_IFLE: /* ..., value ==> ... */
2140 /* op1 = target JavaVM pc, val.i = constant */
2142 var_to_reg_int(s1, src, REG_ITMP1);
2143 if (iptr->val.i == 0) {
2147 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2148 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2149 M_BNEZ(REG_ITMP1, 0);
2152 ICONST(REG_ITMP2, iptr->val.i);
2153 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2154 M_BEQZ(REG_ITMP1, 0);
2157 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2161 case ICMD_IFNE: /* ..., value ==> ... */
2162 /* op1 = target JavaVM pc, val.i = constant */
2164 var_to_reg_int(s1, src, REG_ITMP1);
2165 if (iptr->val.i == 0) {
2169 ICONST(REG_ITMP2, iptr->val.i);
2170 M_BNE(s1, REG_ITMP2, 0);
2172 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2176 case ICMD_IFGT: /* ..., value ==> ... */
2177 /* op1 = target JavaVM pc, val.i = constant */
2179 var_to_reg_int(s1, src, REG_ITMP1);
2180 if (iptr->val.i == 0) {
2184 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2185 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2186 M_BEQZ(REG_ITMP1, 0);
2189 ICONST(REG_ITMP2, iptr->val.i);
2190 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2191 M_BNEZ(REG_ITMP1, 0);
2194 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2198 case ICMD_IFGE: /* ..., value ==> ... */
2199 /* op1 = target JavaVM pc, val.i = constant */
2201 var_to_reg_int(s1, src, REG_ITMP1);
2202 if (iptr->val.i == 0) {
2206 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2207 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2210 ICONST(REG_ITMP2, iptr->val.i);
2211 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2213 M_BEQZ(REG_ITMP1, 0);
2215 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2219 case ICMD_IF_LEQ: /* ..., value ==> ... */
2220 /* op1 = target JavaVM pc, val.l = constant */
2222 var_to_reg_int(s1, src, REG_ITMP1);
2223 if (iptr->val.l == 0) {
2227 LCONST(REG_ITMP2, iptr->val.l);
2228 M_BEQ(s1, REG_ITMP2, 0);
2230 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2234 case ICMD_IF_LLT: /* ..., value ==> ... */
2235 /* op1 = target JavaVM pc, val.l = constant */
2237 var_to_reg_int(s1, src, REG_ITMP1);
2238 if (iptr->val.l == 0) {
2242 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2243 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2246 LCONST(REG_ITMP2, iptr->val.l);
2247 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2249 M_BNEZ(REG_ITMP1, 0);
2251 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2255 case ICMD_IF_LLE: /* ..., value ==> ... */
2256 /* op1 = target JavaVM pc, val.l = constant */
2258 var_to_reg_int(s1, src, REG_ITMP1);
2259 if (iptr->val.l == 0) {
2263 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2264 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2265 M_BNEZ(REG_ITMP1, 0);
2268 LCONST(REG_ITMP2, iptr->val.l);
2269 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2270 M_BEQZ(REG_ITMP1, 0);
2273 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2277 case ICMD_IF_LNE: /* ..., value ==> ... */
2278 /* op1 = target JavaVM pc, val.l = constant */
2280 var_to_reg_int(s1, src, REG_ITMP1);
2281 if (iptr->val.l == 0) {
2285 LCONST(REG_ITMP2, iptr->val.l);
2286 M_BNE(s1, REG_ITMP2, 0);
2288 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2292 case ICMD_IF_LGT: /* ..., value ==> ... */
2293 /* op1 = target JavaVM pc, val.l = constant */
2295 var_to_reg_int(s1, src, REG_ITMP1);
2296 if (iptr->val.l == 0) {
2300 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2301 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2302 M_BEQZ(REG_ITMP1, 0);
2305 LCONST(REG_ITMP2, iptr->val.l);
2306 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2307 M_BNEZ(REG_ITMP1, 0);
2310 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2314 case ICMD_IF_LGE: /* ..., value ==> ... */
2315 /* op1 = target JavaVM pc, val.l = constant */
2317 var_to_reg_int(s1, src, REG_ITMP1);
2318 if (iptr->val.l == 0) {
2322 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2323 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2326 LCONST(REG_ITMP2, iptr->val.l);
2327 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2329 M_BEQZ(REG_ITMP1, 0);
2331 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2335 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2336 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2337 case ICMD_IF_ACMPEQ:
2339 var_to_reg_int(s1, src->prev, REG_ITMP1);
2340 var_to_reg_int(s2, src, REG_ITMP2);
2342 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2346 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2347 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2348 case ICMD_IF_ACMPNE:
2350 var_to_reg_int(s1, src->prev, REG_ITMP1);
2351 var_to_reg_int(s2, src, REG_ITMP2);
2353 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2357 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2358 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2360 var_to_reg_int(s1, src->prev, REG_ITMP1);
2361 var_to_reg_int(s2, src, REG_ITMP2);
2362 M_CMPLT(s1, s2, REG_ITMP1);
2363 M_BNEZ(REG_ITMP1, 0);
2364 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2368 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2369 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2371 var_to_reg_int(s1, src->prev, REG_ITMP1);
2372 var_to_reg_int(s2, src, REG_ITMP2);
2373 M_CMPGT(s1, s2, REG_ITMP1);
2374 M_BNEZ(REG_ITMP1, 0);
2375 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2379 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2380 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2382 var_to_reg_int(s1, src->prev, REG_ITMP1);
2383 var_to_reg_int(s2, src, REG_ITMP2);
2384 M_CMPGT(s1, s2, REG_ITMP1);
2385 M_BEQZ(REG_ITMP1, 0);
2386 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2390 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2391 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2393 var_to_reg_int(s1, src->prev, REG_ITMP1);
2394 var_to_reg_int(s2, src, REG_ITMP2);
2395 M_CMPLT(s1, s2, REG_ITMP1);
2396 M_BEQZ(REG_ITMP1, 0);
2397 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2401 #ifdef CONDITIONAL_LOADCONST
2402 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2404 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2407 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2408 /* val.i = constant */
2410 var_to_reg_int(s1, src, REG_ITMP1);
2411 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2413 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2414 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2415 M_CMPEQ(s1, REG_ZERO, d);
2416 store_reg_to_var_int(iptr->dst, d);
2419 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2420 M_CMPEQ(s1, REG_ZERO, d);
2422 store_reg_to_var_int(iptr->dst, d);
2426 M_MOV(s1, REG_ITMP1);
2429 ICONST(d, iptr[1].val.i);
2431 if ((s3 >= 0) && (s3 <= 255)) {
2432 M_CMOVEQ_IMM(s1, s3, d);
2435 ICONST(REG_ITMP2, s3);
2436 M_CMOVEQ(s1, REG_ITMP2, d);
2438 store_reg_to_var_int(iptr->dst, d);
2441 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2442 /* val.i = constant */
2444 var_to_reg_int(s1, src, REG_ITMP1);
2445 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2447 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2448 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2449 M_CMPEQ(s1, REG_ZERO, d);
2450 store_reg_to_var_int(iptr->dst, d);
2453 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2454 M_CMPEQ(s1, REG_ZERO, d);
2456 store_reg_to_var_int(iptr->dst, d);
2460 M_MOV(s1, REG_ITMP1);
2463 ICONST(d, iptr[1].val.i);
2465 if ((s3 >= 0) && (s3 <= 255)) {
2466 M_CMOVNE_IMM(s1, s3, d);
2469 ICONST(REG_ITMP2, s3);
2470 M_CMOVNE(s1, REG_ITMP2, d);
2472 store_reg_to_var_int(iptr->dst, d);
2475 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2476 /* val.i = constant */
2478 var_to_reg_int(s1, src, REG_ITMP1);
2479 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2481 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2482 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2483 M_CMPLT(s1, REG_ZERO, d);
2484 store_reg_to_var_int(iptr->dst, d);
2487 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2488 M_CMPLE(REG_ZERO, s1, d);
2489 store_reg_to_var_int(iptr->dst, d);
2493 M_MOV(s1, REG_ITMP1);
2496 ICONST(d, iptr[1].val.i);
2498 if ((s3 >= 0) && (s3 <= 255)) {
2499 M_CMOVLT_IMM(s1, s3, d);
2502 ICONST(REG_ITMP2, s3);
2503 M_CMOVLT(s1, REG_ITMP2, d);
2505 store_reg_to_var_int(iptr->dst, d);
2508 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2509 /* val.i = constant */
2511 var_to_reg_int(s1, src, REG_ITMP1);
2512 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2514 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2515 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2516 M_CMPLE(REG_ZERO, s1, d);
2517 store_reg_to_var_int(iptr->dst, d);
2520 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2521 M_CMPLT(s1, REG_ZERO, d);
2522 store_reg_to_var_int(iptr->dst, d);
2526 M_MOV(s1, REG_ITMP1);
2529 ICONST(d, iptr[1].val.i);
2531 if ((s3 >= 0) && (s3 <= 255)) {
2532 M_CMOVGE_IMM(s1, s3, d);
2535 ICONST(REG_ITMP2, s3);
2536 M_CMOVGE(s1, REG_ITMP2, d);
2538 store_reg_to_var_int(iptr->dst, d);
2541 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2542 /* val.i = constant */
2544 var_to_reg_int(s1, src, REG_ITMP1);
2545 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2547 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2548 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2549 M_CMPLT(REG_ZERO, s1, d);
2550 store_reg_to_var_int(iptr->dst, d);
2553 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2554 M_CMPLE(s1, REG_ZERO, d);
2555 store_reg_to_var_int(iptr->dst, d);
2559 M_MOV(s1, REG_ITMP1);
2562 ICONST(d, iptr[1].val.i);
2564 if ((s3 >= 0) && (s3 <= 255)) {
2565 M_CMOVGT_IMM(s1, s3, d);
2568 ICONST(REG_ITMP2, s3);
2569 M_CMOVGT(s1, REG_ITMP2, d);
2571 store_reg_to_var_int(iptr->dst, d);
2574 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2575 /* val.i = constant */
2577 var_to_reg_int(s1, src, REG_ITMP1);
2578 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2580 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2581 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2582 M_CMPLE(s1, REG_ZERO, d);
2583 store_reg_to_var_int(iptr->dst, d);
2586 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2587 M_CMPLT(REG_ZERO, s1, d);
2588 store_reg_to_var_int(iptr->dst, d);
2592 M_MOV(s1, REG_ITMP1);
2595 ICONST(d, iptr[1].val.i);
2597 if ((s3 >= 0) && (s3 <= 255)) {
2598 M_CMOVLE_IMM(s1, s3, d);
2601 ICONST(REG_ITMP2, s3);
2602 M_CMOVLE(s1, REG_ITMP2, d);
2604 store_reg_to_var_int(iptr->dst, d);
2609 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2613 #if defined(USE_THREADS)
2614 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2616 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2617 M_ALD(REG_ITMP3, REG_PV, a);
2618 M_JSR(REG_RA, REG_ITMP3);
2619 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8); /* delay slot */
2620 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2621 M_LDA(REG_PV, REG_RA, disp);
2624 var_to_reg_int(s1, src, REG_RESULT);
2625 M_INTMOVE(s1, REG_RESULT);
2626 goto nowperformreturn;
2628 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2631 #if defined(USE_THREADS)
2632 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2634 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2635 M_ALD(REG_ITMP3, REG_PV, a);
2636 M_JSR(REG_RA, REG_ITMP3);
2637 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8); /* delay slot */
2638 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2639 M_LDA(REG_PV, REG_RA, disp);
2642 var_to_reg_flt(s1, src, REG_FRESULT);
2644 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2645 M_TFLTMOVE(t, s1, REG_FRESULT);
2647 goto nowperformreturn;
2649 case ICMD_RETURN: /* ... ==> ... */
2651 #if defined(USE_THREADS)
2652 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2654 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2655 M_ALD(REG_ITMP3, REG_PV, a);
2656 M_JSR(REG_RA, REG_ITMP3);
2657 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8); /* delay slot */
2658 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2659 M_LDA(REG_PV, REG_RA, disp);
2667 p = parentargs_base;
2669 /* restore return address */
2671 if (!m->isleafmethod) {
2672 p--; M_LLD(REG_RA, REG_SP, 8 * p);
2675 /* restore saved registers */
2677 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2678 p--; M_LLD(rd->savintregs[i], REG_SP, 8 * p);
2680 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2681 p--; M_DLD(rd->savfltregs[i], REG_SP, 8 * p);
2684 /* call trace function */
2687 M_LDA (REG_SP, REG_SP, -24);
2688 M_LST(REG_RA, REG_SP, 0);
2689 M_LST(REG_RESULT, REG_SP, 8);
2690 M_DST(REG_FRESULT, REG_SP,16);
2691 a = dseg_addaddress(cd, m);
2692 M_ALD(rd->argintregs[0], REG_PV, a);
2693 M_MOV(REG_RESULT, rd->argintregs[1]);
2694 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2695 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
2696 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2697 M_ALD(REG_ITMP3, REG_PV, a);
2698 M_JSR (REG_RA, REG_ITMP3);
2700 M_DLD(REG_FRESULT, REG_SP,16);
2701 M_LLD(REG_RESULT, REG_SP, 8);
2702 M_LLD(REG_RA, REG_SP, 0);
2703 M_LDA (REG_SP, REG_SP, 24);
2708 /* deallocate stack */
2710 if (parentargs_base) {
2711 M_LDA(REG_SP, REG_SP, parentargs_base * 8);
2722 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2727 tptr = (void **) iptr->target;
2729 s4ptr = iptr->val.a;
2730 l = s4ptr[1]; /* low */
2731 i = s4ptr[2]; /* high */
2733 var_to_reg_int(s1, src, REG_ITMP1);
2735 {M_INTMOVE(s1, REG_ITMP1);}
2736 else if (l <= 32768) {
2737 M_IADD_IMM(s1, -l, REG_ITMP1);
2740 ICONST(REG_ITMP2, l);
2741 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2747 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
2748 M_BEQZ(REG_ITMP2, 0);
2749 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2750 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
2752 /* build jump table top down and use address of lowest entry */
2754 /* s4ptr += 3 + i; */
2758 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2759 dseg_addtarget(cd, (basicblock *) tptr[0]);
2764 /* length of dataseg after last dseg_addtarget is used by load */
2766 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2767 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2774 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2776 s4 i, /*l, */val, *s4ptr;
2779 tptr = (void **) iptr->target;
2781 s4ptr = iptr->val.a;
2782 /*l = s4ptr[0];*/ /* default */
2783 i = s4ptr[1]; /* count */
2785 MCODECHECK((i<<2)+8);
2786 var_to_reg_int(s1, src, REG_ITMP1);
2792 ICONST(REG_ITMP2, val);
2793 M_BEQ(s1, REG_ITMP2, 0);
2794 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2799 tptr = (void **) iptr->target;
2800 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2807 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2808 /* op1 = return type, val.a = function pointer*/
2812 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2813 /* op1 = return type, val.a = function pointer*/
2817 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2818 /* op1 = return type, val.a = function pointer*/
2822 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2823 /* op1 = arg count, val.a = method pointer */
2825 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2826 /* op1 = arg count, val.a = method pointer */
2828 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2829 /* op1 = arg count, val.a = method pointer */
2831 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2832 /* op1 = arg count, val.a = method pointer */
2839 MCODECHECK((s3 << 1) + 64);
2841 /* copy arguments to registers or stack location */
2843 for (; --s3 >= 0; src = src->prev) {
2844 if (src->varkind == ARGVAR)
2846 if (IS_INT_LNG_TYPE(src->type)) {
2847 if (s3 < INT_ARG_CNT) {
2848 s1 = rd->argintregs[s3];
2849 var_to_reg_int(d, src, s1);
2853 var_to_reg_int(d, src, REG_ITMP1);
2854 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
2858 if (s3 < FLT_ARG_CNT) {
2859 s1 = rd->argfltregs[s3];
2860 var_to_reg_flt(d, src, s1);
2861 M_TFLTMOVE(src->type, d, s1);
2864 var_to_reg_flt(d, src, REG_FTMP1);
2865 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
2871 switch (iptr->opc) {
2875 a = dseg_addaddress(cd, (void *) lm);
2876 d = iptr->op1; /* return type */
2878 M_ALD(REG_ITMP3, REG_PV, a); /* built-in-function pointer */
2879 M_JSR(REG_RA, REG_ITMP3);
2881 goto afteractualcall;
2883 case ICMD_INVOKESTATIC:
2884 case ICMD_INVOKESPECIAL:
2885 a = dseg_addaddress(cd, lm->stubroutine);
2888 M_ALD(REG_PV, REG_PV, a); /* method pointer in pv */
2891 case ICMD_INVOKEVIRTUAL:
2894 gen_nullptr_check(rd->argintregs[0]);
2895 M_ALD(REG_METHODPTR, rd->argintregs[0], OFFSET(java_objectheader, vftbl));
2896 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex);
2899 case ICMD_INVOKEINTERFACE:
2902 gen_nullptr_check(rd->argintregs[0]);
2903 M_ALD(REG_METHODPTR, rd->argintregs[0], OFFSET(java_objectheader, vftbl));
2904 M_ALD(REG_METHODPTR, REG_METHODPTR, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->class->index);
2905 M_ALD(REG_PV, REG_METHODPTR, sizeof(methodptr) * (lm - lm->class->methods));
2909 M_JSR(REG_RA, REG_PV);
2916 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2917 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
2919 s4 ml = -s1, mh = 0;
2920 while (ml < -32768) { ml += 65536; mh--; }
2922 M_IADD_IMM(REG_PV, ml, REG_PV);
2923 M_LADD(REG_PV, REG_RA, REG_PV);
2926 /* d contains return type */
2928 if (d != TYPE_VOID) {
2929 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2930 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2931 M_INTMOVE(REG_RESULT, s1);
2932 store_reg_to_var_int(iptr->dst, s1);
2935 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2936 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
2937 store_reg_to_var_flt(iptr->dst, s1);
2944 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2946 /* op1: 0 == array, 1 == class */
2947 /* val.a: (classinfo*) superclass */
2949 /* superclass is an interface:
2951 * return (sub != NULL) &&
2952 * (sub->vftbl->interfacetablelength > super->index) &&
2953 * (sub->vftbl->interfacetable[-super->index] != NULL);
2955 * superclass is a class:
2957 * return ((sub != NULL) && (0
2958 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2959 * super->vftbl->diffvall));
2963 classinfo *super = (classinfo*) iptr->val.a;
2965 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2966 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
2968 var_to_reg_int(s1, src, REG_ITMP1);
2969 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2971 M_MOV(s1, REG_ITMP1);
2975 if (iptr->op1) { /* class/interface */
2976 if (super->flags & ACC_INTERFACE) { /* interface */
2979 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2980 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2981 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
2982 M_BLEZ(REG_ITMP2, 3);
2984 M_ALD(REG_ITMP1, REG_ITMP1,
2985 OFFSET(vftbl_t, interfacetable[0]) -
2986 super->index * sizeof(methodptr*));
2987 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
2991 s2 = super->vftbl->diffval;
2994 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2995 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2996 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
2997 M_CMPULT_IMM(REG_ITMP1, s2 + 1, d);
3002 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3003 a = dseg_addaddress(cd, (void *) super->vftbl);
3004 M_ALD(REG_ITMP2, REG_PV, a);
3005 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3006 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3008 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3009 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3010 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3011 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3012 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3014 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3015 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3021 panic ("internal error: no inlined array instanceof");
3023 store_reg_to_var_int(iptr->dst, d);
3026 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3028 /* op1: 0 == array, 1 == class */
3029 /* val.a: (classinfo*) superclass */
3031 /* superclass is an interface:
3033 * OK if ((sub == NULL) ||
3034 * (sub->vftbl->interfacetablelength > super->index) &&
3035 * (sub->vftbl->interfacetable[-super->index] != NULL));
3037 * superclass is a class:
3039 * OK if ((sub == NULL) || (0
3040 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3041 * super->vftbl->diffvall));
3045 classinfo *super = (classinfo*) iptr->val.a;
3047 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3048 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3051 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3052 var_to_reg_int(s1, src, d);
3053 if (iptr->op1) { /* class/interface */
3054 if (super->flags & ACC_INTERFACE) { /* interface */
3057 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3058 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3059 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3060 M_BLEZ(REG_ITMP2, 0);
3061 codegen_addxcastrefs(cd, mcodeptr);
3063 M_ALD(REG_ITMP2, REG_ITMP1,
3064 OFFSET(vftbl_t, interfacetable[0]) -
3065 super->index * sizeof(methodptr*));
3066 M_BEQZ(REG_ITMP2, 0);
3067 codegen_addxcastrefs(cd, mcodeptr);
3073 s2 = super->vftbl->diffval;
3074 M_BEQZ(s1, 6 + (s2 != 0));
3076 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3077 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3078 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3080 M_BNEZ(REG_ITMP1, 0);
3083 M_CMPULT_IMM(REG_ITMP1, s2 + 1, REG_ITMP2);
3084 M_BEQZ(REG_ITMP2, 0);
3088 M_BEQZ(s1, 10 + (d == REG_ITMP3));
3090 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3091 a = dseg_addaddress(cd, (void *) super->vftbl);
3092 M_ALD(REG_ITMP2, REG_PV, a);
3093 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3094 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3096 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3097 if (d != REG_ITMP3) {
3098 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3099 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3100 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3101 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3103 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3105 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3106 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3107 M_ALD(REG_ITMP2, REG_PV, a);
3108 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3109 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3110 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3113 M_CMPULT(REG_ITMP2, REG_ITMP1, REG_ITMP2);
3114 M_BNEZ(REG_ITMP2, 0);
3116 codegen_addxcastrefs(cd, mcodeptr);
3121 panic ("internal error: no inlined array checkcast");
3124 store_reg_to_var_int(iptr->dst, d);
3127 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3129 var_to_reg_int(s1, src, REG_ITMP1);
3131 codegen_addxcheckarefs(cd, mcodeptr);
3135 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3137 M_BEQZ(REG_RESULT, 0);
3138 codegen_addxexceptionrefs(cd, mcodeptr);
3142 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3143 /* op1 = dimension, val.a = array descriptor */
3145 /* check for negative sizes and copy sizes to stack if necessary */
3147 MCODECHECK((iptr->op1 << 1) + 64);
3149 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3150 var_to_reg_int(s2, src, REG_ITMP1);
3152 codegen_addxcheckarefs(cd, mcodeptr);
3155 /* copy SAVEDVAR sizes to stack */
3157 if (src->varkind != ARGVAR) {
3158 M_LST(s2, REG_SP, s1 * 8);
3162 /* a0 = dimension count */
3164 ICONST(rd->argintregs[0], iptr->op1);
3166 /* a1 = arraydescriptor */
3168 a = dseg_addaddress(cd, iptr->val.a);
3169 M_ALD(rd->argintregs[1], REG_PV, a);
3171 /* a2 = pointer to dimensions = stack pointer */
3173 M_INTMOVE(REG_SP, rd->argintregs[2]);
3175 a = dseg_addaddress(cd, (void*) builtin_nmultianewarray);
3176 M_ALD(REG_ITMP3, REG_PV, a);
3177 M_JSR(REG_RA, REG_ITMP3);
3179 s1 = (int)((u1*) mcodeptr - cd->mcodebase);
3181 M_LDA (REG_PV, REG_RA, -s1);
3185 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3186 M_INTMOVE(REG_RESULT, s1);
3187 store_reg_to_var_int(iptr->dst, s1);
3191 throw_cacao_exception_exit(string_java_lang_InternalError,
3192 "Unknown ICMD %d", iptr->opc);
3195 } /* for instruction */
3197 /* copy values to interface registers */
3199 src = bptr->outstack;
3200 len = bptr->outdepth;
3204 if ((src->varkind != STACKVAR)) {
3206 if (IS_FLT_DBL_TYPE(s2)) {
3207 var_to_reg_flt(s1, src, REG_FTMP1);
3208 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3209 M_TFLTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3212 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3216 var_to_reg_int(s1, src, REG_ITMP1);
3217 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3218 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3221 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3227 } /* if (bptr -> flags >= BBREACHED) */
3228 } /* for basic block */
3231 /* generate bound check stubs */
3233 s4 *xcodeptr = NULL;
3236 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3237 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3239 (u1 *) mcodeptr - cd->mcodebase);
3243 M_MOV(bref->reg, REG_ITMP1);
3244 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3246 if (xcodeptr != NULL) {
3247 M_BR(xcodeptr - mcodeptr);
3251 xcodeptr = mcodeptr;
3253 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3254 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3256 M_MOV(REG_ITMP1, rd->argintregs[0]);
3257 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3258 M_ALD(REG_ITMP3, REG_PV, a);
3259 M_JSR(REG_RA, REG_ITMP3);
3261 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3263 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3264 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3266 a = dseg_addaddress(cd, asm_handle_exception);
3267 M_ALD(REG_ITMP3, REG_PV, a);
3273 /* generate negative array size check stubs */
3277 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3278 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3279 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3281 (u1 *) xcodeptr - cd->mcodebase - 4);
3285 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3287 (u1 *) mcodeptr - cd->mcodebase);
3291 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3293 if (xcodeptr != NULL) {
3294 M_BR(xcodeptr - mcodeptr);
3298 xcodeptr = mcodeptr;
3300 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3301 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3303 a = dseg_addaddress(cd, new_negativearraysizeexception);
3304 M_ALD(REG_ITMP3, REG_PV, a);
3305 M_JSR(REG_RA, REG_ITMP3);
3307 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3309 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3310 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3312 a = dseg_addaddress(cd, asm_handle_exception);
3313 M_ALD(REG_ITMP3, REG_PV, a);
3319 /* generate cast check stubs */
3323 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3324 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3325 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3327 (u1 *) xcodeptr - cd->mcodebase - 4);
3331 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3333 (u1 *) mcodeptr - cd->mcodebase);
3337 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3339 if (xcodeptr != NULL) {
3340 M_BR(xcodeptr - mcodeptr);
3344 xcodeptr = mcodeptr;
3346 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3347 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3349 a = dseg_addaddress(cd, new_classcastexception);
3350 M_ALD(REG_ITMP3, REG_PV, a);
3351 M_JSR(REG_RA, REG_ITMP3);
3353 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3355 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3356 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3358 a = dseg_addaddress(cd, asm_handle_exception);
3359 M_ALD(REG_ITMP3, REG_PV, a);
3365 /* generate exception check stubs */
3369 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3370 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3371 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3373 (u1 *) xcodeptr - cd->mcodebase - 4);
3377 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3379 (u1 *) mcodeptr - cd->mcodebase);
3383 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3385 if (xcodeptr != NULL) {
3386 M_BR(xcodeptr - mcodeptr);
3390 xcodeptr = mcodeptr;
3392 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3393 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3394 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3396 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3397 M_ALD(REG_ITMP3, REG_PV, a);
3398 M_JSR(REG_RA, REG_ITMP3);
3401 /* get the exceptionptr from the ptrprt and clear it */
3402 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3403 M_AST(REG_ZERO, REG_RESULT, 0);
3405 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3406 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3408 a = dseg_addaddress(cd, &_exceptionptr);
3409 M_ALD(REG_ITMP3, REG_PV, a);
3410 M_ALD(REG_ITMP1_XPTR, REG_ITMP3, 0);
3411 M_AST(REG_ZERO, REG_ITMP3, 0);
3414 a = dseg_addaddress(cd, asm_handle_exception);
3415 M_ALD(REG_ITMP3, REG_PV, a);
3421 /* generate null pointer check stubs */
3425 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3426 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3427 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3429 (u1 *) xcodeptr - cd->mcodebase - 4);
3433 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3435 (u1 *) mcodeptr - cd->mcodebase);
3439 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3441 if (xcodeptr != NULL) {
3442 M_BR(xcodeptr - mcodeptr);
3446 xcodeptr = mcodeptr;
3448 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3449 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3451 a = dseg_addaddress(cd, new_nullpointerexception);
3452 M_ALD(REG_ITMP3, REG_PV, a);
3453 M_JSR(REG_RA, REG_ITMP3);
3455 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3457 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3458 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3460 a = dseg_addaddress(cd, asm_handle_exception);
3461 M_ALD(REG_ITMP3, REG_PV, a);
3468 /* generate put/getstatic stub call code */
3475 for (cref = cd->clinitrefs; cref != NULL; cref = cref->next) {
3476 /* Get machine code which is patched back in later. The call is */
3477 /* 2 instruction words long. */
3478 xcodeptr = (s4 *) (cd->mcodebase + cref->branchpos);
3480 /* We need to split this, because an unaligned 8 byte read causes */
3482 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3484 /* patch in the call to call the following code (done at compile */
3487 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3488 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3490 M_BRS(tmpmcodeptr - (xcodeptr + 1));
3493 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3497 /* move class pointer into REG_ITMP1 */
3498 a = dseg_addaddress(cd, cref->class);
3499 M_ALD(REG_ITMP1, REG_PV, a);
3501 /* move machine code into REG_ITMP2 */
3502 a = dseg_adds8(cd, mcode);
3503 M_LLD(REG_ITMP2, REG_PV, a);
3505 a = dseg_addaddress(cd, asm_check_clinit);
3506 M_ALD(REG_ITMP3, REG_PV, a);
3513 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
3515 docacheflush((void*) m->entrypoint, ((u1*) mcodeptr - cd->mcodebase));
3519 /* function createcompilerstub *************************************************
3521 creates a stub routine which calls the compiler
3523 *******************************************************************************/
3525 #define COMPSTUB_SIZE 4
3527 u1 *createcompilerstub(methodinfo *m)
3529 u8 *s = CNEW(u8, COMPSTUB_SIZE); /* memory to hold the stub */
3530 s4 *mcodeptr = (s4 *) s; /* code generation pointer */
3532 /* code for the stub */
3533 M_ALD(REG_PV, REG_PV, 24); /* load pointer to the compiler */
3535 M_JSR(REG_ITMP1, REG_PV); /* jump to the compiler, return address
3536 in itmp1 is used as method pointer */
3539 s[2] = (u8) m; /* literals to be adressed */
3540 s[3] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3542 (void) docacheflush((void*) s, (char*) mcodeptr - (char*) s);
3544 #if defined(STATISTICS)
3546 count_cstub_len += COMPSTUB_SIZE * 8;
3553 /* function removecompilerstub *************************************************
3555 deletes a compilerstub from memory (simply by freeing it)
3557 *******************************************************************************/
3559 void removecompilerstub(u1 *stub)
3561 CFREE(stub, COMPSTUB_SIZE * 8);
3565 /* function: createnativestub **************************************************
3567 creates a stub routine which calls a native method
3569 *******************************************************************************/
3571 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3572 #define NATIVESTUB_STACK 2
3573 #define NATIVESTUB_THREAD_EXTRA 5
3575 #define NATIVESTUB_STACK 1
3576 #define NATIVESTUB_THREAD_EXTRA 1
3579 #define NATIVESTUB_SIZE (54 + 4 + NATIVESTUB_THREAD_EXTRA - 1)
3580 #define NATIVESTUB_STATIC_SIZE 5
3581 #define NATIVESTUB_VERBOSE_SIZE (50 + 17)
3582 #define NATIVESTUB_OFFSET 10
3585 u1 *createnativestub(functionptr f, methodinfo *m)
3587 u8 *s; /* memory to hold the stub */
3589 s4 *mcodeptr; /* code generation pointer */
3590 s4 stackframesize = 0; /* size of stackframe if needed */
3595 t_inlining_globals *id;
3598 /* mark start of dump memory area */
3600 dumpsize = dump_size();
3602 /* setup registers before using it */
3604 cd = DNEW(codegendata);
3605 rd = DNEW(registerdata);
3606 id = DNEW(t_inlining_globals);
3608 inlining_setup(m, id);
3609 reg_setup(m, rd, id);
3611 descriptor2types(m); /* set paramcount and paramtypes */
3613 stubsize = NATIVESTUB_SIZE; /* calculate nativestub size */
3615 if ((m->flags & ACC_STATIC) && !m->class->initialized)
3616 stubsize += NATIVESTUB_STATIC_SIZE;
3619 stubsize += NATIVESTUB_VERBOSE_SIZE;
3621 s = CNEW(u8, stubsize); /* memory to hold the stub */
3622 cs = s + NATIVESTUB_OFFSET;
3623 mcodeptr = (s4 *) (cs); /* code generation pointer */
3625 /* set some required varibles which are normally set by codegen_setup */
3626 cd->mcodebase = (u1 *) mcodeptr;
3627 cd->clinitrefs = NULL;
3629 *(cs-1) = (u8) f; /* address of native method */
3630 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3631 *(cs-2) = (u8) &builtin_get_exceptionptrptr;
3633 *(cs-2) = (u8) (&_exceptionptr); /* address of exceptionptr */
3635 *(cs-3) = (u8) asm_handle_nat_exception;/* addr of asm exception handler */
3636 *(cs-4) = (u8) (&env); /* addr of jni_environement */
3637 *(cs-5) = (u8) builtin_trace_args;
3639 *(cs-7) = (u8) builtin_displaymethodstop;
3640 *(cs-8) = (u8) m->class;
3641 *(cs-9) = (u8) asm_check_clinit;
3642 *(cs-10) = (u8) NULL; /* filled with machine code */
3644 M_LDA(REG_SP, REG_SP, -NATIVESTUB_STACK * 8); /* build up stackframe */
3645 M_LST(REG_RA, REG_SP, 0); /* store return address */
3647 /* if function is static, check for initialized */
3649 if (m->flags & ACC_STATIC && !m->class->initialized) {
3650 codegen_addclinitref(cd, mcodeptr, m->class);
3653 /* max. 50 instructions */
3658 M_LDA(REG_SP, REG_SP, -(18 * 8));
3659 M_AST(REG_RA, REG_SP, 1 * 8);
3661 /* save integer argument registers */
3662 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3663 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
3666 /* save and copy float arguments into integer registers */
3667 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3668 t = m->paramtypes[p];
3670 if (IS_FLT_DBL_TYPE(t)) {
3671 if (IS_2_WORD_TYPE(t)) {
3672 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3673 M_LLD(rd->argintregs[p], REG_SP, (10 + p) * 8);
3676 M_FST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3677 M_ILD(rd->argintregs[p], REG_SP, (10 + p) * 8);
3681 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3685 M_ALD(REG_ITMP1, REG_PV, -6 * 8); /* method address */
3686 M_AST(REG_ITMP1, REG_SP, 0);
3687 M_ALD(REG_ITMP3, REG_PV, -5 * 8); /* builtin_trace_args */
3688 M_JSR(REG_RA, REG_ITMP3);
3690 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3691 M_LDA(REG_PV, REG_RA, disp);
3693 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3694 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
3697 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3698 t = m->paramtypes[p];
3700 if (IS_FLT_DBL_TYPE(t)) {
3701 if (IS_2_WORD_TYPE(t)) {
3702 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3705 M_FLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3709 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3713 M_ALD(REG_RA, REG_SP, 1 * 8);
3714 M_LDA(REG_SP, REG_SP, 18 * 8);
3717 /* save argument registers on stack -- if we have to */
3718 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
3720 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3721 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3723 stackframesize = stackparamcnt + paramshiftcnt;
3725 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
3727 /* copy stack arguments into new stack frame -- if any */
3728 for (i = 0; i < stackparamcnt; i++) {
3729 M_LLD(REG_ITMP1, REG_SP, (stackparamcnt + 1 + i) * 8);
3730 M_LST(REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
3733 if (m->flags & ACC_STATIC) {
3734 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
3735 M_DST(rd->argfltregs[5], REG_SP, 1 * 8);
3737 M_LST(rd->argintregs[5], REG_SP, 1 * 8);
3740 if (IS_FLT_DBL_TYPE(m->paramtypes[4])) {
3741 M_DST(rd->argfltregs[4], REG_SP, 0 * 8);
3743 M_LST(rd->argintregs[4], REG_SP, 0 * 8);
3747 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
3748 M_DST(rd->argfltregs[5], REG_SP, 0 * 8);
3750 M_LST(rd->argintregs[5], REG_SP, 0 * 8);
3755 if (m->flags & ACC_STATIC) {
3756 M_MOV(rd->argintregs[5], rd->argintregs[7]);
3758 M_DMFC1(REG_ITMP1, rd->argfltregs[5]);
3759 M_DMTC1(REG_ITMP1, rd->argfltregs[7]);
3761 M_MOV(rd->argintregs[4], rd->argintregs[6]);
3763 M_DMFC1(REG_ITMP1, rd->argfltregs[4]);
3764 M_DMTC1(REG_ITMP1, rd->argfltregs[6]);
3766 M_MOV(rd->argintregs[3], rd->argintregs[5]);
3767 M_DMFC1(REG_ITMP1, rd->argfltregs[3]);
3769 M_MOV(rd->argintregs[2], rd->argintregs[4]);
3770 M_DMTC1(REG_ITMP1, rd->argfltregs[5]);
3772 M_MOV(rd->argintregs[1], rd->argintregs[3]);
3773 M_DMFC1(REG_ITMP1, rd->argfltregs[2]);
3775 M_MOV(rd->argintregs[0], rd->argintregs[2]);
3776 M_DMTC1(REG_ITMP1, rd->argfltregs[4]);
3778 M_DMFC1(REG_ITMP1, rd->argfltregs[1]);
3779 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
3781 M_DMFC1(REG_ITMP1, rd->argfltregs[0]);
3782 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
3784 M_ALD(rd->argintregs[1], REG_PV, -8 * 8);
3787 M_MOV(rd->argintregs[6], rd->argintregs[7]);
3789 M_DMFC1(REG_ITMP1, rd->argfltregs[6]);
3790 M_DMTC1(REG_ITMP1, rd->argfltregs[7]);
3792 M_MOV(rd->argintregs[5], rd->argintregs[6]);
3794 M_DMFC1(REG_ITMP1, rd->argfltregs[5]);
3795 M_DMTC1(REG_ITMP1, rd->argfltregs[6]);
3797 M_MOV(rd->argintregs[4], rd->argintregs[5]);
3798 M_DMFC1(REG_ITMP1, rd->argfltregs[4]);
3800 M_MOV(rd->argintregs[3], rd->argintregs[4]);
3801 M_DMTC1(REG_ITMP1, rd->argfltregs[5]);
3803 M_MOV(rd->argintregs[2], rd->argintregs[3]);
3804 M_DMFC1(REG_ITMP1, rd->argfltregs[3]);
3806 M_MOV(rd->argintregs[1], rd->argintregs[2]);
3807 M_DMTC1(REG_ITMP1, rd->argfltregs[4]);
3809 M_MOV(rd->argintregs[0], rd->argintregs[1]);
3810 M_DMFC1(REG_ITMP1, rd->argfltregs[2]);
3812 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
3814 M_DMFC1(REG_ITMP1, rd->argfltregs[1]);
3815 M_DMFC1(REG_ITMP2, rd->argfltregs[0]);
3817 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
3818 M_DMTC1(REG_ITMP2, rd->argfltregs[1]);
3821 M_ALD(rd->argintregs[0], REG_PV, -4 * 8); /* jni environement */
3822 M_ALD(REG_ITMP3, REG_PV, -1 * 8); /* load adress of native method */
3823 M_JSR(REG_RA, REG_ITMP3); /* call native method */
3824 M_NOP; /* delay slot */
3826 /* remove stackframe if there is one */
3827 if (stackframesize) {
3828 M_LDA(REG_SP, REG_SP, stackframesize * 8);
3831 /* 17 instructions */
3833 M_LDA(REG_SP, REG_SP, -(3 * 8));
3834 M_AST(REG_RA, REG_SP, 0 * 8);
3835 M_LST(REG_RESULT, REG_SP, 1 * 8);
3836 M_DST(REG_FRESULT, REG_SP, 2 * 8);
3837 M_ALD(rd->argintregs[0], REG_PV, -6 * 8);
3838 M_MOV(REG_RESULT, rd->argintregs[1]);
3839 M_DMFC1(REG_ITMP1, REG_FRESULT);
3840 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
3841 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
3842 M_ALD(REG_ITMP3, REG_PV, -7 * 8);/* builtin_displaymethodstop */
3843 M_JSR(REG_RA, REG_ITMP3);
3845 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3846 M_LDA(REG_PV, REG_RA, disp);
3847 M_ALD(REG_RA, REG_SP, 0 * 8);
3848 M_LLD(REG_RESULT, REG_SP, 1 * 8);
3849 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
3850 M_LDA(REG_SP, REG_SP, 3 * 8);
3853 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3854 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* builtin_get_exceptionptrptr */
3855 M_JSR(REG_RA, REG_ITMP3);
3858 if (IS_FLT_DBL_TYPE(m->returntype)) {
3859 M_DST(REG_FRESULT, REG_SP, 1 * 8);
3862 M_AST(REG_RESULT, REG_SP, 1 * 8);
3865 M_MOV(REG_RESULT, REG_ITMP3);
3867 if (IS_FLT_DBL_TYPE(m->returntype)) {
3868 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
3871 M_ALD(REG_RESULT, REG_SP, 1 * 8);
3874 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* get address of exceptionptr */
3877 M_LLD(REG_RA, REG_SP, 0); /* load return address */
3878 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
3880 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
3881 M_LDA(REG_SP, REG_SP, NATIVESTUB_STACK * 8);/*remove stackframe, delay slot*/
3883 M_RET(REG_RA); /* return to caller */
3884 M_NOP; /* delay slot */
3886 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
3887 M_ALD(REG_ITMP3, REG_PV, -3 * 8); /* load asm exception handler address */
3889 M_JMP(REG_ITMP3); /* jump to asm exception handler */
3890 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
3893 /* generate static stub call code */
3900 /* there can only be one clinit ref entry */
3901 cref = cd->clinitrefs;
3904 /* Get machine code which is patched back in later. The call is */
3905 /* 2 instruction words long. */
3906 xcodeptr = (s4 *) (cd->mcodebase + cref->branchpos);
3908 /* We need to split this, because an unaligned 8 byte read causes */
3910 *(cs-10) = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3912 /* patch in the call to call the following code (done at compile */
3915 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3916 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3918 M_BRS(tmpmcodeptr - (xcodeptr + 1));
3921 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3923 /* move class pointer into REG_ITMP1 */
3924 M_ALD(REG_ITMP1, REG_PV, -8 * 8); /* class */
3926 /* move machine code into REG_ITMP2 */
3927 M_LLD(REG_ITMP2, REG_PV, -10 * 8); /* machine code */
3929 M_ALD(REG_ITMP3, REG_PV, -9 * 8); /* asm_check_clinit */
3935 (void) docacheflush((void*) cs, (char*) mcodeptr - (char*) cs);
3937 /* Check if the stub size is big enough to hold the whole stub generated. */
3938 /* If not, this can lead into unpredictable crashes, because of heap */
3940 if ((s4) ((ptrint) mcodeptr - (ptrint) s) > stubsize * sizeof(u8)) {
3941 throw_cacao_exception_exit(string_java_lang_InternalError,
3942 "Native stub size %d is to small for current stub size %d",
3943 stubsize, (s4) ((ptrint) mcodeptr - (ptrint) s));
3946 #if defined(STATISTICS)
3948 count_nstub_len += NATIVESTUB_SIZE * 8;
3951 /* release dump area */
3953 dump_release(dumpsize);
3955 return (u1 *) (s + NATIVESTUB_OFFSET);
3959 /* function: removenativestub **************************************************
3961 removes a previously created native-stub from memory
3963 *******************************************************************************/
3965 void removenativestub(u1 *stub)
3967 CFREE((u8 *) stub - NATIVESTUB_OFFSET, NATIVESTUB_SIZE * 8);
3971 void docacheflush(u1 *p, long bytelen)
3973 u1 *e = p + bytelen;
3974 long psize = sysconf(_SC_PAGESIZE);
3975 p -= (long) p & (psize-1);
3976 e += psize - ((((long) e - 1) & (psize-1)) + 1);
3978 mprotect(p, bytelen, PROT_READ|PROT_WRITE|PROT_EXEC);
3983 * These are local overrides for various environment variables in Emacs.
3984 * Please do not remove this and leave it at the end of the file, where
3985 * Emacs will automagically detect them.
3986 * ---------------------------------------------------------------------
3989 * indent-tabs-mode: t