1 /* src/vm/jit/alpha/codegen.c - machine code generator for Alpha
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
30 Changes: Joseph Wenninger
33 $Id: codegen.c 2496 2005-05-23 08:06:06Z twisti $
42 #include "cacao/cacao.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
45 #include "vm/global.h"
46 #include "vm/loader.h"
47 #include "vm/stringlocal.h"
48 #include "vm/tables.h"
49 #include "vm/jit/asmpart.h"
50 #include "vm/jit/jit.h"
52 #include "vm/jit/lsra.h"
54 #include "vm/jit/parse.h"
55 #include "vm/jit/patcher.h"
56 #include "vm/jit/reg.h"
57 #include "vm/jit/alpha/arch.h"
58 #include "vm/jit/alpha/codegen.h"
59 #include "vm/jit/alpha/types.h"
60 #include "vm/jit/alpha/asmoffsets.h"
63 /* *****************************************************************************
65 Datatypes and Register Allocations:
66 -----------------------------------
68 On 64-bit-machines (like the Alpha) all operands are stored in the
69 registers in a 64-bit form, even when the correspondig JavaVM operands
70 only need 32 bits. This is done by a canonical representation:
72 32-bit integers are allways stored as sign-extended 64-bit values (this
73 approach is directly supported by the Alpha architecture and is very easy
76 32-bit-floats are stored in a 64-bit doubleprecision register by simply
77 expanding the exponent and mantissa with zeroes. (also supported by the
83 The calling conventions and the layout of the stack is explained in detail
84 in the documention file: calling.doc
86 *******************************************************************************/
89 /* register descripton - array ************************************************/
91 /* #define REG_RES 0 reserved register for OS or code generator */
92 /* #define REG_RET 1 return value register */
93 /* #define REG_EXC 2 exception value register (only old jit) */
94 /* #define REG_SAV 3 (callee) saved register */
95 /* #define REG_TMP 4 scratch temporary register (caller saved) */
96 /* #define REG_ARG 5 argument register (caller saved) */
98 /* #define REG_END -1 last entry in tables */
100 int nregdescint[] = {
101 REG_RET, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
102 REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
103 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
104 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
107 /* for use of reserved registers, see comment above */
109 int nregdescfloat[] = {
110 REG_RET, REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
111 REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
112 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
113 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES,
117 /* Include independent code generation stuff -- include after register */
118 /* descriptions to avoid extern definitions. */
120 #include "vm/jit/codegen.inc"
121 #include "vm/jit/reg.inc"
123 #include "vm/jit/lsra.inc"
127 /* NullPointerException handlers and exception handling initialisation */
129 typedef struct sigctx_struct {
130 long sc_onstack; /* sigstack state to restore */
131 long sc_mask; /* signal mask to restore */
132 long sc_pc; /* pc at time of signal */
133 long sc_ps; /* psl to retore */
134 long sc_regs[32]; /* processor regs 0 to 31 */
135 long sc_ownedfp; /* fp has been used */
136 long sc_fpregs[32]; /* fp regs 0 to 31 */
137 unsigned long sc_fpcr; /* floating point control register */
138 unsigned long sc_fp_control; /* software fpcr */
140 unsigned long sc_reserved1, sc_reserved2;
141 unsigned long sc_ssize;
143 unsigned long sc_traparg_a0;
144 unsigned long sc_traparg_a1;
145 unsigned long sc_traparg_a2;
146 unsigned long sc_fp_trap_pc;
147 unsigned long sc_fp_trigger_sum;
148 unsigned long sc_fp_trigger_inst;
149 unsigned long sc_retcode[2];
153 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
154 void thread_restartcriticalsection(ucontext_t *uc)
157 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.sc_pc)) != NULL)
158 uc->uc_mcontext.sc_pc = (u8) critical;
163 /* NullPointerException signal handler for hardware null pointer check */
165 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
167 struct sigaction act;
172 ucontext_t *_uc = (ucontext_t *) _p;
173 mcontext_t *sigctx = &_uc->uc_mcontext;
175 instr = *((s4 *) (sigctx->sc_pc));
176 faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f];
178 if (faultaddr == 0) {
179 /* Reset signal handler - necessary for SysV, does no harm for BSD */
180 act.sa_sigaction = catch_NullPointerException;
181 act.sa_flags = SA_SIGINFO;
182 sigaction(sig, &act, NULL);
185 sigaddset(&nsig, sig);
186 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
188 sigctx->sc_regs[REG_ITMP1_XPTR] = (u8) string_java_lang_NullPointerException;
189 sigctx->sc_regs[REG_ITMP2_XPC] = sigctx->sc_pc;
190 sigctx->sc_pc = (u8) asm_throw_and_handle_exception;
194 faultaddr += (long) ((instr << 16) >> 16);
196 throw_cacao_exception_exit(string_java_lang_InternalError,
197 "faulting address: 0x%016lx\n", faultaddr);
204 void init_exceptions(void)
209 /* Linux on Digital Alpha needs an initialisation of the ieee floating point
210 control for IEEE compliant arithmetic (option -mieee of GCC). Under
211 Digital Unix this is done automatically.
216 extern unsigned long ieee_get_fp_control();
217 extern void ieee_set_fp_control(unsigned long fp_control);
219 void init_exceptions(void)
221 struct sigaction act;
223 /* initialize floating point control */
225 ieee_set_fp_control(ieee_get_fp_control()
226 & ~IEEE_TRAP_ENABLE_INV
227 & ~IEEE_TRAP_ENABLE_DZE
228 /* & ~IEEE_TRAP_ENABLE_UNF we dont want underflow */
229 & ~IEEE_TRAP_ENABLE_OVF);
232 /* install signal handlers we need to convert to exceptions */
235 act.sa_sigaction = catch_NullPointerException;
236 act.sa_flags = SA_SIGINFO;
239 sigaction(SIGSEGV, &act, NULL);
243 sigaction(SIGBUS, &act, NULL);
249 /* function gen_mcode **********************************************************
251 generates machine code
253 *******************************************************************************/
255 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
257 s4 len, s1, s2, s3, d;
271 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
273 /* space to save used callee saved registers */
275 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
276 savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
278 parentargs_base = rd->maxmemuse + savedregs_num;
280 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
282 if (checksync && (m->flags & ACC_SYNCHRONIZED))
287 /* create method header */
289 (void) dseg_addaddress(cd, m); /* MethodPointer */
290 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
292 #if defined(USE_THREADS)
294 /* IsSync contains the offset relative to the stack pointer for the
295 argument of monitor_exit used in the exception handler. Since the
296 offset could be zero and give a wrong meaning of the flag it is
300 if (checksync && (m->flags & ACC_SYNCHRONIZED))
301 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8); /* IsSync */
306 (void) dseg_adds4(cd, 0); /* IsSync */
308 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
309 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse);/* IntSave */
310 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse);/* FltSave */
312 dseg_addlinenumbertablesize(cd);
314 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
316 /* create exception table */
318 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
319 dseg_addtarget(cd, ex->start);
320 dseg_addtarget(cd, ex->end);
321 dseg_addtarget(cd, ex->handler);
322 (void) dseg_addaddress(cd, ex->catchtype.cls);
325 /* initialize mcode variables */
327 mcodeptr = (s4 *) cd->mcodebase;
328 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
329 MCODECHECK(128 + m->paramcount);
331 /* create stack frame (if necessary) */
333 if (parentargs_base) {
334 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
337 /* save return address and used callee saved registers */
340 if (!m->isleafmethod) {
341 p--; M_AST(REG_RA, REG_SP, p * 8);
343 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
344 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
346 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
347 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
350 /* copy argument registers to stack and call trace function with pointer
351 to arguments on stack.
356 M_LDA(REG_SP, REG_SP, -((INT_ARG_CNT + FLT_ARG_CNT + 2) * 8));
357 M_AST(REG_RA, REG_SP, 1 * 8);
359 /* save integer argument registers */
360 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
361 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
364 /* save and copy float arguments into integer registers */
365 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
366 t = m->paramtypes[p];
368 if (IS_FLT_DBL_TYPE(t)) {
369 if (IS_2_WORD_TYPE(t)) {
370 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
373 M_FST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
376 M_LLD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
379 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
383 p = dseg_addaddress(cd, m);
384 M_ALD(REG_ITMP1, REG_PV, p);
385 M_AST(REG_ITMP1, REG_SP, 0 * 8);
386 p = dseg_addaddress(cd, (void *) builtin_trace_args);
387 M_ALD(REG_PV, REG_PV, p);
388 M_JSR(REG_RA, REG_PV);
389 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
390 M_LDA(REG_PV, REG_RA, disp);
391 M_ALD(REG_RA, REG_SP, 1 * 8);
393 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
394 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
397 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
398 t = m->paramtypes[p];
400 if (IS_FLT_DBL_TYPE(t)) {
401 if (IS_2_WORD_TYPE(t)) {
402 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
405 M_FLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
409 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
413 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT + 2) * 8);
416 /* take arguments out of register or stack frame */
418 for (p = 0, l = 0; p < m->paramcount; p++) {
419 t = m->paramtypes[p];
420 var = &(rd->locals[l][t]);
422 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
426 if (IS_INT_LNG_TYPE(t)) { /* integer args */
427 if (p < INT_ARG_CNT) { /* register arguments */
428 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
429 M_INTMOVE(rd->argintregs[p], var->regoff);
430 } else { /* reg arg -> spilled */
431 M_LST(rd->argintregs[p], REG_SP, 8 * var->regoff);
434 } else { /* stack arguments */
435 pa = p - INT_ARG_CNT;
436 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
437 M_LLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
439 } else { /* stack arg -> spilled */
440 /* M_LLD(REG_ITMP1, REG_SP, 8 * (parentargs_base + pa)); */
441 /* M_LST(REG_ITMP1, REG_SP, 8 * var->regoff); */
442 var->regoff = parentargs_base + pa;
446 } else { /* floating args */
447 if (p < FLT_ARG_CNT) { /* register arguments */
448 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
449 M_FLTMOVE(rd->argfltregs[p], var->regoff);
451 } else { /* reg arg -> spilled */
452 M_DST(rd->argfltregs[p], REG_SP, 8 * var->regoff);
455 } else { /* stack arguments */
456 pa = p - FLT_ARG_CNT;
457 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
458 M_DLD(var->regoff, REG_SP, 8 * (parentargs_base + pa) );
460 } else { /* stack-arg -> spilled */
461 /* M_DLD(REG_FTMP1, REG_SP, 8 * (parentargs_base + pa)); */
462 /* M_DST(REG_FTMP1, REG_SP, 8 * var->regoff); */
463 var->regoff = parentargs_base + pa;
469 /* call monitorenter function */
471 #if defined(USE_THREADS)
472 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
475 if (m->flags & ACC_STATIC) {
476 p = dseg_addaddress(cd, m->class);
477 M_ALD(REG_ITMP1, REG_PV, p);
478 M_AST(REG_ITMP1, REG_SP, rd->maxmemuse * 8);
479 M_INTMOVE(REG_ITMP1, rd->argintregs[0]);
480 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
481 M_ALD(REG_PV, REG_PV, p);
482 M_JSR(REG_RA, REG_PV);
483 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
484 M_LDA(REG_PV, REG_RA, disp);
487 M_BEQZ(rd->argintregs[0], 0);
488 codegen_addxnullrefs(cd, mcodeptr);
489 M_AST(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
490 p = dseg_addaddress(cd, BUILTIN_monitorenter);
491 M_ALD(REG_PV, REG_PV, p);
492 M_JSR(REG_RA, REG_PV);
493 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
494 M_LDA(REG_PV, REG_RA, disp);
501 /* end of header generation */
503 /* walk through all basic blocks */
504 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
506 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
508 if (bptr->flags >= BBREACHED) {
510 /* branch resolving */
514 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
515 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
516 brefs->branchpos, bptr->mpc);
520 /* copy interface registers to their destination */
527 while (src != NULL) {
529 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
530 /* d = reg_of_var(m, src, REG_ITMP1); */
531 if (!(src->flags & INMEMORY))
535 M_INTMOVE(REG_ITMP1, d);
536 store_reg_to_var_int(src, d);
542 while (src != NULL) {
544 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
545 d = reg_of_var(rd, src, REG_ITMP1);
546 M_INTMOVE(REG_ITMP1, d);
547 store_reg_to_var_int(src, d);
550 d = reg_of_var(rd, src, REG_IFTMP);
551 if ((src->varkind != STACKVAR)) {
553 if (IS_FLT_DBL_TYPE(s2)) {
554 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
555 s1 = rd->interfaces[len][s2].regoff;
559 M_DLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
561 store_reg_to_var_flt(src, d);
564 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
565 s1 = rd->interfaces[len][s2].regoff;
569 M_LLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
571 store_reg_to_var_int(src, d);
581 /* walk through all instructions */
586 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
587 if (iptr->line != currentline) {
588 dseg_addlinenumber(cd, iptr->line, mcodeptr);
589 currentline = iptr->line;
592 MCODECHECK(64); /* an instruction usually needs < 64 words */
595 case ICMD_INLINE_START:
596 case ICMD_INLINE_END:
599 case ICMD_NOP: /* ... ==> ... */
602 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
604 var_to_reg_int(s1, src, REG_ITMP1);
606 codegen_addxnullrefs(cd, mcodeptr);
609 /* constant operations ************************************************/
611 case ICMD_ICONST: /* ... ==> ..., constant */
612 /* op1 = 0, val.i = constant */
614 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
615 ICONST(d, iptr->val.i);
616 store_reg_to_var_int(iptr->dst, d);
619 case ICMD_LCONST: /* ... ==> ..., constant */
620 /* op1 = 0, val.l = constant */
622 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
623 LCONST(d, iptr->val.l);
624 store_reg_to_var_int(iptr->dst, d);
627 case ICMD_FCONST: /* ... ==> ..., constant */
628 /* op1 = 0, val.f = constant */
630 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
631 a = dseg_addfloat(cd, iptr->val.f);
633 store_reg_to_var_flt(iptr->dst, d);
636 case ICMD_DCONST: /* ... ==> ..., constant */
637 /* op1 = 0, val.d = constant */
639 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
640 a = dseg_adddouble(cd, iptr->val.d);
642 store_reg_to_var_flt(iptr->dst, d);
645 case ICMD_ACONST: /* ... ==> ..., constant */
646 /* op1 = 0, val.a = constant */
648 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
650 a = dseg_addaddress(cd, iptr->val.a);
653 M_INTMOVE(REG_ZERO, d);
655 store_reg_to_var_int(iptr->dst, d);
659 /* load/store operations **********************************************/
661 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
662 case ICMD_LLOAD: /* op1 = local variable */
665 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
666 if ((iptr->dst->varkind == LOCALVAR) &&
667 (iptr->dst->varnum == iptr->op1))
669 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
670 if (var->flags & INMEMORY)
671 M_LLD(d, REG_SP, 8 * var->regoff);
673 {M_INTMOVE(var->regoff,d);}
674 store_reg_to_var_int(iptr->dst, d);
677 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
678 case ICMD_DLOAD: /* op1 = local variable */
680 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
681 if ((iptr->dst->varkind == LOCALVAR) &&
682 (iptr->dst->varnum == iptr->op1))
684 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
685 if (var->flags & INMEMORY)
686 M_DLD(d, REG_SP, 8 * var->regoff);
688 {M_FLTMOVE(var->regoff,d);}
689 store_reg_to_var_flt(iptr->dst, d);
693 case ICMD_ISTORE: /* ..., value ==> ... */
694 case ICMD_LSTORE: /* op1 = local variable */
697 if ((src->varkind == LOCALVAR) &&
698 (src->varnum == iptr->op1))
700 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
701 if (var->flags & INMEMORY) {
702 var_to_reg_int(s1, src, REG_ITMP1);
703 M_LST(s1, REG_SP, 8 * var->regoff);
706 var_to_reg_int(s1, src, var->regoff);
707 M_INTMOVE(s1, var->regoff);
711 case ICMD_FSTORE: /* ..., value ==> ... */
712 case ICMD_DSTORE: /* op1 = local variable */
714 if ((src->varkind == LOCALVAR) &&
715 (src->varnum == iptr->op1))
717 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
718 if (var->flags & INMEMORY) {
719 var_to_reg_flt(s1, src, REG_FTMP1);
720 M_DST(s1, REG_SP, 8 * var->regoff);
723 var_to_reg_flt(s1, src, var->regoff);
724 M_FLTMOVE(s1, var->regoff);
729 /* pop/dup/swap operations ********************************************/
731 /* attention: double and longs are only one entry in CACAO ICMDs */
733 case ICMD_POP: /* ..., value ==> ... */
734 case ICMD_POP2: /* ..., value, value ==> ... */
737 case ICMD_DUP: /* ..., a ==> ..., a, a */
738 M_COPY(src, iptr->dst);
741 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
743 M_COPY(src, iptr->dst);
744 M_COPY(src->prev, iptr->dst->prev);
745 M_COPY(iptr->dst, iptr->dst->prev->prev);
748 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
750 M_COPY(src, iptr->dst);
751 M_COPY(src->prev, iptr->dst->prev);
752 M_COPY(src->prev->prev, iptr->dst->prev->prev);
753 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
756 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
758 M_COPY(src, iptr->dst);
759 M_COPY(src->prev, iptr->dst->prev);
762 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
764 M_COPY(src, iptr->dst);
765 M_COPY(src->prev, iptr->dst->prev);
766 M_COPY(src->prev->prev, iptr->dst->prev->prev);
767 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
768 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
771 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
773 M_COPY(src, iptr->dst);
774 M_COPY(src->prev, iptr->dst->prev);
775 M_COPY(src->prev->prev, iptr->dst->prev->prev);
776 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
777 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
778 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
781 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
783 M_COPY(src, iptr->dst->prev);
784 M_COPY(src->prev, iptr->dst);
788 /* integer operations *************************************************/
790 case ICMD_INEG: /* ..., value ==> ..., - value */
792 var_to_reg_int(s1, src, REG_ITMP1);
793 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
794 M_ISUB(REG_ZERO, s1, d);
795 store_reg_to_var_int(iptr->dst, d);
798 case ICMD_LNEG: /* ..., value ==> ..., - value */
800 var_to_reg_int(s1, src, REG_ITMP1);
801 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
802 M_LSUB(REG_ZERO, s1, d);
803 store_reg_to_var_int(iptr->dst, d);
806 case ICMD_I2L: /* ..., value ==> ..., value */
808 var_to_reg_int(s1, src, REG_ITMP1);
809 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
811 store_reg_to_var_int(iptr->dst, d);
814 case ICMD_L2I: /* ..., value ==> ..., value */
816 var_to_reg_int(s1, src, REG_ITMP1);
817 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
818 M_IADD(s1, REG_ZERO, d );
819 store_reg_to_var_int(iptr->dst, d);
822 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
824 var_to_reg_int(s1, src, REG_ITMP1);
825 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
826 if (has_ext_instr_set) {
830 M_SLL_IMM(s1, 56, d);
831 M_SRA_IMM( d, 56, d);
833 store_reg_to_var_int(iptr->dst, d);
836 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
838 var_to_reg_int(s1, src, REG_ITMP1);
839 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
841 store_reg_to_var_int(iptr->dst, d);
844 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
846 var_to_reg_int(s1, src, REG_ITMP1);
847 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
848 if (has_ext_instr_set) {
852 M_SLL_IMM(s1, 48, d);
853 M_SRA_IMM( d, 48, d);
855 store_reg_to_var_int(iptr->dst, d);
859 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
861 var_to_reg_int(s1, src->prev, REG_ITMP1);
862 var_to_reg_int(s2, src, REG_ITMP2);
863 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
865 store_reg_to_var_int(iptr->dst, d);
868 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
869 /* val.i = constant */
871 var_to_reg_int(s1, src, REG_ITMP1);
872 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
873 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
874 M_IADD_IMM(s1, iptr->val.i, d);
877 ICONST(REG_ITMP2, iptr->val.i);
878 M_IADD(s1, REG_ITMP2, d);
880 store_reg_to_var_int(iptr->dst, d);
883 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
885 var_to_reg_int(s1, src->prev, REG_ITMP1);
886 var_to_reg_int(s2, src, REG_ITMP2);
887 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
889 store_reg_to_var_int(iptr->dst, d);
892 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
893 /* val.l = constant */
895 var_to_reg_int(s1, src, REG_ITMP1);
896 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
897 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
898 M_LADD_IMM(s1, iptr->val.l, d);
901 LCONST(REG_ITMP2, iptr->val.l);
902 M_LADD(s1, REG_ITMP2, d);
904 store_reg_to_var_int(iptr->dst, d);
907 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
909 var_to_reg_int(s1, src->prev, REG_ITMP1);
910 var_to_reg_int(s2, src, REG_ITMP2);
911 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
913 store_reg_to_var_int(iptr->dst, d);
916 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
917 /* val.i = constant */
919 var_to_reg_int(s1, src, REG_ITMP1);
920 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
921 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
922 M_ISUB_IMM(s1, iptr->val.i, d);
925 ICONST(REG_ITMP2, iptr->val.i);
926 M_ISUB(s1, REG_ITMP2, d);
928 store_reg_to_var_int(iptr->dst, d);
931 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
933 var_to_reg_int(s1, src->prev, REG_ITMP1);
934 var_to_reg_int(s2, src, REG_ITMP2);
935 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
937 store_reg_to_var_int(iptr->dst, d);
940 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
941 /* val.l = constant */
943 var_to_reg_int(s1, src, REG_ITMP1);
944 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
945 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
946 M_LSUB_IMM(s1, iptr->val.l, d);
949 LCONST(REG_ITMP2, iptr->val.l);
950 M_LSUB(s1, REG_ITMP2, d);
952 store_reg_to_var_int(iptr->dst, d);
955 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
957 var_to_reg_int(s1, src->prev, REG_ITMP1);
958 var_to_reg_int(s2, src, REG_ITMP2);
959 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
961 store_reg_to_var_int(iptr->dst, d);
964 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
965 /* val.i = constant */
967 var_to_reg_int(s1, src, REG_ITMP1);
968 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
969 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
970 M_IMUL_IMM(s1, iptr->val.i, d);
973 ICONST(REG_ITMP2, iptr->val.i);
974 M_IMUL(s1, REG_ITMP2, d);
976 store_reg_to_var_int(iptr->dst, d);
979 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
981 var_to_reg_int(s1, src->prev, REG_ITMP1);
982 var_to_reg_int(s2, src, REG_ITMP2);
983 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
985 store_reg_to_var_int(iptr->dst, d);
988 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
989 /* val.l = constant */
991 var_to_reg_int(s1, src, REG_ITMP1);
992 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
993 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
994 M_LMUL_IMM(s1, iptr->val.l, d);
997 LCONST(REG_ITMP2, iptr->val.l);
998 M_LMUL(s1, REG_ITMP2, d);
1000 store_reg_to_var_int(iptr->dst, d);
1003 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1004 case ICMD_LDIVPOW2: /* val.i = constant */
1006 var_to_reg_int(s1, src, REG_ITMP1);
1007 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1008 if (iptr->val.i <= 15) {
1009 M_LDA(REG_ITMP2, s1, (1 << iptr->val.i) -1);
1010 M_CMOVGE(s1, s1, REG_ITMP2);
1013 M_SRA_IMM(s1, 63, REG_ITMP2);
1014 M_SRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1015 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1017 M_SRA_IMM(REG_ITMP2, iptr->val.i, d);
1018 store_reg_to_var_int(iptr->dst, d);
1021 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1023 var_to_reg_int(s1, src->prev, REG_ITMP1);
1024 var_to_reg_int(s2, src, REG_ITMP2);
1025 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1026 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1027 M_SLL(s1, REG_ITMP3, d);
1028 M_IADD(d, REG_ZERO, d);
1029 store_reg_to_var_int(iptr->dst, d);
1032 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1033 /* val.i = constant */
1035 var_to_reg_int(s1, src, REG_ITMP1);
1036 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1037 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1038 M_IADD(d, REG_ZERO, d);
1039 store_reg_to_var_int(iptr->dst, d);
1042 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1044 var_to_reg_int(s1, src->prev, REG_ITMP1);
1045 var_to_reg_int(s2, src, REG_ITMP2);
1046 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1047 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1048 M_SRA(s1, REG_ITMP3, d);
1049 store_reg_to_var_int(iptr->dst, d);
1052 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1053 /* val.i = constant */
1055 var_to_reg_int(s1, src, REG_ITMP1);
1056 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1057 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1058 store_reg_to_var_int(iptr->dst, d);
1061 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1063 var_to_reg_int(s1, src->prev, REG_ITMP1);
1064 var_to_reg_int(s2, src, REG_ITMP2);
1065 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1066 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1068 M_SRL(d, REG_ITMP2, d);
1069 M_IADD(d, REG_ZERO, d);
1070 store_reg_to_var_int(iptr->dst, d);
1073 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1074 /* val.i = constant */
1076 var_to_reg_int(s1, src, REG_ITMP1);
1077 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1079 M_SRL_IMM(d, iptr->val.i & 0x1f, d);
1080 M_IADD(d, REG_ZERO, d);
1081 store_reg_to_var_int(iptr->dst, d);
1084 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1086 var_to_reg_int(s1, src->prev, REG_ITMP1);
1087 var_to_reg_int(s2, src, REG_ITMP2);
1088 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1090 store_reg_to_var_int(iptr->dst, d);
1093 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1094 /* val.i = constant */
1096 var_to_reg_int(s1, src, REG_ITMP1);
1097 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1098 M_SLL_IMM(s1, iptr->val.i & 0x3f, d);
1099 store_reg_to_var_int(iptr->dst, d);
1102 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1104 var_to_reg_int(s1, src->prev, REG_ITMP1);
1105 var_to_reg_int(s2, src, REG_ITMP2);
1106 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1108 store_reg_to_var_int(iptr->dst, d);
1111 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1112 /* val.i = constant */
1114 var_to_reg_int(s1, src, REG_ITMP1);
1115 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1116 M_SRA_IMM(s1, iptr->val.i & 0x3f, d);
1117 store_reg_to_var_int(iptr->dst, d);
1120 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1122 var_to_reg_int(s1, src->prev, REG_ITMP1);
1123 var_to_reg_int(s2, src, REG_ITMP2);
1124 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1126 store_reg_to_var_int(iptr->dst, d);
1129 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1130 /* val.i = constant */
1132 var_to_reg_int(s1, src, REG_ITMP1);
1133 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1134 M_SRL_IMM(s1, iptr->val.i & 0x3f, d);
1135 store_reg_to_var_int(iptr->dst, d);
1138 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1141 var_to_reg_int(s1, src->prev, REG_ITMP1);
1142 var_to_reg_int(s2, src, REG_ITMP2);
1143 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1145 store_reg_to_var_int(iptr->dst, d);
1148 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1149 /* val.i = constant */
1151 var_to_reg_int(s1, src, REG_ITMP1);
1152 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1153 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1154 M_AND_IMM(s1, iptr->val.i, d);
1156 else if (iptr->val.i == 0xffff) {
1159 else if (iptr->val.i == 0xffffff) {
1160 M_ZAPNOT_IMM(s1, 0x07, d);
1163 ICONST(REG_ITMP2, iptr->val.i);
1164 M_AND(s1, REG_ITMP2, d);
1166 store_reg_to_var_int(iptr->dst, d);
1169 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1170 /* val.i = constant */
1172 var_to_reg_int(s1, src, REG_ITMP1);
1173 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1175 M_MOV(s1, REG_ITMP1);
1178 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1179 M_AND_IMM(s1, iptr->val.i, d);
1181 M_ISUB(REG_ZERO, s1, d);
1182 M_AND_IMM(d, iptr->val.i, d);
1184 else if (iptr->val.i == 0xffff) {
1187 M_ISUB(REG_ZERO, s1, d);
1190 else if (iptr->val.i == 0xffffff) {
1191 M_ZAPNOT_IMM(s1, 0x07, d);
1193 M_ISUB(REG_ZERO, s1, d);
1194 M_ZAPNOT_IMM(d, 0x07, d);
1197 ICONST(REG_ITMP2, iptr->val.i);
1198 M_AND(s1, REG_ITMP2, d);
1200 M_ISUB(REG_ZERO, s1, d);
1201 M_AND(d, REG_ITMP2, d);
1203 M_ISUB(REG_ZERO, d, d);
1204 store_reg_to_var_int(iptr->dst, d);
1207 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1208 /* val.l = constant */
1210 var_to_reg_int(s1, src, REG_ITMP1);
1211 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1212 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1213 M_AND_IMM(s1, iptr->val.l, d);
1215 else if (iptr->val.l == 0xffffL) {
1218 else if (iptr->val.l == 0xffffffL) {
1219 M_ZAPNOT_IMM(s1, 0x07, d);
1221 else if (iptr->val.l == 0xffffffffL) {
1224 else if (iptr->val.l == 0xffffffffffL) {
1225 M_ZAPNOT_IMM(s1, 0x1f, d);
1227 else if (iptr->val.l == 0xffffffffffffL) {
1228 M_ZAPNOT_IMM(s1, 0x3f, d);
1230 else if (iptr->val.l == 0xffffffffffffffL) {
1231 M_ZAPNOT_IMM(s1, 0x7f, d);
1234 LCONST(REG_ITMP2, iptr->val.l);
1235 M_AND(s1, REG_ITMP2, d);
1237 store_reg_to_var_int(iptr->dst, d);
1240 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1241 /* val.l = constant */
1243 var_to_reg_int(s1, src, REG_ITMP1);
1244 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1246 M_MOV(s1, REG_ITMP1);
1249 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1250 M_AND_IMM(s1, iptr->val.l, d);
1252 M_LSUB(REG_ZERO, s1, d);
1253 M_AND_IMM(d, iptr->val.l, d);
1255 else if (iptr->val.l == 0xffffL) {
1258 M_LSUB(REG_ZERO, s1, d);
1261 else if (iptr->val.l == 0xffffffL) {
1262 M_ZAPNOT_IMM(s1, 0x07, d);
1264 M_LSUB(REG_ZERO, s1, d);
1265 M_ZAPNOT_IMM(d, 0x07, d);
1267 else if (iptr->val.l == 0xffffffffL) {
1270 M_LSUB(REG_ZERO, s1, d);
1273 else if (iptr->val.l == 0xffffffffffL) {
1274 M_ZAPNOT_IMM(s1, 0x1f, d);
1276 M_LSUB(REG_ZERO, s1, d);
1277 M_ZAPNOT_IMM(d, 0x1f, d);
1279 else if (iptr->val.l == 0xffffffffffffL) {
1280 M_ZAPNOT_IMM(s1, 0x3f, d);
1282 M_LSUB(REG_ZERO, s1, d);
1283 M_ZAPNOT_IMM(d, 0x3f, d);
1285 else if (iptr->val.l == 0xffffffffffffffL) {
1286 M_ZAPNOT_IMM(s1, 0x7f, d);
1288 M_LSUB(REG_ZERO, s1, d);
1289 M_ZAPNOT_IMM(d, 0x7f, d);
1292 LCONST(REG_ITMP2, iptr->val.l);
1293 M_AND(s1, REG_ITMP2, d);
1295 M_LSUB(REG_ZERO, s1, d);
1296 M_AND(d, REG_ITMP2, d);
1298 M_LSUB(REG_ZERO, d, d);
1299 store_reg_to_var_int(iptr->dst, d);
1302 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1305 var_to_reg_int(s1, src->prev, REG_ITMP1);
1306 var_to_reg_int(s2, src, REG_ITMP2);
1307 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1309 store_reg_to_var_int(iptr->dst, d);
1312 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1313 /* val.i = constant */
1315 var_to_reg_int(s1, src, REG_ITMP1);
1316 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1317 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1318 M_OR_IMM(s1, iptr->val.i, d);
1321 ICONST(REG_ITMP2, iptr->val.i);
1322 M_OR(s1, REG_ITMP2, d);
1324 store_reg_to_var_int(iptr->dst, d);
1327 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1328 /* val.l = constant */
1330 var_to_reg_int(s1, src, REG_ITMP1);
1331 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1332 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1333 M_OR_IMM(s1, iptr->val.l, d);
1336 LCONST(REG_ITMP2, iptr->val.l);
1337 M_OR(s1, REG_ITMP2, d);
1339 store_reg_to_var_int(iptr->dst, d);
1342 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1345 var_to_reg_int(s1, src->prev, REG_ITMP1);
1346 var_to_reg_int(s2, src, REG_ITMP2);
1347 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1349 store_reg_to_var_int(iptr->dst, d);
1352 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1353 /* val.i = constant */
1355 var_to_reg_int(s1, src, REG_ITMP1);
1356 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1357 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1358 M_XOR_IMM(s1, iptr->val.i, d);
1361 ICONST(REG_ITMP2, iptr->val.i);
1362 M_XOR(s1, REG_ITMP2, d);
1364 store_reg_to_var_int(iptr->dst, d);
1367 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1368 /* val.l = constant */
1370 var_to_reg_int(s1, src, REG_ITMP1);
1371 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1372 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1373 M_XOR_IMM(s1, iptr->val.l, d);
1376 LCONST(REG_ITMP2, iptr->val.l);
1377 M_XOR(s1, REG_ITMP2, d);
1379 store_reg_to_var_int(iptr->dst, d);
1383 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1385 var_to_reg_int(s1, src->prev, REG_ITMP1);
1386 var_to_reg_int(s2, src, REG_ITMP2);
1387 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1388 M_CMPLT(s1, s2, REG_ITMP3);
1389 M_CMPLT(s2, s1, REG_ITMP1);
1390 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1391 store_reg_to_var_int(iptr->dst, d);
1395 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1396 /* op1 = variable, val.i = constant */
1398 var = &(rd->locals[iptr->op1][TYPE_INT]);
1399 if (var->flags & INMEMORY) {
1401 M_LLD(s1, REG_SP, 8 * var->regoff);
1405 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1406 M_IADD_IMM(s1, iptr->val.i, s1);
1408 else if ((iptr->val.i > -256) && (iptr->val.i < 0)) {
1409 M_ISUB_IMM(s1, (-iptr->val.i), s1);
1412 M_LDA (s1, s1, iptr->val.i);
1413 M_IADD(s1, REG_ZERO, s1);
1415 if (var->flags & INMEMORY)
1416 M_LST(s1, REG_SP, 8 * var->regoff);
1420 /* floating operations ************************************************/
1422 case ICMD_FNEG: /* ..., value ==> ..., - value */
1424 var_to_reg_flt(s1, src, REG_FTMP1);
1425 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1427 store_reg_to_var_flt(iptr->dst, d);
1430 case ICMD_DNEG: /* ..., value ==> ..., - value */
1432 var_to_reg_flt(s1, src, REG_FTMP1);
1433 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1435 store_reg_to_var_flt(iptr->dst, d);
1438 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1440 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1441 var_to_reg_flt(s2, src, REG_FTMP2);
1442 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1447 if (d == s1 || d == s2) {
1448 M_FADDS(s1, s2, REG_FTMP3);
1450 M_FMOV(REG_FTMP3, d);
1457 store_reg_to_var_flt(iptr->dst, d);
1460 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1462 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1463 var_to_reg_flt(s2, src, REG_FTMP2);
1464 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1469 if (d == s1 || d == s2) {
1470 M_DADDS(s1, s2, REG_FTMP3);
1472 M_FMOV(REG_FTMP3, d);
1479 store_reg_to_var_flt(iptr->dst, d);
1482 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1484 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1485 var_to_reg_flt(s2, src, REG_FTMP2);
1486 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1491 if (d == s1 || d == s2) {
1492 M_FSUBS(s1, s2, REG_FTMP3);
1494 M_FMOV(REG_FTMP3, d);
1501 store_reg_to_var_flt(iptr->dst, d);
1504 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1506 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1507 var_to_reg_flt(s2, src, REG_FTMP2);
1508 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1513 if (d == s1 || d == s2) {
1514 M_DSUBS(s1, s2, REG_FTMP3);
1516 M_FMOV(REG_FTMP3, d);
1523 store_reg_to_var_flt(iptr->dst, d);
1526 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1528 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1529 var_to_reg_flt(s2, src, REG_FTMP2);
1530 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1535 if (d == s1 || d == s2) {
1536 M_FMULS(s1, s2, REG_FTMP3);
1538 M_FMOV(REG_FTMP3, d);
1545 store_reg_to_var_flt(iptr->dst, d);
1548 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1550 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1551 var_to_reg_flt(s2, src, REG_FTMP2);
1552 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1557 if (d == s1 || d == s2) {
1558 M_DMULS(s1, s2, REG_FTMP3);
1560 M_FMOV(REG_FTMP3, d);
1567 store_reg_to_var_flt(iptr->dst, d);
1570 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1572 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1573 var_to_reg_flt(s2, src, REG_FTMP2);
1574 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1579 if (d == s1 || d == s2) {
1580 M_FDIVS(s1, s2, REG_FTMP3);
1582 M_FMOV(REG_FTMP3, d);
1589 store_reg_to_var_flt(iptr->dst, d);
1592 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1594 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1595 var_to_reg_flt(s2, src, REG_FTMP2);
1596 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1601 if (d == s1 || d == s2) {
1602 M_DDIVS(s1, s2, REG_FTMP3);
1604 M_FMOV(REG_FTMP3, d);
1611 store_reg_to_var_flt(iptr->dst, d);
1614 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1616 var_to_reg_int(s1, src, REG_ITMP1);
1617 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1618 a = dseg_adddouble(cd, 0.0);
1619 M_LST (s1, REG_PV, a);
1620 M_DLD (d, REG_PV, a);
1622 store_reg_to_var_flt(iptr->dst, d);
1625 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1627 var_to_reg_int(s1, src, REG_ITMP1);
1628 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1629 a = dseg_adddouble(cd, 0.0);
1630 M_LST (s1, REG_PV, a);
1631 M_DLD (d, REG_PV, a);
1633 store_reg_to_var_flt(iptr->dst, d);
1636 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1638 var_to_reg_flt(s1, src, REG_FTMP1);
1639 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1640 a = dseg_adddouble(cd, 0.0);
1641 M_CVTDL_C(s1, REG_FTMP2);
1642 M_CVTLI(REG_FTMP2, REG_FTMP3);
1643 M_DST (REG_FTMP3, REG_PV, a);
1644 M_ILD (d, REG_PV, a);
1645 store_reg_to_var_int(iptr->dst, d);
1648 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1650 var_to_reg_flt(s1, src, REG_FTMP1);
1651 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1652 a = dseg_adddouble(cd, 0.0);
1653 M_CVTDL_C(s1, REG_FTMP2);
1654 M_DST (REG_FTMP2, REG_PV, a);
1655 M_LLD (d, REG_PV, a);
1656 store_reg_to_var_int(iptr->dst, d);
1659 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1661 var_to_reg_flt(s1, src, REG_FTMP1);
1662 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1665 store_reg_to_var_flt(iptr->dst, d);
1668 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1670 var_to_reg_flt(s1, src, REG_FTMP1);
1671 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1679 store_reg_to_var_flt(iptr->dst, d);
1682 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1684 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1685 var_to_reg_flt(s2, src, REG_FTMP2);
1686 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1688 M_LSUB_IMM(REG_ZERO, 1, d);
1689 M_FCMPEQ(s1, s2, REG_FTMP3);
1690 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1692 M_FCMPLT(s2, s1, REG_FTMP3);
1693 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1694 M_LADD_IMM(REG_ZERO, 1, d);
1697 M_LSUB_IMM(REG_ZERO, 1, d);
1698 M_FCMPEQS(s1, s2, REG_FTMP3);
1700 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1702 M_FCMPLTS(s2, s1, REG_FTMP3);
1704 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1705 M_LADD_IMM(REG_ZERO, 1, d);
1707 store_reg_to_var_int(iptr->dst, d);
1710 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1712 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1713 var_to_reg_flt(s2, src, REG_FTMP2);
1714 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1716 M_LADD_IMM(REG_ZERO, 1, d);
1717 M_FCMPEQ(s1, s2, REG_FTMP3);
1718 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1720 M_FCMPLT(s1, s2, REG_FTMP3);
1721 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1722 M_LSUB_IMM(REG_ZERO, 1, d);
1725 M_LADD_IMM(REG_ZERO, 1, d);
1726 M_FCMPEQS(s1, s2, REG_FTMP3);
1728 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1730 M_FCMPLTS(s1, s2, REG_FTMP3);
1732 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1733 M_LSUB_IMM(REG_ZERO, 1, d);
1735 store_reg_to_var_int(iptr->dst, d);
1739 /* memory operations **************************************************/
1741 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1743 var_to_reg_int(s1, src, REG_ITMP1);
1744 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1745 gen_nullptr_check(s1);
1746 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1747 store_reg_to_var_int(iptr->dst, d);
1750 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1752 var_to_reg_int(s1, src->prev, REG_ITMP1);
1753 var_to_reg_int(s2, src, REG_ITMP2);
1754 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1755 if (iptr->op1 == 0) {
1756 gen_nullptr_check(s1);
1759 M_SAADDQ(s2, s1, REG_ITMP1);
1760 M_ALD( d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1761 store_reg_to_var_int(iptr->dst, d);
1764 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1766 var_to_reg_int(s1, src->prev, REG_ITMP1);
1767 var_to_reg_int(s2, src, REG_ITMP2);
1768 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1769 if (iptr->op1 == 0) {
1770 gen_nullptr_check(s1);
1773 M_S8ADDQ(s2, s1, REG_ITMP1);
1774 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1775 store_reg_to_var_int(iptr->dst, d);
1778 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1780 var_to_reg_int(s1, src->prev, REG_ITMP1);
1781 var_to_reg_int(s2, src, REG_ITMP2);
1782 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1783 if (iptr->op1 == 0) {
1784 gen_nullptr_check(s1);
1788 M_S4ADDQ(s2, s1, REG_ITMP1);
1789 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1790 store_reg_to_var_int(iptr->dst, d);
1793 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1795 var_to_reg_int(s1, src->prev, REG_ITMP1);
1796 var_to_reg_int(s2, src, REG_ITMP2);
1797 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1798 if (iptr->op1 == 0) {
1799 gen_nullptr_check(s1);
1802 M_S4ADDQ(s2, s1, REG_ITMP1);
1803 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1804 store_reg_to_var_flt(iptr->dst, d);
1807 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1809 var_to_reg_int(s1, src->prev, REG_ITMP1);
1810 var_to_reg_int(s2, src, REG_ITMP2);
1811 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1812 if (iptr->op1 == 0) {
1813 gen_nullptr_check(s1);
1816 M_S8ADDQ(s2, s1, REG_ITMP1);
1817 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1818 store_reg_to_var_flt(iptr->dst, d);
1821 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1823 var_to_reg_int(s1, src->prev, REG_ITMP1);
1824 var_to_reg_int(s2, src, REG_ITMP2);
1825 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1826 if (iptr->op1 == 0) {
1827 gen_nullptr_check(s1);
1830 if (has_ext_instr_set) {
1831 M_LADD(s2, s1, REG_ITMP1);
1832 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1833 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1836 M_LADD (s2, s1, REG_ITMP1);
1837 M_LADD (s2, REG_ITMP1, REG_ITMP1);
1838 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
1839 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
1840 M_EXTWL(REG_ITMP2, REG_ITMP1, d);
1842 store_reg_to_var_int(iptr->dst, d);
1845 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1847 var_to_reg_int(s1, src->prev, REG_ITMP1);
1848 var_to_reg_int(s2, src, REG_ITMP2);
1849 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1850 if (iptr->op1 == 0) {
1851 gen_nullptr_check(s1);
1854 if (has_ext_instr_set) {
1855 M_LADD(s2, s1, REG_ITMP1);
1856 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1857 M_SLDU( d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
1861 M_LADD(s2, s1, REG_ITMP1);
1862 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1863 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
1864 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0])+2);
1865 M_EXTQH(REG_ITMP2, REG_ITMP1, d);
1866 M_SRA_IMM(d, 48, d);
1868 store_reg_to_var_int(iptr->dst, d);
1871 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1873 var_to_reg_int(s1, src->prev, REG_ITMP1);
1874 var_to_reg_int(s2, src, REG_ITMP2);
1875 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1876 if (iptr->op1 == 0) {
1877 gen_nullptr_check(s1);
1880 if (has_ext_instr_set) {
1881 M_LADD (s2, s1, REG_ITMP1);
1882 M_BLDU (d, REG_ITMP1, OFFSET (java_bytearray, data[0]));
1886 M_LADD(s2, s1, REG_ITMP1);
1887 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1888 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0])+1);
1889 M_EXTQH(REG_ITMP2, REG_ITMP1, d);
1890 M_SRA_IMM(d, 56, d);
1892 store_reg_to_var_int(iptr->dst, d);
1896 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1898 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1899 var_to_reg_int(s2, src->prev, REG_ITMP2);
1900 if (iptr->op1 == 0) {
1901 gen_nullptr_check(s1);
1904 var_to_reg_int(s3, src, REG_ITMP3);
1905 M_SAADDQ(s2, s1, REG_ITMP1);
1906 M_AST (s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1909 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1911 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1912 var_to_reg_int(s2, src->prev, REG_ITMP2);
1913 if (iptr->op1 == 0) {
1914 gen_nullptr_check(s1);
1917 var_to_reg_int(s3, src, REG_ITMP3);
1918 M_S8ADDQ(s2, s1, REG_ITMP1);
1919 M_LST (s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1922 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1924 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1925 var_to_reg_int(s2, src->prev, REG_ITMP2);
1926 if (iptr->op1 == 0) {
1927 gen_nullptr_check(s1);
1931 var_to_reg_int(s3, src, REG_ITMP3);
1932 M_S4ADDQ(s2, s1, REG_ITMP1);
1933 M_IST (s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1936 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1938 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1939 var_to_reg_int(s2, src->prev, REG_ITMP2);
1940 if (iptr->op1 == 0) {
1941 gen_nullptr_check(s1);
1944 var_to_reg_flt(s3, src, REG_FTMP3);
1945 M_S4ADDQ(s2, s1, REG_ITMP1);
1946 M_FST (s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1949 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1951 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1952 var_to_reg_int(s2, src->prev, REG_ITMP2);
1953 if (iptr->op1 == 0) {
1954 gen_nullptr_check(s1);
1957 var_to_reg_flt(s3, src, REG_FTMP3);
1958 M_S8ADDQ(s2, s1, REG_ITMP1);
1959 M_DST (s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1962 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1964 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1965 var_to_reg_int(s2, src->prev, REG_ITMP2);
1966 if (iptr->op1 == 0) {
1967 gen_nullptr_check(s1);
1970 var_to_reg_int(s3, src, REG_ITMP3);
1971 if (has_ext_instr_set) {
1972 M_LADD(s2, s1, REG_ITMP1);
1973 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1974 M_SST (s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1977 M_LADD (s2, s1, REG_ITMP1);
1978 M_LADD (s2, REG_ITMP1, REG_ITMP1);
1979 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
1980 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
1981 M_INSWL(s3, REG_ITMP1, REG_ITMP3);
1982 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
1983 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
1984 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
1988 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1990 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1991 var_to_reg_int(s2, src->prev, REG_ITMP2);
1992 if (iptr->op1 == 0) {
1993 gen_nullptr_check(s1);
1996 var_to_reg_int(s3, src, REG_ITMP3);
1997 if (has_ext_instr_set) {
1998 M_LADD(s2, s1, REG_ITMP1);
1999 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2000 M_SST (s3, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2003 M_LADD (s2, s1, REG_ITMP1);
2004 M_LADD (s2, REG_ITMP1, REG_ITMP1);
2005 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2006 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2007 M_INSWL(s3, REG_ITMP1, REG_ITMP3);
2008 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2009 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2010 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2014 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2016 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2017 var_to_reg_int(s2, src->prev, REG_ITMP2);
2018 if (iptr->op1 == 0) {
2019 gen_nullptr_check(s1);
2022 var_to_reg_int(s3, src, REG_ITMP3);
2023 if (has_ext_instr_set) {
2024 M_LADD(s2, s1, REG_ITMP1);
2025 M_BST (s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2028 M_LADD (s2, s1, REG_ITMP1);
2029 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2030 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2031 M_INSBL(s3, REG_ITMP1, REG_ITMP3);
2032 M_MSKBL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2033 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2034 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2039 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2041 var_to_reg_int(s1, src->prev, REG_ITMP1);
2042 var_to_reg_int(s2, src, REG_ITMP2);
2043 if (iptr->op1 == 0) {
2044 gen_nullptr_check(s1);
2047 M_S4ADDQ(s2, s1, REG_ITMP1);
2048 M_IST(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
2051 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2053 var_to_reg_int(s1, src->prev, REG_ITMP1);
2054 var_to_reg_int(s2, src, REG_ITMP2);
2055 if (iptr->op1 == 0) {
2056 gen_nullptr_check(s1);
2059 M_S8ADDQ(s2, s1, REG_ITMP1);
2060 M_LST(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
2063 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2065 var_to_reg_int(s1, src->prev, REG_ITMP1);
2066 var_to_reg_int(s2, src, REG_ITMP2);
2067 if (iptr->op1 == 0) {
2068 gen_nullptr_check(s1);
2071 M_SAADDQ(s2, s1, REG_ITMP1);
2072 M_AST(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2075 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2077 var_to_reg_int(s1, src->prev, REG_ITMP1);
2078 var_to_reg_int(s2, src, REG_ITMP2);
2079 if (iptr->op1 == 0) {
2080 gen_nullptr_check(s1);
2083 if (has_ext_instr_set) {
2084 M_LADD(s2, s1, REG_ITMP1);
2085 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2088 M_LADD(s2, s1, REG_ITMP1);
2089 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2090 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2091 M_INSBL(REG_ZERO, REG_ITMP1, REG_ITMP3);
2092 M_MSKBL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2093 M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2094 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2098 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2100 var_to_reg_int(s1, src->prev, REG_ITMP1);
2101 var_to_reg_int(s2, src, REG_ITMP2);
2102 if (iptr->op1 == 0) {
2103 gen_nullptr_check(s1);
2106 if (has_ext_instr_set) {
2107 M_LADD(s2, s1, REG_ITMP1);
2108 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2109 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
2112 M_LADD(s2, s1, REG_ITMP1);
2113 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2114 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
2115 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
2116 M_INSWL(REG_ZERO, REG_ITMP1, REG_ITMP3);
2117 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2118 M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2119 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2123 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2125 var_to_reg_int(s1, src->prev, REG_ITMP1);
2126 var_to_reg_int(s2, src, REG_ITMP2);
2127 if (iptr->op1 == 0) {
2128 gen_nullptr_check(s1);
2131 if (has_ext_instr_set) {
2132 M_LADD(s2, s1, REG_ITMP1);
2133 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2134 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2137 M_LADD(s2, s1, REG_ITMP1);
2138 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2139 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2140 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2141 M_INSWL(REG_ZERO, REG_ITMP1, REG_ITMP3);
2142 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2143 M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2144 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2149 case ICMD_GETSTATIC: /* ... ==> ..., value */
2150 /* op1 = type, val.a = field address */
2153 codegen_addpatchref(cd, mcodeptr,
2154 PATCHER_get_putstatic,
2155 (unresolved_field *) iptr->target);
2157 if (showdisassemble)
2163 fieldinfo *fi = iptr->val.a;
2165 if (!fi->class->initialized) {
2166 codegen_addpatchref(cd, mcodeptr,
2167 PATCHER_clinit, fi->class);
2169 if (showdisassemble)
2173 a = (ptrint) &(fi->value);
2176 a = dseg_addaddress(cd, a);
2177 M_ALD(REG_ITMP1, REG_PV, a);
2178 switch (iptr->op1) {
2180 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2181 M_ILD(d, REG_ITMP1, 0);
2182 store_reg_to_var_int(iptr->dst, d);
2185 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2186 M_LLD(d, REG_ITMP1, 0);
2187 store_reg_to_var_int(iptr->dst, d);
2190 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2191 M_ALD(d, REG_ITMP1, 0);
2192 store_reg_to_var_int(iptr->dst, d);
2195 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2196 M_FLD(d, REG_ITMP1, 0);
2197 store_reg_to_var_flt(iptr->dst, d);
2200 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2201 M_DLD(d, REG_ITMP1, 0);
2202 store_reg_to_var_flt(iptr->dst, d);
2207 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2208 /* op1 = type, val.a = field address */
2211 codegen_addpatchref(cd, mcodeptr,
2212 PATCHER_get_putstatic,
2213 (unresolved_field *) iptr->target);
2215 if (showdisassemble)
2221 fieldinfo *fi = iptr->val.a;
2223 if (!fi->class->initialized) {
2224 codegen_addpatchref(cd, mcodeptr,
2225 PATCHER_clinit, fi->class);
2227 if (showdisassemble)
2231 a = (ptrint) &(fi->value);
2234 a = dseg_addaddress(cd, a);
2235 M_ALD(REG_ITMP1, REG_PV, a);
2236 switch (iptr->op1) {
2238 var_to_reg_int(s2, src, REG_ITMP2);
2239 M_IST(s2, REG_ITMP1, 0);
2242 var_to_reg_int(s2, src, REG_ITMP2);
2243 M_LST(s2, REG_ITMP1, 0);
2246 var_to_reg_int(s2, src, REG_ITMP2);
2247 M_AST(s2, REG_ITMP1, 0);
2250 var_to_reg_flt(s2, src, REG_FTMP2);
2251 M_FST(s2, REG_ITMP1, 0);
2254 var_to_reg_flt(s2, src, REG_FTMP2);
2255 M_DST(s2, REG_ITMP1, 0);
2260 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2261 /* val = value (in current instruction) */
2262 /* op1 = type, val.a = field address (in */
2263 /* following NOP) */
2265 if (!iptr[1].val.a) {
2266 codegen_addpatchref(cd, mcodeptr,
2267 PATCHER_get_putstatic,
2268 (unresolved_field *) iptr[1].target);
2270 if (showdisassemble)
2276 fieldinfo *fi = iptr[1].val.a;
2278 if (!fi->class->initialized) {
2279 codegen_addpatchref(cd, mcodeptr,
2280 PATCHER_clinit, fi->class);
2282 if (showdisassemble)
2286 a = (ptrint) &(fi->value);
2289 a = dseg_addaddress(cd, a);
2290 M_ALD(REG_ITMP1, REG_PV, a);
2291 switch (iptr->op1) {
2293 M_IST(REG_ZERO, REG_ITMP1, 0);
2296 M_LST(REG_ZERO, REG_ITMP1, 0);
2299 M_AST(REG_ZERO, REG_ITMP1, 0);
2302 M_FST(REG_ZERO, REG_ITMP1, 0);
2305 M_DST(REG_ZERO, REG_ITMP1, 0);
2311 case ICMD_GETFIELD: /* ... ==> ..., value */
2312 /* op1 = type, val.i = field offset */
2314 var_to_reg_int(s1, src, REG_ITMP1);
2315 gen_nullptr_check(s1);
2318 codegen_addpatchref(cd, mcodeptr,
2319 PATCHER_get_putfield,
2320 (unresolved_field *) iptr->target);
2322 if (showdisassemble)
2328 a = ((fieldinfo *) (iptr->val.a))->offset;
2331 switch (iptr->op1) {
2333 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2335 store_reg_to_var_int(iptr->dst, d);
2338 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2340 store_reg_to_var_int(iptr->dst, d);
2343 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2345 store_reg_to_var_int(iptr->dst, d);
2348 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2350 store_reg_to_var_flt(iptr->dst, d);
2353 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2355 store_reg_to_var_flt(iptr->dst, d);
2360 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2361 /* op1 = type, val.a = field address */
2363 var_to_reg_int(s1, src->prev, REG_ITMP1);
2364 gen_nullptr_check(s1);
2366 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2367 var_to_reg_int(s2, src, REG_ITMP2);
2369 var_to_reg_flt(s2, src, REG_FTMP2);
2373 codegen_addpatchref(cd, mcodeptr,
2374 PATCHER_get_putfield,
2375 (unresolved_field *) iptr->target);
2377 if (showdisassemble)
2383 a = ((fieldinfo *) (iptr->val.a))->offset;
2386 switch (iptr->op1) {
2405 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2406 /* val = value (in current instruction) */
2407 /* op1 = type, val.a = field address (in */
2408 /* following NOP) */
2410 var_to_reg_int(s1, src, REG_ITMP1);
2411 gen_nullptr_check(s1);
2413 if (!iptr[1].val.a) {
2414 codegen_addpatchref(cd, mcodeptr,
2415 PATCHER_get_putfield,
2416 (unresolved_field *) iptr[1].target);
2418 if (showdisassemble)
2424 a = ((fieldinfo *) (iptr[1].val.a))->offset;
2427 switch (iptr[1].op1) {
2429 M_IST(REG_ZERO, s1, a);
2432 M_LST(REG_ZERO, s1, a);
2435 M_AST(REG_ZERO, s1, a);
2438 M_FST(REG_ZERO, s1, a);
2441 M_DST(REG_ZERO, s1, a);
2447 /* branch operations **************************************************/
2449 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2451 var_to_reg_int(s1, src, REG_ITMP1);
2452 M_INTMOVE(s1, REG_ITMP1_XPTR);
2453 a = dseg_addaddress(cd, asm_handle_exception);
2454 M_ALD(REG_ITMP2, REG_PV, a);
2455 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2456 M_NOP; /* nop ensures that XPC is less than the end */
2457 /* of basic block */
2461 case ICMD_GOTO: /* ... ==> ... */
2462 /* op1 = target JavaVM pc */
2464 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2468 case ICMD_JSR: /* ... ==> ... */
2469 /* op1 = target JavaVM pc */
2471 M_BSR(REG_ITMP1, 0);
2472 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2475 case ICMD_RET: /* ... ==> ... */
2476 /* op1 = local variable */
2478 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2479 if (var->flags & INMEMORY) {
2480 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2481 M_RET(REG_ZERO, REG_ITMP1);
2484 M_RET(REG_ZERO, var->regoff);
2488 case ICMD_IFNULL: /* ..., value ==> ... */
2489 /* op1 = target JavaVM pc */
2491 var_to_reg_int(s1, src, REG_ITMP1);
2493 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2496 case ICMD_IFNONNULL: /* ..., value ==> ... */
2497 /* op1 = target JavaVM pc */
2499 var_to_reg_int(s1, src, REG_ITMP1);
2501 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2504 case ICMD_IFEQ: /* ..., value ==> ... */
2505 /* op1 = target JavaVM pc, val.i = constant */
2507 var_to_reg_int(s1, src, REG_ITMP1);
2508 if (iptr->val.i == 0) {
2512 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2513 M_CMPEQ_IMM(s1, iptr->val.i, REG_ITMP1);
2516 ICONST(REG_ITMP2, iptr->val.i);
2517 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2519 M_BNEZ(REG_ITMP1, 0);
2521 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2524 case ICMD_IFLT: /* ..., value ==> ... */
2525 /* op1 = target JavaVM pc, val.i = constant */
2527 var_to_reg_int(s1, src, REG_ITMP1);
2528 if (iptr->val.i == 0) {
2532 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2533 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2536 ICONST(REG_ITMP2, iptr->val.i);
2537 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2539 M_BNEZ(REG_ITMP1, 0);
2541 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2544 case ICMD_IFLE: /* ..., value ==> ... */
2545 /* op1 = target JavaVM pc, val.i = constant */
2547 var_to_reg_int(s1, src, REG_ITMP1);
2548 if (iptr->val.i == 0) {
2552 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2553 M_CMPLE_IMM(s1, iptr->val.i, REG_ITMP1);
2556 ICONST(REG_ITMP2, iptr->val.i);
2557 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2559 M_BNEZ(REG_ITMP1, 0);
2561 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2564 case ICMD_IFNE: /* ..., value ==> ... */
2565 /* op1 = target JavaVM pc, val.i = constant */
2567 var_to_reg_int(s1, src, REG_ITMP1);
2568 if (iptr->val.i == 0) {
2572 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2573 M_CMPEQ_IMM(s1, iptr->val.i, REG_ITMP1);
2576 ICONST(REG_ITMP2, iptr->val.i);
2577 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2579 M_BEQZ(REG_ITMP1, 0);
2581 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2584 case ICMD_IFGT: /* ..., value ==> ... */
2585 /* op1 = target JavaVM pc, val.i = constant */
2587 var_to_reg_int(s1, src, REG_ITMP1);
2588 if (iptr->val.i == 0) {
2592 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2593 M_CMPLE_IMM(s1, iptr->val.i, REG_ITMP1);
2596 ICONST(REG_ITMP2, iptr->val.i);
2597 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2599 M_BEQZ(REG_ITMP1, 0);
2601 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2604 case ICMD_IFGE: /* ..., value ==> ... */
2605 /* op1 = target JavaVM pc, val.i = constant */
2607 var_to_reg_int(s1, src, REG_ITMP1);
2608 if (iptr->val.i == 0) {
2612 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2613 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2616 ICONST(REG_ITMP2, iptr->val.i);
2617 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2619 M_BEQZ(REG_ITMP1, 0);
2621 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2624 case ICMD_IF_LEQ: /* ..., value ==> ... */
2625 /* op1 = target JavaVM pc, val.l = constant */
2627 var_to_reg_int(s1, src, REG_ITMP1);
2628 if (iptr->val.l == 0) {
2632 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2633 M_CMPEQ_IMM(s1, iptr->val.l, REG_ITMP1);
2636 LCONST(REG_ITMP2, iptr->val.l);
2637 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2639 M_BNEZ(REG_ITMP1, 0);
2641 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2644 case ICMD_IF_LLT: /* ..., value ==> ... */
2645 /* op1 = target JavaVM pc, val.l = constant */
2647 var_to_reg_int(s1, src, REG_ITMP1);
2648 if (iptr->val.l == 0) {
2652 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2653 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2656 LCONST(REG_ITMP2, iptr->val.l);
2657 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2659 M_BNEZ(REG_ITMP1, 0);
2661 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2664 case ICMD_IF_LLE: /* ..., value ==> ... */
2665 /* op1 = target JavaVM pc, val.l = constant */
2667 var_to_reg_int(s1, src, REG_ITMP1);
2668 if (iptr->val.l == 0) {
2672 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2673 M_CMPLE_IMM(s1, iptr->val.l, REG_ITMP1);
2676 LCONST(REG_ITMP2, iptr->val.l);
2677 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2679 M_BNEZ(REG_ITMP1, 0);
2681 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2684 case ICMD_IF_LNE: /* ..., value ==> ... */
2685 /* op1 = target JavaVM pc, val.l = constant */
2687 var_to_reg_int(s1, src, REG_ITMP1);
2688 if (iptr->val.l == 0) {
2692 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2693 M_CMPEQ_IMM(s1, iptr->val.l, REG_ITMP1);
2696 LCONST(REG_ITMP2, iptr->val.l);
2697 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2699 M_BEQZ(REG_ITMP1, 0);
2701 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2704 case ICMD_IF_LGT: /* ..., value ==> ... */
2705 /* op1 = target JavaVM pc, val.l = constant */
2707 var_to_reg_int(s1, src, REG_ITMP1);
2708 if (iptr->val.l == 0) {
2712 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2713 M_CMPLE_IMM(s1, iptr->val.l, REG_ITMP1);
2716 LCONST(REG_ITMP2, iptr->val.l);
2717 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2719 M_BEQZ(REG_ITMP1, 0);
2721 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2724 case ICMD_IF_LGE: /* ..., value ==> ... */
2725 /* op1 = target JavaVM pc, val.l = constant */
2727 var_to_reg_int(s1, src, REG_ITMP1);
2728 if (iptr->val.l == 0) {
2732 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2733 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2736 LCONST(REG_ITMP2, iptr->val.l);
2737 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2739 M_BEQZ(REG_ITMP1, 0);
2741 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2744 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2745 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2746 case ICMD_IF_ACMPEQ:
2748 var_to_reg_int(s1, src->prev, REG_ITMP1);
2749 var_to_reg_int(s2, src, REG_ITMP2);
2750 M_CMPEQ(s1, s2, REG_ITMP1);
2751 M_BNEZ(REG_ITMP1, 0);
2752 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2755 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2756 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2757 case ICMD_IF_ACMPNE:
2759 var_to_reg_int(s1, src->prev, REG_ITMP1);
2760 var_to_reg_int(s2, src, REG_ITMP2);
2761 M_CMPEQ(s1, s2, REG_ITMP1);
2762 M_BEQZ(REG_ITMP1, 0);
2763 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2766 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2767 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2769 var_to_reg_int(s1, src->prev, REG_ITMP1);
2770 var_to_reg_int(s2, src, REG_ITMP2);
2771 M_CMPLT(s1, s2, REG_ITMP1);
2772 M_BNEZ(REG_ITMP1, 0);
2773 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2776 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2777 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2779 var_to_reg_int(s1, src->prev, REG_ITMP1);
2780 var_to_reg_int(s2, src, REG_ITMP2);
2781 M_CMPLE(s1, s2, REG_ITMP1);
2782 M_BEQZ(REG_ITMP1, 0);
2783 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2786 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2787 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2789 var_to_reg_int(s1, src->prev, REG_ITMP1);
2790 var_to_reg_int(s2, src, REG_ITMP2);
2791 M_CMPLE(s1, s2, REG_ITMP1);
2792 M_BNEZ(REG_ITMP1, 0);
2793 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2796 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2797 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2799 var_to_reg_int(s1, src->prev, REG_ITMP1);
2800 var_to_reg_int(s2, src, REG_ITMP2);
2801 M_CMPLT(s1, s2, REG_ITMP1);
2802 M_BEQZ(REG_ITMP1, 0);
2803 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2806 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2808 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2811 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2812 /* val.i = constant */
2814 var_to_reg_int(s1, src, REG_ITMP1);
2815 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2817 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2818 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2819 M_CMPEQ(s1, REG_ZERO, d);
2820 store_reg_to_var_int(iptr->dst, d);
2823 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2824 M_CMPEQ(s1, REG_ZERO, d);
2826 store_reg_to_var_int(iptr->dst, d);
2830 M_MOV(s1, REG_ITMP1);
2833 ICONST(d, iptr[1].val.i);
2835 if ((s3 >= 0) && (s3 <= 255)) {
2836 M_CMOVEQ_IMM(s1, s3, d);
2839 ICONST(REG_ITMP2, s3);
2840 M_CMOVEQ(s1, REG_ITMP2, d);
2842 store_reg_to_var_int(iptr->dst, d);
2845 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2846 /* val.i = constant */
2848 var_to_reg_int(s1, src, REG_ITMP1);
2849 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2851 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2852 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2853 M_CMPEQ(s1, REG_ZERO, d);
2854 store_reg_to_var_int(iptr->dst, d);
2857 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2858 M_CMPEQ(s1, REG_ZERO, d);
2860 store_reg_to_var_int(iptr->dst, d);
2864 M_MOV(s1, REG_ITMP1);
2867 ICONST(d, iptr[1].val.i);
2869 if ((s3 >= 0) && (s3 <= 255)) {
2870 M_CMOVNE_IMM(s1, s3, d);
2873 ICONST(REG_ITMP2, s3);
2874 M_CMOVNE(s1, REG_ITMP2, d);
2876 store_reg_to_var_int(iptr->dst, d);
2879 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2880 /* val.i = constant */
2882 var_to_reg_int(s1, src, REG_ITMP1);
2883 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2885 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2886 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2887 M_CMPLT(s1, REG_ZERO, d);
2888 store_reg_to_var_int(iptr->dst, d);
2891 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2892 M_CMPLE(REG_ZERO, s1, d);
2893 store_reg_to_var_int(iptr->dst, d);
2897 M_MOV(s1, REG_ITMP1);
2900 ICONST(d, iptr[1].val.i);
2902 if ((s3 >= 0) && (s3 <= 255)) {
2903 M_CMOVLT_IMM(s1, s3, d);
2906 ICONST(REG_ITMP2, s3);
2907 M_CMOVLT(s1, REG_ITMP2, d);
2909 store_reg_to_var_int(iptr->dst, d);
2912 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2913 /* val.i = constant */
2915 var_to_reg_int(s1, src, REG_ITMP1);
2916 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2918 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2919 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2920 M_CMPLE(REG_ZERO, s1, d);
2921 store_reg_to_var_int(iptr->dst, d);
2924 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2925 M_CMPLT(s1, REG_ZERO, d);
2926 store_reg_to_var_int(iptr->dst, d);
2930 M_MOV(s1, REG_ITMP1);
2933 ICONST(d, iptr[1].val.i);
2935 if ((s3 >= 0) && (s3 <= 255)) {
2936 M_CMOVGE_IMM(s1, s3, d);
2939 ICONST(REG_ITMP2, s3);
2940 M_CMOVGE(s1, REG_ITMP2, d);
2942 store_reg_to_var_int(iptr->dst, d);
2945 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2946 /* val.i = constant */
2948 var_to_reg_int(s1, src, REG_ITMP1);
2949 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2951 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2952 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2953 M_CMPLT(REG_ZERO, s1, d);
2954 store_reg_to_var_int(iptr->dst, d);
2957 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2958 M_CMPLE(s1, REG_ZERO, d);
2959 store_reg_to_var_int(iptr->dst, d);
2963 M_MOV(s1, REG_ITMP1);
2966 ICONST(d, iptr[1].val.i);
2968 if ((s3 >= 0) && (s3 <= 255)) {
2969 M_CMOVGT_IMM(s1, s3, d);
2972 ICONST(REG_ITMP2, s3);
2973 M_CMOVGT(s1, REG_ITMP2, d);
2975 store_reg_to_var_int(iptr->dst, d);
2978 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2979 /* val.i = constant */
2981 var_to_reg_int(s1, src, REG_ITMP1);
2982 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2984 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2985 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2986 M_CMPLE(s1, REG_ZERO, d);
2987 store_reg_to_var_int(iptr->dst, d);
2990 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2991 M_CMPLT(REG_ZERO, s1, d);
2992 store_reg_to_var_int(iptr->dst, d);
2996 M_MOV(s1, REG_ITMP1);
2999 ICONST(d, iptr[1].val.i);
3001 if ((s3 >= 0) && (s3 <= 255)) {
3002 M_CMOVLE_IMM(s1, s3, d);
3005 ICONST(REG_ITMP2, s3);
3006 M_CMOVLE(s1, REG_ITMP2, d);
3008 store_reg_to_var_int(iptr->dst, d);
3012 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3016 var_to_reg_int(s1, src, REG_RESULT);
3017 M_INTMOVE(s1, REG_RESULT);
3019 goto nowperformreturn;
3021 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3024 var_to_reg_flt(s1, src, REG_FRESULT);
3025 M_FLTMOVE(s1, REG_FRESULT);
3027 goto nowperformreturn;
3029 case ICMD_RETURN: /* ... ==> ... */
3035 p = parentargs_base;
3037 /* call trace function */
3040 M_LDA(REG_SP, REG_SP, -3 * 8);
3041 M_AST(REG_RA, REG_SP, 0 * 8);
3042 M_LST(REG_RESULT, REG_SP, 1 * 8);
3043 M_DST(REG_FRESULT, REG_SP, 2 * 8);
3044 a = dseg_addaddress(cd, m);
3045 M_ALD(rd->argintregs[0], REG_PV, a);
3046 M_MOV(REG_RESULT, rd->argintregs[1]);
3047 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
3048 M_FLTMOVE(REG_FRESULT, rd->argfltregs[3]);
3049 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
3050 M_ALD(REG_PV, REG_PV, a);
3051 M_JSR(REG_RA, REG_PV);
3052 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3053 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3055 s4 ml = -s1, mh = 0;
3056 while (ml < -32768) { ml += 65536; mh--; }
3057 M_LDA(REG_PV, REG_RA, ml);
3058 M_LDAH(REG_PV, REG_PV, mh);
3060 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
3061 M_LLD(REG_RESULT, REG_SP, 1 * 8);
3062 M_ALD(REG_RA, REG_SP, 0 * 8);
3063 M_LDA(REG_SP, REG_SP, 3 * 8);
3066 #if defined(USE_THREADS)
3067 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3070 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
3072 switch (iptr->opc) {
3076 M_LST(REG_RESULT, REG_SP, rd->maxmemuse * 8);
3080 M_DST(REG_FRESULT, REG_SP, rd->maxmemuse * 8);
3084 a = dseg_addaddress(cd, BUILTIN_monitorexit);
3085 M_ALD(REG_PV, REG_PV, a);
3086 M_JSR(REG_RA, REG_PV);
3087 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
3088 M_LDA(REG_PV, REG_RA, disp);
3090 switch (iptr->opc) {
3094 M_LLD(REG_RESULT, REG_SP, rd->maxmemuse * 8);
3098 M_DLD(REG_FRESULT, REG_SP, rd->maxmemuse * 8);
3104 /* restore return address */
3106 if (!m->isleafmethod) {
3107 p--; M_LLD(REG_RA, REG_SP, p * 8);
3110 /* restore saved registers */
3112 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
3113 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
3115 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
3116 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
3119 /* deallocate stack */
3121 if (parentargs_base) {
3122 M_LDA(REG_SP, REG_SP, parentargs_base * 8);
3125 M_RET(REG_ZERO, REG_RA);
3131 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3136 tptr = (void **) iptr->target;
3138 s4ptr = iptr->val.a;
3139 l = s4ptr[1]; /* low */
3140 i = s4ptr[2]; /* high */
3142 var_to_reg_int(s1, src, REG_ITMP1);
3144 {M_INTMOVE(s1, REG_ITMP1);}
3145 else if (l <= 32768) {
3146 M_LDA(REG_ITMP1, s1, -l);
3149 ICONST(REG_ITMP2, l);
3150 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3157 M_CMPULE_IMM(REG_ITMP1, i - 1, REG_ITMP2);
3159 M_LDA(REG_ITMP2, REG_ZERO, i - 1);
3160 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3162 M_BEQZ(REG_ITMP2, 0);
3165 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
3166 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
3168 /* build jump table top down and use address of lowest entry */
3170 /* s4ptr += 3 + i; */
3174 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
3175 dseg_addtarget(cd, (basicblock *) tptr[0]);
3180 /* length of dataseg after last dseg_addtarget is used by load */
3182 M_SAADDQ(REG_ITMP1, REG_PV, REG_ITMP2);
3183 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
3184 M_JMP(REG_ZERO, REG_ITMP2);
3189 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3191 s4 i, l, val, *s4ptr;
3194 tptr = (void **) iptr->target;
3196 s4ptr = iptr->val.a;
3197 l = s4ptr[0]; /* default */
3198 i = s4ptr[1]; /* count */
3200 MCODECHECK((i<<2)+8);
3201 var_to_reg_int(s1, src, REG_ITMP1);
3207 if ((val >= 0) && (val <= 255)) {
3208 M_CMPEQ_IMM(s1, val, REG_ITMP2);
3211 if ((val >= -32768) && (val <= 32767)) {
3212 M_LDA(REG_ITMP2, REG_ZERO, val);
3215 a = dseg_adds4(cd, val);
3216 M_ILD(REG_ITMP2, REG_PV, a);
3218 M_CMPEQ(s1, REG_ITMP2, REG_ITMP2);
3220 M_BNEZ(REG_ITMP2, 0);
3221 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
3222 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
3226 /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
3228 tptr = (void **) iptr->target;
3229 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
3236 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3237 /* op1 = return type, val.a = function pointer*/
3241 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3242 /* op1 = return type, val.a = function pointer*/
3246 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3247 /* op1 = return type, val.a = function pointer*/
3251 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3252 /* op1 = arg count, val.a = method pointer */
3254 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3255 /* op1 = arg count, val.a = method pointer */
3257 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3258 /* op1 = arg count, val.a = method pointer */
3260 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3261 /* op1 = arg count, val.a = method pointer */
3268 MCODECHECK((s3 << 1) + 64);
3270 /* copy arguments to registers or stack location */
3272 for (; --s3 >= 0; src = src->prev) {
3273 if (src->varkind == ARGVAR)
3275 if (IS_INT_LNG_TYPE(src->type)) {
3276 if (s3 < INT_ARG_CNT) {
3277 s1 = rd->argintregs[s3];
3278 var_to_reg_int(d, src, s1);
3282 var_to_reg_int(d, src, REG_ITMP1);
3283 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3287 if (s3 < FLT_ARG_CNT) {
3288 s1 = rd->argfltregs[s3];
3289 var_to_reg_flt(d, src, s1);
3293 var_to_reg_flt(d, src, REG_FTMP1);
3294 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3300 switch (iptr->opc) {
3305 codegen_addpatchref(cd, mcodeptr,
3306 (functionptr) lm, iptr->target);
3308 if (showdisassemble)
3317 a = dseg_addaddress(cd, a);
3320 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
3323 case ICMD_INVOKESPECIAL:
3324 gen_nullptr_check(rd->argintregs[0]);
3325 M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr */
3328 case ICMD_INVOKESTATIC:
3330 unresolved_method *um = iptr->target;
3332 codegen_addpatchref(cd, mcodeptr,
3333 PATCHER_invokestatic_special, um);
3335 if (showdisassemble)
3339 d = um->methodref->parseddesc.md->returntype.type;
3342 a = (ptrint) lm->stubroutine;
3343 d = lm->parseddesc->returntype.type;
3346 a = dseg_addaddress(cd, a);
3347 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
3350 case ICMD_INVOKEVIRTUAL:
3351 gen_nullptr_check(rd->argintregs[0]);
3354 unresolved_method *um = iptr->target;
3356 codegen_addpatchref(cd, mcodeptr,
3357 PATCHER_invokevirtual, um);
3359 if (showdisassemble)
3363 d = um->methodref->parseddesc.md->returntype.type;
3366 s1 = OFFSET(vftbl_t, table[0]) +
3367 sizeof(methodptr) * lm->vftblindex;
3368 d = lm->parseddesc->returntype.type;
3371 M_ALD(REG_METHODPTR, rd->argintregs[0],
3372 OFFSET(java_objectheader, vftbl));
3373 M_ALD(REG_PV, REG_METHODPTR, s1);
3376 case ICMD_INVOKEINTERFACE:
3377 gen_nullptr_check(rd->argintregs[0]);
3380 unresolved_method *um = iptr->target;
3382 codegen_addpatchref(cd, mcodeptr,
3383 PATCHER_invokeinterface, um);
3385 if (showdisassemble)
3390 d = um->methodref->parseddesc.md->returntype.type;
3393 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3394 sizeof(methodptr*) * lm->class->index;
3396 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3398 d = lm->parseddesc->returntype.type;
3401 M_ALD(REG_METHODPTR, rd->argintregs[0],
3402 OFFSET(java_objectheader, vftbl));
3403 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3404 M_ALD(REG_PV, REG_METHODPTR, s2);
3408 M_JSR(REG_RA, REG_PV);
3412 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3413 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3415 s4 ml = -s1, mh = 0;
3416 while (ml < -32768) { ml += 65536; mh--; }
3417 M_LDA(REG_PV, REG_RA, ml);
3418 M_LDAH(REG_PV, REG_PV, mh);
3421 /* d contains return type */
3423 if (d != TYPE_VOID) {
3424 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3425 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3426 M_INTMOVE(REG_RESULT, s1);
3427 store_reg_to_var_int(iptr->dst, s1);
3430 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3431 M_FLTMOVE(REG_FRESULT, s1);
3432 store_reg_to_var_flt(iptr->dst, s1);
3439 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3441 /* op1: 0 == array, 1 == class */
3442 /* val.a: (classinfo*) superclass */
3444 /* superclass is an interface:
3446 * OK if ((sub == NULL) ||
3447 * (sub->vftbl->interfacetablelength > super->index) &&
3448 * (sub->vftbl->interfacetable[-super->index] != NULL));
3450 * superclass is a class:
3452 * OK if ((sub == NULL) || (0
3453 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3454 * super->vftbl->diffval));
3459 vftbl_t *supervftbl;
3462 super = (classinfo *) iptr->val.a;
3469 superindex = super->index;
3470 supervftbl = super->vftbl;
3473 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3474 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3476 var_to_reg_int(s1, src, REG_ITMP1);
3478 /* calculate interface checkcast code size */
3482 s2 += showdisassemble ? 1 : 0;
3484 /* calculate class checkcast code size */
3486 s3 = 9 /* 8 + (s1 == REG_ITMP1) */;
3488 s3 += showdisassemble ? 1 : 0;
3490 /* if class is not resolved, check which code to call */
3493 M_BEQZ(s1, 4 + (showdisassemble ? 1 : 0) + s2 + 1 + s3);
3495 codegen_addpatchref(cd, mcodeptr,
3496 PATCHER_checkcast_instanceof_flags,
3497 (constant_classref *) iptr->target);
3499 if (showdisassemble)
3502 a = dseg_adds4(cd, 0); /* super->flags */
3503 M_ILD(REG_ITMP2, REG_PV, a);
3504 a = dseg_adds4(cd, ACC_INTERFACE);
3505 M_ILD(REG_ITMP3, REG_PV, a);
3506 M_AND(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3507 M_BEQZ(REG_ITMP2, s2 + 1);
3510 /* interface checkcast code */
3512 if (!super || (super->flags & ACC_INTERFACE)) {
3517 codegen_addpatchref(cd, mcodeptr,
3518 PATCHER_checkcast_instanceof_interface,
3519 (constant_classref *) iptr->target);
3521 if (showdisassemble)
3525 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3526 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3527 M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
3528 M_BLEZ(REG_ITMP3, 0);
3529 codegen_addxcastrefs(cd, mcodeptr);
3530 M_ALD(REG_ITMP3, REG_ITMP2,
3531 OFFSET(vftbl_t, interfacetable[0]) -
3532 superindex * sizeof(methodptr*));
3533 M_BEQZ(REG_ITMP3, 0);
3534 codegen_addxcastrefs(cd, mcodeptr);
3540 /* class checkcast code */
3542 if (!super || !(super->flags & ACC_INTERFACE)) {
3547 codegen_addpatchref(cd, mcodeptr,
3548 PATCHER_checkcast_instanceof_class,
3549 (constant_classref *) iptr->target);
3551 if (showdisassemble)
3555 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3556 a = dseg_addaddress(cd, supervftbl);
3557 M_ALD(REG_ITMP3, REG_PV, a);
3558 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3559 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3561 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3562 /* if (s1 != REG_ITMP1) { */
3563 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3564 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3565 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3566 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3568 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3571 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3572 M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3573 M_ALD(REG_ITMP3, REG_PV, a);
3574 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3575 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3576 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3579 M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3);
3580 M_BEQZ(REG_ITMP3, 0);
3581 codegen_addxcastrefs(cd, mcodeptr);
3583 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3585 store_reg_to_var_int(iptr->dst, d);
3589 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3591 /* op1: 0 == array, 1 == class */
3592 /* val.a: (classinfo*) superclass */
3594 /* superclass is an interface:
3596 * return (sub != NULL) &&
3597 * (sub->vftbl->interfacetablelength > super->index) &&
3598 * (sub->vftbl->interfacetable[-super->index] != NULL);
3600 * superclass is a class:
3602 * return ((sub != NULL) && (0
3603 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3604 * super->vftbl->diffvall));
3609 vftbl_t *supervftbl;
3612 super = (classinfo *) iptr->val.a;
3619 superindex = super->index;
3620 supervftbl = super->vftbl;
3623 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3624 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3626 var_to_reg_int(s1, src, REG_ITMP1);
3627 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3629 M_MOV(s1, REG_ITMP1);
3633 /* calculate interface instanceof code size */
3637 s2 += (d == REG_ITMP2 ? 1 : 0) + (showdisassemble ? 1 : 0);
3639 /* calculate class instanceof code size */
3643 s3 += (showdisassemble ? 1 : 0);
3645 /* if class is not resolved, check which code to call */
3649 M_BEQZ(s1, 4 + (showdisassemble ? 1 : 0) + s2 + 1 + s3);
3651 codegen_addpatchref(cd, mcodeptr,
3652 PATCHER_checkcast_instanceof_flags,
3653 (constant_classref *) iptr->target);
3655 if (showdisassemble)
3658 a = dseg_adds4(cd, 0); /* super->flags */
3659 M_ILD(REG_ITMP3, REG_PV, a);
3660 a = dseg_adds4(cd, ACC_INTERFACE);
3661 M_ILD(REG_ITMP2, REG_PV, a);
3662 M_AND(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3663 M_BEQZ(REG_ITMP3, s2 + 1);
3666 /* interface instanceof code */
3668 if (!super || (super->flags & ACC_INTERFACE)) {
3674 /* If d == REG_ITMP2, then it's destroyed in check code */
3679 codegen_addpatchref(cd, mcodeptr,
3680 PATCHER_checkcast_instanceof_interface,
3681 (constant_classref *) iptr->target);
3683 if (showdisassemble)
3687 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3688 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3689 M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
3690 M_BLEZ(REG_ITMP3, 2);
3691 M_ALD(REG_ITMP1, REG_ITMP1,
3692 OFFSET(vftbl_t, interfacetable[0]) -
3693 superindex * sizeof(methodptr*));
3694 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3700 /* class instanceof code */
3702 if (!super || !(super->flags & ACC_INTERFACE)) {
3708 codegen_addpatchref(cd, mcodeptr,
3709 PATCHER_checkcast_instanceof_class,
3710 (constant_classref *) iptr->target);
3712 if (showdisassemble)
3716 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3717 a = dseg_addaddress(cd, supervftbl);
3718 M_ALD(REG_ITMP2, REG_PV, a);
3719 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3720 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3722 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3723 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3724 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3725 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3726 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3728 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3729 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3731 store_reg_to_var_int(iptr->dst, d);
3736 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3738 var_to_reg_int(s1, src, REG_ITMP1);
3740 codegen_addxcheckarefs(cd, mcodeptr);
3743 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3745 M_BEQZ(REG_RESULT, 0);
3746 codegen_addxexceptionrefs(cd, mcodeptr);
3749 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3750 /* op1 = dimension, val.a = array descriptor */
3752 /* check for negative sizes and copy sizes to stack if necessary */
3754 MCODECHECK((iptr->op1 << 1) + 64);
3756 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3757 var_to_reg_int(s2, src, REG_ITMP1);
3759 codegen_addxcheckarefs(cd, mcodeptr);
3761 /* copy SAVEDVAR sizes to stack */
3763 if (src->varkind != ARGVAR) {
3764 M_LST(s2, REG_SP, s1 * 8);
3768 /* is patcher function set? */
3771 codegen_addpatchref(cd, mcodeptr,
3772 (functionptr) iptr->target, iptr->val.a);
3774 if (showdisassemble)
3780 a = (ptrint) iptr->val.a;
3783 /* a0 = dimension count */
3785 ICONST(rd->argintregs[0], iptr->op1);
3787 /* a1 = arraydescriptor */
3789 a = dseg_addaddress(cd, a);
3790 M_ALD(rd->argintregs[1], REG_PV, a);
3792 /* a2 = pointer to dimensions = stack pointer */
3794 M_INTMOVE(REG_SP, rd->argintregs[2]);
3796 a = dseg_addaddress(cd, (void *) BUILTIN_multianewarray);
3797 M_ALD(REG_PV, REG_PV, a);
3798 M_JSR(REG_RA, REG_PV);
3799 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3801 M_LDA(REG_PV, REG_RA, -s1);
3803 s4 ml = -s1, mh = 0;
3804 while (ml < -32768) { ml += 65536; mh--; }
3805 M_LDA(REG_PV, REG_RA, ml);
3806 M_LDAH(REG_PV, REG_PV, mh);
3808 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3809 M_INTMOVE(REG_RESULT, s1);
3810 store_reg_to_var_int(iptr->dst, s1);
3814 throw_cacao_exception_exit(string_java_lang_InternalError,
3815 "Unknown ICMD %d", iptr->opc);
3818 } /* for instruction */
3820 /* copy values to interface registers */
3822 src = bptr->outstack;
3823 len = bptr->outdepth;
3830 if ((src->varkind != STACKVAR)) {
3832 if (IS_FLT_DBL_TYPE(s2)) {
3833 var_to_reg_flt(s1, src, REG_FTMP1);
3834 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3835 M_FLTMOVE(s1,rd->interfaces[len][s2].regoff);
3838 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3842 var_to_reg_int(s1, src, REG_ITMP1);
3843 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3844 M_INTMOVE(s1,rd->interfaces[len][s2].regoff);
3847 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3853 } /* if (bptr -> flags >= BBREACHED) */
3854 } /* for basic block */
3856 codegen_createlinenumbertable(cd);
3859 /* generate bound check stubs */
3861 s4 *xcodeptr = NULL;
3864 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3865 gen_resolvebranch((u1*) cd->mcodebase + bref->branchpos,
3867 (u1*) mcodeptr - cd->mcodebase);
3871 /* move index register into REG_ITMP1 */
3872 M_MOV(bref->reg, REG_ITMP1);
3873 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3875 if (xcodeptr != NULL) {
3876 M_BR(xcodeptr - mcodeptr - 1);
3879 xcodeptr = mcodeptr;
3881 a = dseg_addaddress(cd, asm_throw_and_handle_arrayindexoutofbounds_exception);
3882 M_ALD(REG_PV, REG_PV, a);
3884 M_JSR(REG_RA, REG_PV);
3887 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3888 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3890 s4 ml = -s1, mh = 0;
3891 while (ml < -32768) { ml += 65536; mh--; }
3892 M_LDA(REG_PV, REG_RA, ml);
3893 M_LDAH(REG_PV, REG_PV, mh);
3898 /* generate negative array size check stubs */
3902 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3903 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3904 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3906 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3910 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3912 (u1 *) mcodeptr - cd->mcodebase);
3916 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3918 if (xcodeptr != NULL) {
3919 M_BR(xcodeptr - mcodeptr - 1);
3922 xcodeptr = mcodeptr;
3925 a = dseg_addaddress(cd, string_java_lang_NegativeArraySizeException);
3926 M_ALD(REG_ITMP1_XPTR,REG_PV,a);
3928 a = dseg_addaddress(cd, asm_throw_and_handle_nat_exception);
3929 M_ALD(REG_PV, REG_PV, a);
3931 M_JSR(REG_RA, REG_PV);
3934 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3935 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3937 s4 ml = -s1, mh = 0;
3938 while (ml < -32768) { ml += 65536; mh--; }
3939 M_LDA(REG_PV, REG_RA, ml);
3940 M_LDAH(REG_PV, REG_PV, mh);
3947 /* generate cast check stubs */
3951 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3952 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3953 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3955 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3959 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3961 (u1 *) mcodeptr - cd->mcodebase);
3965 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3967 if (xcodeptr != NULL) {
3968 M_BR(xcodeptr - mcodeptr - 1);
3971 xcodeptr = mcodeptr;
3973 a = dseg_addaddress(cd, string_java_lang_ClassCastException);
3974 M_ALD(REG_ITMP1_XPTR,REG_PV,a);
3976 a = dseg_addaddress(cd, asm_throw_and_handle_nat_exception);
3977 M_ALD(REG_PV, REG_PV, a);
3979 M_JSR(REG_RA, REG_PV);
3982 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3983 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3985 s4 ml = -s1, mh = 0;
3986 while (ml < -32768) { ml += 65536; mh--; }
3987 M_LDA(REG_PV, REG_RA, ml);
3988 M_LDAH(REG_PV, REG_PV, mh);
3994 /* generate exception check stubs */
3998 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3999 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4000 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
4002 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
4006 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
4008 (u1 *) mcodeptr - cd->mcodebase);
4012 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
4014 if (xcodeptr != NULL) {
4015 M_BR(xcodeptr - mcodeptr - 1);
4018 xcodeptr = mcodeptr;
4020 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4021 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
4022 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
4024 a = dseg_addaddress(cd, &builtin_get_exceptionptrptr);
4025 M_ALD(REG_PV, REG_PV, a);
4026 M_JSR(REG_RA, REG_PV);
4029 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4030 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
4032 s4 ml = -s1, mh = 0;
4033 while (ml < -32768) { ml += 65536; mh--; }
4034 M_LDA(REG_PV, REG_RA, ml);
4035 M_LDAH(REG_PV, REG_PV, mh);
4038 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
4039 M_AST(REG_ZERO, REG_RESULT, 0);
4041 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
4042 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
4044 a = dseg_addaddress(cd, &_exceptionptr);
4045 M_ALD(REG_ITMP3, REG_PV, a);
4046 M_ALD(REG_ITMP1_XPTR, REG_ITMP3, 0);
4047 M_AST(REG_ZERO, REG_ITMP3, 0);
4050 a = dseg_addaddress(cd, asm_refillin_and_handle_exception);
4051 M_ALD(REG_PV, REG_PV, a);
4053 M_JMP(REG_RA, REG_PV);
4056 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4057 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
4059 s4 ml = -s1, mh = 0;
4060 while (ml < -32768) { ml += 65536; mh--; }
4061 M_LDA(REG_PV, REG_RA, ml);
4062 M_LDAH(REG_PV, REG_PV, mh);
4068 /* generate null pointer check stubs */
4072 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
4073 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4074 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
4076 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
4080 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
4082 (u1 *) mcodeptr - cd->mcodebase);
4086 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
4088 if (xcodeptr != NULL) {
4089 M_BR(xcodeptr - mcodeptr - 1);
4092 xcodeptr = mcodeptr;
4094 a = dseg_addaddress(cd, string_java_lang_NullPointerException);
4095 M_ALD(REG_ITMP1_XPTR,REG_PV,a);
4097 a = dseg_addaddress(cd, asm_throw_and_handle_nat_exception);
4098 M_ALD(REG_PV, REG_PV, a);
4100 M_JSR(REG_RA, REG_PV);
4103 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4104 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
4106 s4 ml = -s1, mh = 0;
4107 while (ml < -32768) { ml += 65536; mh--; }
4108 M_LDA(REG_PV, REG_RA, ml);
4109 M_LDAH(REG_PV, REG_PV, mh);
4115 /* generate put/getstatic stub call code */
4122 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4123 /* check code segment size */
4125 MCODECHECK(13 + 4 + 1);
4127 /* Get machine code which is patched back in later. The call is */
4128 /* 1 instruction word long. */
4130 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4133 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4134 /* create a virtual java_objectheader */
4136 /* align data structure to 8-byte */
4140 *((ptrint *) (mcodeptr + 0)) = 0; /* vftbl */
4141 *((ptrint *) (mcodeptr + 2)) = (ptrint) get_dummyLR(); /* monitorPtr */
4143 mcodeptr += 2 * 2; /* mcodeptr is a `u4*' pointer */
4146 /* patch in the call to call the following code (done at compile */
4149 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4150 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4152 M_BSR(REG_ITMP3, tmpmcodeptr - (xcodeptr + 1));
4154 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4156 /* create stack frame */
4158 M_LSUB_IMM(REG_SP, 5 * 8, REG_SP);
4160 /* move return address onto stack */
4162 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4164 /* move pointer to java_objectheader onto stack */
4166 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4167 M_BSR(REG_ITMP3, 0);
4168 M_LSUB_IMM(REG_ITMP3, 3 * 4 + 2 * 8, REG_ITMP3);
4169 M_AST(REG_ITMP3, REG_SP, 3 * 8);
4171 M_AST(REG_ZERO, REG_SP, 3 * 8);
4174 /* move machine code onto stack */
4176 a = dseg_adds4(cd, mcode);
4177 M_ILD(REG_ITMP3, REG_PV, a);
4178 M_IST(REG_ITMP3, REG_SP, 2 * 8);
4180 /* move class/method/field reference onto stack */
4182 a = dseg_addaddress(cd, pref->ref);
4183 M_ALD(REG_ITMP3, REG_PV, a);
4184 M_AST(REG_ITMP3, REG_SP, 1 * 8);
4186 /* move patcher function pointer onto stack */
4188 a = dseg_addaddress(cd, pref->patcher);
4189 M_ALD(REG_ITMP3, REG_PV, a);
4190 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4192 a = dseg_addaddress(cd, asm_wrapper_patcher);
4193 M_ALD(REG_ITMP3, REG_PV, a);
4194 M_JMP(REG_ZERO, REG_ITMP3);
4199 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4203 /* function createcompilerstub *************************************************
4205 creates a stub routine which calls the compiler
4207 *******************************************************************************/
4209 #define COMPSTUBSIZE 3
4211 u1 *createcompilerstub(methodinfo *m)
4213 u8 *s = CNEW(u8, COMPSTUBSIZE); /* memory to hold the stub */
4214 s4 *mcodeptr = (s4 *) s; /* code generation pointer */
4216 /* code for the stub */
4217 M_ALD(REG_PV, REG_PV, 16); /* load pointer to the compiler */
4218 M_JMP(0, REG_PV); /* jump to the compiler, return address
4219 in reg 0 is used as method pointer */
4220 s[1] = (u8) m; /* literals to be adressed */
4221 s[2] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
4223 #if defined(STATISTICS)
4225 count_cstub_len += COMPSTUBSIZE * 8;
4232 /* function removecompilerstub *************************************************
4234 deletes a compilerstub from memory (simply by freeing it)
4236 *******************************************************************************/
4238 void removecompilerstub(u1 *stub)
4240 CFREE(stub, COMPSTUBSIZE * 8);
4244 /* function: createnativestub **************************************************
4246 creates a stub routine which calls a native method
4248 *******************************************************************************/
4251 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4252 #define NATIVESTUB_STACK 8/*ra,native result, oldThreadspecificHeadValue, addressOfThreadspecificHead, method, 0,0,ra*/
4253 #define NATIVESTUB_THREAD_EXTRA (6 + 20) /*20 for additional frame creation*/
4254 #define NATIVESTUB_STACKTRACE_OFFSET 1
4256 #define NATIVESTUB_STACK 7/*ra,oldThreadspecificHeadValue, addressOfThreadspecificHead, method, 0,0,ra*/
4257 #define NATIVESTUB_THREAD_EXTRA (1 + 20) /*20 for additional frame creation*/
4258 #define NATIVESTUB_STACKTRACE_OFFSET 0
4261 #define NATIVESTUB_SIZE (44 + NATIVESTUB_THREAD_EXTRA - 1)
4262 #define NATIVESTUB_STATIC_SIZE 5
4263 #define NATIVESTUB_VERBOSE_SIZE (39 + 13)
4264 #define NATIVESTUB_OFFSET 12
4267 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4268 #define NATIVESTUB_STACK 2
4269 #define NATIVESTUB_THREAD_EXTRA 6
4271 #define NATIVESTUB_STACK 1
4272 #define NATIVESTUB_THREAD_EXTRA 1
4275 #define NATIVESTUB_SIZE (44 + NATIVESTUB_THREAD_EXTRA - 1)
4276 #define NATIVESTUB_STATIC_SIZE 4
4277 #define NATIVESTUB_VERBOSE_SIZE (39 + 13)
4278 #define NATIVESTUB_OFFSET 10
4281 u1 *createnativestub(functionptr f, methodinfo *m)
4283 u8 *s; /* memory pointer to hold the stub */
4285 s4 *mcodeptr; /* code generation pointer */
4286 s4 stackframesize = 0; /* size of stackframe if needed */
4291 t_inlining_globals *id;
4294 /* mark start of dump memory area */
4296 dumpsize = dump_size();
4298 /* setup registers before using it */
4300 cd = DNEW(codegendata);
4301 rd = DNEW(registerdata);
4302 id = DNEW(t_inlining_globals);
4304 inlining_setup(m, id);
4305 reg_setup(m, rd, id);
4307 method_descriptor2types(m); /* set paramcount and paramtypes */
4309 stubsize = NATIVESTUB_SIZE; /* calculate nativestub size */
4311 if ((m->flags & ACC_STATIC) && !m->class->initialized)
4312 stubsize += NATIVESTUB_STATIC_SIZE;
4315 stubsize += NATIVESTUB_VERBOSE_SIZE;
4317 s = CNEW(u8, stubsize); /* memory to hold the stub */
4318 cs = s + NATIVESTUB_OFFSET;
4319 mcodeptr = (s4 *) cs; /* code generation pointer */
4321 /* set some required varibles which are normally set by codegen_setup */
4322 cd->mcodebase = (u1 *) mcodeptr;
4323 cd->patchrefs = NULL;
4325 *(cs-1) = (u8) f; /* address of native method */
4326 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4327 *(cs-2) = (u8) &builtin_get_exceptionptrptr;
4329 *(cs-2) = (u8) (&_exceptionptr); /* address of exceptionptr */
4331 *(cs-3) = (u8) asm_handle_nat_exception; /* addr of asm exception handler*/
4332 *(cs-4) = (u8) (&env); /* addr of jni_environement */
4333 *(cs-5) = (u8) builtin_trace_args;
4335 *(cs-7) = (u8) builtin_displaymethodstop;
4336 *(cs-8) = (u8) m->class;
4337 *(cs-9) = (u8) asm_wrapper_patcher;
4338 *(cs-10) = (u8) &builtin_asm_get_stackframeinfo;
4339 *(cs-11) = (u8) NULL; /* filled with machine code */
4340 *(cs-12) = (u8) PATCHER_clinit;
4342 M_LDA(REG_SP, REG_SP, -NATIVESTUB_STACK * 8); /* build up stackframe */
4343 M_AST(REG_RA, REG_SP, 0 * 8); /* store return address */
4345 M_AST(REG_RA, REG_SP, (6+NATIVESTUB_STACKTRACE_OFFSET) * 8); /* store return address in stackinfo helper*/
4347 /* if function is static, check for initialized */
4349 if (m->flags & ACC_STATIC) {
4350 /* if class isn't yet initialized, do it */
4351 if (!m->class->initialized) {
4352 codegen_addpatchref(cd, mcodeptr, NULL, NULL);
4356 /* max. 39 +9 instructions */
4360 M_LDA(REG_SP, REG_SP, -((INT_ARG_CNT + FLT_ARG_CNT + 2) * 8));
4361 M_AST(REG_RA, REG_SP, 1 * 8);
4363 /* save integer argument registers */
4364 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
4365 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
4368 /* save and copy float arguments into integer registers */
4369 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
4370 t = m->paramtypes[p];
4372 if (IS_FLT_DBL_TYPE(t)) {
4373 if (IS_2_WORD_TYPE(t)) {
4374 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4375 M_LLD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4378 M_FST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4379 M_ILD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4383 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4388 M_ALD(REG_ITMP1, REG_PV, -6 * 8);
4389 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4390 M_ALD(REG_PV, REG_PV, -5 * 8);
4391 M_JSR(REG_RA, REG_PV);
4392 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4393 M_LDA(REG_PV, REG_RA, disp);
4398 M_ALD(REG_PV, REG_PV, -10 * 8); /* builtin_asm_get_stackframeinfo */
4399 M_JSR(REG_RA, REG_PV);
4400 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4401 M_LDA(REG_PV, REG_RA, disp);
4404 M_MOV(REG_RESULT,REG_ITMP3);
4405 M_LST(REG_RESULT,REG_ITMP3,0);
4407 M_LST(REG_RESULT,REG_SP, ((INT_ARG_CNT + FLT_ARG_CNT + 2) * 8)+(2+NATIVESTUB_STACKTRACE_OFFSET)*8);/*save adress of pointer*/
4408 M_LLD(REG_ITMP3,REG_RESULT,0); /* get pointer*/
4409 M_LST(REG_ITMP3,REG_SP,(1+NATIVESTUB_STACKTRACE_OFFSET)*8+((INT_ARG_CNT + FLT_ARG_CNT + 2) * 8)); /*save old value*/
4410 M_LDA(REG_ITMP3,REG_SP,(1+NATIVESTUB_STACKTRACE_OFFSET)*8+((INT_ARG_CNT + FLT_ARG_CNT + 2) * 8)); /*calculate new value*/
4411 M_LLD(REG_ITMP2,REG_ITMP3,8);
4412 M_LST(REG_ITMP3,REG_ITMP2,0); /*store new value*/
4413 M_LLD(REG_ITMP2,REG_PV,-6*8);
4414 M_LST(REG_ITMP2,REG_SP,(3+NATIVESTUB_STACKTRACE_OFFSET)*8+((INT_ARG_CNT + FLT_ARG_CNT + 2) * 8));
4415 M_LST(REG_ZERO,REG_SP,(4+NATIVESTUB_STACKTRACE_OFFSET)*8+((INT_ARG_CNT + FLT_ARG_CNT + 2) * 8));
4416 M_LST(REG_ZERO,REG_SP,(5+NATIVESTUB_STACKTRACE_OFFSET)*8+((INT_ARG_CNT + FLT_ARG_CNT + 2) * 8));
4417 /*stack info -end */
4420 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
4421 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
4424 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
4425 t = m->paramtypes[p];
4427 if (IS_FLT_DBL_TYPE(t)) {
4428 if (IS_2_WORD_TYPE(t)) {
4429 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4432 M_FLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4436 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4440 M_ALD(REG_RA, REG_SP, 1 * 8);
4441 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT + 2) * 8);
4444 /* save argument registers on stack -- if we have to */
4445 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
4447 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
4448 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
4450 stackframesize = stackparamcnt + paramshiftcnt;
4452 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
4454 /* copy stack arguments into new stack frame -- if any */
4455 for (i = 0; i < stackparamcnt; i++) {
4456 M_LLD(REG_ITMP1, REG_SP, (stackparamcnt + 1 + i) * 8);
4457 M_LST(REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
4460 if (m->flags & ACC_STATIC) {
4461 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4462 M_DST(rd->argfltregs[5], REG_SP, 1 * 8);
4464 M_LST(rd->argintregs[5], REG_SP, 1 * 8);
4467 if (IS_FLT_DBL_TYPE(m->paramtypes[4])) {
4468 M_DST(rd->argfltregs[4], REG_SP, 0 * 8);
4470 M_LST(rd->argintregs[4], REG_SP, 0 * 8);
4474 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4475 M_DST(rd->argfltregs[5], REG_SP, 0 * 8);
4477 M_LST(rd->argintregs[5], REG_SP, 0 * 8);
4485 if (m->flags & ACC_STATIC) {
4486 /* shift iargs count if less than INT_ARG_CNT, or all */
4487 for (i = (m->paramcount < (INT_ARG_CNT - 2)) ? m->paramcount : (INT_ARG_CNT - 2); i >= 0; i--) {
4488 M_MOV(rd->argintregs[i], rd->argintregs[i + 2]);
4489 M_FMOV(rd->argfltregs[i], rd->argfltregs[i + 2]);
4492 /* put class into second argument register */
4493 M_ALD(rd->argintregs[1], REG_PV, -8 * 8);
4496 /* shift iargs count if less than INT_ARG_CNT, or all */
4497 for (i = (m->paramcount < (INT_ARG_CNT - 1)) ? m->paramcount : (INT_ARG_CNT - 1); i >= 0; i--) {
4498 M_MOV(rd->argintregs[i], rd->argintregs[i + 1]);
4499 M_FMOV(rd->argfltregs[i], rd->argfltregs[i + 1]);
4504 if (m->flags & ACC_STATIC) {
4505 M_MOV(rd->argintregs[3], rd->argintregs[5]);
4506 M_MOV(rd->argintregs[2], rd->argintregs[4]);
4507 M_MOV(rd->argintregs[1], rd->argintregs[3]);
4508 M_MOV(rd->argintregs[0], rd->argintregs[2]);
4509 M_FMOV(rd->argfltregs[3], rd->argfltregs[5]);
4510 M_FMOV(rd->argfltregs[2], rd->argfltregs[4]);
4511 M_FMOV(rd->argfltregs[1], rd->argfltregs[3]);
4512 M_FMOV(rd->argfltregs[0], rd->argfltregs[2]);
4514 /* put class into second argument register */
4515 M_ALD(rd->argintregs[1], REG_PV, -8 * 8);
4518 M_MOV(rd->argintregs[4], rd->argintregs[5]);
4519 M_MOV(rd->argintregs[3], rd->argintregs[4]);
4520 M_MOV(rd->argintregs[2], rd->argintregs[3]);
4521 M_MOV(rd->argintregs[1], rd->argintregs[2]);
4522 M_MOV(rd->argintregs[0], rd->argintregs[1]);
4523 M_FMOV(rd->argfltregs[4], rd->argfltregs[5]);
4524 M_FMOV(rd->argfltregs[3], rd->argfltregs[4]);
4525 M_FMOV(rd->argfltregs[2], rd->argfltregs[3]);
4526 M_FMOV(rd->argfltregs[1], rd->argfltregs[2]);
4527 M_FMOV(rd->argfltregs[0], rd->argfltregs[1]);
4531 /* put env into first argument register */
4532 M_ALD(rd->argintregs[0], REG_PV, -4 * 8);
4534 M_ALD(REG_PV, REG_PV, -1 * 8); /* load adress of native method */
4535 M_JSR(REG_RA, REG_PV); /* call native method */
4536 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4537 M_LDA(REG_PV, REG_RA, disp); /* recompute pv from ra */
4539 /* remove stackframe if there is one */
4540 if (stackframesize) {
4541 M_LDA(REG_SP, REG_SP, stackframesize * 8);
4544 /* 13 instructions */
4546 M_LDA(REG_SP, REG_SP, -2 * 8);
4547 M_ALD(rd->argintregs[0], REG_PV, -6 * 8); /* load method adress */
4548 M_LST(REG_RESULT, REG_SP, 0 * 8);
4549 M_DST(REG_FRESULT, REG_SP, 1 * 8);
4550 M_MOV(REG_RESULT, rd->argintregs[1]);
4551 M_FMOV(REG_FRESULT, rd->argfltregs[2]);
4552 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
4553 M_ALD(REG_PV, REG_PV, -7 * 8); /* builtin_displaymethodstop */
4554 M_JSR(REG_RA, REG_PV);
4555 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4556 M_LDA(REG_PV, REG_RA, disp);
4557 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4558 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
4559 M_LDA(REG_SP, REG_SP, 2 * 8);
4562 M_LLD(REG_ITMP3,REG_SP,(2+NATIVESTUB_STACKTRACE_OFFSET)*8); /*get address of stacktrace helper pointer*/
4563 M_LLD(REG_ITMP1,REG_SP,(1+NATIVESTUB_STACKTRACE_OFFSET)*8); /*get old value*/
4564 M_LST(REG_ITMP1,REG_ITMP3,0); /*set old value*/
4566 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4567 if (IS_FLT_DBL_TYPE(m->returntype))
4568 M_DST(REG_FRESULT, REG_SP, 1 * 8);
4570 M_AST(REG_RESULT, REG_SP, 1 * 8);
4571 M_ALD(REG_PV, REG_PV, -2 * 8); /* builtin_get_exceptionptrptr */
4572 M_JSR(REG_RA, REG_PV);
4573 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4574 M_LDA(REG_PV, REG_RA, disp);
4575 M_MOV(REG_RESULT, REG_ITMP3);
4576 if (IS_FLT_DBL_TYPE(m->returntype))
4577 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
4579 M_ALD(REG_RESULT, REG_SP, 1 * 8);
4581 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* get address of exceptionptr */
4583 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4584 M_BNEZ(REG_ITMP1, 3); /* if no exception then return */
4586 M_ALD(REG_RA, REG_SP, 0 * 8); /* load return address */
4587 M_LDA(REG_SP, REG_SP, NATIVESTUB_STACK * 8); /* remove stackframe */
4588 M_RET(REG_ZERO, REG_RA); /* return to caller */
4590 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4592 M_ALD(REG_RA, REG_SP, 0 * 8); /* load return address */
4593 M_LDA(REG_SP, REG_SP, NATIVESTUB_STACK * 8); /* remove stackframe */
4594 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4595 M_ALD(REG_ITMP3, REG_PV, -3 * 8); /* load asm exception handler address */
4596 M_JMP(REG_ZERO, REG_ITMP3); /* jump to asm exception handler */
4598 /* generate put/getstatic stub call code */
4605 /* there can only be one <clinit> ref entry */
4606 pref = cd->patchrefs;
4609 /* Get machine code which is patched back in later. The call is */
4610 /* 1 instruction word long. */
4612 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4613 *(cs-11) = (u4) *xcodeptr;
4615 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4616 /* create a virtual java_objectheader */
4618 /* align data structure to 8-byte */
4622 *((ptrint *) (mcodeptr + 0)) = 0; /* vftbl */
4623 *((ptrint *) (mcodeptr + 2)) = (ptrint) get_dummyLR(); /* monitorPtr */
4625 mcodeptr += 2 * 2; /* mcodeptr is a `u4*' pointer */
4628 /* patch in the call to call the following code (done at compile */
4631 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4632 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4634 M_BSR(REG_ITMP3, tmpmcodeptr - (xcodeptr + 1));
4636 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4638 /* create stack frame */
4640 M_LSUB_IMM(REG_SP, 5 * 8, REG_SP);
4642 /* move return address onto stack */
4644 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4646 /* move pointer to java_objectheader onto stack */
4648 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4649 M_BSR(REG_ITMP3, 0);
4650 M_LSUB_IMM(REG_ITMP3, 3 * 4 + 2 * 8, REG_ITMP3);
4651 M_AST(REG_ITMP3, REG_SP, 3 * 8);
4653 M_AST(REG_ZERO, REG_SP, 3 * 8);
4656 /* move machine code onto stack */
4658 M_ILD(REG_ITMP3, REG_PV, -11 * 8); /* machine code */
4659 M_IST(REG_ITMP3, REG_SP, 2 * 8);
4661 /* move class reference onto stack */
4663 M_ALD(REG_ITMP3, REG_PV, -8 * 8); /* class */
4664 M_AST(REG_ITMP3, REG_SP, 1 * 8);
4666 /* move patcher function pointer onto stack */
4668 M_ALD(REG_ITMP3, REG_PV, -12 * 8); /* patcher function */
4669 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4671 M_ALD(REG_ITMP3, REG_PV, -9 * 8); /* asm_wrapper_patcher */
4672 M_JMP(REG_ZERO, REG_ITMP3);
4676 /* Check if the stub size is big enough to hold the whole stub generated. */
4677 /* If not, this can lead into unpredictable crashes, because of heap */
4679 if ((s4) ((ptrint) mcodeptr - (ptrint) s) > stubsize * sizeof(u8)) {
4680 throw_cacao_exception_exit(string_java_lang_InternalError,
4681 "Native stub size %d is to small for current stub size %d",
4682 stubsize, (s4) ((ptrint) mcodeptr - (ptrint) s));
4685 #if defined(STATISTICS)
4687 count_nstub_len += NATIVESTUB_SIZE * 8;
4690 /* release dump area */
4692 dump_release(dumpsize);
4694 return (u1 *) (s + NATIVESTUB_OFFSET);
4698 /* function: removenativestub **************************************************
4700 removes a previously created native-stub from memory
4702 *******************************************************************************/
4704 void removenativestub(u1 *stub)
4706 CFREE((u8 *) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 8);
4711 * These are local overrides for various environment variables in Emacs.
4712 * Please do not remove this and leave it at the end of the file, where
4713 * Emacs will automagically detect them.
4714 * ---------------------------------------------------------------------
4717 * indent-tabs-mode: t