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 1735 2004-12-07 14:33:27Z twisti $
44 #include "native/native.h"
45 #include "vm/builtin.h"
46 #include "vm/jit/asmpart.h"
47 #include "vm/jit/jit.h"
48 #include "vm/jit/reg.h"
49 #include "vm/jit/mips/codegen.h"
50 #include "vm/jit/mips/types.h"
53 /* *****************************************************************************
55 Datatypes and Register Allocations:
56 -----------------------------------
58 On 64-bit-machines (like the MIPS) all operands are stored in the
59 registers in a 64-bit form, even when the correspondig JavaVM operands
60 only need 32 bits. This is done by a canonical representation:
62 32-bit integers are allways stored as sign-extended 64-bit values (this
63 approach is directly supported by the MIPS architecture and is very easy
66 32-bit-floats are stored in a 64-bit double precision register by simply
67 expanding the exponent and mantissa with zeroes. (also supported by the
73 The calling conventions and the layout of the stack is explained in detail
74 in the documention file: calling.doc
76 *******************************************************************************/
79 /* register descripton - array ************************************************/
81 /* #define REG_RES 0 reserved register for OS or code generator */
82 /* #define REG_RET 1 return value register */
83 /* #define REG_EXC 2 exception value register (only old jit) */
84 /* #define REG_SAV 3 (callee) saved register */
85 /* #define REG_TMP 4 scratch temporary register (caller saved) */
86 /* #define REG_ARG 5 argument register (caller saved) */
88 /* #define REG_END -1 last entry in tables */
90 static int nregdescint[] = {
91 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
92 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
93 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
94 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
97 /* for use of reserved registers, see comment above */
99 static int nregdescfloat[] = {
100 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
101 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
102 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
103 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
106 /* for use of reserved registers, see comment above */
109 /* Include independent code generation stuff -- include after register */
110 /* descriptions to avoid extern definitions. */
112 #include "vm/jit/codegen.inc"
113 #include "vm/jit/reg.inc"
115 #include "vm/jit/lsra.inc"
119 /* NullPointerException handlers and exception handling initialisation */
121 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
122 void thread_restartcriticalsection(ucontext_t *uc)
125 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[CTX_EPC])) != NULL)
126 uc->uc_mcontext.gregs[CTX_EPC] = (u8) critical;
130 /* NullPointerException signal handler for hardware null pointer check */
132 void catch_NullPointerException(int sig, int code, struct sigcontext *sigctx)
137 java_objectheader *xptr;
139 /* Reset signal handler - necessary for SysV, does no harm for BSD */
141 instr = *((int*)(sigctx->sc_pc));
142 faultaddr = sigctx->sc_regs[(instr >> 21) & 0x1f];
144 if (faultaddr == 0) {
146 sigaddset(&nsig, sig);
147 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
149 xptr = new_nullpointerexception();
151 sigctx->sc_regs[REG_ITMP1_XPTR] = (u8) xptr;
152 sigctx->sc_regs[REG_ITMP2_XPC] = sigctx->sc_pc;
153 sigctx->sc_pc = (u8) asm_handle_exception;
156 faultaddr += (long) ((instr << 16) >> 16);
157 fprintf(stderr, "faulting address: 0x%lx at 0x%lx\n", (long) faultaddr, (long) sigctx->sc_pc);
158 panic("Stack overflow");
165 void init_exceptions(void)
168 sigset_t unblockmask;
170 /* The Boehm GC initialization blocks the SIGSEGV signal. So we do a
171 dummy allocation here to ensure that the GC is initialized.
173 heap_allocate(1, 0, NULL);
175 /* install signal handlers we need to convert to exceptions */
177 sigemptyset(&unblockmask);
179 sa.sa_sigaction = (functionptr) catch_NullPointerException;
180 sigemptyset(&sa.sa_mask);
184 sigaction(SIGSEGV, &sa, NULL);
185 sigaddset(&unblockmask, SIGSEGV);
189 sigaction(SIGBUS, &sa, NULL);
190 sigaddset(&unblockmask, SIGBUS);
194 sigprocmask(SIG_UNBLOCK, &unblockmask, NULL);
196 /* Turn off flush-to-zero */
199 n.fc_word = get_fpc_csr();
200 n.fc_struct.flush = 0;
201 set_fpc_csr(n.fc_word);
206 /* function gen_mcode **********************************************************
208 generates machine code
210 *******************************************************************************/
212 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
214 s4 len, s1, s2, s3, d;
228 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
230 /* space to save used callee saved registers */
232 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
233 savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
235 parentargs_base = rd->maxmemuse + savedregs_num;
237 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
239 if (checksync && (m->flags & ACC_SYNCHRONIZED))
244 /* adjust frame size for 16 byte alignment */
246 if (parentargs_base & 1)
249 /* create method header */
252 (void) dseg_addaddress(cd, m); /* Filler */
254 (void) dseg_addaddress(cd, m); /* MethodPointer */
255 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
257 #if defined(USE_THREADS)
259 /* IsSync contains the offset relative to the stack pointer for the
260 argument of monitor_exit used in the exception handler. Since the
261 offset could be zero and give a wrong meaning of the flag it is
265 if (checksync && (m->flags & ACC_SYNCHRONIZED))
266 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8); /* IsSync */
271 (void) dseg_adds4(cd, 0); /* IsSync */
273 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
274 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse);/* IntSave */
275 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse);/* FltSave */
276 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
278 /* create exception table */
280 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
281 dseg_addtarget(cd, ex->start);
282 dseg_addtarget(cd, ex->end);
283 dseg_addtarget(cd, ex->handler);
284 (void) dseg_addaddress(cd, ex->catchtype);
287 /* initialize mcode variables */
289 mcodeptr = (s4 *) cd->mcodebase;
290 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
291 MCODECHECK(128 + m->paramcount);
293 /* create stack frame (if necessary) */
295 if (parentargs_base) {
296 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
299 /* save return address and used callee saved registers */
302 if (!m->isleafmethod) {
303 p--; M_LST(REG_RA, REG_SP, 8 * p);
305 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
306 p--; M_LST(rd->savintregs[i], REG_SP, 8 * p);
308 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
309 p--; M_DST(rd->savfltregs[i], REG_SP, 8 * p);
312 /* save monitorenter argument */
314 #if defined(USE_THREADS)
315 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
316 if (m->flags & ACC_STATIC) {
317 p = dseg_addaddress(cd, m->class);
318 M_ALD(REG_ITMP1, REG_PV, p);
319 M_AST(REG_ITMP1, REG_SP, rd->maxmemuse * 8);
322 M_AST(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
327 /* copy argument registers to stack and call trace function with pointer
328 to arguments on stack. ToDo: save floating point registers !!!!!!!!!
332 M_LDA(REG_SP, REG_SP, -(18 * 8));
333 M_LST(REG_RA, REG_SP, 1 * 8);
335 /* save integer argument registers */
336 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
337 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
340 /* save and copy float arguments into integer registers */
341 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
342 t = m->paramtypes[p];
344 if (IS_FLT_DBL_TYPE(t)) {
345 if (IS_2_WORD_TYPE(t)) {
346 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
347 M_LLD(rd->argintregs[p], REG_SP, (10 + p) * 8);
350 M_FST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
351 M_ILD(rd->argintregs[p], REG_SP, (10 + p) * 8);
355 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
359 p = dseg_addaddress(cd, m);
360 M_ALD(REG_ITMP1, REG_PV, p);
361 M_LST(REG_ITMP1, REG_SP, 0);
362 p = dseg_addaddress(cd, (void *) builtin_trace_args);
363 M_ALD(REG_ITMP3, REG_PV, p);
364 M_JSR(REG_RA, REG_ITMP3);
367 M_LLD(REG_RA, REG_SP, 1 * 8);
369 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
370 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
373 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
374 t = m->paramtypes[p];
376 if (IS_FLT_DBL_TYPE(t)) {
377 if (IS_2_WORD_TYPE(t)) {
378 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
381 M_FLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
385 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
389 M_LDA(REG_SP, REG_SP, 18 * 8);
392 /* take arguments out of register or stack frame */
394 for (p = 0, l = 0; p < m->paramcount; p++) {
395 t = m->paramtypes[p];
396 var = &(rd->locals[l][t]);
398 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
402 if (IS_INT_LNG_TYPE(t)) { /* integer args */
403 if (p < INT_ARG_CNT) { /* register arguments */
404 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
405 M_INTMOVE(rd->argintregs[p], var->regoff);
406 } else { /* reg arg -> spilled */
407 M_LST(rd->argintregs[p], REG_SP, 8 * var->regoff);
410 } else { /* stack arguments */
411 pa = p - INT_ARG_CNT;
412 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
413 M_LLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
415 } else { /* stack arg -> spilled */
416 M_LLD(REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
417 M_LST(REG_ITMP1, REG_SP, 8 * var->regoff);
421 } else { /* floating args */
422 if (p < FLT_ARG_CNT) { /* register arguments */
423 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
424 M_TFLTMOVE(var->type, rd->argfltregs[p], var->regoff);
426 } else { /* reg arg -> spilled */
427 M_DST(rd->argfltregs[p], REG_SP, var->regoff * 8);
430 } else { /* stack arguments */
431 pa = p - FLT_ARG_CNT;
432 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
433 M_DLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
435 } else { /* stack-arg -> spilled */
436 M_DLD(REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
437 M_DST(REG_FTMP1, REG_SP, 8 * var->regoff);
443 /* call monitorenter function */
445 #if defined(USE_THREADS)
446 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
448 s8 func_enter = (m->flags & ACC_STATIC) ?
449 (s8) builtin_staticmonitorenter : (s8) builtin_monitorenter;
450 p = dseg_addaddress(cd, (void *) func_enter);
451 M_ALD(REG_ITMP3, REG_PV, p);
452 M_JSR(REG_RA, REG_ITMP3);
453 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
454 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
455 M_LDA(REG_PV, REG_RA, disp);
460 /* end of header generation */
462 /* walk through all basic blocks */
463 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
465 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
467 if (bptr->flags >= BBREACHED) {
469 /* branch resolving */
472 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
473 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
479 /* copy interface registers to their destination */
484 while (src != NULL) {
486 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
487 d = reg_of_var(rd, src, REG_ITMP1);
488 M_INTMOVE(REG_ITMP1, d);
489 store_reg_to_var_int(src, d);
492 d = reg_of_var(rd, src, REG_IFTMP);
493 if ((src->varkind != STACKVAR)) {
495 if (IS_FLT_DBL_TYPE(s2)) {
496 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
497 s1 = rd->interfaces[len][s2].regoff;
498 M_TFLTMOVE(s2, s1, d);
501 M_DLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
503 store_reg_to_var_flt(src, d);
506 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
507 s1 = rd->interfaces[len][s2].regoff;
511 M_LLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
513 store_reg_to_var_int(src, d);
520 /* walk through all instructions */
524 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
526 MCODECHECK(64); /* an instruction usually needs < 64 words */
529 case ICMD_NOP: /* ... ==> ... */
532 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
534 var_to_reg_int(s1, src, REG_ITMP1);
536 codegen_addxnullrefs(cd, mcodeptr);
540 /* constant operations ************************************************/
542 case ICMD_ICONST: /* ... ==> ..., constant */
543 /* op1 = 0, val.i = constant */
545 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
546 ICONST(d, iptr->val.i);
547 store_reg_to_var_int(iptr->dst, d);
550 case ICMD_LCONST: /* ... ==> ..., constant */
551 /* op1 = 0, val.l = constant */
553 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
554 LCONST(d, iptr->val.l);
555 store_reg_to_var_int(iptr->dst, d);
558 case ICMD_FCONST: /* ... ==> ..., constant */
559 /* op1 = 0, val.f = constant */
561 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
562 a = dseg_addfloat(cd, iptr->val.f);
564 store_reg_to_var_flt(iptr->dst, d);
567 case ICMD_DCONST: /* ... ==> ..., constant */
568 /* op1 = 0, val.d = constant */
570 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
571 a = dseg_adddouble(cd, iptr->val.d);
573 store_reg_to_var_flt (iptr->dst, d);
576 case ICMD_ACONST: /* ... ==> ..., constant */
577 /* op1 = 0, val.a = constant */
579 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
581 a = dseg_addaddress(cd, iptr->val.a);
584 M_INTMOVE(REG_ZERO, d);
586 store_reg_to_var_int(iptr->dst, d);
590 /* load/store operations **********************************************/
592 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
593 case ICMD_LLOAD: /* op1 = local variable */
596 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
597 if ((iptr->dst->varkind == LOCALVAR) &&
598 (iptr->dst->varnum == iptr->op1))
600 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
601 if (var->flags & INMEMORY) {
602 M_LLD(d, REG_SP, 8 * var->regoff);
604 M_INTMOVE(var->regoff,d);
606 store_reg_to_var_int(iptr->dst, d);
609 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
610 case ICMD_DLOAD: /* op1 = local variable */
612 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
613 if ((iptr->dst->varkind == LOCALVAR) &&
614 (iptr->dst->varnum == iptr->op1))
616 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
618 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
619 if (var->flags & INMEMORY) {
620 M_CCFLD(var->type, t2, d, REG_SP, 8 * var->regoff);
622 M_CCFLTMOVE(var->type, t2, var->regoff, d);
625 store_reg_to_var_flt(iptr->dst, d);
629 case ICMD_ISTORE: /* ..., value ==> ... */
630 case ICMD_LSTORE: /* op1 = local variable */
633 if ((src->varkind == LOCALVAR) &&
634 (src->varnum == iptr->op1))
636 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
637 if (var->flags & INMEMORY) {
638 var_to_reg_int(s1, src, REG_ITMP1);
639 M_LST(s1, REG_SP, 8 * var->regoff);
642 var_to_reg_int(s1, src, var->regoff);
643 M_INTMOVE(s1, var->regoff);
647 case ICMD_FSTORE: /* ..., value ==> ... */
648 case ICMD_DSTORE: /* op1 = local variable */
650 if ((src->varkind == LOCALVAR) &&
651 (src->varnum == iptr->op1))
653 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
655 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
656 if (var->flags & INMEMORY) {
657 var_to_reg_flt(s1, src, REG_FTMP1);
658 M_CCFST(t1, var->type, s1, REG_SP, 8 * var->regoff);
661 var_to_reg_flt(s1, src, var->regoff);
662 M_CCFLTMOVE(t1, var->type, s1, var->regoff);
668 /* pop/dup/swap operations ********************************************/
670 /* attention: double and longs are only one entry in CACAO ICMDs */
672 case ICMD_POP: /* ..., value ==> ... */
673 case ICMD_POP2: /* ..., value, value ==> ... */
676 case ICMD_DUP: /* ..., a ==> ..., a, a */
677 M_COPY(src, iptr->dst);
680 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
682 M_COPY(src, iptr->dst);
683 M_COPY(src->prev, iptr->dst->prev);
684 M_COPY(iptr->dst, iptr->dst->prev->prev);
687 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
689 M_COPY(src, iptr->dst);
690 M_COPY(src->prev, iptr->dst->prev);
691 M_COPY(src->prev->prev, iptr->dst->prev->prev);
692 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
695 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
697 M_COPY(src, iptr->dst);
698 M_COPY(src->prev, iptr->dst->prev);
701 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
703 M_COPY(src, iptr->dst);
704 M_COPY(src->prev, iptr->dst->prev);
705 M_COPY(src->prev->prev, iptr->dst->prev->prev);
706 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
707 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
710 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
712 M_COPY(src, iptr->dst);
713 M_COPY(src->prev, iptr->dst->prev);
714 M_COPY(src->prev->prev, iptr->dst->prev->prev);
715 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
716 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
717 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
720 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
722 M_COPY(src, iptr->dst->prev);
723 M_COPY(src->prev, iptr->dst);
727 /* integer operations *************************************************/
729 case ICMD_INEG: /* ..., value ==> ..., - value */
731 var_to_reg_int(s1, src, REG_ITMP1);
732 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
733 M_ISUB(REG_ZERO, s1, d);
734 store_reg_to_var_int(iptr->dst, d);
737 case ICMD_LNEG: /* ..., value ==> ..., - value */
739 var_to_reg_int(s1, src, REG_ITMP1);
740 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
741 M_LSUB(REG_ZERO, s1, d);
742 store_reg_to_var_int(iptr->dst, d);
745 case ICMD_I2L: /* ..., value ==> ..., value */
747 var_to_reg_int(s1, src, REG_ITMP1);
748 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
750 store_reg_to_var_int(iptr->dst, d);
753 case ICMD_L2I: /* ..., value ==> ..., value */
755 var_to_reg_int(s1, src, REG_ITMP1);
756 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
757 M_ISLL_IMM(s1, 0, d );
758 store_reg_to_var_int(iptr->dst, d);
761 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
763 var_to_reg_int(s1, src, REG_ITMP1);
764 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
765 M_LSLL_IMM(s1, 56, d);
766 M_LSRA_IMM( d, 56, d);
767 store_reg_to_var_int(iptr->dst, d);
770 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
772 var_to_reg_int(s1, src, REG_ITMP1);
773 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
775 store_reg_to_var_int(iptr->dst, d);
778 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
780 var_to_reg_int(s1, src, REG_ITMP1);
781 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
782 M_LSLL_IMM(s1, 48, d);
783 M_LSRA_IMM( d, 48, d);
784 store_reg_to_var_int(iptr->dst, d);
788 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
790 var_to_reg_int(s1, src->prev, REG_ITMP1);
791 var_to_reg_int(s2, src, REG_ITMP2);
792 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
794 store_reg_to_var_int(iptr->dst, d);
797 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
798 /* val.i = constant */
800 var_to_reg_int(s1, src, REG_ITMP1);
801 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
802 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
803 M_IADD_IMM(s1, iptr->val.i, d);
806 ICONST(REG_ITMP2, iptr->val.i);
807 M_IADD(s1, REG_ITMP2, d);
809 store_reg_to_var_int(iptr->dst, d);
812 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
814 var_to_reg_int(s1, src->prev, REG_ITMP1);
815 var_to_reg_int(s2, src, REG_ITMP2);
816 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
818 store_reg_to_var_int(iptr->dst, d);
821 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
822 /* val.l = constant */
824 var_to_reg_int(s1, src, REG_ITMP1);
825 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
826 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
827 M_LADD_IMM(s1, iptr->val.l, d);
830 LCONST(REG_ITMP2, iptr->val.l);
831 M_LADD(s1, REG_ITMP2, d);
833 store_reg_to_var_int(iptr->dst, d);
836 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
838 var_to_reg_int(s1, src->prev, REG_ITMP1);
839 var_to_reg_int(s2, src, REG_ITMP2);
840 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
842 store_reg_to_var_int(iptr->dst, d);
845 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
846 /* val.i = constant */
848 var_to_reg_int(s1, src, REG_ITMP1);
849 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
850 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
851 M_IADD_IMM(s1, -iptr->val.i, d);
854 ICONST(REG_ITMP2, iptr->val.i);
855 M_ISUB(s1, REG_ITMP2, d);
857 store_reg_to_var_int(iptr->dst, d);
860 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
862 var_to_reg_int(s1, src->prev, REG_ITMP1);
863 var_to_reg_int(s2, src, REG_ITMP2);
864 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
866 store_reg_to_var_int(iptr->dst, d);
869 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
870 /* val.l = constant */
872 var_to_reg_int(s1, src, REG_ITMP1);
873 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
874 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
875 M_LADD_IMM(s1, -iptr->val.l, d);
878 LCONST(REG_ITMP2, iptr->val.l);
879 M_LSUB(s1, REG_ITMP2, d);
881 store_reg_to_var_int(iptr->dst, d);
884 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
886 var_to_reg_int(s1, src->prev, REG_ITMP1);
887 var_to_reg_int(s2, src, REG_ITMP2);
888 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
893 store_reg_to_var_int(iptr->dst, d);
896 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
897 /* val.i = constant */
899 var_to_reg_int(s1, src, REG_ITMP1);
900 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
901 ICONST(REG_ITMP2, iptr->val.i);
902 M_IMUL(s1, REG_ITMP2);
906 store_reg_to_var_int(iptr->dst, d);
909 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
911 var_to_reg_int(s1, src->prev, REG_ITMP1);
912 var_to_reg_int(s2, src, REG_ITMP2);
913 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
918 store_reg_to_var_int(iptr->dst, d);
921 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
922 /* val.l = constant */
924 var_to_reg_int(s1, src, REG_ITMP1);
925 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
926 LCONST(REG_ITMP2, iptr->val.l);
927 M_LMUL(s1, REG_ITMP2);
931 store_reg_to_var_int(iptr->dst, d);
934 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
936 var_to_reg_int(s1, src->prev, REG_ITMP1);
937 var_to_reg_int(s2, src, REG_ITMP2);
938 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
943 store_reg_to_var_int(iptr->dst, d);
946 case ICMD_IDIVCONST: /* ..., value ==> ..., value / constant */
947 /* val.i = constant */
949 var_to_reg_int(s1, src, REG_ITMP1);
950 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
951 ICONST(REG_ITMP2, iptr->val.i);
952 M_IDIV(s1, REG_ITMP2);
956 store_reg_to_var_int(iptr->dst, d);
959 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
961 var_to_reg_int(s1, src->prev, REG_ITMP1);
962 var_to_reg_int(s2, src, REG_ITMP2);
963 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
968 store_reg_to_var_int(iptr->dst, d);
971 case ICMD_LDIVCONST: /* ..., value ==> ..., value / constant */
972 /* val.l = constant */
974 var_to_reg_int(s1, src, REG_ITMP1);
975 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
976 LCONST(REG_ITMP2, iptr->val.l);
977 M_LDIV(s1, REG_ITMP2);
981 store_reg_to_var_int(iptr->dst, d);
984 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
986 var_to_reg_int(s1, src->prev, REG_ITMP1);
987 var_to_reg_int(s2, src, REG_ITMP2);
988 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
993 store_reg_to_var_int(iptr->dst, d);
996 case ICMD_IREMCONST: /* ..., value ==> ..., value % constant */
997 /* val.i = constant */
999 var_to_reg_int(s1, src, REG_ITMP1);
1000 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1001 ICONST(REG_ITMP2, iptr->val.i);
1002 M_IDIV(s1, REG_ITMP2);
1006 store_reg_to_var_int(iptr->dst, d);
1009 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1011 var_to_reg_int(s1, src->prev, REG_ITMP1);
1012 var_to_reg_int(s2, src, REG_ITMP2);
1013 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1018 store_reg_to_var_int(iptr->dst, d);
1021 case ICMD_LREMCONST: /* ..., value ==> ..., value % constant */
1022 /* val.l = constant */
1024 var_to_reg_int(s1, src, REG_ITMP1);
1025 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1026 LCONST(REG_ITMP2, iptr->val.l);
1027 M_LDIV(s1, REG_ITMP2);
1031 store_reg_to_var_int(iptr->dst, d);
1034 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1035 case ICMD_LDIVPOW2: /* val.i = constant */
1037 var_to_reg_int(s1, src, REG_ITMP1);
1038 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1039 M_LSRA_IMM(s1, 63, REG_ITMP2);
1040 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1041 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1042 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
1043 store_reg_to_var_int(iptr->dst, d);
1046 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1048 var_to_reg_int(s1, src->prev, REG_ITMP1);
1049 var_to_reg_int(s2, src, REG_ITMP2);
1050 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1052 store_reg_to_var_int(iptr->dst, d);
1055 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1056 /* val.i = constant */
1058 var_to_reg_int(s1, src, REG_ITMP1);
1059 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1060 M_ISLL_IMM(s1, iptr->val.i, d);
1061 store_reg_to_var_int(iptr->dst, d);
1064 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1066 var_to_reg_int(s1, src->prev, REG_ITMP1);
1067 var_to_reg_int(s2, src, REG_ITMP2);
1068 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1070 store_reg_to_var_int(iptr->dst, d);
1073 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1074 /* val.i = constant */
1076 var_to_reg_int(s1, src, REG_ITMP1);
1077 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1078 M_ISRA_IMM(s1, iptr->val.i, d);
1079 store_reg_to_var_int(iptr->dst, d);
1082 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1084 var_to_reg_int(s1, src->prev, REG_ITMP1);
1085 var_to_reg_int(s2, src, REG_ITMP2);
1086 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1088 store_reg_to_var_int(iptr->dst, d);
1091 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1092 /* val.i = constant */
1094 var_to_reg_int(s1, src, REG_ITMP1);
1095 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1096 M_ISRL_IMM(s1, iptr->val.i, d);
1097 store_reg_to_var_int(iptr->dst, d);
1100 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1102 var_to_reg_int(s1, src->prev, REG_ITMP1);
1103 var_to_reg_int(s2, src, REG_ITMP2);
1104 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1106 store_reg_to_var_int(iptr->dst, d);
1109 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1110 /* val.i = constant */
1112 var_to_reg_int(s1, src, REG_ITMP1);
1113 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1114 M_LSLL_IMM(s1, iptr->val.i, d);
1115 store_reg_to_var_int(iptr->dst, d);
1118 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1120 var_to_reg_int(s1, src->prev, REG_ITMP1);
1121 var_to_reg_int(s2, src, REG_ITMP2);
1122 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1124 store_reg_to_var_int(iptr->dst, d);
1127 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1128 /* val.i = constant */
1130 var_to_reg_int(s1, src, REG_ITMP1);
1131 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1132 M_LSRA_IMM(s1, iptr->val.i, d);
1133 store_reg_to_var_int(iptr->dst, d);
1136 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1138 var_to_reg_int(s1, src->prev, REG_ITMP1);
1139 var_to_reg_int(s2, src, REG_ITMP2);
1140 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1142 store_reg_to_var_int(iptr->dst, d);
1145 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1146 /* val.i = constant */
1148 var_to_reg_int(s1, src, REG_ITMP1);
1149 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1150 M_LSRL_IMM(s1, iptr->val.i, d);
1151 store_reg_to_var_int(iptr->dst, d);
1154 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1157 var_to_reg_int(s1, src->prev, REG_ITMP1);
1158 var_to_reg_int(s2, src, REG_ITMP2);
1159 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1161 store_reg_to_var_int(iptr->dst, d);
1164 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1165 /* val.i = constant */
1167 var_to_reg_int(s1, src, REG_ITMP1);
1168 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1169 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1170 M_AND_IMM(s1, iptr->val.i, d);
1173 ICONST(REG_ITMP2, iptr->val.i);
1174 M_AND(s1, REG_ITMP2, d);
1176 store_reg_to_var_int(iptr->dst, d);
1179 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1180 /* val.i = constant */
1182 var_to_reg_int(s1, src, REG_ITMP1);
1183 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1185 M_MOV(s1, REG_ITMP1);
1188 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1189 M_AND_IMM(s1, iptr->val.i, d);
1192 M_ISUB(REG_ZERO, s1, d);
1193 M_AND_IMM(d, iptr->val.i, d);
1196 ICONST(REG_ITMP2, iptr->val.i);
1197 M_AND(s1, REG_ITMP2, d);
1200 M_ISUB(REG_ZERO, s1, d);
1201 M_AND(d, REG_ITMP2, d);
1203 M_ISUB(REG_ZERO, d, d);
1204 store_reg_to_var_int(iptr->dst, d);
1207 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1208 /* val.l = constant */
1210 var_to_reg_int(s1, src, REG_ITMP1);
1211 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1212 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1213 M_AND_IMM(s1, iptr->val.l, d);
1216 LCONST(REG_ITMP2, iptr->val.l);
1217 M_AND(s1, REG_ITMP2, d);
1219 store_reg_to_var_int(iptr->dst, d);
1222 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1223 /* val.l = constant */
1225 var_to_reg_int(s1, src, REG_ITMP1);
1226 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1228 M_MOV(s1, REG_ITMP1);
1231 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1232 M_AND_IMM(s1, iptr->val.l, d);
1235 M_LSUB(REG_ZERO, s1, d);
1236 M_AND_IMM(d, iptr->val.l, d);
1239 LCONST(REG_ITMP2, iptr->val.l);
1240 M_AND(s1, REG_ITMP2, d);
1243 M_LSUB(REG_ZERO, s1, d);
1244 M_AND(d, REG_ITMP2, d);
1246 M_LSUB(REG_ZERO, d, d);
1247 store_reg_to_var_int(iptr->dst, d);
1250 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1253 var_to_reg_int(s1, src->prev, REG_ITMP1);
1254 var_to_reg_int(s2, src, REG_ITMP2);
1255 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1257 store_reg_to_var_int(iptr->dst, d);
1260 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1261 /* val.i = constant */
1263 var_to_reg_int(s1, src, REG_ITMP1);
1264 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1265 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1266 M_OR_IMM(s1, iptr->val.i, d);
1269 ICONST(REG_ITMP2, iptr->val.i);
1270 M_OR(s1, REG_ITMP2, d);
1272 store_reg_to_var_int(iptr->dst, d);
1275 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1276 /* val.l = constant */
1278 var_to_reg_int(s1, src, REG_ITMP1);
1279 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1280 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1281 M_OR_IMM(s1, iptr->val.l, d);
1284 LCONST(REG_ITMP2, iptr->val.l);
1285 M_OR(s1, REG_ITMP2, d);
1287 store_reg_to_var_int(iptr->dst, d);
1290 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1293 var_to_reg_int(s1, src->prev, REG_ITMP1);
1294 var_to_reg_int(s2, src, REG_ITMP2);
1295 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1297 store_reg_to_var_int(iptr->dst, d);
1300 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1301 /* val.i = constant */
1303 var_to_reg_int(s1, src, REG_ITMP1);
1304 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1305 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1306 M_XOR_IMM(s1, iptr->val.i, d);
1309 ICONST(REG_ITMP2, iptr->val.i);
1310 M_XOR(s1, REG_ITMP2, d);
1312 store_reg_to_var_int(iptr->dst, d);
1315 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1316 /* val.l = constant */
1318 var_to_reg_int(s1, src, REG_ITMP1);
1319 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1320 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1321 M_XOR_IMM(s1, iptr->val.l, d);
1324 LCONST(REG_ITMP2, iptr->val.l);
1325 M_XOR(s1, REG_ITMP2, d);
1327 store_reg_to_var_int(iptr->dst, d);
1331 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1333 var_to_reg_int(s1, src->prev, REG_ITMP1);
1334 var_to_reg_int(s2, src, REG_ITMP2);
1335 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1336 M_CMPLT(s1, s2, REG_ITMP3);
1337 M_CMPLT(s2, s1, REG_ITMP1);
1338 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1339 store_reg_to_var_int(iptr->dst, d);
1343 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1344 /* op1 = variable, val.i = constant */
1346 var = &(rd->locals[iptr->op1][TYPE_INT]);
1347 if (var->flags & INMEMORY) {
1349 M_LLD(s1, REG_SP, 8 * var->regoff);
1353 M_IADD_IMM(s1, iptr->val.i, s1);
1354 if (var->flags & INMEMORY)
1355 M_LST(s1, REG_SP, 8 * var->regoff);
1359 /* floating operations ************************************************/
1361 case ICMD_FNEG: /* ..., value ==> ..., - value */
1363 var_to_reg_flt(s1, src, REG_FTMP1);
1364 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1366 store_reg_to_var_flt(iptr->dst, d);
1369 case ICMD_DNEG: /* ..., value ==> ..., - value */
1371 var_to_reg_flt(s1, src, REG_FTMP1);
1372 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1374 store_reg_to_var_flt(iptr->dst, d);
1377 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1379 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1380 var_to_reg_flt(s2, src, REG_FTMP2);
1381 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1383 store_reg_to_var_flt(iptr->dst, d);
1386 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1388 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1389 var_to_reg_flt(s2, src, REG_FTMP2);
1390 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1392 store_reg_to_var_flt(iptr->dst, d);
1395 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1397 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1398 var_to_reg_flt(s2, src, REG_FTMP2);
1399 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1401 store_reg_to_var_flt(iptr->dst, d);
1404 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1406 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1407 var_to_reg_flt(s2, src, REG_FTMP2);
1408 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1410 store_reg_to_var_flt(iptr->dst, d);
1413 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1415 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1416 var_to_reg_flt(s2, src, REG_FTMP2);
1417 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1419 store_reg_to_var_flt(iptr->dst, d);
1422 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1424 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1425 var_to_reg_flt(s2, src, REG_FTMP2);
1426 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1428 store_reg_to_var_flt(iptr->dst, d);
1431 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1433 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1434 var_to_reg_flt(s2, src, REG_FTMP2);
1435 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1437 store_reg_to_var_flt(iptr->dst, d);
1440 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1442 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1443 var_to_reg_flt(s2, src, REG_FTMP2);
1444 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1446 store_reg_to_var_flt(iptr->dst, d);
1449 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1452 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1453 var_to_reg_flt(s2, src, REG_FTMP2);
1454 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1455 M_FDIV(s1,s2, REG_FTMP3);
1456 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1457 M_CVTLF(REG_FTMP3, REG_FTMP3);
1458 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1459 M_FSUB(s1, REG_FTMP3, d);
1460 store_reg_to_var_flt(iptr->dst, d);
1463 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1465 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1466 var_to_reg_flt(s2, src, REG_FTMP2);
1467 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1468 M_DDIV(s1,s2, REG_FTMP3);
1469 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1470 M_CVTLD(REG_FTMP3, REG_FTMP3);
1471 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1472 M_DSUB(s1, REG_FTMP3, d);
1473 store_reg_to_var_flt(iptr->dst, d);
1476 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1478 var_to_reg_int(s1, src, REG_ITMP1);
1479 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1482 store_reg_to_var_flt(iptr->dst, d);
1485 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1487 var_to_reg_int(s1, src, REG_ITMP1);
1488 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1491 store_reg_to_var_flt(iptr->dst, d);
1494 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1496 var_to_reg_flt(s1, src, REG_FTMP1);
1497 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1498 M_TRUNCFI(s1, REG_FTMP1);
1499 M_MOVDI(REG_FTMP1, d);
1501 store_reg_to_var_int(iptr->dst, d);
1504 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1506 var_to_reg_flt(s1, src, REG_FTMP1);
1507 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1508 M_TRUNCDI(s1, REG_FTMP1);
1509 M_MOVDI(REG_FTMP1, d);
1511 store_reg_to_var_int(iptr->dst, d);
1514 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1516 var_to_reg_flt(s1, src, REG_FTMP1);
1517 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1518 M_TRUNCFL(s1, REG_FTMP1);
1519 M_MOVDL(REG_FTMP1, d);
1521 store_reg_to_var_int(iptr->dst, d);
1524 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1526 var_to_reg_flt(s1, src, REG_FTMP1);
1527 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1528 M_TRUNCDL(s1, REG_FTMP1);
1529 M_MOVDL(REG_FTMP1, d);
1531 store_reg_to_var_int(iptr->dst, d);
1534 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1536 var_to_reg_flt(s1, src, REG_FTMP1);
1537 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1539 store_reg_to_var_flt(iptr->dst, d);
1542 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1544 var_to_reg_flt(s1, src, REG_FTMP1);
1545 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1547 store_reg_to_var_flt(iptr->dst, d);
1550 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1552 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1553 var_to_reg_flt(s2, src, REG_FTMP2);
1554 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1557 M_LADD_IMM(REG_ZERO, 1, d);
1561 M_LSUB_IMM(REG_ZERO, 1, d);
1562 M_CMOVT(REG_ZERO, d);
1563 store_reg_to_var_int(iptr->dst, d);
1566 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1568 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1569 var_to_reg_flt(s2, src, REG_FTMP2);
1570 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1573 M_LADD_IMM(REG_ZERO, 1, d);
1577 M_LSUB_IMM(REG_ZERO, 1, d);
1578 M_CMOVT(REG_ZERO, d);
1579 store_reg_to_var_int(iptr->dst, d);
1582 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1584 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1585 var_to_reg_flt(s2, src, REG_FTMP2);
1586 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1589 M_LSUB_IMM(REG_ZERO, 1, d);
1593 M_LADD_IMM(REG_ZERO, 1, d);
1594 M_CMOVT(REG_ZERO, d);
1595 store_reg_to_var_int(iptr->dst, d);
1598 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1600 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1601 var_to_reg_flt(s2, src, REG_FTMP2);
1602 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1605 M_LSUB_IMM(REG_ZERO, 1, d);
1609 M_LADD_IMM(REG_ZERO, 1, d);
1610 M_CMOVT(REG_ZERO, d);
1611 store_reg_to_var_int(iptr->dst, d);
1615 /* memory operations **************************************************/
1617 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1619 var_to_reg_int(s1, src, REG_ITMP1);
1620 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1621 gen_nullptr_check(s1);
1622 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1623 store_reg_to_var_int(iptr->dst, d);
1626 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1628 var_to_reg_int(s1, src->prev, REG_ITMP1);
1629 var_to_reg_int(s2, src, REG_ITMP2);
1630 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1631 if (iptr->op1 == 0) {
1632 gen_nullptr_check(s1);
1635 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1636 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1637 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1638 store_reg_to_var_int(iptr->dst, d);
1641 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1643 var_to_reg_int(s1, src->prev, REG_ITMP1);
1644 var_to_reg_int(s2, src, REG_ITMP2);
1645 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1646 if (iptr->op1 == 0) {
1647 gen_nullptr_check(s1);
1650 M_ASLL_IMM(s2, 2, REG_ITMP2);
1651 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1652 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1653 store_reg_to_var_int(iptr->dst, d);
1656 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1658 var_to_reg_int(s1, src->prev, REG_ITMP1);
1659 var_to_reg_int(s2, src, REG_ITMP2);
1660 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1661 if (iptr->op1 == 0) {
1662 gen_nullptr_check(s1);
1665 M_ASLL_IMM(s2, 3, REG_ITMP2);
1666 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1667 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1668 store_reg_to_var_int(iptr->dst, d);
1671 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1673 var_to_reg_int(s1, src->prev, REG_ITMP1);
1674 var_to_reg_int(s2, src, REG_ITMP2);
1675 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1676 if (iptr->op1 == 0) {
1677 gen_nullptr_check(s1);
1680 M_ASLL_IMM(s2, 2, REG_ITMP2);
1681 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1682 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1683 store_reg_to_var_flt(iptr->dst, d);
1686 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1688 var_to_reg_int(s1, src->prev, REG_ITMP1);
1689 var_to_reg_int(s2, src, REG_ITMP2);
1690 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1691 if (iptr->op1 == 0) {
1692 gen_nullptr_check(s1);
1695 M_ASLL_IMM(s2, 3, REG_ITMP2);
1696 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1697 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1698 store_reg_to_var_flt(iptr->dst, d);
1701 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1703 var_to_reg_int(s1, src->prev, REG_ITMP1);
1704 var_to_reg_int(s2, src, REG_ITMP2);
1705 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1706 if (iptr->op1 == 0) {
1707 gen_nullptr_check(s1);
1710 M_AADD(s2, s1, REG_ITMP1);
1711 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1712 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1713 store_reg_to_var_int(iptr->dst, d);
1716 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1718 var_to_reg_int(s1, src->prev, REG_ITMP1);
1719 var_to_reg_int(s2, src, REG_ITMP2);
1720 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1721 if (iptr->op1 == 0) {
1722 gen_nullptr_check(s1);
1725 M_AADD(s2, s1, REG_ITMP1);
1726 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1727 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1728 store_reg_to_var_int(iptr->dst, d);
1731 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1733 var_to_reg_int(s1, src->prev, REG_ITMP1);
1734 var_to_reg_int(s2, src, REG_ITMP2);
1735 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1736 if (iptr->op1 == 0) {
1737 gen_nullptr_check(s1);
1740 M_AADD(s2, s1, REG_ITMP1);
1741 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1742 store_reg_to_var_int(iptr->dst, d);
1746 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1748 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1749 var_to_reg_int(s2, src->prev, REG_ITMP2);
1750 if (iptr->op1 == 0) {
1751 gen_nullptr_check(s1);
1754 var_to_reg_int(s3, src, REG_ITMP3);
1755 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1756 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1757 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1760 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1762 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1763 var_to_reg_int(s2, src->prev, REG_ITMP2);
1764 if (iptr->op1 == 0) {
1765 gen_nullptr_check(s1);
1768 var_to_reg_int(s3, src, REG_ITMP3);
1769 M_ASLL_IMM(s2, 2, REG_ITMP2);
1770 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1771 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1774 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1776 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1777 var_to_reg_int(s2, src->prev, REG_ITMP2);
1778 if (iptr->op1 == 0) {
1779 gen_nullptr_check(s1);
1782 var_to_reg_int(s3, src, REG_ITMP3);
1783 M_ASLL_IMM(s2, 3, REG_ITMP2);
1784 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1785 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1788 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1790 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1791 var_to_reg_int(s2, src->prev, REG_ITMP2);
1792 if (iptr->op1 == 0) {
1793 gen_nullptr_check(s1);
1796 var_to_reg_flt(s3, src, REG_FTMP3);
1797 M_ASLL_IMM(s2, 2, REG_ITMP2);
1798 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1799 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1802 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1804 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1805 var_to_reg_int(s2, src->prev, REG_ITMP2);
1806 if (iptr->op1 == 0) {
1807 gen_nullptr_check(s1);
1810 var_to_reg_flt(s3, src, REG_FTMP3);
1811 M_ASLL_IMM(s2, 3, REG_ITMP2);
1812 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1813 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1816 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1817 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1819 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1820 var_to_reg_int(s2, src->prev, REG_ITMP2);
1821 if (iptr->op1 == 0) {
1822 gen_nullptr_check(s1);
1825 var_to_reg_int(s3, src, REG_ITMP3);
1826 M_AADD(s2, s1, REG_ITMP1);
1827 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1828 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1831 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1833 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1834 var_to_reg_int(s2, src->prev, REG_ITMP2);
1835 if (iptr->op1 == 0) {
1836 gen_nullptr_check(s1);
1839 var_to_reg_int(s3, src, REG_ITMP3);
1840 M_AADD(s2, s1, REG_ITMP1);
1841 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1845 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1846 /* op1 = type, val.a = field address */
1848 /* If the static fields' class is not yet initialized, we do it */
1849 /* now. The call code is generated later. */
1850 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1851 codegen_addclinitref(cd, mcodeptr, ((fieldinfo *) iptr->val.a)->class);
1853 /* This is just for debugging purposes. Is very difficult to */
1854 /* read patched code. Here we patch the following 2 nop's */
1855 /* so that the real code keeps untouched. */
1856 if (showdisassemble) {
1862 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1863 M_ALD(REG_ITMP1, REG_PV, a);
1864 switch (iptr->op1) {
1866 var_to_reg_int(s2, src, REG_ITMP2);
1867 M_IST(s2, REG_ITMP1, 0);
1870 var_to_reg_int(s2, src, REG_ITMP2);
1871 M_LST(s2, REG_ITMP1, 0);
1874 var_to_reg_int(s2, src, REG_ITMP2);
1875 M_AST(s2, REG_ITMP1, 0);
1878 var_to_reg_flt(s2, src, REG_FTMP2);
1879 M_FST(s2, REG_ITMP1, 0);
1882 var_to_reg_flt(s2, src, REG_FTMP2);
1883 M_DST(s2, REG_ITMP1, 0);
1886 throw_cacao_exception_exit(string_java_lang_InternalError,
1887 "Unknown PUTSTATIC operand type %d",
1892 case ICMD_GETSTATIC: /* ... ==> ..., value */
1893 /* op1 = type, val.a = field address */
1895 /* If the static fields' class is not yet initialized, we do it */
1896 /* now. The call code is generated later. */
1897 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1898 codegen_addclinitref(cd, mcodeptr, ((fieldinfo *) iptr->val.a)->class);
1900 /* This is just for debugging purposes. Is very difficult to */
1901 /* read patched code. Here we patch the following 2 nop's */
1902 /* so that the real code keeps untouched. */
1903 if (showdisassemble) {
1909 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1910 M_ALD(REG_ITMP1, REG_PV, a);
1911 switch (iptr->op1) {
1913 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1914 M_ILD(d, REG_ITMP1, 0);
1915 store_reg_to_var_int(iptr->dst, d);
1918 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1919 M_LLD(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_ALD(d, REG_ITMP1, 0);
1925 store_reg_to_var_int(iptr->dst, d);
1928 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1929 M_FLD(d, REG_ITMP1, 0);
1930 store_reg_to_var_flt(iptr->dst, d);
1933 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1934 M_DLD(d, REG_ITMP1, 0);
1935 store_reg_to_var_flt(iptr->dst, d);
1938 throw_cacao_exception_exit(string_java_lang_InternalError,
1939 "Unknown GETSTATIC operand type %d",
1945 case ICMD_PUTFIELD: /* ..., value ==> ... */
1946 /* op1 = type, val.i = field offset */
1948 a = ((fieldinfo *)(iptr->val.a))->offset;
1949 switch (iptr->op1) {
1951 var_to_reg_int(s1, src->prev, REG_ITMP1);
1952 var_to_reg_int(s2, src, REG_ITMP2);
1953 gen_nullptr_check(s1);
1957 var_to_reg_int(s1, src->prev, REG_ITMP1);
1958 var_to_reg_int(s2, src, REG_ITMP2);
1959 gen_nullptr_check(s1);
1963 var_to_reg_int(s1, src->prev, REG_ITMP1);
1964 var_to_reg_int(s2, src, REG_ITMP2);
1965 gen_nullptr_check(s1);
1969 var_to_reg_int(s1, src->prev, REG_ITMP1);
1970 var_to_reg_flt(s2, src, REG_FTMP2);
1971 gen_nullptr_check(s1);
1975 var_to_reg_int(s1, src->prev, REG_ITMP1);
1976 var_to_reg_flt(s2, src, REG_FTMP2);
1977 gen_nullptr_check(s1);
1981 throw_cacao_exception_exit(string_java_lang_InternalError,
1982 "Unknown PUTFIELD operand type %d",
1987 case ICMD_GETFIELD: /* ... ==> ..., value */
1988 /* op1 = type, val.i = field offset */
1990 a = ((fieldinfo *)(iptr->val.a))->offset;
1991 switch (iptr->op1) {
1993 var_to_reg_int(s1, src, REG_ITMP1);
1994 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1995 gen_nullptr_check(s1);
1997 store_reg_to_var_int(iptr->dst, d);
2000 var_to_reg_int(s1, src, REG_ITMP1);
2001 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2002 gen_nullptr_check(s1);
2004 store_reg_to_var_int(iptr->dst, d);
2007 var_to_reg_int(s1, src, REG_ITMP1);
2008 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2009 gen_nullptr_check(s1);
2011 store_reg_to_var_int(iptr->dst, d);
2014 var_to_reg_int(s1, src, REG_ITMP1);
2015 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2016 gen_nullptr_check(s1);
2018 store_reg_to_var_flt(iptr->dst, d);
2021 var_to_reg_int(s1, src, REG_ITMP1);
2022 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2023 gen_nullptr_check(s1);
2025 store_reg_to_var_flt(iptr->dst, d);
2028 throw_cacao_exception_exit(string_java_lang_InternalError,
2029 "Unknown GETFIELD operand type %d",
2035 /* branch operations **************************************************/
2037 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2039 var_to_reg_int(s1, src, REG_ITMP1);
2040 M_INTMOVE(s1, REG_ITMP1_XPTR);
2041 a = dseg_addaddress(cd, asm_handle_exception);
2042 M_ALD(REG_ITMP2, REG_PV, a);
2043 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2045 M_NOP; /* nop ensures that XPC is less than the end */
2046 /* of basic block */
2050 case ICMD_GOTO: /* ... ==> ... */
2051 /* op1 = target JavaVM pc */
2053 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2058 case ICMD_JSR: /* ... ==> ... */
2059 /* op1 = target JavaVM pc */
2061 dseg_addtarget(cd, BlockPtrOfPC(iptr->op1));
2062 M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
2063 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2067 case ICMD_RET: /* ... ==> ... */
2068 /* op1 = local variable */
2069 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2070 if (var->flags & INMEMORY) {
2071 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2080 case ICMD_IFNULL: /* ..., value ==> ... */
2081 /* op1 = target JavaVM pc */
2083 var_to_reg_int(s1, src, REG_ITMP1);
2085 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2089 case ICMD_IFNONNULL: /* ..., value ==> ... */
2090 /* op1 = target JavaVM pc */
2092 var_to_reg_int(s1, src, REG_ITMP1);
2094 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2098 case ICMD_IFEQ: /* ..., value ==> ... */
2099 /* op1 = target JavaVM pc, val.i = constant */
2101 var_to_reg_int(s1, src, REG_ITMP1);
2102 if (iptr->val.i == 0) {
2106 ICONST(REG_ITMP2, iptr->val.i);
2107 M_BEQ(s1, REG_ITMP2, 0);
2109 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2113 case ICMD_IFLT: /* ..., value ==> ... */
2114 /* op1 = target JavaVM pc, val.i = constant */
2116 var_to_reg_int(s1, src, REG_ITMP1);
2117 if (iptr->val.i == 0) {
2121 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2122 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2125 ICONST(REG_ITMP2, iptr->val.i);
2126 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2128 M_BNEZ(REG_ITMP1, 0);
2130 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2134 case ICMD_IFLE: /* ..., value ==> ... */
2135 /* op1 = target JavaVM pc, val.i = constant */
2137 var_to_reg_int(s1, src, REG_ITMP1);
2138 if (iptr->val.i == 0) {
2142 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2143 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2144 M_BNEZ(REG_ITMP1, 0);
2147 ICONST(REG_ITMP2, iptr->val.i);
2148 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2149 M_BEQZ(REG_ITMP1, 0);
2152 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2156 case ICMD_IFNE: /* ..., value ==> ... */
2157 /* op1 = target JavaVM pc, val.i = constant */
2159 var_to_reg_int(s1, src, REG_ITMP1);
2160 if (iptr->val.i == 0) {
2164 ICONST(REG_ITMP2, iptr->val.i);
2165 M_BNE(s1, REG_ITMP2, 0);
2167 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2171 case ICMD_IFGT: /* ..., value ==> ... */
2172 /* op1 = target JavaVM pc, val.i = constant */
2174 var_to_reg_int(s1, src, REG_ITMP1);
2175 if (iptr->val.i == 0) {
2179 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2180 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2181 M_BEQZ(REG_ITMP1, 0);
2184 ICONST(REG_ITMP2, iptr->val.i);
2185 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2186 M_BNEZ(REG_ITMP1, 0);
2189 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2193 case ICMD_IFGE: /* ..., value ==> ... */
2194 /* op1 = target JavaVM pc, val.i = constant */
2196 var_to_reg_int(s1, src, REG_ITMP1);
2197 if (iptr->val.i == 0) {
2201 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2202 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2205 ICONST(REG_ITMP2, iptr->val.i);
2206 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2208 M_BEQZ(REG_ITMP1, 0);
2210 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2214 case ICMD_IF_LEQ: /* ..., value ==> ... */
2215 /* op1 = target JavaVM pc, val.l = constant */
2217 var_to_reg_int(s1, src, REG_ITMP1);
2218 if (iptr->val.l == 0) {
2222 LCONST(REG_ITMP2, iptr->val.l);
2223 M_BEQ(s1, REG_ITMP2, 0);
2225 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2229 case ICMD_IF_LLT: /* ..., value ==> ... */
2230 /* op1 = target JavaVM pc, val.l = constant */
2232 var_to_reg_int(s1, src, REG_ITMP1);
2233 if (iptr->val.l == 0) {
2237 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2238 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2241 LCONST(REG_ITMP2, iptr->val.l);
2242 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2244 M_BNEZ(REG_ITMP1, 0);
2246 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2250 case ICMD_IF_LLE: /* ..., value ==> ... */
2251 /* op1 = target JavaVM pc, val.l = constant */
2253 var_to_reg_int(s1, src, REG_ITMP1);
2254 if (iptr->val.l == 0) {
2258 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2259 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2260 M_BNEZ(REG_ITMP1, 0);
2263 LCONST(REG_ITMP2, iptr->val.l);
2264 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2265 M_BEQZ(REG_ITMP1, 0);
2268 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2272 case ICMD_IF_LNE: /* ..., value ==> ... */
2273 /* op1 = target JavaVM pc, val.l = constant */
2275 var_to_reg_int(s1, src, REG_ITMP1);
2276 if (iptr->val.l == 0) {
2280 LCONST(REG_ITMP2, iptr->val.l);
2281 M_BNE(s1, REG_ITMP2, 0);
2283 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2287 case ICMD_IF_LGT: /* ..., value ==> ... */
2288 /* op1 = target JavaVM pc, val.l = constant */
2290 var_to_reg_int(s1, src, REG_ITMP1);
2291 if (iptr->val.l == 0) {
2295 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2296 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2297 M_BEQZ(REG_ITMP1, 0);
2300 LCONST(REG_ITMP2, iptr->val.l);
2301 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2302 M_BNEZ(REG_ITMP1, 0);
2305 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2309 case ICMD_IF_LGE: /* ..., value ==> ... */
2310 /* op1 = target JavaVM pc, val.l = constant */
2312 var_to_reg_int(s1, src, REG_ITMP1);
2313 if (iptr->val.l == 0) {
2317 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2318 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2321 LCONST(REG_ITMP2, iptr->val.l);
2322 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2324 M_BEQZ(REG_ITMP1, 0);
2326 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2330 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2331 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2332 case ICMD_IF_ACMPEQ:
2334 var_to_reg_int(s1, src->prev, REG_ITMP1);
2335 var_to_reg_int(s2, src, REG_ITMP2);
2337 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2341 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2342 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2343 case ICMD_IF_ACMPNE:
2345 var_to_reg_int(s1, src->prev, REG_ITMP1);
2346 var_to_reg_int(s2, src, REG_ITMP2);
2348 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2352 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2353 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2355 var_to_reg_int(s1, src->prev, REG_ITMP1);
2356 var_to_reg_int(s2, src, REG_ITMP2);
2357 M_CMPLT(s1, s2, REG_ITMP1);
2358 M_BNEZ(REG_ITMP1, 0);
2359 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2363 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2364 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2366 var_to_reg_int(s1, src->prev, REG_ITMP1);
2367 var_to_reg_int(s2, src, REG_ITMP2);
2368 M_CMPGT(s1, s2, REG_ITMP1);
2369 M_BNEZ(REG_ITMP1, 0);
2370 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2374 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2375 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2377 var_to_reg_int(s1, src->prev, REG_ITMP1);
2378 var_to_reg_int(s2, src, REG_ITMP2);
2379 M_CMPGT(s1, s2, REG_ITMP1);
2380 M_BEQZ(REG_ITMP1, 0);
2381 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2385 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2386 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2388 var_to_reg_int(s1, src->prev, REG_ITMP1);
2389 var_to_reg_int(s2, src, REG_ITMP2);
2390 M_CMPLT(s1, s2, REG_ITMP1);
2391 M_BEQZ(REG_ITMP1, 0);
2392 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2396 #ifdef CONDITIONAL_LOADCONST
2397 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2399 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2402 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2403 /* val.i = constant */
2405 var_to_reg_int(s1, src, REG_ITMP1);
2406 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2408 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2409 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2410 M_CMPEQ(s1, REG_ZERO, d);
2411 store_reg_to_var_int(iptr->dst, d);
2414 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2415 M_CMPEQ(s1, REG_ZERO, d);
2417 store_reg_to_var_int(iptr->dst, d);
2421 M_MOV(s1, REG_ITMP1);
2424 ICONST(d, iptr[1].val.i);
2426 if ((s3 >= 0) && (s3 <= 255)) {
2427 M_CMOVEQ_IMM(s1, s3, d);
2430 ICONST(REG_ITMP2, s3);
2431 M_CMOVEQ(s1, REG_ITMP2, d);
2433 store_reg_to_var_int(iptr->dst, d);
2436 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2437 /* val.i = constant */
2439 var_to_reg_int(s1, src, REG_ITMP1);
2440 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2442 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2443 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2444 M_CMPEQ(s1, REG_ZERO, d);
2445 store_reg_to_var_int(iptr->dst, d);
2448 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2449 M_CMPEQ(s1, REG_ZERO, d);
2451 store_reg_to_var_int(iptr->dst, d);
2455 M_MOV(s1, REG_ITMP1);
2458 ICONST(d, iptr[1].val.i);
2460 if ((s3 >= 0) && (s3 <= 255)) {
2461 M_CMOVNE_IMM(s1, s3, d);
2464 ICONST(REG_ITMP2, s3);
2465 M_CMOVNE(s1, REG_ITMP2, d);
2467 store_reg_to_var_int(iptr->dst, d);
2470 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2471 /* val.i = constant */
2473 var_to_reg_int(s1, src, REG_ITMP1);
2474 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2476 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2477 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2478 M_CMPLT(s1, REG_ZERO, d);
2479 store_reg_to_var_int(iptr->dst, d);
2482 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2483 M_CMPLE(REG_ZERO, s1, d);
2484 store_reg_to_var_int(iptr->dst, d);
2488 M_MOV(s1, REG_ITMP1);
2491 ICONST(d, iptr[1].val.i);
2493 if ((s3 >= 0) && (s3 <= 255)) {
2494 M_CMOVLT_IMM(s1, s3, d);
2497 ICONST(REG_ITMP2, s3);
2498 M_CMOVLT(s1, REG_ITMP2, d);
2500 store_reg_to_var_int(iptr->dst, d);
2503 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2504 /* val.i = constant */
2506 var_to_reg_int(s1, src, REG_ITMP1);
2507 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2509 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2510 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2511 M_CMPLE(REG_ZERO, s1, d);
2512 store_reg_to_var_int(iptr->dst, d);
2515 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2516 M_CMPLT(s1, REG_ZERO, d);
2517 store_reg_to_var_int(iptr->dst, d);
2521 M_MOV(s1, REG_ITMP1);
2524 ICONST(d, iptr[1].val.i);
2526 if ((s3 >= 0) && (s3 <= 255)) {
2527 M_CMOVGE_IMM(s1, s3, d);
2530 ICONST(REG_ITMP2, s3);
2531 M_CMOVGE(s1, REG_ITMP2, d);
2533 store_reg_to_var_int(iptr->dst, d);
2536 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2537 /* val.i = constant */
2539 var_to_reg_int(s1, src, REG_ITMP1);
2540 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2542 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2543 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2544 M_CMPLT(REG_ZERO, s1, d);
2545 store_reg_to_var_int(iptr->dst, d);
2548 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2549 M_CMPLE(s1, REG_ZERO, d);
2550 store_reg_to_var_int(iptr->dst, d);
2554 M_MOV(s1, REG_ITMP1);
2557 ICONST(d, iptr[1].val.i);
2559 if ((s3 >= 0) && (s3 <= 255)) {
2560 M_CMOVGT_IMM(s1, s3, d);
2563 ICONST(REG_ITMP2, s3);
2564 M_CMOVGT(s1, REG_ITMP2, d);
2566 store_reg_to_var_int(iptr->dst, d);
2569 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2570 /* val.i = constant */
2572 var_to_reg_int(s1, src, REG_ITMP1);
2573 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2575 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2576 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2577 M_CMPLE(s1, REG_ZERO, d);
2578 store_reg_to_var_int(iptr->dst, d);
2581 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2582 M_CMPLT(REG_ZERO, s1, d);
2583 store_reg_to_var_int(iptr->dst, d);
2587 M_MOV(s1, REG_ITMP1);
2590 ICONST(d, iptr[1].val.i);
2592 if ((s3 >= 0) && (s3 <= 255)) {
2593 M_CMOVLE_IMM(s1, s3, d);
2596 ICONST(REG_ITMP2, s3);
2597 M_CMOVLE(s1, REG_ITMP2, d);
2599 store_reg_to_var_int(iptr->dst, d);
2604 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2608 #if defined(USE_THREADS)
2609 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2611 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2612 M_ALD(REG_ITMP3, REG_PV, a);
2613 M_JSR(REG_RA, REG_ITMP3);
2614 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8); /* delay slot */
2615 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2616 M_LDA(REG_PV, REG_RA, disp);
2619 var_to_reg_int(s1, src, REG_RESULT);
2620 M_INTMOVE(s1, REG_RESULT);
2621 goto nowperformreturn;
2623 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2626 #if defined(USE_THREADS)
2627 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2629 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2630 M_ALD(REG_ITMP3, REG_PV, a);
2631 M_JSR(REG_RA, REG_ITMP3);
2632 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8); /* delay slot */
2633 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2634 M_LDA(REG_PV, REG_RA, disp);
2637 var_to_reg_flt(s1, src, REG_FRESULT);
2639 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2640 M_TFLTMOVE(t, s1, REG_FRESULT);
2642 goto nowperformreturn;
2644 case ICMD_RETURN: /* ... ==> ... */
2646 #if defined(USE_THREADS)
2647 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2649 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2650 M_ALD(REG_ITMP3, REG_PV, a);
2651 M_JSR(REG_RA, REG_ITMP3);
2652 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8); /* delay slot */
2653 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2654 M_LDA(REG_PV, REG_RA, disp);
2662 p = parentargs_base;
2664 /* restore return address */
2666 if (!m->isleafmethod) {
2667 p--; M_LLD(REG_RA, REG_SP, 8 * p);
2670 /* restore saved registers */
2672 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2673 p--; M_LLD(rd->savintregs[i], REG_SP, 8 * p);
2675 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2676 p--; M_DLD(rd->savfltregs[i], REG_SP, 8 * p);
2679 /* call trace function */
2682 M_LDA (REG_SP, REG_SP, -24);
2683 M_LST(REG_RA, REG_SP, 0);
2684 M_LST(REG_RESULT, REG_SP, 8);
2685 M_DST(REG_FRESULT, REG_SP,16);
2686 a = dseg_addaddress(cd, m);
2687 M_ALD(rd->argintregs[0], REG_PV, a);
2688 M_MOV(REG_RESULT, rd->argintregs[1]);
2689 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2690 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
2691 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2692 M_ALD(REG_ITMP3, REG_PV, a);
2693 M_JSR (REG_RA, REG_ITMP3);
2695 M_DLD(REG_FRESULT, REG_SP,16);
2696 M_LLD(REG_RESULT, REG_SP, 8);
2697 M_LLD(REG_RA, REG_SP, 0);
2698 M_LDA (REG_SP, REG_SP, 24);
2703 /* deallocate stack */
2705 if (parentargs_base) {
2706 M_LDA(REG_SP, REG_SP, parentargs_base * 8);
2717 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2722 tptr = (void **) iptr->target;
2724 s4ptr = iptr->val.a;
2725 l = s4ptr[1]; /* low */
2726 i = s4ptr[2]; /* high */
2728 var_to_reg_int(s1, src, REG_ITMP1);
2730 {M_INTMOVE(s1, REG_ITMP1);}
2731 else if (l <= 32768) {
2732 M_IADD_IMM(s1, -l, REG_ITMP1);
2735 ICONST(REG_ITMP2, l);
2736 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2742 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
2743 M_BEQZ(REG_ITMP2, 0);
2744 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2745 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
2747 /* build jump table top down and use address of lowest entry */
2749 /* s4ptr += 3 + i; */
2753 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2754 dseg_addtarget(cd, (basicblock *) tptr[0]);
2759 /* length of dataseg after last dseg_addtarget is used by load */
2761 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2762 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2769 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2771 s4 i, /*l, */val, *s4ptr;
2774 tptr = (void **) iptr->target;
2776 s4ptr = iptr->val.a;
2777 /*l = s4ptr[0];*/ /* default */
2778 i = s4ptr[1]; /* count */
2780 MCODECHECK((i<<2)+8);
2781 var_to_reg_int(s1, src, REG_ITMP1);
2787 ICONST(REG_ITMP2, val);
2788 M_BEQ(s1, REG_ITMP2, 0);
2789 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2794 tptr = (void **) iptr->target;
2795 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2802 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2803 /* op1 = return type, val.a = function pointer*/
2807 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2808 /* op1 = return type, val.a = function pointer*/
2812 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2813 /* op1 = return type, val.a = function pointer*/
2817 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2818 /* op1 = arg count, val.a = method pointer */
2820 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2821 /* op1 = arg count, val.a = method pointer */
2823 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2824 /* op1 = arg count, val.a = method pointer */
2826 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2827 /* op1 = arg count, val.a = method pointer */
2834 MCODECHECK((s3 << 1) + 64);
2836 /* copy arguments to registers or stack location */
2838 for (; --s3 >= 0; src = src->prev) {
2839 if (src->varkind == ARGVAR)
2841 if (IS_INT_LNG_TYPE(src->type)) {
2842 if (s3 < INT_ARG_CNT) {
2843 s1 = rd->argintregs[s3];
2844 var_to_reg_int(d, src, s1);
2848 var_to_reg_int(d, src, REG_ITMP1);
2849 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
2853 if (s3 < FLT_ARG_CNT) {
2854 s1 = rd->argfltregs[s3];
2855 var_to_reg_flt(d, src, s1);
2856 M_TFLTMOVE(src->type, d, s1);
2859 var_to_reg_flt(d, src, REG_FTMP1);
2860 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
2866 switch (iptr->opc) {
2870 a = dseg_addaddress(cd, (void *) lm);
2871 d = iptr->op1; /* return type */
2873 M_ALD(REG_ITMP3, REG_PV, a); /* built-in-function pointer */
2874 M_JSR(REG_RA, REG_ITMP3);
2876 goto afteractualcall;
2878 case ICMD_INVOKESTATIC:
2879 case ICMD_INVOKESPECIAL:
2880 a = dseg_addaddress(cd, lm->stubroutine);
2883 M_ALD(REG_PV, REG_PV, a); /* method pointer in pv */
2886 case ICMD_INVOKEVIRTUAL:
2889 gen_nullptr_check(rd->argintregs[0]);
2890 M_ALD(REG_METHODPTR, rd->argintregs[0], OFFSET(java_objectheader, vftbl));
2891 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex);
2894 case ICMD_INVOKEINTERFACE:
2897 gen_nullptr_check(rd->argintregs[0]);
2898 M_ALD(REG_METHODPTR, rd->argintregs[0], OFFSET(java_objectheader, vftbl));
2899 M_ALD(REG_METHODPTR, REG_METHODPTR, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->class->index);
2900 M_ALD(REG_PV, REG_METHODPTR, sizeof(methodptr) * (lm - lm->class->methods));
2904 M_JSR(REG_RA, REG_PV);
2911 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2912 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
2914 s4 ml = -s1, mh = 0;
2915 while (ml < -32768) { ml += 65536; mh--; }
2917 M_IADD_IMM(REG_PV, ml, REG_PV);
2918 M_LADD(REG_PV, REG_RA, REG_PV);
2921 /* d contains return type */
2923 if (d != TYPE_VOID) {
2924 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2925 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2926 M_INTMOVE(REG_RESULT, s1);
2927 store_reg_to_var_int(iptr->dst, s1);
2930 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2931 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
2932 store_reg_to_var_flt(iptr->dst, s1);
2939 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2941 /* op1: 0 == array, 1 == class */
2942 /* val.a: (classinfo*) superclass */
2944 /* superclass is an interface:
2946 * return (sub != NULL) &&
2947 * (sub->vftbl->interfacetablelength > super->index) &&
2948 * (sub->vftbl->interfacetable[-super->index] != NULL);
2950 * superclass is a class:
2952 * return ((sub != NULL) && (0
2953 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2954 * super->vftbl->diffvall));
2958 classinfo *super = (classinfo*) iptr->val.a;
2960 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2961 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
2963 var_to_reg_int(s1, src, REG_ITMP1);
2964 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2966 M_MOV(s1, REG_ITMP1);
2970 if (iptr->op1) { /* class/interface */
2971 if (super->flags & ACC_INTERFACE) { /* interface */
2974 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2975 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2976 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
2977 M_BLEZ(REG_ITMP2, 3);
2979 M_ALD(REG_ITMP1, REG_ITMP1,
2980 OFFSET(vftbl_t, interfacetable[0]) -
2981 super->index * sizeof(methodptr*));
2982 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
2986 s2 = super->vftbl->diffval;
2989 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2990 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2991 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
2992 M_CMPULT_IMM(REG_ITMP1, s2 + 1, d);
2997 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2998 a = dseg_addaddress(cd, (void *) super->vftbl);
2999 M_ALD(REG_ITMP2, REG_PV, a);
3000 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3001 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3003 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3004 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3005 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3006 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3007 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3009 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3010 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3016 panic ("internal error: no inlined array instanceof");
3018 store_reg_to_var_int(iptr->dst, d);
3021 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3023 /* op1: 0 == array, 1 == class */
3024 /* val.a: (classinfo*) superclass */
3026 /* superclass is an interface:
3028 * OK if ((sub == NULL) ||
3029 * (sub->vftbl->interfacetablelength > super->index) &&
3030 * (sub->vftbl->interfacetable[-super->index] != NULL));
3032 * superclass is a class:
3034 * OK if ((sub == NULL) || (0
3035 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3036 * super->vftbl->diffvall));
3040 classinfo *super = (classinfo*) iptr->val.a;
3042 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3043 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3046 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3047 var_to_reg_int(s1, src, d);
3048 if (iptr->op1) { /* class/interface */
3049 if (super->flags & ACC_INTERFACE) { /* interface */
3052 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3053 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3054 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3055 M_BLEZ(REG_ITMP2, 0);
3056 codegen_addxcastrefs(cd, mcodeptr);
3058 M_ALD(REG_ITMP2, REG_ITMP1,
3059 OFFSET(vftbl_t, interfacetable[0]) -
3060 super->index * sizeof(methodptr*));
3061 M_BEQZ(REG_ITMP2, 0);
3062 codegen_addxcastrefs(cd, mcodeptr);
3068 s2 = super->vftbl->diffval;
3069 M_BEQZ(s1, 6 + (s2 != 0));
3071 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3072 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3073 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3075 M_BNEZ(REG_ITMP1, 0);
3078 M_CMPULT_IMM(REG_ITMP1, s2 + 1, REG_ITMP2);
3079 M_BEQZ(REG_ITMP2, 0);
3083 M_BEQZ(s1, 10 + (d == REG_ITMP3));
3085 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3086 a = dseg_addaddress(cd, (void *) super->vftbl);
3087 M_ALD(REG_ITMP2, REG_PV, a);
3088 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3089 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3091 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3092 if (d != REG_ITMP3) {
3093 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3094 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3095 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3096 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3098 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3100 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3101 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3102 M_ALD(REG_ITMP2, REG_PV, a);
3103 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3104 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3105 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3108 M_CMPULT(REG_ITMP2, REG_ITMP1, REG_ITMP2);
3109 M_BNEZ(REG_ITMP2, 0);
3111 codegen_addxcastrefs(cd, mcodeptr);
3116 panic ("internal error: no inlined array checkcast");
3119 store_reg_to_var_int(iptr->dst, d);
3122 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3124 var_to_reg_int(s1, src, REG_ITMP1);
3126 codegen_addxcheckarefs(cd, mcodeptr);
3130 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3132 M_BEQZ(REG_RESULT, 0);
3133 codegen_addxexceptionrefs(cd, mcodeptr);
3137 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3138 /* op1 = dimension, val.a = array descriptor */
3140 /* check for negative sizes and copy sizes to stack if necessary */
3142 MCODECHECK((iptr->op1 << 1) + 64);
3144 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3145 var_to_reg_int(s2, src, REG_ITMP1);
3147 codegen_addxcheckarefs(cd, mcodeptr);
3150 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3152 if (src->varkind != ARGVAR) {
3153 M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
3157 /* a0 = dimension count */
3159 ICONST(rd->argintregs[0], iptr->op1);
3161 /* a1 = arraydescriptor */
3163 a = dseg_addaddress(cd, iptr->val.a);
3164 M_ALD(rd->argintregs[1], REG_PV, a);
3166 /* a2 = pointer to dimensions = stack pointer */
3168 M_INTMOVE(REG_SP, rd->argintregs[2]);
3170 a = dseg_addaddress(cd, (void*) builtin_nmultianewarray);
3171 M_ALD(REG_ITMP3, REG_PV, a);
3172 M_JSR(REG_RA, REG_ITMP3);
3174 s1 = (int)((u1*) mcodeptr - cd->mcodebase);
3176 M_LDA (REG_PV, REG_RA, -s1);
3180 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3181 M_INTMOVE(REG_RESULT, s1);
3182 store_reg_to_var_int(iptr->dst, s1);
3186 throw_cacao_exception_exit(string_java_lang_InternalError,
3187 "Unknown ICMD %d", iptr->opc);
3190 } /* for instruction */
3192 /* copy values to interface registers */
3194 src = bptr->outstack;
3195 len = bptr->outdepth;
3199 if ((src->varkind != STACKVAR)) {
3201 if (IS_FLT_DBL_TYPE(s2)) {
3202 var_to_reg_flt(s1, src, REG_FTMP1);
3203 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3204 M_TFLTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3207 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3211 var_to_reg_int(s1, src, REG_ITMP1);
3212 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3213 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3216 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3222 } /* if (bptr -> flags >= BBREACHED) */
3223 } /* for basic block */
3226 /* generate bound check stubs */
3228 s4 *xcodeptr = NULL;
3231 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3232 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3234 (u1 *) mcodeptr - cd->mcodebase);
3238 M_MOV(bref->reg, REG_ITMP1);
3239 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3241 if (xcodeptr != NULL) {
3242 M_BR(xcodeptr - mcodeptr);
3246 xcodeptr = mcodeptr;
3248 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3249 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3251 M_MOV(REG_ITMP1, rd->argintregs[0]);
3252 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3253 M_ALD(REG_ITMP3, REG_PV, a);
3254 M_JSR(REG_RA, REG_ITMP3);
3256 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3258 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3259 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3261 a = dseg_addaddress(cd, asm_handle_exception);
3262 M_ALD(REG_ITMP3, REG_PV, a);
3268 /* generate negative array size check stubs */
3272 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3273 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3274 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3276 (u1 *) xcodeptr - cd->mcodebase - 4);
3280 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3282 (u1 *) mcodeptr - cd->mcodebase);
3286 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3288 if (xcodeptr != NULL) {
3289 M_BR(xcodeptr - mcodeptr);
3293 xcodeptr = mcodeptr;
3295 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3296 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3298 a = dseg_addaddress(cd, new_negativearraysizeexception);
3299 M_ALD(REG_ITMP3, REG_PV, a);
3300 M_JSR(REG_RA, REG_ITMP3);
3302 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3304 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3305 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3307 a = dseg_addaddress(cd, asm_handle_exception);
3308 M_ALD(REG_ITMP3, REG_PV, a);
3314 /* generate cast check stubs */
3318 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3319 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3320 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3322 (u1 *) xcodeptr - cd->mcodebase - 4);
3326 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3328 (u1 *) mcodeptr - cd->mcodebase);
3332 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3334 if (xcodeptr != NULL) {
3335 M_BR(xcodeptr - mcodeptr);
3339 xcodeptr = mcodeptr;
3341 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3342 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3344 a = dseg_addaddress(cd, new_classcastexception);
3345 M_ALD(REG_ITMP3, REG_PV, a);
3346 M_JSR(REG_RA, REG_ITMP3);
3348 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3350 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3351 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3353 a = dseg_addaddress(cd, asm_handle_exception);
3354 M_ALD(REG_ITMP3, REG_PV, a);
3360 /* generate exception check stubs */
3364 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3365 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3366 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3368 (u1 *) xcodeptr - cd->mcodebase - 4);
3372 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3374 (u1 *) mcodeptr - cd->mcodebase);
3378 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3380 if (xcodeptr != NULL) {
3381 M_BR(xcodeptr - mcodeptr);
3385 xcodeptr = mcodeptr;
3387 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3388 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3389 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3391 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3392 M_ALD(REG_ITMP3, REG_PV, a);
3393 M_JSR(REG_RA, REG_ITMP3);
3396 /* get the exceptionptr from the ptrprt and clear it */
3397 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3398 M_AST(REG_ZERO, REG_RESULT, 0);
3400 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3401 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3403 a = dseg_addaddress(cd, &_exceptionptr);
3404 M_ALD(REG_ITMP3, REG_PV, a);
3405 M_ALD(REG_ITMP1_XPTR, REG_ITMP3, 0);
3406 M_AST(REG_ZERO, REG_ITMP3, 0);
3409 a = dseg_addaddress(cd, asm_handle_exception);
3410 M_ALD(REG_ITMP3, REG_PV, a);
3416 /* generate null pointer check stubs */
3420 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3421 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3422 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3424 (u1 *) xcodeptr - cd->mcodebase - 4);
3428 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3430 (u1 *) mcodeptr - cd->mcodebase);
3434 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3436 if (xcodeptr != NULL) {
3437 M_BR(xcodeptr - mcodeptr);
3441 xcodeptr = mcodeptr;
3443 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3444 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3446 a = dseg_addaddress(cd, new_nullpointerexception);
3447 M_ALD(REG_ITMP3, REG_PV, a);
3448 M_JSR(REG_RA, REG_ITMP3);
3450 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3452 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3453 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3455 a = dseg_addaddress(cd, asm_handle_exception);
3456 M_ALD(REG_ITMP3, REG_PV, a);
3463 /* generate put/getstatic stub call code */
3470 for (cref = cd->clinitrefs; cref != NULL; cref = cref->next) {
3471 /* Get machine code which is patched back in later. The call is */
3472 /* 2 instruction words long. */
3473 xcodeptr = (s4 *) (cd->mcodebase + cref->branchpos);
3475 /* We need to split this, because an unaligned 8 byte read causes */
3477 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3479 /* patch in the call to call the following code (done at compile */
3482 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3483 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3485 M_BRS(tmpmcodeptr - (xcodeptr + 1));
3488 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3492 /* move class pointer into REG_ITMP1 */
3493 a = dseg_addaddress(cd, cref->class);
3494 M_ALD(REG_ITMP1, REG_PV, a);
3496 /* move machine code into REG_ITMP2 */
3497 a = dseg_adds8(cd, mcode);
3498 M_LLD(REG_ITMP2, REG_PV, a);
3500 a = dseg_addaddress(cd, asm_check_clinit);
3501 M_ALD(REG_ITMP3, REG_PV, a);
3508 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
3510 docacheflush((void*) m->entrypoint, ((u1*) mcodeptr - cd->mcodebase));
3514 /* function createcompilerstub *************************************************
3516 creates a stub routine which calls the compiler
3518 *******************************************************************************/
3520 #define COMPSTUB_SIZE 4
3522 u1 *createcompilerstub(methodinfo *m)
3524 u8 *s = CNEW(u8, COMPSTUB_SIZE); /* memory to hold the stub */
3525 s4 *mcodeptr = (s4 *) s; /* code generation pointer */
3527 /* code for the stub */
3528 M_ALD(REG_PV, REG_PV, 24); /* load pointer to the compiler */
3530 M_JSR(REG_ITMP1, REG_PV); /* jump to the compiler, return address
3531 in itmp1 is used as method pointer */
3534 s[2] = (u8) m; /* literals to be adressed */
3535 s[3] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3537 (void) docacheflush((void*) s, (char*) mcodeptr - (char*) s);
3539 #if defined(STATISTICS)
3541 count_cstub_len += COMPSTUB_SIZE * 8;
3548 /* function removecompilerstub *************************************************
3550 deletes a compilerstub from memory (simply by freeing it)
3552 *******************************************************************************/
3554 void removecompilerstub(u1 *stub)
3556 CFREE(stub, COMPSTUB_SIZE * 8);
3560 /* function: createnativestub **************************************************
3562 creates a stub routine which calls a native method
3564 *******************************************************************************/
3566 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3567 #define NATIVESTUB_STACK 2
3568 #define NATIVESTUB_THREAD_EXTRA 5
3570 #define NATIVESTUB_STACK 1
3571 #define NATIVESTUB_THREAD_EXTRA 1
3574 #define NATIVESTUB_SIZE (54 + 4 + NATIVESTUB_THREAD_EXTRA - 1)
3575 #define NATIVESTUB_STATIC_SIZE 5
3576 #define NATIVESTUB_VERBOSE_SIZE (50 + 17)
3577 #define NATIVESTUB_OFFSET 10
3580 u1 *createnativestub(functionptr f, methodinfo *m)
3582 u8 *s; /* memory to hold the stub */
3584 s4 *mcodeptr; /* code generation pointer */
3585 s4 stackframesize = 0; /* size of stackframe if needed */
3590 t_inlining_globals *id;
3593 /* mark start of dump memory area */
3595 dumpsize = dump_size();
3597 /* setup registers before using it */
3599 cd = DNEW(codegendata);
3600 rd = DNEW(registerdata);
3601 id = DNEW(t_inlining_globals);
3603 inlining_setup(m, id);
3604 reg_setup(m, rd, id);
3606 descriptor2types(m); /* set paramcount and paramtypes */
3608 stubsize = NATIVESTUB_SIZE; /* calculate nativestub size */
3610 if ((m->flags & ACC_STATIC) && !m->class->initialized)
3611 stubsize += NATIVESTUB_STATIC_SIZE;
3614 stubsize += NATIVESTUB_VERBOSE_SIZE;
3616 s = CNEW(u8, stubsize); /* memory to hold the stub */
3617 cs = s + NATIVESTUB_OFFSET;
3618 mcodeptr = (s4 *) (cs); /* code generation pointer */
3620 /* set some required varibles which are normally set by codegen_setup */
3621 cd->mcodebase = (u1 *) mcodeptr;
3622 cd->clinitrefs = NULL;
3624 *(cs-1) = (u8) f; /* address of native method */
3625 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3626 *(cs-2) = (u8) &builtin_get_exceptionptrptr;
3628 *(cs-2) = (u8) (&_exceptionptr); /* address of exceptionptr */
3630 *(cs-3) = (u8) asm_handle_nat_exception;/* addr of asm exception handler */
3631 *(cs-4) = (u8) (&env); /* addr of jni_environement */
3632 *(cs-5) = (u8) builtin_trace_args;
3634 *(cs-7) = (u8) builtin_displaymethodstop;
3635 *(cs-8) = (u8) m->class;
3636 *(cs-9) = (u8) asm_check_clinit;
3637 *(cs-10) = (u8) NULL; /* filled with machine code */
3639 M_LDA(REG_SP, REG_SP, -NATIVESTUB_STACK * 8); /* build up stackframe */
3640 M_LST(REG_RA, REG_SP, 0); /* store return address */
3642 /* if function is static, check for initialized */
3644 if (m->flags & ACC_STATIC && !m->class->initialized) {
3645 codegen_addclinitref(cd, mcodeptr, m->class);
3648 /* max. 50 instructions */
3653 M_LDA(REG_SP, REG_SP, -(18 * 8));
3654 M_AST(REG_RA, REG_SP, 1 * 8);
3656 /* save integer argument registers */
3657 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3658 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
3661 /* save and copy float arguments into integer registers */
3662 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3663 t = m->paramtypes[p];
3665 if (IS_FLT_DBL_TYPE(t)) {
3666 if (IS_2_WORD_TYPE(t)) {
3667 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3668 M_LLD(rd->argintregs[p], REG_SP, (10 + p) * 8);
3671 M_FST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3672 M_ILD(rd->argintregs[p], REG_SP, (10 + p) * 8);
3676 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3680 M_ALD(REG_ITMP1, REG_PV, -6 * 8); /* method address */
3681 M_AST(REG_ITMP1, REG_SP, 0);
3682 M_ALD(REG_ITMP3, REG_PV, -5 * 8); /* builtin_trace_args */
3683 M_JSR(REG_RA, REG_ITMP3);
3685 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3686 M_LDA(REG_PV, REG_RA, disp);
3688 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3689 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
3692 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3693 t = m->paramtypes[p];
3695 if (IS_FLT_DBL_TYPE(t)) {
3696 if (IS_2_WORD_TYPE(t)) {
3697 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3700 M_FLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3704 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3708 M_ALD(REG_RA, REG_SP, 1 * 8);
3709 M_LDA(REG_SP, REG_SP, 18 * 8);
3712 /* save argument registers on stack -- if we have to */
3713 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
3715 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3716 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3718 stackframesize = stackparamcnt + paramshiftcnt;
3720 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
3722 /* copy stack arguments into new stack frame -- if any */
3723 for (i = 0; i < stackparamcnt; i++) {
3724 M_LLD(REG_ITMP1, REG_SP, (stackparamcnt + 1 + i) * 8);
3725 M_LST(REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
3728 if (m->flags & ACC_STATIC) {
3729 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
3730 M_DST(rd->argfltregs[5], REG_SP, 1 * 8);
3732 M_LST(rd->argintregs[5], REG_SP, 1 * 8);
3735 if (IS_FLT_DBL_TYPE(m->paramtypes[4])) {
3736 M_DST(rd->argfltregs[4], REG_SP, 0 * 8);
3738 M_LST(rd->argintregs[4], REG_SP, 0 * 8);
3742 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
3743 M_DST(rd->argfltregs[5], REG_SP, 0 * 8);
3745 M_LST(rd->argintregs[5], REG_SP, 0 * 8);
3750 if (m->flags & ACC_STATIC) {
3751 M_MOV(rd->argintregs[5], rd->argintregs[7]);
3753 M_DMFC1(REG_ITMP1, rd->argfltregs[5]);
3754 M_DMTC1(REG_ITMP1, rd->argfltregs[7]);
3756 M_MOV(rd->argintregs[4], rd->argintregs[6]);
3758 M_DMFC1(REG_ITMP1, rd->argfltregs[4]);
3759 M_DMTC1(REG_ITMP1, rd->argfltregs[6]);
3761 M_MOV(rd->argintregs[3], rd->argintregs[5]);
3762 M_DMFC1(REG_ITMP1, rd->argfltregs[3]);
3764 M_MOV(rd->argintregs[2], rd->argintregs[4]);
3765 M_DMTC1(REG_ITMP1, rd->argfltregs[5]);
3767 M_MOV(rd->argintregs[1], rd->argintregs[3]);
3768 M_DMFC1(REG_ITMP1, rd->argfltregs[2]);
3770 M_MOV(rd->argintregs[0], rd->argintregs[2]);
3771 M_DMTC1(REG_ITMP1, rd->argfltregs[4]);
3773 M_DMFC1(REG_ITMP1, rd->argfltregs[1]);
3774 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
3776 M_DMFC1(REG_ITMP1, rd->argfltregs[0]);
3777 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
3779 M_ALD(rd->argintregs[1], REG_PV, -8 * 8);
3782 M_MOV(rd->argintregs[6], rd->argintregs[7]);
3784 M_DMFC1(REG_ITMP1, rd->argfltregs[6]);
3785 M_DMTC1(REG_ITMP1, rd->argfltregs[7]);
3787 M_MOV(rd->argintregs[5], rd->argintregs[6]);
3789 M_DMFC1(REG_ITMP1, rd->argfltregs[5]);
3790 M_DMTC1(REG_ITMP1, rd->argfltregs[6]);
3792 M_MOV(rd->argintregs[4], rd->argintregs[5]);
3793 M_DMFC1(REG_ITMP1, rd->argfltregs[4]);
3795 M_MOV(rd->argintregs[3], rd->argintregs[4]);
3796 M_DMTC1(REG_ITMP1, rd->argfltregs[5]);
3798 M_MOV(rd->argintregs[2], rd->argintregs[3]);
3799 M_DMFC1(REG_ITMP1, rd->argfltregs[3]);
3801 M_MOV(rd->argintregs[1], rd->argintregs[2]);
3802 M_DMTC1(REG_ITMP1, rd->argfltregs[4]);
3804 M_MOV(rd->argintregs[0], rd->argintregs[1]);
3805 M_DMFC1(REG_ITMP1, rd->argfltregs[2]);
3807 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
3809 M_DMFC1(REG_ITMP1, rd->argfltregs[1]);
3810 M_DMFC1(REG_ITMP2, rd->argfltregs[0]);
3812 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
3813 M_DMTC1(REG_ITMP2, rd->argfltregs[1]);
3816 M_ALD(rd->argintregs[0], REG_PV, -4 * 8); /* jni environement */
3817 M_ALD(REG_ITMP3, REG_PV, -1 * 8); /* load adress of native method */
3818 M_JSR(REG_RA, REG_ITMP3); /* call native method */
3819 M_NOP; /* delay slot */
3821 /* remove stackframe if there is one */
3822 if (stackframesize) {
3823 M_LDA(REG_SP, REG_SP, stackframesize * 8);
3826 /* 17 instructions */
3828 M_LDA(REG_SP, REG_SP, -(3 * 8));
3829 M_AST(REG_RA, REG_SP, 0 * 8);
3830 M_LST(REG_RESULT, REG_SP, 1 * 8);
3831 M_DST(REG_FRESULT, REG_SP, 2 * 8);
3832 M_ALD(rd->argintregs[0], REG_PV, -6 * 8);
3833 M_MOV(REG_RESULT, rd->argintregs[1]);
3834 M_DMFC1(REG_ITMP1, REG_FRESULT);
3835 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
3836 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
3837 M_ALD(REG_ITMP3, REG_PV, -7 * 8);/* builtin_displaymethodstop */
3838 M_JSR(REG_RA, REG_ITMP3);
3840 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3841 M_LDA(REG_PV, REG_RA, disp);
3842 M_ALD(REG_RA, REG_SP, 0 * 8);
3843 M_LLD(REG_RESULT, REG_SP, 1 * 8);
3844 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
3845 M_LDA(REG_SP, REG_SP, 3 * 8);
3848 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3849 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* builtin_get_exceptionptrptr */
3850 M_JSR(REG_RA, REG_ITMP3);
3853 if (IS_FLT_DBL_TYPE(m->returntype)) {
3854 M_DST(REG_FRESULT, REG_SP, 1 * 8);
3857 M_AST(REG_RESULT, REG_SP, 1 * 8);
3860 M_MOV(REG_RESULT, REG_ITMP3);
3862 if (IS_FLT_DBL_TYPE(m->returntype)) {
3863 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
3866 M_ALD(REG_RESULT, REG_SP, 1 * 8);
3869 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* get address of exceptionptr */
3872 M_LLD(REG_RA, REG_SP, 0); /* load return address */
3873 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
3875 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
3876 M_LDA(REG_SP, REG_SP, NATIVESTUB_STACK * 8);/*remove stackframe, delay slot*/
3878 M_RET(REG_RA); /* return to caller */
3879 M_NOP; /* delay slot */
3881 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
3882 M_ALD(REG_ITMP3, REG_PV, -3 * 8); /* load asm exception handler address */
3884 M_JMP(REG_ITMP3); /* jump to asm exception handler */
3885 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
3888 /* generate static stub call code */
3895 /* there can only be one clinit ref entry */
3896 cref = cd->clinitrefs;
3899 /* Get machine code which is patched back in later. The call is */
3900 /* 2 instruction words long. */
3901 xcodeptr = (s4 *) (cd->mcodebase + cref->branchpos);
3903 /* We need to split this, because an unaligned 8 byte read causes */
3905 *(cs-10) = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3907 /* patch in the call to call the following code (done at compile */
3910 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3911 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3913 M_BRS(tmpmcodeptr - (xcodeptr + 1));
3916 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3918 /* move class pointer into REG_ITMP1 */
3919 M_ALD(REG_ITMP1, REG_PV, -8 * 8); /* class */
3921 /* move machine code into REG_ITMP2 */
3922 M_LLD(REG_ITMP2, REG_PV, -10 * 8); /* machine code */
3924 M_ALD(REG_ITMP3, REG_PV, -9 * 8); /* asm_check_clinit */
3930 (void) docacheflush((void*) cs, (char*) mcodeptr - (char*) cs);
3933 dolog_plain("stubsize: %d (for %d params)\n",
3934 (int) (mcodeptr - (s4*) s), m->paramcount);
3937 #if defined(STATISTICS)
3939 count_nstub_len += NATIVESTUB_SIZE * 8;
3942 /* release dump area */
3944 dump_release(dumpsize);
3946 return (u1 *) (s + NATIVESTUB_OFFSET);
3950 /* function: removenativestub **************************************************
3952 removes a previously created native-stub from memory
3954 *******************************************************************************/
3956 void removenativestub(u1 *stub)
3958 CFREE((u8 *) stub - NATIVESTUB_OFFSET, NATIVESTUB_SIZE * 8);
3962 void docacheflush(u1 *p, long bytelen)
3964 u1 *e = p + bytelen;
3965 long psize = sysconf(_SC_PAGESIZE);
3966 p -= (long) p & (psize-1);
3967 e += psize - ((((long) e - 1) & (psize-1)) + 1);
3969 mprotect(p, bytelen, PROT_READ|PROT_WRITE|PROT_EXEC);
3974 * These are local overrides for various environment variables in Emacs.
3975 * Please do not remove this and leave it at the end of the file, where
3976 * Emacs will automagically detect them.
3977 * ---------------------------------------------------------------------
3980 * indent-tabs-mode: t