1 /* vm/jit/mips/codegen.c - machine code generator for mips
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 Institut f. Computersprachen, TU Wien
5 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6 S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
9 This file is part of CACAO.
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2, or (at
14 your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Andreas Krall
31 Contains the codegenerator for an MIPS (R4000 or higher) processor.
32 This module generates MIPS machine code for a sequence of
33 intermediate code commands (ICMDs).
35 $Id: codegen.c 1652 2004-12-02 10:27:24Z twisti $
45 #include "native/native.h"
46 #include "vm/builtin.h"
47 #include "vm/jit/asmpart.h"
48 #include "vm/jit/jit.h"
49 #include "vm/jit/reg.h"
50 #include "vm/jit/mips/codegen.h"
51 #include "vm/jit/mips/types.h"
54 /* *****************************************************************************
56 Datatypes and Register Allocations:
57 -----------------------------------
59 On 64-bit-machines (like the MIPS) all operands are stored in the
60 registers in a 64-bit form, even when the correspondig JavaVM operands
61 only need 32 bits. This is done by a canonical representation:
63 32-bit integers are allways stored as sign-extended 64-bit values (this
64 approach is directly supported by the MIPS architecture and is very easy
67 32-bit-floats are stored in a 64-bit double precision register by simply
68 expanding the exponent and mantissa with zeroes. (also supported by the
74 The calling conventions and the layout of the stack is explained in detail
75 in the documention file: calling.doc
77 *******************************************************************************/
80 /* register descripton - array ************************************************/
82 /* #define REG_RES 0 reserved register for OS or code generator */
83 /* #define REG_RET 1 return value register */
84 /* #define REG_EXC 2 exception value register (only old jit) */
85 /* #define REG_SAV 3 (callee) saved register */
86 /* #define REG_TMP 4 scratch temporary register (caller saved) */
87 /* #define REG_ARG 5 argument register (caller saved) */
89 /* #define REG_END -1 last entry in tables */
91 static int nregdescint[] = {
92 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
93 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
94 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
95 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
98 /* for use of reserved registers, see comment above */
100 static int nregdescfloat[] = {
101 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
102 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
103 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
104 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
107 /* for use of reserved registers, see comment above */
110 /* Include independent code generation stuff -- include after register */
111 /* descriptions to avoid extern definitions. */
113 #include "vm/jit/codegen.inc"
114 #include "vm/jit/reg.inc"
116 #include "vm/jit/lsra.inc"
120 /* NullPointerException handlers and exception handling initialisation */
122 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
123 void thread_restartcriticalsection(ucontext_t *uc)
126 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[CTX_EPC])) != NULL)
127 uc->uc_mcontext.gregs[CTX_EPC] = (u8) critical;
131 /* NullPointerException signal handler for hardware null pointer check */
133 void catch_NullPointerException(int sig, int code, struct sigcontext *sigctx)
138 java_objectheader *xptr;
140 /* Reset signal handler - necessary for SysV, does no harm for BSD */
142 instr = *((int*)(sigctx->sc_pc));
143 faultaddr = sigctx->sc_regs[(instr >> 21) & 0x1f];
145 if (faultaddr == 0) {
147 sigaddset(&nsig, sig);
148 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
150 xptr = new_nullpointerexception();
152 sigctx->sc_regs[REG_ITMP1_XPTR] = (u8) xptr;
153 sigctx->sc_regs[REG_ITMP2_XPC] = sigctx->sc_pc;
154 sigctx->sc_pc = (u8) asm_handle_exception;
157 faultaddr += (long) ((instr << 16) >> 16);
158 fprintf(stderr, "faulting address: 0x%lx at 0x%lx\n", (long) faultaddr, (long) sigctx->sc_pc);
159 panic("Stack overflow");
166 void init_exceptions(void)
169 sigset_t unblockmask;
171 /* The Boehm GC initialization blocks the SIGSEGV signal. So we do a
172 dummy allocation here to ensure that the GC is initialized.
174 heap_allocate(1, 0, NULL);
176 /* install signal handlers we need to convert to exceptions */
178 sigemptyset(&unblockmask);
180 sa.sa_sigaction = (functionptr) catch_NullPointerException;
181 sigemptyset(&sa.sa_mask);
185 sigaction(SIGSEGV, &sa, NULL);
186 sigaddset(&unblockmask, SIGSEGV);
190 sigaction(SIGBUS, &sa, NULL);
191 sigaddset(&unblockmask, SIGBUS);
195 sigprocmask(SIG_UNBLOCK, &unblockmask, NULL);
197 /* Turn off flush-to-zero */
200 n.fc_word = get_fpc_csr();
201 n.fc_struct.flush = 0;
202 set_fpc_csr(n.fc_word);
207 /* function gen_mcode **********************************************************
209 generates machine code
211 *******************************************************************************/
213 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
215 s4 len, s1, s2, s3, d;
229 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
231 /* space to save used callee saved registers */
233 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
234 savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
236 parentargs_base = rd->maxmemuse + savedregs_num;
238 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
240 if (checksync && (m->flags & ACC_SYNCHRONIZED))
245 /* adjust frame size for 16 byte alignment */
247 if (parentargs_base & 1)
250 /* create method header */
253 (void) dseg_addaddress(cd, m); /* Filler */
255 (void) dseg_addaddress(cd, m); /* MethodPointer */
256 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
258 #if defined(USE_THREADS)
260 /* IsSync contains the offset relative to the stack pointer for the
261 argument of monitor_exit used in the exception handler. Since the
262 offset could be zero and give a wrong meaning of the flag it is
266 if (checksync && (m->flags & ACC_SYNCHRONIZED))
267 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8); /* IsSync */
272 (void) dseg_adds4(cd, 0); /* IsSync */
274 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
275 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse);/* IntSave */
276 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse);/* FltSave */
277 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
279 /* create exception table */
281 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
282 dseg_addtarget(cd, ex->start);
283 dseg_addtarget(cd, ex->end);
284 dseg_addtarget(cd, ex->handler);
285 (void) dseg_addaddress(cd, ex->catchtype);
288 /* initialize mcode variables */
290 mcodeptr = (s4 *) cd->mcodebase;
291 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
292 MCODECHECK(128 + m->paramcount);
294 /* create stack frame (if necessary) */
296 if (parentargs_base) {
297 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
300 /* save return address and used callee saved registers */
303 if (!m->isleafmethod) {
304 p--; M_LST(REG_RA, REG_SP, 8 * p);
306 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
307 p--; M_LST(rd->savintregs[i], REG_SP, 8 * p);
309 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
310 p--; M_DST(rd->savfltregs[i], REG_SP, 8 * p);
313 /* save monitorenter argument */
315 #if defined(USE_THREADS)
316 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
317 if (m->flags & ACC_STATIC) {
318 p = dseg_addaddress(cd, m->class);
319 M_ALD(REG_ITMP1, REG_PV, p);
320 M_AST(REG_ITMP1, REG_SP, rd->maxmemuse * 8);
323 M_AST(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
328 /* copy argument registers to stack and call trace function with pointer
329 to arguments on stack. ToDo: save floating point registers !!!!!!!!!
333 M_LDA(REG_SP, REG_SP, -(18 * 8));
334 M_LST(REG_RA, REG_SP, 1 * 8);
336 /* save integer argument registers */
337 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
338 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
341 /* save and copy float arguments into integer registers */
342 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
343 t = m->paramtypes[p];
345 if (IS_FLT_DBL_TYPE(t)) {
346 if (IS_2_WORD_TYPE(t)) {
347 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
348 M_LLD(rd->argintregs[p], REG_SP, (10 + p) * 8);
351 M_FST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
352 M_ILD(rd->argintregs[p], REG_SP, (10 + p) * 8);
356 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
360 p = dseg_addaddress(cd, m);
361 M_ALD(REG_ITMP1, REG_PV, p);
362 M_LST(REG_ITMP1, REG_SP, 0);
363 p = dseg_addaddress(cd, (void *) builtin_trace_args);
364 M_ALD(REG_ITMP3, REG_PV, p);
365 M_JSR(REG_RA, REG_ITMP3);
368 M_LLD(REG_RA, REG_SP, 1 * 8);
370 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
371 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
374 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
375 t = m->paramtypes[p];
377 if (IS_FLT_DBL_TYPE(t)) {
378 if (IS_2_WORD_TYPE(t)) {
379 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
382 M_FLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
386 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
390 M_LDA(REG_SP, REG_SP, 18 * 8);
393 /* take arguments out of register or stack frame */
395 for (p = 0, l = 0; p < m->paramcount; p++) {
396 t = m->paramtypes[p];
397 var = &(rd->locals[l][t]);
399 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
403 if (IS_INT_LNG_TYPE(t)) { /* integer args */
404 if (p < INT_ARG_CNT) { /* register arguments */
405 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
406 M_INTMOVE(rd->argintregs[p], var->regoff);
407 } else { /* reg arg -> spilled */
408 M_LST(rd->argintregs[p], REG_SP, 8 * var->regoff);
411 } else { /* stack arguments */
412 pa = p - INT_ARG_CNT;
413 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
414 M_LLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
416 } else { /* stack arg -> spilled */
417 M_LLD(REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
418 M_LST(REG_ITMP1, REG_SP, 8 * var->regoff);
422 } else { /* floating args */
423 if (p < FLT_ARG_CNT) { /* register arguments */
424 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
425 M_TFLTMOVE(var->type, rd->argfltregs[p], var->regoff);
427 } else { /* reg arg -> spilled */
428 M_DST(rd->argfltregs[p], REG_SP, var->regoff * 8);
431 } else { /* stack arguments */
432 pa = p - FLT_ARG_CNT;
433 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
434 M_DLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
436 } else { /* stack-arg -> spilled */
437 M_DLD(REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
438 M_DST(REG_FTMP1, REG_SP, 8 * var->regoff);
444 /* call monitorenter function */
446 #if defined(USE_THREADS)
447 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
449 s8 func_enter = (m->flags & ACC_STATIC) ?
450 (s8) builtin_staticmonitorenter : (s8) builtin_monitorenter;
451 p = dseg_addaddress(cd, (void *) func_enter);
452 M_ALD(REG_ITMP3, REG_PV, p);
453 M_JSR(REG_RA, REG_ITMP3);
454 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
455 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
456 M_LDA(REG_PV, REG_RA, disp);
461 /* end of header generation */
463 /* walk through all basic blocks */
464 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
466 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
468 if (bptr->flags >= BBREACHED) {
470 /* branch resolving */
473 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
474 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
480 /* copy interface registers to their destination */
485 while (src != NULL) {
487 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
488 d = reg_of_var(rd, src, REG_ITMP1);
489 M_INTMOVE(REG_ITMP1, d);
490 store_reg_to_var_int(src, d);
493 d = reg_of_var(rd, src, REG_IFTMP);
494 if ((src->varkind != STACKVAR)) {
496 if (IS_FLT_DBL_TYPE(s2)) {
497 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
498 s1 = rd->interfaces[len][s2].regoff;
499 M_TFLTMOVE(s2, s1, d);
502 M_DLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
504 store_reg_to_var_flt(src, d);
507 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
508 s1 = rd->interfaces[len][s2].regoff;
512 M_LLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
514 store_reg_to_var_int(src, d);
521 /* walk through all instructions */
525 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
527 MCODECHECK(64); /* an instruction usually needs < 64 words */
530 case ICMD_NOP: /* ... ==> ... */
533 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
535 var_to_reg_int(s1, src, REG_ITMP1);
537 codegen_addxnullrefs(cd, mcodeptr);
541 /* constant operations ************************************************/
543 case ICMD_ICONST: /* ... ==> ..., constant */
544 /* op1 = 0, val.i = constant */
546 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
547 ICONST(d, iptr->val.i);
548 store_reg_to_var_int(iptr->dst, d);
551 case ICMD_LCONST: /* ... ==> ..., constant */
552 /* op1 = 0, val.l = constant */
554 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
555 LCONST(d, iptr->val.l);
556 store_reg_to_var_int(iptr->dst, d);
559 case ICMD_FCONST: /* ... ==> ..., constant */
560 /* op1 = 0, val.f = constant */
562 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
563 a = dseg_addfloat(cd, iptr->val.f);
565 store_reg_to_var_flt(iptr->dst, d);
568 case ICMD_DCONST: /* ... ==> ..., constant */
569 /* op1 = 0, val.d = constant */
571 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
572 a = dseg_adddouble(cd, iptr->val.d);
574 store_reg_to_var_flt (iptr->dst, d);
577 case ICMD_ACONST: /* ... ==> ..., constant */
578 /* op1 = 0, val.a = constant */
580 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
582 a = dseg_addaddress(cd, iptr->val.a);
585 M_INTMOVE(REG_ZERO, d);
587 store_reg_to_var_int(iptr->dst, d);
591 /* load/store operations **********************************************/
593 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
594 case ICMD_LLOAD: /* op1 = local variable */
597 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
598 if ((iptr->dst->varkind == LOCALVAR) &&
599 (iptr->dst->varnum == iptr->op1))
601 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
602 if (var->flags & INMEMORY) {
603 M_LLD(d, REG_SP, 8 * var->regoff);
605 M_INTMOVE(var->regoff,d);
607 store_reg_to_var_int(iptr->dst, d);
610 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
611 case ICMD_DLOAD: /* op1 = local variable */
613 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
614 if ((iptr->dst->varkind == LOCALVAR) &&
615 (iptr->dst->varnum == iptr->op1))
617 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
619 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
620 if (var->flags & INMEMORY) {
621 M_CCFLD(var->type, t2, d, REG_SP, 8 * var->regoff);
623 M_CCFLTMOVE(var->type, t2, var->regoff, d);
626 store_reg_to_var_flt(iptr->dst, d);
630 case ICMD_ISTORE: /* ..., value ==> ... */
631 case ICMD_LSTORE: /* op1 = local variable */
634 if ((src->varkind == LOCALVAR) &&
635 (src->varnum == iptr->op1))
637 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
638 if (var->flags & INMEMORY) {
639 var_to_reg_int(s1, src, REG_ITMP1);
640 M_LST(s1, REG_SP, 8 * var->regoff);
643 var_to_reg_int(s1, src, var->regoff);
644 M_INTMOVE(s1, var->regoff);
648 case ICMD_FSTORE: /* ..., value ==> ... */
649 case ICMD_DSTORE: /* op1 = local variable */
651 if ((src->varkind == LOCALVAR) &&
652 (src->varnum == iptr->op1))
654 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
656 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
657 if (var->flags & INMEMORY) {
658 var_to_reg_flt(s1, src, REG_FTMP1);
659 M_CCFST(t1, var->type, s1, REG_SP, 8 * var->regoff);
662 var_to_reg_flt(s1, src, var->regoff);
663 M_CCFLTMOVE(t1, var->type, s1, var->regoff);
669 /* pop/dup/swap operations ********************************************/
671 /* attention: double and longs are only one entry in CACAO ICMDs */
673 case ICMD_POP: /* ..., value ==> ... */
674 case ICMD_POP2: /* ..., value, value ==> ... */
677 case ICMD_DUP: /* ..., a ==> ..., a, a */
678 M_COPY(src, iptr->dst);
681 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
683 M_COPY(src, iptr->dst);
684 M_COPY(src->prev, iptr->dst->prev);
685 M_COPY(iptr->dst, iptr->dst->prev->prev);
688 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
690 M_COPY(src, iptr->dst);
691 M_COPY(src->prev, iptr->dst->prev);
692 M_COPY(src->prev->prev, iptr->dst->prev->prev);
693 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
696 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
698 M_COPY(src, iptr->dst);
699 M_COPY(src->prev, iptr->dst->prev);
702 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
704 M_COPY(src, iptr->dst);
705 M_COPY(src->prev, iptr->dst->prev);
706 M_COPY(src->prev->prev, iptr->dst->prev->prev);
707 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
708 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
711 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
713 M_COPY(src, iptr->dst);
714 M_COPY(src->prev, iptr->dst->prev);
715 M_COPY(src->prev->prev, iptr->dst->prev->prev);
716 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
717 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
718 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
721 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
723 M_COPY(src, iptr->dst->prev);
724 M_COPY(src->prev, iptr->dst);
728 /* integer operations *************************************************/
730 case ICMD_INEG: /* ..., value ==> ..., - value */
732 var_to_reg_int(s1, src, REG_ITMP1);
733 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
734 M_ISUB(REG_ZERO, s1, d);
735 store_reg_to_var_int(iptr->dst, d);
738 case ICMD_LNEG: /* ..., value ==> ..., - value */
740 var_to_reg_int(s1, src, REG_ITMP1);
741 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
742 M_LSUB(REG_ZERO, s1, d);
743 store_reg_to_var_int(iptr->dst, d);
746 case ICMD_I2L: /* ..., value ==> ..., value */
748 var_to_reg_int(s1, src, REG_ITMP1);
749 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
751 store_reg_to_var_int(iptr->dst, d);
754 case ICMD_L2I: /* ..., value ==> ..., value */
756 var_to_reg_int(s1, src, REG_ITMP1);
757 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
758 M_ISLL_IMM(s1, 0, d );
759 store_reg_to_var_int(iptr->dst, d);
762 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
764 var_to_reg_int(s1, src, REG_ITMP1);
765 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
766 M_LSLL_IMM(s1, 56, d);
767 M_LSRA_IMM( d, 56, d);
768 store_reg_to_var_int(iptr->dst, d);
771 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
773 var_to_reg_int(s1, src, REG_ITMP1);
774 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
776 store_reg_to_var_int(iptr->dst, d);
779 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
781 var_to_reg_int(s1, src, REG_ITMP1);
782 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
783 M_LSLL_IMM(s1, 48, d);
784 M_LSRA_IMM( d, 48, d);
785 store_reg_to_var_int(iptr->dst, d);
789 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
791 var_to_reg_int(s1, src->prev, REG_ITMP1);
792 var_to_reg_int(s2, src, REG_ITMP2);
793 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
795 store_reg_to_var_int(iptr->dst, d);
798 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
799 /* val.i = constant */
801 var_to_reg_int(s1, src, REG_ITMP1);
802 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
803 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
804 M_IADD_IMM(s1, iptr->val.i, d);
807 ICONST(REG_ITMP2, iptr->val.i);
808 M_IADD(s1, REG_ITMP2, d);
810 store_reg_to_var_int(iptr->dst, d);
813 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
815 var_to_reg_int(s1, src->prev, REG_ITMP1);
816 var_to_reg_int(s2, src, REG_ITMP2);
817 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
819 store_reg_to_var_int(iptr->dst, d);
822 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
823 /* val.l = constant */
825 var_to_reg_int(s1, src, REG_ITMP1);
826 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
827 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
828 M_LADD_IMM(s1, iptr->val.l, d);
831 LCONST(REG_ITMP2, iptr->val.l);
832 M_LADD(s1, REG_ITMP2, d);
834 store_reg_to_var_int(iptr->dst, d);
837 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
839 var_to_reg_int(s1, src->prev, REG_ITMP1);
840 var_to_reg_int(s2, src, REG_ITMP2);
841 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
843 store_reg_to_var_int(iptr->dst, d);
846 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
847 /* val.i = constant */
849 var_to_reg_int(s1, src, REG_ITMP1);
850 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
851 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
852 M_IADD_IMM(s1, -iptr->val.i, d);
855 ICONST(REG_ITMP2, iptr->val.i);
856 M_ISUB(s1, REG_ITMP2, d);
858 store_reg_to_var_int(iptr->dst, d);
861 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
863 var_to_reg_int(s1, src->prev, REG_ITMP1);
864 var_to_reg_int(s2, src, REG_ITMP2);
865 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
867 store_reg_to_var_int(iptr->dst, d);
870 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
871 /* val.l = constant */
873 var_to_reg_int(s1, src, REG_ITMP1);
874 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
875 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
876 M_LADD_IMM(s1, -iptr->val.l, d);
879 LCONST(REG_ITMP2, iptr->val.l);
880 M_LSUB(s1, REG_ITMP2, d);
882 store_reg_to_var_int(iptr->dst, d);
885 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
887 var_to_reg_int(s1, src->prev, REG_ITMP1);
888 var_to_reg_int(s2, src, REG_ITMP2);
889 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
894 store_reg_to_var_int(iptr->dst, d);
897 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
898 /* val.i = constant */
900 var_to_reg_int(s1, src, REG_ITMP1);
901 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
902 ICONST(REG_ITMP2, iptr->val.i);
903 M_IMUL(s1, REG_ITMP2);
907 store_reg_to_var_int(iptr->dst, d);
910 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
912 var_to_reg_int(s1, src->prev, REG_ITMP1);
913 var_to_reg_int(s2, src, REG_ITMP2);
914 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
919 store_reg_to_var_int(iptr->dst, d);
922 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
923 /* val.l = constant */
925 var_to_reg_int(s1, src, REG_ITMP1);
926 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
927 LCONST(REG_ITMP2, iptr->val.l);
928 M_LMUL(s1, REG_ITMP2);
932 store_reg_to_var_int(iptr->dst, d);
935 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
937 var_to_reg_int(s1, src->prev, REG_ITMP1);
938 var_to_reg_int(s2, src, REG_ITMP2);
939 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
944 store_reg_to_var_int(iptr->dst, d);
947 case ICMD_IDIVCONST: /* ..., value ==> ..., value / constant */
948 /* val.i = constant */
950 var_to_reg_int(s1, src, REG_ITMP1);
951 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
952 ICONST(REG_ITMP2, iptr->val.i);
953 M_IDIV(s1, REG_ITMP2);
957 store_reg_to_var_int(iptr->dst, d);
960 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
962 var_to_reg_int(s1, src->prev, REG_ITMP1);
963 var_to_reg_int(s2, src, REG_ITMP2);
964 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
969 store_reg_to_var_int(iptr->dst, d);
972 case ICMD_LDIVCONST: /* ..., value ==> ..., value / constant */
973 /* val.l = constant */
975 var_to_reg_int(s1, src, REG_ITMP1);
976 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
977 LCONST(REG_ITMP2, iptr->val.l);
978 M_LDIV(s1, REG_ITMP2);
982 store_reg_to_var_int(iptr->dst, d);
985 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
987 var_to_reg_int(s1, src->prev, REG_ITMP1);
988 var_to_reg_int(s2, src, REG_ITMP2);
989 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
994 store_reg_to_var_int(iptr->dst, d);
997 case ICMD_IREMCONST: /* ..., value ==> ..., value % constant */
998 /* val.i = constant */
1000 var_to_reg_int(s1, src, REG_ITMP1);
1001 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1002 ICONST(REG_ITMP2, iptr->val.i);
1003 M_IDIV(s1, REG_ITMP2);
1007 store_reg_to_var_int(iptr->dst, d);
1010 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1012 var_to_reg_int(s1, src->prev, REG_ITMP1);
1013 var_to_reg_int(s2, src, REG_ITMP2);
1014 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1019 store_reg_to_var_int(iptr->dst, d);
1022 case ICMD_LREMCONST: /* ..., value ==> ..., value % constant */
1023 /* val.l = constant */
1025 var_to_reg_int(s1, src, REG_ITMP1);
1026 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1027 LCONST(REG_ITMP2, iptr->val.l);
1028 M_LDIV(s1, REG_ITMP2);
1032 store_reg_to_var_int(iptr->dst, d);
1035 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1036 case ICMD_LDIVPOW2: /* val.i = constant */
1038 var_to_reg_int(s1, src, REG_ITMP1);
1039 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1040 M_LSRA_IMM(s1, 63, REG_ITMP2);
1041 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1042 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1043 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
1044 store_reg_to_var_int(iptr->dst, d);
1047 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1049 var_to_reg_int(s1, src->prev, REG_ITMP1);
1050 var_to_reg_int(s2, src, REG_ITMP2);
1051 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1053 store_reg_to_var_int(iptr->dst, d);
1056 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1057 /* val.i = constant */
1059 var_to_reg_int(s1, src, REG_ITMP1);
1060 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1061 M_ISLL_IMM(s1, iptr->val.i, d);
1062 store_reg_to_var_int(iptr->dst, d);
1065 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1067 var_to_reg_int(s1, src->prev, REG_ITMP1);
1068 var_to_reg_int(s2, src, REG_ITMP2);
1069 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1071 store_reg_to_var_int(iptr->dst, d);
1074 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1075 /* val.i = constant */
1077 var_to_reg_int(s1, src, REG_ITMP1);
1078 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1079 M_ISRA_IMM(s1, iptr->val.i, d);
1080 store_reg_to_var_int(iptr->dst, d);
1083 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1085 var_to_reg_int(s1, src->prev, REG_ITMP1);
1086 var_to_reg_int(s2, src, REG_ITMP2);
1087 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1089 store_reg_to_var_int(iptr->dst, d);
1092 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1093 /* val.i = constant */
1095 var_to_reg_int(s1, src, REG_ITMP1);
1096 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1097 M_ISRL_IMM(s1, iptr->val.i, d);
1098 store_reg_to_var_int(iptr->dst, d);
1101 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1103 var_to_reg_int(s1, src->prev, REG_ITMP1);
1104 var_to_reg_int(s2, src, REG_ITMP2);
1105 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1107 store_reg_to_var_int(iptr->dst, d);
1110 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1111 /* val.i = constant */
1113 var_to_reg_int(s1, src, REG_ITMP1);
1114 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1115 M_LSLL_IMM(s1, iptr->val.i, d);
1116 store_reg_to_var_int(iptr->dst, d);
1119 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1121 var_to_reg_int(s1, src->prev, REG_ITMP1);
1122 var_to_reg_int(s2, src, REG_ITMP2);
1123 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1125 store_reg_to_var_int(iptr->dst, d);
1128 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1129 /* val.i = constant */
1131 var_to_reg_int(s1, src, REG_ITMP1);
1132 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1133 M_LSRA_IMM(s1, iptr->val.i, d);
1134 store_reg_to_var_int(iptr->dst, d);
1137 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1139 var_to_reg_int(s1, src->prev, REG_ITMP1);
1140 var_to_reg_int(s2, src, REG_ITMP2);
1141 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1143 store_reg_to_var_int(iptr->dst, d);
1146 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1147 /* val.i = constant */
1149 var_to_reg_int(s1, src, REG_ITMP1);
1150 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1151 M_LSRL_IMM(s1, iptr->val.i, d);
1152 store_reg_to_var_int(iptr->dst, d);
1155 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1158 var_to_reg_int(s1, src->prev, REG_ITMP1);
1159 var_to_reg_int(s2, src, REG_ITMP2);
1160 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1162 store_reg_to_var_int(iptr->dst, d);
1165 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1166 /* val.i = constant */
1168 var_to_reg_int(s1, src, REG_ITMP1);
1169 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1170 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1171 M_AND_IMM(s1, iptr->val.i, d);
1174 ICONST(REG_ITMP2, iptr->val.i);
1175 M_AND(s1, REG_ITMP2, d);
1177 store_reg_to_var_int(iptr->dst, d);
1180 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1181 /* val.i = constant */
1183 var_to_reg_int(s1, src, REG_ITMP1);
1184 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1186 M_MOV(s1, REG_ITMP1);
1189 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1190 M_AND_IMM(s1, iptr->val.i, d);
1193 M_ISUB(REG_ZERO, s1, d);
1194 M_AND_IMM(d, iptr->val.i, d);
1197 ICONST(REG_ITMP2, iptr->val.i);
1198 M_AND(s1, REG_ITMP2, d);
1201 M_ISUB(REG_ZERO, s1, d);
1202 M_AND(d, REG_ITMP2, d);
1204 M_ISUB(REG_ZERO, d, d);
1205 store_reg_to_var_int(iptr->dst, d);
1208 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1209 /* val.l = constant */
1211 var_to_reg_int(s1, src, REG_ITMP1);
1212 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1213 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1214 M_AND_IMM(s1, iptr->val.l, d);
1217 LCONST(REG_ITMP2, iptr->val.l);
1218 M_AND(s1, REG_ITMP2, d);
1220 store_reg_to_var_int(iptr->dst, d);
1223 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1224 /* val.l = constant */
1226 var_to_reg_int(s1, src, REG_ITMP1);
1227 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1229 M_MOV(s1, REG_ITMP1);
1232 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1233 M_AND_IMM(s1, iptr->val.l, d);
1236 M_LSUB(REG_ZERO, s1, d);
1237 M_AND_IMM(d, iptr->val.l, d);
1240 LCONST(REG_ITMP2, iptr->val.l);
1241 M_AND(s1, REG_ITMP2, d);
1244 M_LSUB(REG_ZERO, s1, d);
1245 M_AND(d, REG_ITMP2, d);
1247 M_LSUB(REG_ZERO, d, d);
1248 store_reg_to_var_int(iptr->dst, d);
1251 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1254 var_to_reg_int(s1, src->prev, REG_ITMP1);
1255 var_to_reg_int(s2, src, REG_ITMP2);
1256 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1258 store_reg_to_var_int(iptr->dst, d);
1261 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1262 /* val.i = constant */
1264 var_to_reg_int(s1, src, REG_ITMP1);
1265 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1266 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1267 M_OR_IMM(s1, iptr->val.i, d);
1270 ICONST(REG_ITMP2, iptr->val.i);
1271 M_OR(s1, REG_ITMP2, d);
1273 store_reg_to_var_int(iptr->dst, d);
1276 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1277 /* val.l = constant */
1279 var_to_reg_int(s1, src, REG_ITMP1);
1280 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1281 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1282 M_OR_IMM(s1, iptr->val.l, d);
1285 LCONST(REG_ITMP2, iptr->val.l);
1286 M_OR(s1, REG_ITMP2, d);
1288 store_reg_to_var_int(iptr->dst, d);
1291 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1294 var_to_reg_int(s1, src->prev, REG_ITMP1);
1295 var_to_reg_int(s2, src, REG_ITMP2);
1296 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1298 store_reg_to_var_int(iptr->dst, d);
1301 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1302 /* val.i = constant */
1304 var_to_reg_int(s1, src, REG_ITMP1);
1305 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1306 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1307 M_XOR_IMM(s1, iptr->val.i, d);
1310 ICONST(REG_ITMP2, iptr->val.i);
1311 M_XOR(s1, REG_ITMP2, d);
1313 store_reg_to_var_int(iptr->dst, d);
1316 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1317 /* val.l = constant */
1319 var_to_reg_int(s1, src, REG_ITMP1);
1320 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1321 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1322 M_XOR_IMM(s1, iptr->val.l, d);
1325 LCONST(REG_ITMP2, iptr->val.l);
1326 M_XOR(s1, REG_ITMP2, d);
1328 store_reg_to_var_int(iptr->dst, d);
1332 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1334 var_to_reg_int(s1, src->prev, REG_ITMP1);
1335 var_to_reg_int(s2, src, REG_ITMP2);
1336 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1337 M_CMPLT(s1, s2, REG_ITMP3);
1338 M_CMPLT(s2, s1, REG_ITMP1);
1339 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1340 store_reg_to_var_int(iptr->dst, d);
1344 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1345 /* op1 = variable, val.i = constant */
1347 var = &(rd->locals[iptr->op1][TYPE_INT]);
1348 if (var->flags & INMEMORY) {
1350 M_LLD(s1, REG_SP, 8 * var->regoff);
1354 M_IADD_IMM(s1, iptr->val.i, s1);
1355 if (var->flags & INMEMORY)
1356 M_LST(s1, REG_SP, 8 * var->regoff);
1360 /* floating operations ************************************************/
1362 case ICMD_FNEG: /* ..., value ==> ..., - value */
1364 var_to_reg_flt(s1, src, REG_FTMP1);
1365 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1367 store_reg_to_var_flt(iptr->dst, d);
1370 case ICMD_DNEG: /* ..., value ==> ..., - value */
1372 var_to_reg_flt(s1, src, REG_FTMP1);
1373 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1375 store_reg_to_var_flt(iptr->dst, d);
1378 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1380 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1381 var_to_reg_flt(s2, src, REG_FTMP2);
1382 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1384 store_reg_to_var_flt(iptr->dst, d);
1387 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1389 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1390 var_to_reg_flt(s2, src, REG_FTMP2);
1391 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1393 store_reg_to_var_flt(iptr->dst, d);
1396 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1398 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1399 var_to_reg_flt(s2, src, REG_FTMP2);
1400 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1402 store_reg_to_var_flt(iptr->dst, d);
1405 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1407 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1408 var_to_reg_flt(s2, src, REG_FTMP2);
1409 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1411 store_reg_to_var_flt(iptr->dst, d);
1414 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1416 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1417 var_to_reg_flt(s2, src, REG_FTMP2);
1418 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1420 store_reg_to_var_flt(iptr->dst, d);
1423 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1425 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1426 var_to_reg_flt(s2, src, REG_FTMP2);
1427 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1429 store_reg_to_var_flt(iptr->dst, d);
1432 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1434 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1435 var_to_reg_flt(s2, src, REG_FTMP2);
1436 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1438 store_reg_to_var_flt(iptr->dst, d);
1441 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1443 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1444 var_to_reg_flt(s2, src, REG_FTMP2);
1445 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1447 store_reg_to_var_flt(iptr->dst, d);
1450 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1453 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1454 var_to_reg_flt(s2, src, REG_FTMP2);
1455 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1456 M_FDIV(s1,s2, REG_FTMP3);
1457 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1458 M_CVTLF(REG_FTMP3, REG_FTMP3);
1459 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1460 M_FSUB(s1, REG_FTMP3, d);
1461 store_reg_to_var_flt(iptr->dst, d);
1464 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1466 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1467 var_to_reg_flt(s2, src, REG_FTMP2);
1468 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1469 M_DDIV(s1,s2, REG_FTMP3);
1470 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1471 M_CVTLD(REG_FTMP3, REG_FTMP3);
1472 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1473 M_DSUB(s1, REG_FTMP3, d);
1474 store_reg_to_var_flt(iptr->dst, d);
1477 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1479 var_to_reg_int(s1, src, REG_ITMP1);
1480 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1483 store_reg_to_var_flt(iptr->dst, d);
1486 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1488 var_to_reg_int(s1, src, REG_ITMP1);
1489 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1492 store_reg_to_var_flt(iptr->dst, d);
1495 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1497 var_to_reg_flt(s1, src, REG_FTMP1);
1498 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1499 M_TRUNCFI(s1, REG_FTMP1);
1500 M_MOVDI(REG_FTMP1, d);
1502 store_reg_to_var_int(iptr->dst, d);
1505 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1507 var_to_reg_flt(s1, src, REG_FTMP1);
1508 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1509 M_TRUNCDI(s1, REG_FTMP1);
1510 M_MOVDI(REG_FTMP1, d);
1512 store_reg_to_var_int(iptr->dst, d);
1515 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1517 var_to_reg_flt(s1, src, REG_FTMP1);
1518 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1519 M_TRUNCFL(s1, REG_FTMP1);
1520 M_MOVDL(REG_FTMP1, d);
1522 store_reg_to_var_int(iptr->dst, d);
1525 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1527 var_to_reg_flt(s1, src, REG_FTMP1);
1528 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1529 M_TRUNCDL(s1, REG_FTMP1);
1530 M_MOVDL(REG_FTMP1, d);
1532 store_reg_to_var_int(iptr->dst, d);
1535 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1537 var_to_reg_flt(s1, src, REG_FTMP1);
1538 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1540 store_reg_to_var_flt(iptr->dst, d);
1543 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1545 var_to_reg_flt(s1, src, REG_FTMP1);
1546 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1548 store_reg_to_var_flt(iptr->dst, d);
1551 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1553 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1554 var_to_reg_flt(s2, src, REG_FTMP2);
1555 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1558 M_LADD_IMM(REG_ZERO, 1, d);
1562 M_LSUB_IMM(REG_ZERO, 1, d);
1563 M_CMOVT(REG_ZERO, d);
1564 store_reg_to_var_int(iptr->dst, d);
1567 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1569 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1570 var_to_reg_flt(s2, src, REG_FTMP2);
1571 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1574 M_LADD_IMM(REG_ZERO, 1, d);
1578 M_LSUB_IMM(REG_ZERO, 1, d);
1579 M_CMOVT(REG_ZERO, d);
1580 store_reg_to_var_int(iptr->dst, d);
1583 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1585 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1586 var_to_reg_flt(s2, src, REG_FTMP2);
1587 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1590 M_LSUB_IMM(REG_ZERO, 1, d);
1594 M_LADD_IMM(REG_ZERO, 1, d);
1595 M_CMOVT(REG_ZERO, d);
1596 store_reg_to_var_int(iptr->dst, d);
1599 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1601 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1602 var_to_reg_flt(s2, src, REG_FTMP2);
1603 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1606 M_LSUB_IMM(REG_ZERO, 1, d);
1610 M_LADD_IMM(REG_ZERO, 1, d);
1611 M_CMOVT(REG_ZERO, d);
1612 store_reg_to_var_int(iptr->dst, d);
1616 /* memory operations **************************************************/
1618 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1620 var_to_reg_int(s1, src, REG_ITMP1);
1621 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1622 gen_nullptr_check(s1);
1623 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1624 store_reg_to_var_int(iptr->dst, d);
1627 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1629 var_to_reg_int(s1, src->prev, REG_ITMP1);
1630 var_to_reg_int(s2, src, REG_ITMP2);
1631 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1632 if (iptr->op1 == 0) {
1633 gen_nullptr_check(s1);
1636 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1637 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1638 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1639 store_reg_to_var_int(iptr->dst, d);
1642 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1644 var_to_reg_int(s1, src->prev, REG_ITMP1);
1645 var_to_reg_int(s2, src, REG_ITMP2);
1646 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1647 if (iptr->op1 == 0) {
1648 gen_nullptr_check(s1);
1651 M_ASLL_IMM(s2, 2, REG_ITMP2);
1652 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1653 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1654 store_reg_to_var_int(iptr->dst, d);
1657 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1659 var_to_reg_int(s1, src->prev, REG_ITMP1);
1660 var_to_reg_int(s2, src, REG_ITMP2);
1661 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1662 if (iptr->op1 == 0) {
1663 gen_nullptr_check(s1);
1666 M_ASLL_IMM(s2, 3, REG_ITMP2);
1667 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1668 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1669 store_reg_to_var_int(iptr->dst, d);
1672 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1674 var_to_reg_int(s1, src->prev, REG_ITMP1);
1675 var_to_reg_int(s2, src, REG_ITMP2);
1676 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1677 if (iptr->op1 == 0) {
1678 gen_nullptr_check(s1);
1681 M_ASLL_IMM(s2, 2, REG_ITMP2);
1682 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1683 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1684 store_reg_to_var_flt(iptr->dst, d);
1687 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1689 var_to_reg_int(s1, src->prev, REG_ITMP1);
1690 var_to_reg_int(s2, src, REG_ITMP2);
1691 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1692 if (iptr->op1 == 0) {
1693 gen_nullptr_check(s1);
1696 M_ASLL_IMM(s2, 3, REG_ITMP2);
1697 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1698 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1699 store_reg_to_var_flt(iptr->dst, d);
1702 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1704 var_to_reg_int(s1, src->prev, REG_ITMP1);
1705 var_to_reg_int(s2, src, REG_ITMP2);
1706 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1707 if (iptr->op1 == 0) {
1708 gen_nullptr_check(s1);
1711 M_AADD(s2, s1, REG_ITMP1);
1712 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1713 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1714 store_reg_to_var_int(iptr->dst, d);
1717 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1719 var_to_reg_int(s1, src->prev, REG_ITMP1);
1720 var_to_reg_int(s2, src, REG_ITMP2);
1721 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1722 if (iptr->op1 == 0) {
1723 gen_nullptr_check(s1);
1726 M_AADD(s2, s1, REG_ITMP1);
1727 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1728 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1729 store_reg_to_var_int(iptr->dst, d);
1732 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1734 var_to_reg_int(s1, src->prev, REG_ITMP1);
1735 var_to_reg_int(s2, src, REG_ITMP2);
1736 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1737 if (iptr->op1 == 0) {
1738 gen_nullptr_check(s1);
1741 M_AADD(s2, s1, REG_ITMP1);
1742 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1743 store_reg_to_var_int(iptr->dst, d);
1747 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1749 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1750 var_to_reg_int(s2, src->prev, REG_ITMP2);
1751 if (iptr->op1 == 0) {
1752 gen_nullptr_check(s1);
1755 var_to_reg_int(s3, src, REG_ITMP3);
1756 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1757 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1758 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1761 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1763 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1764 var_to_reg_int(s2, src->prev, REG_ITMP2);
1765 if (iptr->op1 == 0) {
1766 gen_nullptr_check(s1);
1769 var_to_reg_int(s3, src, REG_ITMP3);
1770 M_ASLL_IMM(s2, 2, REG_ITMP2);
1771 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1772 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1775 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1777 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1778 var_to_reg_int(s2, src->prev, REG_ITMP2);
1779 if (iptr->op1 == 0) {
1780 gen_nullptr_check(s1);
1783 var_to_reg_int(s3, src, REG_ITMP3);
1784 M_ASLL_IMM(s2, 3, REG_ITMP2);
1785 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1786 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1789 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1791 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1792 var_to_reg_int(s2, src->prev, REG_ITMP2);
1793 if (iptr->op1 == 0) {
1794 gen_nullptr_check(s1);
1797 var_to_reg_flt(s3, src, REG_FTMP3);
1798 M_ASLL_IMM(s2, 2, REG_ITMP2);
1799 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1800 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1803 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1805 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1806 var_to_reg_int(s2, src->prev, REG_ITMP2);
1807 if (iptr->op1 == 0) {
1808 gen_nullptr_check(s1);
1811 var_to_reg_flt(s3, src, REG_FTMP3);
1812 M_ASLL_IMM(s2, 3, REG_ITMP2);
1813 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1814 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1817 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1818 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1820 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1821 var_to_reg_int(s2, src->prev, REG_ITMP2);
1822 if (iptr->op1 == 0) {
1823 gen_nullptr_check(s1);
1826 var_to_reg_int(s3, src, REG_ITMP3);
1827 M_AADD(s2, s1, REG_ITMP1);
1828 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1829 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1832 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1834 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1835 var_to_reg_int(s2, src->prev, REG_ITMP2);
1836 if (iptr->op1 == 0) {
1837 gen_nullptr_check(s1);
1840 var_to_reg_int(s3, src, REG_ITMP3);
1841 M_AADD(s2, s1, REG_ITMP1);
1842 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1846 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1847 /* op1 = type, val.a = field address */
1849 /* If the static fields' class is not yet initialized, we do it */
1850 /* now. The call code is generated later. */
1851 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1852 codegen_addclinitref(cd, mcodeptr, ((fieldinfo *) iptr->val.a)->class);
1854 /* This is just for debugging purposes. Is very difficult to */
1855 /* read patched code. Here we patch the following 2 nop's */
1856 /* so that the real code keeps untouched. */
1857 if (showdisassemble) {
1863 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1864 M_ALD(REG_ITMP1, REG_PV, a);
1865 switch (iptr->op1) {
1867 var_to_reg_int(s2, src, REG_ITMP2);
1868 M_IST(s2, REG_ITMP1, 0);
1871 var_to_reg_int(s2, src, REG_ITMP2);
1872 M_LST(s2, REG_ITMP1, 0);
1875 var_to_reg_int(s2, src, REG_ITMP2);
1876 M_AST(s2, REG_ITMP1, 0);
1879 var_to_reg_flt(s2, src, REG_FTMP2);
1880 M_FST(s2, REG_ITMP1, 0);
1883 var_to_reg_flt(s2, src, REG_FTMP2);
1884 M_DST(s2, REG_ITMP1, 0);
1887 throw_cacao_exception_exit(string_java_lang_InternalError,
1888 "Unknown PUTSTATIC operand type %d",
1893 case ICMD_GETSTATIC: /* ... ==> ..., value */
1894 /* op1 = type, val.a = field address */
1896 /* If the static fields' class is not yet initialized, we do it */
1897 /* now. The call code is generated later. */
1898 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1899 codegen_addclinitref(cd, mcodeptr, ((fieldinfo *) iptr->val.a)->class);
1901 /* This is just for debugging purposes. Is very difficult to */
1902 /* read patched code. Here we patch the following 2 nop's */
1903 /* so that the real code keeps untouched. */
1904 if (showdisassemble) {
1910 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1911 M_ALD(REG_ITMP1, REG_PV, a);
1912 switch (iptr->op1) {
1914 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1915 M_ILD(d, REG_ITMP1, 0);
1916 store_reg_to_var_int(iptr->dst, d);
1919 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1920 M_LLD(d, REG_ITMP1, 0);
1921 store_reg_to_var_int(iptr->dst, d);
1924 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1925 M_ALD(d, REG_ITMP1, 0);
1926 store_reg_to_var_int(iptr->dst, d);
1929 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1930 M_FLD(d, REG_ITMP1, 0);
1931 store_reg_to_var_flt(iptr->dst, d);
1934 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1935 M_DLD(d, REG_ITMP1, 0);
1936 store_reg_to_var_flt(iptr->dst, d);
1939 throw_cacao_exception_exit(string_java_lang_InternalError,
1940 "Unknown GETSTATIC operand type %d",
1946 case ICMD_PUTFIELD: /* ..., value ==> ... */
1947 /* op1 = type, val.i = field offset */
1949 a = ((fieldinfo *)(iptr->val.a))->offset;
1950 switch (iptr->op1) {
1952 var_to_reg_int(s1, src->prev, REG_ITMP1);
1953 var_to_reg_int(s2, src, REG_ITMP2);
1954 gen_nullptr_check(s1);
1958 var_to_reg_int(s1, src->prev, REG_ITMP1);
1959 var_to_reg_int(s2, src, REG_ITMP2);
1960 gen_nullptr_check(s1);
1964 var_to_reg_int(s1, src->prev, REG_ITMP1);
1965 var_to_reg_int(s2, src, REG_ITMP2);
1966 gen_nullptr_check(s1);
1970 var_to_reg_int(s1, src->prev, REG_ITMP1);
1971 var_to_reg_flt(s2, src, REG_FTMP2);
1972 gen_nullptr_check(s1);
1976 var_to_reg_int(s1, src->prev, REG_ITMP1);
1977 var_to_reg_flt(s2, src, REG_FTMP2);
1978 gen_nullptr_check(s1);
1982 throw_cacao_exception_exit(string_java_lang_InternalError,
1983 "Unknown PUTFIELD operand type %d",
1988 case ICMD_GETFIELD: /* ... ==> ..., value */
1989 /* op1 = type, val.i = field offset */
1991 a = ((fieldinfo *)(iptr->val.a))->offset;
1992 switch (iptr->op1) {
1994 var_to_reg_int(s1, src, REG_ITMP1);
1995 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1996 gen_nullptr_check(s1);
1998 store_reg_to_var_int(iptr->dst, d);
2001 var_to_reg_int(s1, src, REG_ITMP1);
2002 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2003 gen_nullptr_check(s1);
2005 store_reg_to_var_int(iptr->dst, d);
2008 var_to_reg_int(s1, src, REG_ITMP1);
2009 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2010 gen_nullptr_check(s1);
2012 store_reg_to_var_int(iptr->dst, d);
2015 var_to_reg_int(s1, src, REG_ITMP1);
2016 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2017 gen_nullptr_check(s1);
2019 store_reg_to_var_flt(iptr->dst, d);
2022 var_to_reg_int(s1, src, REG_ITMP1);
2023 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2024 gen_nullptr_check(s1);
2026 store_reg_to_var_flt(iptr->dst, d);
2029 throw_cacao_exception_exit(string_java_lang_InternalError,
2030 "Unknown GETFIELD operand type %d",
2036 /* branch operations **************************************************/
2038 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2040 var_to_reg_int(s1, src, REG_ITMP1);
2041 M_INTMOVE(s1, REG_ITMP1_XPTR);
2042 a = dseg_addaddress(cd, asm_handle_exception);
2043 M_ALD(REG_ITMP2, REG_PV, a);
2044 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2046 M_NOP; /* nop ensures that XPC is less than the end */
2047 /* of basic block */
2051 case ICMD_GOTO: /* ... ==> ... */
2052 /* op1 = target JavaVM pc */
2054 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2059 case ICMD_JSR: /* ... ==> ... */
2060 /* op1 = target JavaVM pc */
2062 dseg_addtarget(cd, BlockPtrOfPC(iptr->op1));
2063 M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
2064 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2068 case ICMD_RET: /* ... ==> ... */
2069 /* op1 = local variable */
2070 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2071 if (var->flags & INMEMORY) {
2072 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2081 case ICMD_IFNULL: /* ..., value ==> ... */
2082 /* op1 = target JavaVM pc */
2084 var_to_reg_int(s1, src, REG_ITMP1);
2086 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2090 case ICMD_IFNONNULL: /* ..., value ==> ... */
2091 /* op1 = target JavaVM pc */
2093 var_to_reg_int(s1, src, REG_ITMP1);
2095 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2099 case ICMD_IFEQ: /* ..., value ==> ... */
2100 /* op1 = target JavaVM pc, val.i = constant */
2102 var_to_reg_int(s1, src, REG_ITMP1);
2103 if (iptr->val.i == 0) {
2107 ICONST(REG_ITMP2, iptr->val.i);
2108 M_BEQ(s1, REG_ITMP2, 0);
2110 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2114 case ICMD_IFLT: /* ..., value ==> ... */
2115 /* op1 = target JavaVM pc, val.i = constant */
2117 var_to_reg_int(s1, src, REG_ITMP1);
2118 if (iptr->val.i == 0) {
2122 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2123 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2126 ICONST(REG_ITMP2, iptr->val.i);
2127 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2129 M_BNEZ(REG_ITMP1, 0);
2131 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2135 case ICMD_IFLE: /* ..., value ==> ... */
2136 /* op1 = target JavaVM pc, val.i = constant */
2138 var_to_reg_int(s1, src, REG_ITMP1);
2139 if (iptr->val.i == 0) {
2143 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2144 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2145 M_BNEZ(REG_ITMP1, 0);
2148 ICONST(REG_ITMP2, iptr->val.i);
2149 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2150 M_BEQZ(REG_ITMP1, 0);
2153 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2157 case ICMD_IFNE: /* ..., value ==> ... */
2158 /* op1 = target JavaVM pc, val.i = constant */
2160 var_to_reg_int(s1, src, REG_ITMP1);
2161 if (iptr->val.i == 0) {
2165 ICONST(REG_ITMP2, iptr->val.i);
2166 M_BNE(s1, REG_ITMP2, 0);
2168 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2172 case ICMD_IFGT: /* ..., value ==> ... */
2173 /* op1 = target JavaVM pc, val.i = constant */
2175 var_to_reg_int(s1, src, REG_ITMP1);
2176 if (iptr->val.i == 0) {
2180 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2181 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2182 M_BEQZ(REG_ITMP1, 0);
2185 ICONST(REG_ITMP2, iptr->val.i);
2186 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2187 M_BNEZ(REG_ITMP1, 0);
2190 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2194 case ICMD_IFGE: /* ..., value ==> ... */
2195 /* op1 = target JavaVM pc, val.i = constant */
2197 var_to_reg_int(s1, src, REG_ITMP1);
2198 if (iptr->val.i == 0) {
2202 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2203 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2206 ICONST(REG_ITMP2, iptr->val.i);
2207 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2209 M_BEQZ(REG_ITMP1, 0);
2211 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2215 case ICMD_IF_LEQ: /* ..., value ==> ... */
2216 /* op1 = target JavaVM pc, val.l = constant */
2218 var_to_reg_int(s1, src, REG_ITMP1);
2219 if (iptr->val.l == 0) {
2223 LCONST(REG_ITMP2, iptr->val.l);
2224 M_BEQ(s1, REG_ITMP2, 0);
2226 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2230 case ICMD_IF_LLT: /* ..., value ==> ... */
2231 /* op1 = target JavaVM pc, val.l = constant */
2233 var_to_reg_int(s1, src, REG_ITMP1);
2234 if (iptr->val.l == 0) {
2238 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2239 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2242 LCONST(REG_ITMP2, iptr->val.l);
2243 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2245 M_BNEZ(REG_ITMP1, 0);
2247 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2251 case ICMD_IF_LLE: /* ..., value ==> ... */
2252 /* op1 = target JavaVM pc, val.l = constant */
2254 var_to_reg_int(s1, src, REG_ITMP1);
2255 if (iptr->val.l == 0) {
2259 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2260 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2261 M_BNEZ(REG_ITMP1, 0);
2264 LCONST(REG_ITMP2, iptr->val.l);
2265 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2266 M_BEQZ(REG_ITMP1, 0);
2269 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2273 case ICMD_IF_LNE: /* ..., value ==> ... */
2274 /* op1 = target JavaVM pc, val.l = constant */
2276 var_to_reg_int(s1, src, REG_ITMP1);
2277 if (iptr->val.l == 0) {
2281 LCONST(REG_ITMP2, iptr->val.l);
2282 M_BNE(s1, REG_ITMP2, 0);
2284 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2288 case ICMD_IF_LGT: /* ..., value ==> ... */
2289 /* op1 = target JavaVM pc, val.l = constant */
2291 var_to_reg_int(s1, src, REG_ITMP1);
2292 if (iptr->val.l == 0) {
2296 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2297 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2298 M_BEQZ(REG_ITMP1, 0);
2301 LCONST(REG_ITMP2, iptr->val.l);
2302 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2303 M_BNEZ(REG_ITMP1, 0);
2306 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2310 case ICMD_IF_LGE: /* ..., value ==> ... */
2311 /* op1 = target JavaVM pc, val.l = constant */
2313 var_to_reg_int(s1, src, REG_ITMP1);
2314 if (iptr->val.l == 0) {
2318 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2319 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2322 LCONST(REG_ITMP2, iptr->val.l);
2323 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2325 M_BEQZ(REG_ITMP1, 0);
2327 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2331 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2332 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2333 case ICMD_IF_ACMPEQ:
2335 var_to_reg_int(s1, src->prev, REG_ITMP1);
2336 var_to_reg_int(s2, src, REG_ITMP2);
2338 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2342 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2343 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2344 case ICMD_IF_ACMPNE:
2346 var_to_reg_int(s1, src->prev, REG_ITMP1);
2347 var_to_reg_int(s2, src, REG_ITMP2);
2349 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2353 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2354 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2356 var_to_reg_int(s1, src->prev, REG_ITMP1);
2357 var_to_reg_int(s2, src, REG_ITMP2);
2358 M_CMPLT(s1, s2, REG_ITMP1);
2359 M_BNEZ(REG_ITMP1, 0);
2360 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2364 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2365 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2367 var_to_reg_int(s1, src->prev, REG_ITMP1);
2368 var_to_reg_int(s2, src, REG_ITMP2);
2369 M_CMPGT(s1, s2, REG_ITMP1);
2370 M_BNEZ(REG_ITMP1, 0);
2371 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2375 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2376 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2378 var_to_reg_int(s1, src->prev, REG_ITMP1);
2379 var_to_reg_int(s2, src, REG_ITMP2);
2380 M_CMPGT(s1, s2, REG_ITMP1);
2381 M_BEQZ(REG_ITMP1, 0);
2382 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2386 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2387 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2389 var_to_reg_int(s1, src->prev, REG_ITMP1);
2390 var_to_reg_int(s2, src, REG_ITMP2);
2391 M_CMPLT(s1, s2, REG_ITMP1);
2392 M_BEQZ(REG_ITMP1, 0);
2393 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2397 #ifdef CONDITIONAL_LOADCONST
2398 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2400 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2403 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2404 /* val.i = constant */
2406 var_to_reg_int(s1, src, REG_ITMP1);
2407 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2409 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2410 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2411 M_CMPEQ(s1, REG_ZERO, d);
2412 store_reg_to_var_int(iptr->dst, d);
2415 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2416 M_CMPEQ(s1, REG_ZERO, d);
2418 store_reg_to_var_int(iptr->dst, d);
2422 M_MOV(s1, REG_ITMP1);
2425 ICONST(d, iptr[1].val.i);
2427 if ((s3 >= 0) && (s3 <= 255)) {
2428 M_CMOVEQ_IMM(s1, s3, d);
2431 ICONST(REG_ITMP2, s3);
2432 M_CMOVEQ(s1, REG_ITMP2, d);
2434 store_reg_to_var_int(iptr->dst, d);
2437 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2438 /* val.i = constant */
2440 var_to_reg_int(s1, src, REG_ITMP1);
2441 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2443 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2444 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2445 M_CMPEQ(s1, REG_ZERO, d);
2446 store_reg_to_var_int(iptr->dst, d);
2449 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2450 M_CMPEQ(s1, REG_ZERO, d);
2452 store_reg_to_var_int(iptr->dst, d);
2456 M_MOV(s1, REG_ITMP1);
2459 ICONST(d, iptr[1].val.i);
2461 if ((s3 >= 0) && (s3 <= 255)) {
2462 M_CMOVNE_IMM(s1, s3, d);
2465 ICONST(REG_ITMP2, s3);
2466 M_CMOVNE(s1, REG_ITMP2, d);
2468 store_reg_to_var_int(iptr->dst, d);
2471 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2472 /* val.i = constant */
2474 var_to_reg_int(s1, src, REG_ITMP1);
2475 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2477 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2478 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2479 M_CMPLT(s1, REG_ZERO, d);
2480 store_reg_to_var_int(iptr->dst, d);
2483 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2484 M_CMPLE(REG_ZERO, s1, d);
2485 store_reg_to_var_int(iptr->dst, d);
2489 M_MOV(s1, REG_ITMP1);
2492 ICONST(d, iptr[1].val.i);
2494 if ((s3 >= 0) && (s3 <= 255)) {
2495 M_CMOVLT_IMM(s1, s3, d);
2498 ICONST(REG_ITMP2, s3);
2499 M_CMOVLT(s1, REG_ITMP2, d);
2501 store_reg_to_var_int(iptr->dst, d);
2504 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2505 /* val.i = constant */
2507 var_to_reg_int(s1, src, REG_ITMP1);
2508 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2510 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2511 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2512 M_CMPLE(REG_ZERO, s1, d);
2513 store_reg_to_var_int(iptr->dst, d);
2516 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2517 M_CMPLT(s1, REG_ZERO, d);
2518 store_reg_to_var_int(iptr->dst, d);
2522 M_MOV(s1, REG_ITMP1);
2525 ICONST(d, iptr[1].val.i);
2527 if ((s3 >= 0) && (s3 <= 255)) {
2528 M_CMOVGE_IMM(s1, s3, d);
2531 ICONST(REG_ITMP2, s3);
2532 M_CMOVGE(s1, REG_ITMP2, d);
2534 store_reg_to_var_int(iptr->dst, d);
2537 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2538 /* val.i = constant */
2540 var_to_reg_int(s1, src, REG_ITMP1);
2541 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2543 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2544 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2545 M_CMPLT(REG_ZERO, s1, d);
2546 store_reg_to_var_int(iptr->dst, d);
2549 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2550 M_CMPLE(s1, REG_ZERO, d);
2551 store_reg_to_var_int(iptr->dst, d);
2555 M_MOV(s1, REG_ITMP1);
2558 ICONST(d, iptr[1].val.i);
2560 if ((s3 >= 0) && (s3 <= 255)) {
2561 M_CMOVGT_IMM(s1, s3, d);
2564 ICONST(REG_ITMP2, s3);
2565 M_CMOVGT(s1, REG_ITMP2, d);
2567 store_reg_to_var_int(iptr->dst, d);
2570 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2571 /* val.i = constant */
2573 var_to_reg_int(s1, src, REG_ITMP1);
2574 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2576 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2577 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2578 M_CMPLE(s1, REG_ZERO, d);
2579 store_reg_to_var_int(iptr->dst, d);
2582 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2583 M_CMPLT(REG_ZERO, s1, d);
2584 store_reg_to_var_int(iptr->dst, d);
2588 M_MOV(s1, REG_ITMP1);
2591 ICONST(d, iptr[1].val.i);
2593 if ((s3 >= 0) && (s3 <= 255)) {
2594 M_CMOVLE_IMM(s1, s3, d);
2597 ICONST(REG_ITMP2, s3);
2598 M_CMOVLE(s1, REG_ITMP2, d);
2600 store_reg_to_var_int(iptr->dst, d);
2605 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2609 #if defined(USE_THREADS)
2610 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2612 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2613 M_ALD(REG_ITMP3, REG_PV, a);
2614 M_JSR(REG_RA, REG_ITMP3);
2615 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8); /* delay slot */
2616 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2617 M_LDA(REG_PV, REG_RA, disp);
2620 var_to_reg_int(s1, src, REG_RESULT);
2621 M_INTMOVE(s1, REG_RESULT);
2622 goto nowperformreturn;
2624 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2627 #if defined(USE_THREADS)
2628 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2630 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2631 M_ALD(REG_ITMP3, REG_PV, a);
2632 M_JSR(REG_RA, REG_ITMP3);
2633 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8); /* delay slot */
2634 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2635 M_LDA(REG_PV, REG_RA, disp);
2638 var_to_reg_flt(s1, src, REG_FRESULT);
2640 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2641 M_TFLTMOVE(t, s1, REG_FRESULT);
2643 goto nowperformreturn;
2645 case ICMD_RETURN: /* ... ==> ... */
2647 #if defined(USE_THREADS)
2648 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2650 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2651 M_ALD(REG_ITMP3, REG_PV, a);
2652 M_JSR(REG_RA, REG_ITMP3);
2653 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8); /* delay slot */
2654 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2655 M_LDA(REG_PV, REG_RA, disp);
2663 p = parentargs_base;
2665 /* restore return address */
2667 if (!m->isleafmethod) {
2668 p--; M_LLD(REG_RA, REG_SP, 8 * p);
2671 /* restore saved registers */
2673 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2674 p--; M_LLD(rd->savintregs[i], REG_SP, 8 * p);
2676 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2677 p--; M_DLD(rd->savfltregs[i], REG_SP, 8 * p);
2680 /* call trace function */
2683 M_LDA (REG_SP, REG_SP, -24);
2684 M_LST(REG_RA, REG_SP, 0);
2685 M_LST(REG_RESULT, REG_SP, 8);
2686 M_DST(REG_FRESULT, REG_SP,16);
2687 a = dseg_addaddress(cd, m);
2688 M_ALD(rd->argintregs[0], REG_PV, a);
2689 M_MOV(REG_RESULT, rd->argintregs[1]);
2690 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2691 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
2692 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2693 M_ALD(REG_ITMP3, REG_PV, a);
2694 M_JSR (REG_RA, REG_ITMP3);
2696 M_DLD(REG_FRESULT, REG_SP,16);
2697 M_LLD(REG_RESULT, REG_SP, 8);
2698 M_LLD(REG_RA, REG_SP, 0);
2699 M_LDA (REG_SP, REG_SP, 24);
2704 /* deallocate stack */
2706 if (parentargs_base) {
2707 M_LDA(REG_SP, REG_SP, parentargs_base * 8);
2718 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2723 tptr = (void **) iptr->target;
2725 s4ptr = iptr->val.a;
2726 l = s4ptr[1]; /* low */
2727 i = s4ptr[2]; /* high */
2729 var_to_reg_int(s1, src, REG_ITMP1);
2731 {M_INTMOVE(s1, REG_ITMP1);}
2732 else if (l <= 32768) {
2733 M_IADD_IMM(s1, -l, REG_ITMP1);
2736 ICONST(REG_ITMP2, l);
2737 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2743 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
2744 M_BEQZ(REG_ITMP2, 0);
2745 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2746 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
2748 /* build jump table top down and use address of lowest entry */
2750 /* s4ptr += 3 + i; */
2754 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2755 dseg_addtarget(cd, (basicblock *) tptr[0]);
2760 /* length of dataseg after last dseg_addtarget is used by load */
2762 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2763 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2770 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2772 s4 i, /*l, */val, *s4ptr;
2775 tptr = (void **) iptr->target;
2777 s4ptr = iptr->val.a;
2778 /*l = s4ptr[0];*/ /* default */
2779 i = s4ptr[1]; /* count */
2781 MCODECHECK((i<<2)+8);
2782 var_to_reg_int(s1, src, REG_ITMP1);
2788 ICONST(REG_ITMP2, val);
2789 M_BEQ(s1, REG_ITMP2, 0);
2790 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2795 tptr = (void **) iptr->target;
2796 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2803 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2804 /* op1 = return type, val.a = function pointer*/
2808 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2809 /* op1 = return type, val.a = function pointer*/
2813 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2814 /* op1 = return type, val.a = function pointer*/
2818 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2819 /* op1 = arg count, val.a = method pointer */
2821 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2822 /* op1 = arg count, val.a = method pointer */
2824 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2825 /* op1 = arg count, val.a = method pointer */
2827 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2828 /* op1 = arg count, val.a = method pointer */
2835 MCODECHECK((s3 << 1) + 64);
2837 /* copy arguments to registers or stack location */
2839 for (; --s3 >= 0; src = src->prev) {
2840 if (src->varkind == ARGVAR)
2842 if (IS_INT_LNG_TYPE(src->type)) {
2843 if (s3 < INT_ARG_CNT) {
2844 s1 = rd->argintregs[s3];
2845 var_to_reg_int(d, src, s1);
2849 var_to_reg_int(d, src, REG_ITMP1);
2850 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
2854 if (s3 < FLT_ARG_CNT) {
2855 s1 = rd->argfltregs[s3];
2856 var_to_reg_flt(d, src, s1);
2857 M_TFLTMOVE(src->type, d, s1);
2860 var_to_reg_flt(d, src, REG_FTMP1);
2861 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
2867 switch (iptr->opc) {
2871 a = dseg_addaddress(cd, (void *) lm);
2872 d = iptr->op1; /* return type */
2874 M_ALD(REG_ITMP3, REG_PV, a); /* built-in-function pointer */
2875 M_JSR(REG_RA, REG_ITMP3);
2877 goto afteractualcall;
2879 case ICMD_INVOKESTATIC:
2880 case ICMD_INVOKESPECIAL:
2881 a = dseg_addaddress(cd, lm->stubroutine);
2884 M_ALD(REG_PV, REG_PV, a); /* method pointer in pv */
2887 case ICMD_INVOKEVIRTUAL:
2890 gen_nullptr_check(rd->argintregs[0]);
2891 M_ALD(REG_METHODPTR, rd->argintregs[0], OFFSET(java_objectheader, vftbl));
2892 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex);
2895 case ICMD_INVOKEINTERFACE:
2898 gen_nullptr_check(rd->argintregs[0]);
2899 M_ALD(REG_METHODPTR, rd->argintregs[0], OFFSET(java_objectheader, vftbl));
2900 M_ALD(REG_METHODPTR, REG_METHODPTR, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->class->index);
2901 M_ALD(REG_PV, REG_METHODPTR, sizeof(methodptr) * (lm - lm->class->methods));
2905 M_JSR(REG_RA, REG_PV);
2912 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2913 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
2915 s4 ml = -s1, mh = 0;
2916 while (ml < -32768) { ml += 65536; mh--; }
2918 M_IADD_IMM(REG_PV, ml, REG_PV);
2919 M_LADD(REG_PV, REG_RA, REG_PV);
2922 /* d contains return type */
2924 if (d != TYPE_VOID) {
2925 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2926 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2927 M_INTMOVE(REG_RESULT, s1);
2928 store_reg_to_var_int(iptr->dst, s1);
2931 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2932 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
2933 store_reg_to_var_flt(iptr->dst, s1);
2940 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2942 /* op1: 0 == array, 1 == class */
2943 /* val.a: (classinfo*) superclass */
2945 /* superclass is an interface:
2947 * return (sub != NULL) &&
2948 * (sub->vftbl->interfacetablelength > super->index) &&
2949 * (sub->vftbl->interfacetable[-super->index] != NULL);
2951 * superclass is a class:
2953 * return ((sub != NULL) && (0
2954 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2955 * super->vftbl->diffvall));
2959 classinfo *super = (classinfo*) iptr->val.a;
2961 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2962 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
2964 var_to_reg_int(s1, src, REG_ITMP1);
2965 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2967 M_MOV(s1, REG_ITMP1);
2971 if (iptr->op1) { /* class/interface */
2972 if (super->flags & ACC_INTERFACE) { /* interface */
2975 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2976 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2977 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
2978 M_BLEZ(REG_ITMP2, 3);
2980 M_ALD(REG_ITMP1, REG_ITMP1,
2981 OFFSET(vftbl_t, interfacetable[0]) -
2982 super->index * sizeof(methodptr*));
2983 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
2987 s2 = super->vftbl->diffval;
2990 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2991 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2992 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
2993 M_CMPULT_IMM(REG_ITMP1, s2 + 1, d);
2998 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2999 a = dseg_addaddress(cd, (void *) super->vftbl);
3000 M_ALD(REG_ITMP2, REG_PV, a);
3001 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3002 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3004 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3005 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3006 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3007 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3008 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3010 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3011 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3017 panic ("internal error: no inlined array instanceof");
3019 store_reg_to_var_int(iptr->dst, d);
3022 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3024 /* op1: 0 == array, 1 == class */
3025 /* val.a: (classinfo*) superclass */
3027 /* superclass is an interface:
3029 * OK if ((sub == NULL) ||
3030 * (sub->vftbl->interfacetablelength > super->index) &&
3031 * (sub->vftbl->interfacetable[-super->index] != NULL));
3033 * superclass is a class:
3035 * OK if ((sub == NULL) || (0
3036 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3037 * super->vftbl->diffvall));
3041 classinfo *super = (classinfo*) iptr->val.a;
3043 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3044 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3047 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3048 var_to_reg_int(s1, src, d);
3049 if (iptr->op1) { /* class/interface */
3050 if (super->flags & ACC_INTERFACE) { /* interface */
3053 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3054 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3055 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3056 M_BLEZ(REG_ITMP2, 0);
3057 codegen_addxcastrefs(cd, mcodeptr);
3059 M_ALD(REG_ITMP2, REG_ITMP1,
3060 OFFSET(vftbl_t, interfacetable[0]) -
3061 super->index * sizeof(methodptr*));
3062 M_BEQZ(REG_ITMP2, 0);
3063 codegen_addxcastrefs(cd, mcodeptr);
3069 s2 = super->vftbl->diffval;
3070 M_BEQZ(s1, 6 + (s2 != 0));
3072 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3073 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3074 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3076 M_BNEZ(REG_ITMP1, 0);
3079 M_CMPULT_IMM(REG_ITMP1, s2 + 1, REG_ITMP2);
3080 M_BEQZ(REG_ITMP2, 0);
3084 M_BEQZ(s1, 10 + (d == REG_ITMP3));
3086 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3087 a = dseg_addaddress(cd, (void *) super->vftbl);
3088 M_ALD(REG_ITMP2, REG_PV, a);
3089 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3090 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3092 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3093 if (d != REG_ITMP3) {
3094 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3095 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3096 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3097 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3099 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3101 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3102 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3103 M_ALD(REG_ITMP2, REG_PV, a);
3104 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3105 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3106 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3109 M_CMPULT(REG_ITMP2, REG_ITMP1, REG_ITMP2);
3110 M_BNEZ(REG_ITMP2, 0);
3112 codegen_addxcastrefs(cd, mcodeptr);
3117 panic ("internal error: no inlined array checkcast");
3120 store_reg_to_var_int(iptr->dst, d);
3123 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3125 var_to_reg_int(s1, src, REG_ITMP1);
3127 codegen_addxcheckarefs(cd, mcodeptr);
3131 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3133 M_BEQZ(REG_RESULT, 0);
3134 codegen_addxexceptionrefs(cd, mcodeptr);
3138 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3139 /* op1 = dimension, val.a = array descriptor */
3141 /* check for negative sizes and copy sizes to stack if necessary */
3143 MCODECHECK((iptr->op1 << 1) + 64);
3145 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3146 var_to_reg_int(s2, src, REG_ITMP1);
3148 codegen_addxcheckarefs(cd, mcodeptr);
3151 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3153 if (src->varkind != ARGVAR) {
3154 M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
3158 /* a0 = dimension count */
3160 ICONST(rd->argintregs[0], iptr->op1);
3162 /* a1 = arraydescriptor */
3164 a = dseg_addaddress(cd, iptr->val.a);
3165 M_ALD(rd->argintregs[1], REG_PV, a);
3167 /* a2 = pointer to dimensions = stack pointer */
3169 M_INTMOVE(REG_SP, rd->argintregs[2]);
3171 a = dseg_addaddress(cd, (void*) builtin_nmultianewarray);
3172 M_ALD(REG_ITMP3, REG_PV, a);
3173 M_JSR(REG_RA, REG_ITMP3);
3175 s1 = (int)((u1*) mcodeptr - cd->mcodebase);
3177 M_LDA (REG_PV, REG_RA, -s1);
3181 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3182 M_INTMOVE(REG_RESULT, s1);
3183 store_reg_to_var_int(iptr->dst, s1);
3187 throw_cacao_exception_exit(string_java_lang_InternalError,
3188 "Unknown ICMD %d", iptr->opc);
3191 } /* for instruction */
3193 /* copy values to interface registers */
3195 src = bptr->outstack;
3196 len = bptr->outdepth;
3200 if ((src->varkind != STACKVAR)) {
3202 if (IS_FLT_DBL_TYPE(s2)) {
3203 var_to_reg_flt(s1, src, REG_FTMP1);
3204 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3205 M_TFLTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3208 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3212 var_to_reg_int(s1, src, REG_ITMP1);
3213 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3214 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3217 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3223 } /* if (bptr -> flags >= BBREACHED) */
3224 } /* for basic block */
3227 /* generate bound check stubs */
3229 s4 *xcodeptr = NULL;
3232 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3233 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3235 (u1 *) mcodeptr - cd->mcodebase);
3239 M_MOV(bref->reg, REG_ITMP1);
3240 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3242 if (xcodeptr != NULL) {
3243 M_BR(xcodeptr - mcodeptr);
3247 xcodeptr = mcodeptr;
3249 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3250 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3252 M_MOV(REG_ITMP1, rd->argintregs[0]);
3253 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3254 M_ALD(REG_ITMP3, REG_PV, a);
3255 M_JSR(REG_RA, REG_ITMP3);
3257 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3259 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3260 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3262 a = dseg_addaddress(cd, asm_handle_exception);
3263 M_ALD(REG_ITMP3, REG_PV, a);
3269 /* generate negative array size check stubs */
3273 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3274 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3275 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3277 (u1 *) xcodeptr - cd->mcodebase - 4);
3281 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3283 (u1 *) mcodeptr - cd->mcodebase);
3287 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3289 if (xcodeptr != NULL) {
3290 M_BR(xcodeptr - mcodeptr);
3294 xcodeptr = mcodeptr;
3296 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3297 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3299 a = dseg_addaddress(cd, new_negativearraysizeexception);
3300 M_ALD(REG_ITMP3, REG_PV, a);
3301 M_JSR(REG_RA, REG_ITMP3);
3303 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3305 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3306 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3308 a = dseg_addaddress(cd, asm_handle_exception);
3309 M_ALD(REG_ITMP3, REG_PV, a);
3315 /* generate cast check stubs */
3319 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3320 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3321 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3323 (u1 *) xcodeptr - cd->mcodebase - 4);
3327 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3329 (u1 *) mcodeptr - cd->mcodebase);
3333 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3335 if (xcodeptr != NULL) {
3336 M_BR(xcodeptr - mcodeptr);
3340 xcodeptr = mcodeptr;
3342 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3343 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3345 a = dseg_addaddress(cd, new_classcastexception);
3346 M_ALD(REG_ITMP3, REG_PV, a);
3347 M_JSR(REG_RA, REG_ITMP3);
3349 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3351 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3352 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3354 a = dseg_addaddress(cd, asm_handle_exception);
3355 M_ALD(REG_ITMP3, REG_PV, a);
3361 /* generate exception check stubs */
3365 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3366 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3367 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3369 (u1 *) xcodeptr - cd->mcodebase - 4);
3373 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3375 (u1 *) mcodeptr - cd->mcodebase);
3379 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3381 if (xcodeptr != NULL) {
3382 M_BR(xcodeptr - mcodeptr);
3386 xcodeptr = mcodeptr;
3388 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3389 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3390 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3392 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3393 M_ALD(REG_ITMP3, REG_PV, a);
3394 M_JSR(REG_RA, REG_ITMP3);
3397 /* get the exceptionptr from the ptrprt and clear it */
3398 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3399 M_AST(REG_ZERO, REG_RESULT, 0);
3401 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3402 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3404 a = dseg_addaddress(cd, &_exceptionptr);
3405 M_ALD(REG_ITMP3, REG_PV, a);
3406 M_ALD(REG_ITMP1_XPTR, REG_ITMP3, 0);
3407 M_AST(REG_ZERO, REG_ITMP3, 0);
3410 a = dseg_addaddress(cd, asm_handle_exception);
3411 M_ALD(REG_ITMP3, REG_PV, a);
3417 /* generate null pointer check stubs */
3421 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3422 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3423 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3425 (u1 *) xcodeptr - cd->mcodebase - 4);
3429 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3431 (u1 *) mcodeptr - cd->mcodebase);
3435 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3437 if (xcodeptr != NULL) {
3438 M_BR(xcodeptr - mcodeptr);
3442 xcodeptr = mcodeptr;
3444 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3445 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3447 a = dseg_addaddress(cd, new_nullpointerexception);
3448 M_ALD(REG_ITMP3, REG_PV, a);
3449 M_JSR(REG_RA, REG_ITMP3);
3451 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3453 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3454 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3456 a = dseg_addaddress(cd, asm_handle_exception);
3457 M_ALD(REG_ITMP3, REG_PV, a);
3464 /* generate put/getstatic stub call code */
3471 for (cref = cd->clinitrefs; cref != NULL; cref = cref->next) {
3472 /* Get machine code which is patched back in later. The call is */
3473 /* 2 instruction words long. */
3474 xcodeptr = (s4 *) (cd->mcodebase + cref->branchpos);
3476 /* We need to split this, because an unaligned 8 byte read causes */
3478 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3480 /* patch in the call to call the following code (done at compile */
3483 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3484 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3486 M_BRS(tmpmcodeptr - (xcodeptr + 1));
3489 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3493 /* move class pointer into REG_ITMP1 */
3494 a = dseg_addaddress(cd, cref->class);
3495 M_ALD(REG_ITMP1, REG_PV, a);
3497 /* move machine code into REG_ITMP2 */
3498 a = dseg_adds8(cd, mcode);
3499 M_LLD(REG_ITMP2, REG_PV, a);
3501 a = dseg_addaddress(cd, asm_check_clinit);
3502 M_ALD(REG_ITMP3, REG_PV, a);
3509 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
3511 docacheflush((void*) m->entrypoint, ((u1*) mcodeptr - cd->mcodebase));
3515 /* function createcompilerstub *************************************************
3517 creates a stub routine which calls the compiler
3519 *******************************************************************************/
3521 #define COMPSTUB_SIZE 4
3523 u1 *createcompilerstub(methodinfo *m)
3525 u8 *s = CNEW(u8, COMPSTUB_SIZE); /* memory to hold the stub */
3526 s4 *mcodeptr = (s4 *) s; /* code generation pointer */
3528 /* code for the stub */
3529 M_ALD(REG_PV, REG_PV, 24); /* load pointer to the compiler */
3531 M_JSR(REG_ITMP1, REG_PV); /* jump to the compiler, return address
3532 in itmp1 is used as method pointer */
3535 s[2] = (u8) m; /* literals to be adressed */
3536 s[3] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3538 (void) docacheflush((void*) s, (char*) mcodeptr - (char*) s);
3540 #if defined(STATISTICS)
3542 count_cstub_len += COMPSTUB_SIZE * 8;
3549 /* function removecompilerstub *************************************************
3551 deletes a compilerstub from memory (simply by freeing it)
3553 *******************************************************************************/
3555 void removecompilerstub(u1 *stub)
3557 CFREE(stub, COMPSTUB_SIZE * 8);
3561 /* function: createnativestub **************************************************
3563 creates a stub routine which calls a native method
3565 *******************************************************************************/
3567 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3568 #define NATIVESTUB_STACK 2
3569 #define NATIVESTUB_THREAD_EXTRA 5
3571 #define NATIVESTUB_STACK 1
3572 #define NATIVESTUB_THREAD_EXTRA 1
3575 #define NATIVESTUB_SIZE (54 + 4 + NATIVESTUB_THREAD_EXTRA - 1)
3576 #define NATIVESTUB_STATIC_SIZE 5
3577 #define NATIVESTUB_VERBOSE_SIZE (50 + 17)
3578 #define NATIVESTUB_OFFSET 10
3581 u1 *createnativestub(functionptr f, methodinfo *m)
3583 u8 *s; /* memory to hold the stub */
3585 s4 *mcodeptr; /* code generation pointer */
3586 s4 stackframesize = 0; /* size of stackframe if needed */
3591 t_inlining_globals *id;
3594 /* mark start of dump memory area */
3596 dumpsize = dump_size();
3598 /* setup registers before using it */
3600 cd = DNEW(codegendata);
3601 rd = DNEW(registerdata);
3602 id = DNEW(t_inlining_globals);
3604 inlining_setup(m, id);
3605 reg_setup(m, rd, id);
3607 descriptor2types(m); /* set paramcount and paramtypes */
3609 stubsize = NATIVESTUB_SIZE; /* calculate nativestub size */
3611 if ((m->flags & ACC_STATIC) && !m->class->initialized)
3612 stubsize += NATIVESTUB_STATIC_SIZE;
3615 stubsize += NATIVESTUB_VERBOSE_SIZE;
3617 s = CNEW(u8, stubsize); /* memory to hold the stub */
3618 cs = s + NATIVESTUB_OFFSET;
3619 mcodeptr = (s4 *) (cs); /* code generation pointer */
3621 /* set some required varibles which are normally set by codegen_setup */
3622 cd->mcodebase = (u1 *) mcodeptr;
3623 cd->clinitrefs = NULL;
3625 *(cs-1) = (u8) f; /* address of native method */
3626 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3627 *(cs-2) = (u8) &builtin_get_exceptionptrptr;
3629 *(cs-2) = (u8) (&_exceptionptr); /* address of exceptionptr */
3631 *(cs-3) = (u8) asm_handle_nat_exception;/* addr of asm exception handler */
3632 *(cs-4) = (u8) (&env); /* addr of jni_environement */
3633 *(cs-5) = (u8) builtin_trace_args;
3635 *(cs-7) = (u8) builtin_displaymethodstop;
3636 *(cs-8) = (u8) m->class;
3637 *(cs-9) = (u8) asm_check_clinit;
3638 *(cs-10) = (u8) NULL; /* filled with machine code */
3640 M_LDA(REG_SP, REG_SP, -NATIVESTUB_STACK * 8); /* build up stackframe */
3641 M_LST(REG_RA, REG_SP, 0); /* store return address */
3643 /* if function is static, check for initialized */
3645 if (m->flags & ACC_STATIC && !m->class->initialized) {
3646 codegen_addclinitref(cd, mcodeptr, m->class);
3649 /* max. 50 instructions */
3654 M_LDA(REG_SP, REG_SP, -(18 * 8));
3655 M_AST(REG_RA, REG_SP, 1 * 8);
3657 /* save integer argument registers */
3658 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3659 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
3662 /* save and copy float arguments into integer registers */
3663 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3664 t = m->paramtypes[p];
3666 if (IS_FLT_DBL_TYPE(t)) {
3667 if (IS_2_WORD_TYPE(t)) {
3668 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3669 M_LLD(rd->argintregs[p], REG_SP, (10 + p) * 8);
3672 M_FST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3673 M_ILD(rd->argintregs[p], REG_SP, (10 + p) * 8);
3677 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3681 M_ALD(REG_ITMP1, REG_PV, -6 * 8); /* method address */
3682 M_AST(REG_ITMP1, REG_SP, 0);
3683 M_ALD(REG_ITMP3, REG_PV, -5 * 8); /* builtin_trace_args */
3684 M_JSR(REG_RA, REG_ITMP3);
3686 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3687 M_LDA(REG_PV, REG_RA, disp);
3689 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3690 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
3693 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3694 t = m->paramtypes[p];
3696 if (IS_FLT_DBL_TYPE(t)) {
3697 if (IS_2_WORD_TYPE(t)) {
3698 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3701 M_FLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3705 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3709 M_ALD(REG_RA, REG_SP, 1 * 8);
3710 M_LDA(REG_SP, REG_SP, 18 * 8);
3713 /* save argument registers on stack -- if we have to */
3714 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
3716 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3717 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3719 stackframesize = stackparamcnt + paramshiftcnt;
3721 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
3723 /* copy stack arguments into new stack frame -- if any */
3724 for (i = 0; i < stackparamcnt; i++) {
3725 M_LLD(REG_ITMP1, REG_SP, (stackparamcnt + 1 + i) * 8);
3726 M_LST(REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
3729 if (m->flags & ACC_STATIC) {
3730 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
3731 M_DST(rd->argfltregs[5], REG_SP, 1 * 8);
3733 M_LST(rd->argintregs[5], REG_SP, 1 * 8);
3736 if (IS_FLT_DBL_TYPE(m->paramtypes[4])) {
3737 M_DST(rd->argfltregs[4], REG_SP, 0 * 8);
3739 M_LST(rd->argintregs[4], REG_SP, 0 * 8);
3743 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
3744 M_DST(rd->argfltregs[5], REG_SP, 0 * 8);
3746 M_LST(rd->argintregs[5], REG_SP, 0 * 8);
3751 if (m->flags & ACC_STATIC) {
3752 M_MOV(rd->argintregs[5], rd->argintregs[7]);
3754 M_DMFC1(REG_ITMP1, rd->argfltregs[5]);
3755 M_DMTC1(REG_ITMP1, rd->argfltregs[7]);
3757 M_MOV(rd->argintregs[4], rd->argintregs[6]);
3759 M_DMFC1(REG_ITMP1, rd->argfltregs[4]);
3760 M_DMTC1(REG_ITMP1, rd->argfltregs[6]);
3762 M_MOV(rd->argintregs[3], rd->argintregs[5]);
3763 M_DMFC1(REG_ITMP1, rd->argfltregs[3]);
3765 M_MOV(rd->argintregs[2], rd->argintregs[4]);
3766 M_DMTC1(REG_ITMP1, rd->argfltregs[5]);
3768 M_MOV(rd->argintregs[1], rd->argintregs[3]);
3769 M_DMFC1(REG_ITMP1, rd->argfltregs[2]);
3771 M_MOV(rd->argintregs[0], rd->argintregs[2]);
3772 M_DMTC1(REG_ITMP1, rd->argfltregs[4]);
3774 M_DMFC1(REG_ITMP1, rd->argfltregs[1]);
3775 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
3777 M_DMFC1(REG_ITMP1, rd->argfltregs[0]);
3778 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
3780 M_ALD(rd->argintregs[1], REG_PV, -8 * 8);
3783 M_MOV(rd->argintregs[6], rd->argintregs[7]);
3785 M_DMFC1(REG_ITMP1, rd->argfltregs[6]);
3786 M_DMTC1(REG_ITMP1, rd->argfltregs[7]);
3788 M_MOV(rd->argintregs[5], rd->argintregs[6]);
3790 M_DMFC1(REG_ITMP1, rd->argfltregs[5]);
3791 M_DMTC1(REG_ITMP1, rd->argfltregs[6]);
3793 M_MOV(rd->argintregs[4], rd->argintregs[5]);
3794 M_DMFC1(REG_ITMP1, rd->argfltregs[4]);
3796 M_MOV(rd->argintregs[3], rd->argintregs[4]);
3797 M_DMTC1(REG_ITMP1, rd->argfltregs[5]);
3799 M_MOV(rd->argintregs[2], rd->argintregs[3]);
3800 M_DMFC1(REG_ITMP1, rd->argfltregs[3]);
3802 M_MOV(rd->argintregs[1], rd->argintregs[2]);
3803 M_DMTC1(REG_ITMP1, rd->argfltregs[4]);
3805 M_MOV(rd->argintregs[0], rd->argintregs[1]);
3806 M_DMFC1(REG_ITMP1, rd->argfltregs[2]);
3808 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
3810 M_DMFC1(REG_ITMP1, rd->argfltregs[1]);
3811 M_DMFC1(REG_ITMP2, rd->argfltregs[0]);
3813 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
3814 M_DMTC1(REG_ITMP2, rd->argfltregs[1]);
3817 M_ALD(rd->argintregs[0], REG_PV, -4 * 8); /* jni environement */
3818 M_ALD(REG_ITMP3, REG_PV, -1 * 8); /* load adress of native method */
3819 M_JSR(REG_RA, REG_ITMP3); /* call native method */
3820 M_NOP; /* delay slot */
3822 /* remove stackframe if there is one */
3823 if (stackframesize) {
3824 M_LDA(REG_SP, REG_SP, stackframesize * 8);
3827 /* 17 instructions */
3829 M_LDA(REG_SP, REG_SP, -(3 * 8));
3830 M_AST(REG_RA, REG_SP, 0 * 8);
3831 M_LST(REG_RESULT, REG_SP, 1 * 8);
3832 M_DST(REG_FRESULT, REG_SP, 2 * 8);
3833 M_ALD(rd->argintregs[0], REG_PV, -6 * 8);
3834 M_MOV(REG_RESULT, rd->argintregs[1]);
3835 M_DMFC1(REG_ITMP1, REG_FRESULT);
3836 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
3837 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
3838 M_ALD(REG_ITMP3, REG_PV, -7 * 8);/* builtin_displaymethodstop */
3839 M_JSR(REG_RA, REG_ITMP3);
3841 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3842 M_LDA(REG_PV, REG_RA, disp);
3843 M_ALD(REG_RA, REG_SP, 0 * 8);
3844 M_LLD(REG_RESULT, REG_SP, 1 * 8);
3845 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
3846 M_LDA(REG_SP, REG_SP, 3 * 8);
3849 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3850 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* builtin_get_exceptionptrptr */
3851 M_JSR(REG_RA, REG_ITMP3);
3854 if (IS_FLT_DBL_TYPE(m->returntype)) {
3855 M_DST(REG_FRESULT, REG_SP, 1 * 8);
3858 M_AST(REG_RESULT, REG_SP, 1 * 8);
3861 M_MOV(REG_RESULT, REG_ITMP3);
3863 if (IS_FLT_DBL_TYPE(m->returntype)) {
3864 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
3867 M_ALD(REG_RESULT, REG_SP, 1 * 8);
3870 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* get address of exceptionptr */
3873 M_LLD(REG_RA, REG_SP, 0); /* load return address */
3874 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
3876 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
3877 M_LDA(REG_SP, REG_SP, NATIVESTUB_STACK * 8);/*remove stackframe, delay slot*/
3879 M_RET(REG_RA); /* return to caller */
3880 M_NOP; /* delay slot */
3882 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
3883 M_ALD(REG_ITMP3, REG_PV, -3 * 8); /* load asm exception handler address */
3885 M_JMP(REG_ITMP3); /* jump to asm exception handler */
3886 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
3889 /* generate static stub call code */
3896 /* there can only be one clinit ref entry */
3897 cref = cd->clinitrefs;
3900 /* Get machine code which is patched back in later. The call is */
3901 /* 2 instruction words long. */
3902 xcodeptr = (s4 *) (cd->mcodebase + cref->branchpos);
3904 /* We need to split this, because an unaligned 8 byte read causes */
3906 *(cs-10) = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3908 /* patch in the call to call the following code (done at compile */
3911 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3912 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3914 M_BRS(tmpmcodeptr - (xcodeptr + 1));
3917 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3919 /* move class pointer into REG_ITMP1 */
3920 M_ALD(REG_ITMP1, REG_PV, -8 * 8); /* class */
3922 /* move machine code into REG_ITMP2 */
3923 M_LLD(REG_ITMP2, REG_PV, -10 * 8); /* machine code */
3925 M_ALD(REG_ITMP3, REG_PV, -9 * 8); /* asm_check_clinit */
3931 (void) docacheflush((void*) cs, (char*) mcodeptr - (char*) cs);
3934 dolog_plain("stubsize: %d (for %d params)\n",
3935 (int) (mcodeptr - (s4*) s), m->paramcount);
3938 #if defined(STATISTICS)
3940 count_nstub_len += NATIVESTUB_SIZE * 8;
3943 /* release dump area */
3945 dump_release(dumpsize);
3947 return (u1 *) (s + NATIVESTUB_OFFSET);
3951 /* function: removenativestub **************************************************
3953 removes a previously created native-stub from memory
3955 *******************************************************************************/
3957 void removenativestub(u1 *stub)
3959 CFREE((u8 *) stub - NATIVESTUB_OFFSET, NATIVESTUB_SIZE * 8);
3963 void docacheflush(u1 *p, long bytelen)
3965 u1 *e = p + bytelen;
3966 long psize = sysconf(_SC_PAGESIZE);
3967 p -= (long) p & (psize-1);
3968 e += psize - ((((long) e - 1) & (psize-1)) + 1);
3970 mprotect(p, bytelen, PROT_READ|PROT_WRITE|PROT_EXEC);
3975 * These are local overrides for various environment variables in Emacs.
3976 * Please do not remove this and leave it at the end of the file, where
3977 * Emacs will automagically detect them.
3978 * ---------------------------------------------------------------------
3981 * indent-tabs-mode: t