1 /* jit/mips/codegen.c - machine code generator for mips
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 Institut f. Computersprachen, TU Wien
5 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6 S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
9 This file is part of CACAO.
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2, or (at
14 your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Andreas Krall
31 Contains the codegenerator for an MIPS (R4000 or higher) processor.
32 This module generates MIPS machine code for a sequence of
33 intermediate code commands (ICMDs).
35 $Id: codegen.c 1271 2004-07-03 10:35:42Z stefan $
56 /* include independent code generation stuff */
57 #include "codegen.inc"
61 /* *****************************************************************************
63 Datatypes and Register Allocations:
64 -----------------------------------
66 On 64-bit-machines (like the MIPS) all operands are stored in the
67 registers in a 64-bit form, even when the correspondig JavaVM operands
68 only need 32 bits. This is done by a canonical representation:
70 32-bit integers are allways stored as sign-extended 64-bit values (this
71 approach is directly supported by the MIPS architecture and is very easy
74 32-bit-floats are stored in a 64-bit double precision register by simply
75 expanding the exponent and mantissa with zeroes. (also supported by the
81 The calling conventions and the layout of the stack is explained in detail
82 in the documention file: calling.doc
84 *******************************************************************************/
87 /* register descripton - array ************************************************/
89 /* #define REG_RES 0 reserved register for OS or code generator */
90 /* #define REG_RET 1 return value register */
91 /* #define REG_EXC 2 exception value register (only old jit) */
92 /* #define REG_SAV 3 (callee) saved register */
93 /* #define REG_TMP 4 scratch temporary register (caller saved) */
94 /* #define REG_ARG 5 argument register (caller saved) */
96 /* #define REG_END -1 last entry in tables */
99 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
100 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
101 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
102 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
105 /* for use of reserved registers, see comment above */
107 int nregdescfloat[] = {
108 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
109 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
110 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
111 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
114 /* for use of reserved registers, see comment above */
117 /* parameter allocation mode */
119 int nreg_parammode = PARAMMODE_NUMBERED;
121 /* parameter-registers will be allocated by assigning the
122 1. parameter: int/float-reg a0
123 2. parameter: int/float-reg a1
124 3. parameter: int/float-reg a2 ....
128 /* stackframe-infos ***********************************************************/
130 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
132 /* -> see file 'calling.doc' */
135 /* additional functions and macros to generate code ***************************/
137 /* #define BlockPtrOfPC(pc) block+block_index[pc] */
138 #define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
142 #define COUNT_SPILLS count_spills++
148 /* gen_nullptr_check(objreg) */
150 #define gen_nullptr_check(objreg) \
152 M_BEQZ((objreg), 0); \
153 codegen_addxnullrefs(mcodeptr); \
158 /* MCODECHECK(icnt) */
160 #define MCODECHECK(icnt) \
161 if ((mcodeptr + (icnt)) > mcodeend) mcodeptr = codegen_increase((u1 *) mcodeptr)
164 generates an integer-move from register a to b.
165 if a and b are the same int-register, no code will be generated.
168 #define M_INTMOVE(a,b) if (a != b) { M_MOV(a, b); }
172 generates a floating-point-move from register a to b.
173 if a and b are the same float-register, no code will be generated
176 #define M_FLTMOVE(a,b) if (a != b) { M_DMOV(a, b); }
178 #define M_TFLTMOVE(t,a,b) \
182 else {M_FMOV(a,b);} \
185 #define M_TFLD(t,a,b,disp) \
191 #define M_TFST(t,a,b,disp) \
197 #define M_CCFLTMOVE(t1,t2,a,b) \
199 {M_TFLTMOVE(t1,a,b);} \
201 if ((t1)==TYPE_DBL) \
206 #define M_CCFLD(t1,t2,a,b,disp) \
210 M_DLD(REG_FTMP1,b,disp); \
211 if ((t1)==TYPE_DBL) \
212 {M_CVTDF(REG_FTMP1,a);} \
214 {M_CVTFD(REG_FTMP1,a);} \
217 #define M_CCFST(t1,t2,a,b,disp) \
221 if ((t1)==TYPE_DBL) \
222 {M_CVTDF(a,REG_FTMP1);} \
224 {M_CVTFD(a,REG_FTMP1);} \
225 M_DST(REG_FTMP1,b,disp); \
230 this function generates code to fetch data from a pseudo-register
231 into a real register.
232 If the pseudo-register has actually been assigned to a real
233 register, no code will be emitted, since following operations
234 can use this register directly.
236 v: pseudoregister to be fetched from
237 tempregnum: temporary register to be used if v is actually spilled to ram
239 return: the register number, where the operand can be found after
240 fetching (this wil be either tempregnum or the register
241 number allready given to v)
244 #define var_to_reg_int(regnr,v,tempnr) { \
245 if ((v)->flags & INMEMORY) \
246 {COUNT_SPILLS;M_LLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
247 else regnr=(v)->regoff; \
251 #define var_to_reg_flt(regnr,v,tempnr) { \
252 if ((v)->flags & INMEMORY) \
253 {COUNT_SPILLS;M_DLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
254 else regnr=(v)->regoff; \
259 This function determines a register, to which the result of an operation
260 should go, when it is ultimatively intended to store the result in
262 If v is assigned to an actual register, this register will be returned.
263 Otherwise (when v is spilled) this function returns tempregnum.
264 If not already done, regoff and flags are set in the stack location.
267 static int reg_of_var(stackptr v, int tempregnum)
271 switch (v->varkind) {
273 if (!(v->flags & INMEMORY))
277 var = &(interfaces[v->varnum][v->type]);
278 v->regoff = var->regoff;
279 if (!(var->flags & INMEMORY))
283 var = &(locals[v->varnum][v->type]);
284 v->regoff = var->regoff;
285 if (!(var->flags & INMEMORY))
289 v->regoff = v->varnum;
290 if (IS_FLT_DBL_TYPE(v->type)) {
291 if (v->varnum < fltreg_argnum) {
292 v->regoff = argfltregs[v->varnum];
293 return(argfltregs[v->varnum]);
297 if (v->varnum < intreg_argnum) {
298 v->regoff = argintregs[v->varnum];
299 return(argintregs[v->varnum]);
301 v->regoff -= intreg_argnum;
304 v->flags |= INMEMORY;
309 /* store_reg_to_var_xxx:
310 This function generates the code to store the result of an operation
311 back into a spilled pseudo-variable.
312 If the pseudo-variable has not been spilled in the first place, this
313 function will generate nothing.
315 v ............ Pseudovariable
316 tempregnum ... Number of the temporary registers as returned by
320 #define store_reg_to_var_int(sptr, tempregnum) { \
321 if ((sptr)->flags & INMEMORY) { \
323 M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
327 #define store_reg_to_var_flt(sptr, tempregnum) { \
328 if ((sptr)->flags & INMEMORY) { \
330 M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
335 /* NullPointerException handlers and exception handling initialisation */
337 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
338 void thread_restartcriticalsection(ucontext_t *uc)
341 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[CTX_EPC])) != NULL)
342 uc->uc_mcontext.gregs[CTX_EPC] = (u8) critical;
346 /* NullPointerException signal handler for hardware null pointer check */
348 void catch_NullPointerException(int sig, int code, struct sigcontext *sigctx)
353 java_objectheader *xptr;
355 /* Reset signal handler - necessary for SysV, does no harm for BSD */
357 instr = *((int*)(sigctx->sc_pc));
358 faultaddr = sigctx->sc_regs[(instr >> 21) & 0x1f];
360 if (faultaddr == 0) {
362 sigaddset(&nsig, sig);
363 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
365 xptr = new_exception(string_java_lang_NullPointerException);
368 sigctx->sc_regs[REG_ITMP1_XPTR] = (u8) xptr;
369 sigctx->sc_regs[REG_ITMP2_XPC] = sigctx->sc_pc;
370 sigctx->sc_pc = (u8) asm_handle_exception;
373 faultaddr += (long) ((instr << 16) >> 16);
374 fprintf(stderr, "faulting address: 0x%lx at 0x%lx\n", (long) faultaddr, (long) sigctx->sc_pc);
375 panic("Stack overflow");
382 void init_exceptions(void)
385 sigset_t unblockmask;
387 /* The Boehm GC initialization blocks the SIGSEGV signal. So we do a
388 dummy allocation here to ensure that the GC is initialized.
390 heap_allocate(1, 0, NULL);
392 /* install signal handlers we need to convert to exceptions */
394 sigemptyset(&unblockmask);
396 sa.sa_sigaction = catch_NullPointerException;
397 sigemptyset(&sa.sa_mask);
401 sigaction(SIGSEGV, &sa, NULL);
402 sigaddset(&unblockmask, SIGSEGV);
406 sigaction(SIGBUS, &sa, NULL);
407 sigaddset(&unblockmask, SIGBUS);
411 sigprocmask(SIG_UNBLOCK, &unblockmask, NULL);
413 /* Turn off flush-to-zero */
416 n.fc_word = get_fpc_csr();
417 n.fc_struct.flush = 0;
418 set_fpc_csr(n.fc_word);
423 /* function gen_mcode **********************************************************
425 generates machine code
427 *******************************************************************************/
431 int len, s1, s2, s3, d;
443 savedregs_num = (isleafmethod) ? 0 : 1; /* space to save the RA */
445 /* space to save used callee saved registers */
447 savedregs_num += (savintregcnt - maxsavintreguse);
448 savedregs_num += (savfltregcnt - maxsavfltreguse);
450 parentargs_base = maxmemuse + savedregs_num;
452 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
454 if (checksync && (method->flags & ACC_SYNCHRONIZED))
459 /* adjust frame size for 16 byte alignment */
461 if (parentargs_base & 1)
464 /* create method header */
467 (void) dseg_addaddress(method); /* Filler */
469 (void) dseg_addaddress(method); /* MethodPointer */
470 (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
472 #if defined(USE_THREADS)
474 /* IsSync contains the offset relative to the stack pointer for the
475 argument of monitor_exit used in the exception handler. Since the
476 offset could be zero and give a wrong meaning of the flag it is
480 if (checksync && (method->flags & ACC_SYNCHRONIZED))
481 (void) dseg_adds4((maxmemuse + 1) * 8); /* IsSync */
486 (void) dseg_adds4(0); /* IsSync */
488 (void) dseg_adds4(isleafmethod); /* IsLeaf */
489 (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
490 (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
491 (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
493 /* create exception table */
495 for (ex = extable; ex != NULL; ex = ex->down) {
496 dseg_addtarget(ex->start);
497 dseg_addtarget(ex->end);
498 dseg_addtarget(ex->handler);
499 (void) dseg_addaddress(ex->catchtype);
502 /* initialize mcode variables */
504 mcodeptr = (s4*) mcodebase;
505 mcodeend = (s4*) (mcodebase + mcodesize);
506 MCODECHECK(128 + mparamcount);
508 /* create stack frame (if necessary) */
511 {M_LDA(REG_SP, REG_SP, -parentargs_base * 8);}
513 /* save return address and used callee saved registers */
517 {p--; M_LST(REG_RA, REG_SP, 8*p);}
518 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
519 {p--; M_LST(savintregs[r], REG_SP, 8 * p);}
520 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
521 {p--; M_DST(savfltregs[r], REG_SP, 8 * p);}
523 /* save monitorenter argument */
525 #if defined(USE_THREADS)
526 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
527 if (method->flags & ACC_STATIC) {
528 p = dseg_addaddress(class);
529 M_ALD(REG_ITMP1, REG_PV, p);
530 M_AST(REG_ITMP1, REG_SP, maxmemuse * 8);
533 M_AST(argintregs[0], REG_SP, maxmemuse * 8);
538 /* copy argument registers to stack and call trace function with pointer
539 to arguments on stack. ToDo: save floating point registers !!!!!!!!!
543 M_LDA(REG_SP, REG_SP, -(18 * 8));
544 M_LST(REG_RA, REG_SP, 1 * 8);
546 /* save integer argument registers */
547 for (p = 0; p < mparamcount && p < INT_ARG_CNT; p++) {
548 M_LST(argintregs[p], REG_SP, (2 + p) * 8);
551 /* save and copy float arguments into integer registers */
552 for (p = 0; p < mparamcount && p < FLT_ARG_CNT; p++) {
555 if (IS_FLT_DBL_TYPE(t)) {
556 if (IS_2_WORD_TYPE(t)) {
557 M_DST(argfltregs[p], REG_SP, (10 + p) * 8);
558 M_LLD(argintregs[p], REG_SP, (10 + p) * 8);
561 M_FST(argfltregs[p], REG_SP, (10 + p) * 8);
562 M_ILD(argintregs[p], REG_SP, (10 + p) * 8);
566 M_DST(argfltregs[p], REG_SP, (10 + p) * 8);
570 p = dseg_addaddress(method);
571 M_ALD(REG_ITMP1, REG_PV, p);
572 M_LST(REG_ITMP1, REG_SP, 0);
573 p = dseg_addaddress((void *) builtin_trace_args);
574 M_ALD(REG_ITMP3, REG_PV, p);
575 M_JSR(REG_RA, REG_ITMP3);
578 M_LLD(REG_RA, REG_SP, 1 * 8);
580 for (p = 0; p < mparamcount && p < INT_ARG_CNT; p++) {
581 M_LLD(argintregs[p], REG_SP, (2 + p) * 8);
584 for (p = 0; p < mparamcount && p < FLT_ARG_CNT; p++) {
587 if (IS_FLT_DBL_TYPE(t)) {
588 if (IS_2_WORD_TYPE(t)) {
589 M_DLD(argfltregs[p], REG_SP, (10 + p) * 8);
591 M_FLD(argfltregs[p], REG_SP, (10 + p) * 8);
594 M_DLD(argfltregs[p], REG_SP, (10 + p) * 8);
598 M_LDA(REG_SP, REG_SP, 18 * 8);
601 /* take arguments out of register or stack frame */
603 for (p = 0, l = 0; p < mparamcount; p++) {
605 var = &(locals[l][t]);
607 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
612 if (IS_INT_LNG_TYPE(t)) { /* integer args */
613 if (p < INT_ARG_CNT) { /* register arguments */
614 if (!(var->flags & INMEMORY)) /* reg arg -> register */
615 {M_INTMOVE (argintregs[p], r);}
616 else /* reg arg -> spilled */
617 M_LST (argintregs[p], REG_SP, 8 * r);
619 else { /* stack arguments */
620 pa = p - INT_ARG_CNT;
621 if (!(var->flags & INMEMORY)) /* stack arg -> register */
622 M_LLD (r, REG_SP, 8 * (parentargs_base + pa));
623 else { /* stack arg -> spilled */
624 M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
625 M_LST (REG_ITMP1, REG_SP, 8 * r);
629 else { /* floating args */
630 if (p < FLT_ARG_CNT) { /* register arguments */
631 if (!(var->flags & INMEMORY)) /* reg arg -> register */
632 {M_TFLTMOVE (var->type, argfltregs[p], r);}
633 else /* reg arg -> spilled */
634 M_DST (argfltregs[p], REG_SP, 8 * r);
636 else { /* stack arguments */
637 pa = p - FLT_ARG_CNT;
638 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
639 M_DLD (r, REG_SP, 8 * (parentargs_base + pa) );
640 } else { /* stack-arg -> spilled */
641 M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
642 M_DST (REG_FTMP1, REG_SP, 8 * r);
648 /* call trace function */
651 if (runverbose && !isleafmethod) {
652 M_LDA (REG_SP, REG_SP, -8);
653 p = dseg_addaddress (method);
654 M_ALD(REG_ITMP1, REG_PV, p);
655 M_AST(REG_ITMP1, REG_SP, 0);
656 p = dseg_addaddress ((void*) (builtin_trace_args));
657 M_ALD(REG_ITMP3, REG_PV, p);
658 M_JSR(REG_RA, REG_ITMP3);
660 M_LDA(REG_SP, REG_SP, 8);
664 /* call monitorenter function */
666 #if defined(USE_THREADS)
667 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
669 s8 func_enter = (method->flags & ACC_STATIC) ?
670 (s8) builtin_staticmonitorenter : (s8) builtin_monitorenter;
671 p = dseg_addaddress((void *) func_enter);
672 M_ALD(REG_ITMP3, REG_PV, p);
673 M_JSR(REG_RA, REG_ITMP3);
674 M_ALD(argintregs[0], REG_SP, maxmemuse * 8);
675 disp = -(s4)((u1 *) mcodeptr - mcodebase);
676 M_LDA(REG_PV, REG_RA, disp);
681 /* end of header generation */
683 /* walk through all basic blocks */
684 for (bptr = block; bptr != NULL; bptr = bptr->next) {
686 bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
688 if (bptr->flags >= BBREACHED) {
690 /* branch resolving */
694 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
695 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
696 brefs->branchpos, bptr->mpc);
700 /* copy interface registers to their destination */
705 while (src != NULL) {
707 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
708 d = reg_of_var(src, REG_ITMP1);
709 M_INTMOVE(REG_ITMP1, d);
710 store_reg_to_var_int(src, d);
713 d = reg_of_var(src, REG_IFTMP);
714 if ((src->varkind != STACKVAR)) {
716 if (IS_FLT_DBL_TYPE(s2)) {
717 if (!(interfaces[len][s2].flags & INMEMORY)) {
718 s1 = interfaces[len][s2].regoff;
722 M_DLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
724 store_reg_to_var_flt(src, d);
727 if (!(interfaces[len][s2].flags & INMEMORY)) {
728 s1 = interfaces[len][s2].regoff;
732 M_LLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
734 store_reg_to_var_int(src, d);
741 /* walk through all instructions */
745 for (iptr = bptr->iinstr;
747 src = iptr->dst, len--, iptr++) {
749 MCODECHECK(64); /* an instruction usually needs < 64 words */
752 case ICMD_NOP: /* ... ==> ... */
755 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
757 var_to_reg_int(s1, src, REG_ITMP1);
759 codegen_addxnullrefs(mcodeptr);
763 /* constant operations ************************************************/
765 #define ICONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_IADD_IMM(REG_ZERO,c,r);} \
766 else if(((c)>=0)&&((c)<=0xffff)){M_OR_IMM(REG_ZERO,c,r);} \
767 else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
769 #define LCONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LADD_IMM(REG_ZERO,c,r);} \
770 else if(((c)>=0)&&((c)<=0xffff)){M_OR_IMM(REG_ZERO,c,r);} \
771 else{a=dseg_adds8(c);M_LLD(r,REG_PV,a);}
773 case ICMD_ICONST: /* ... ==> ..., constant */
774 /* op1 = 0, val.i = constant */
776 d = reg_of_var(iptr->dst, REG_ITMP1);
777 ICONST(d, iptr->val.i);
778 store_reg_to_var_int(iptr->dst, d);
781 case ICMD_LCONST: /* ... ==> ..., constant */
782 /* op1 = 0, val.l = constant */
784 d = reg_of_var(iptr->dst, REG_ITMP1);
785 LCONST(d, iptr->val.l);
786 store_reg_to_var_int(iptr->dst, d);
789 case ICMD_FCONST: /* ... ==> ..., constant */
790 /* op1 = 0, val.f = constant */
792 d = reg_of_var (iptr->dst, REG_FTMP1);
793 a = dseg_addfloat (iptr->val.f);
795 store_reg_to_var_flt (iptr->dst, d);
798 case ICMD_DCONST: /* ... ==> ..., constant */
799 /* op1 = 0, val.d = constant */
801 d = reg_of_var (iptr->dst, REG_FTMP1);
802 a = dseg_adddouble (iptr->val.d);
804 store_reg_to_var_flt (iptr->dst, d);
807 case ICMD_ACONST: /* ... ==> ..., constant */
808 /* op1 = 0, val.a = constant */
810 d = reg_of_var(iptr->dst, REG_ITMP1);
812 a = dseg_addaddress (iptr->val.a);
816 M_INTMOVE(REG_ZERO, d);
818 store_reg_to_var_int(iptr->dst, d);
822 /* load/store operations **********************************************/
824 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
825 case ICMD_LLOAD: /* op1 = local variable */
828 d = reg_of_var(iptr->dst, REG_ITMP1);
829 if ((iptr->dst->varkind == LOCALVAR) &&
830 (iptr->dst->varnum == iptr->op1))
832 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
833 if (var->flags & INMEMORY)
834 M_LLD(d, REG_SP, 8 * var->regoff);
836 {M_INTMOVE(var->regoff,d);}
837 store_reg_to_var_int(iptr->dst, d);
840 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
841 case ICMD_DLOAD: /* op1 = local variable */
843 d = reg_of_var(iptr->dst, REG_FTMP1);
844 if ((iptr->dst->varkind == LOCALVAR) &&
845 (iptr->dst->varnum == iptr->op1))
847 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
849 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
850 if (var->flags & INMEMORY)
851 {M_CCFLD(var->type,t2,d, REG_SP, 8 * var->regoff);}
853 {M_CCFLTMOVE(var->type,t2,var->regoff,d);}
855 store_reg_to_var_flt(iptr->dst, d);
859 case ICMD_ISTORE: /* ..., value ==> ... */
860 case ICMD_LSTORE: /* op1 = local variable */
863 if ((src->varkind == LOCALVAR) &&
864 (src->varnum == iptr->op1))
866 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
867 if (var->flags & INMEMORY) {
868 var_to_reg_int(s1, src, REG_ITMP1);
869 M_LST(s1, REG_SP, 8 * var->regoff);
872 var_to_reg_int(s1, src, var->regoff);
873 M_INTMOVE(s1, var->regoff);
877 case ICMD_FSTORE: /* ..., value ==> ... */
878 case ICMD_DSTORE: /* op1 = local variable */
880 if ((src->varkind == LOCALVAR) &&
881 (src->varnum == iptr->op1))
883 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
885 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
886 if (var->flags & INMEMORY) {
887 var_to_reg_flt(s1, src, REG_FTMP1);
888 M_CCFST(t1,var->type,s1, REG_SP, 8 * var->regoff);
891 var_to_reg_flt(s1, src, var->regoff);
892 M_CCFLTMOVE(t1,var->type,s1, var->regoff);
898 /* pop/dup/swap operations ********************************************/
900 /* attention: double and longs are only one entry in CACAO ICMDs */
902 case ICMD_POP: /* ..., value ==> ... */
903 case ICMD_POP2: /* ..., value, value ==> ... */
906 #define M_COPY(from,to) \
907 d = reg_of_var(to, REG_IFTMP); \
908 if ((from->regoff != to->regoff) || \
909 ((from->flags ^ to->flags) & INMEMORY)) { \
910 if (IS_FLT_DBL_TYPE(from->type)) { \
911 var_to_reg_flt(s1, from, d); \
912 M_TFLTMOVE(from->type,s1,d); \
913 store_reg_to_var_flt(to, d); \
916 var_to_reg_int(s1, from, d); \
918 store_reg_to_var_int(to, d); \
922 case ICMD_DUP: /* ..., a ==> ..., a, a */
923 M_COPY(src, iptr->dst);
926 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
928 M_COPY(src, iptr->dst->prev->prev);
930 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
932 M_COPY(src, iptr->dst);
933 M_COPY(src->prev, iptr->dst->prev);
936 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
938 M_COPY(src->prev, iptr->dst->prev->prev->prev);
940 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
942 M_COPY(src, iptr->dst);
943 M_COPY(src->prev, iptr->dst->prev);
944 M_COPY(src->prev->prev, iptr->dst->prev->prev);
945 M_COPY(src, iptr->dst->prev->prev->prev);
948 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
950 M_COPY(src, iptr->dst);
951 M_COPY(src->prev, iptr->dst->prev);
952 M_COPY(src->prev->prev, iptr->dst->prev->prev);
953 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
954 M_COPY(src, iptr->dst->prev->prev->prev->prev);
955 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
958 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
960 M_COPY(src, iptr->dst->prev);
961 M_COPY(src->prev, iptr->dst);
965 /* integer operations *************************************************/
967 case ICMD_INEG: /* ..., value ==> ..., - value */
969 var_to_reg_int(s1, src, REG_ITMP1);
970 d = reg_of_var(iptr->dst, REG_ITMP3);
971 M_ISUB(REG_ZERO, s1, d);
972 store_reg_to_var_int(iptr->dst, d);
975 case ICMD_LNEG: /* ..., value ==> ..., - value */
977 var_to_reg_int(s1, src, REG_ITMP1);
978 d = reg_of_var(iptr->dst, REG_ITMP3);
979 M_LSUB(REG_ZERO, s1, d);
980 store_reg_to_var_int(iptr->dst, d);
983 case ICMD_I2L: /* ..., value ==> ..., value */
985 var_to_reg_int(s1, src, REG_ITMP1);
986 d = reg_of_var(iptr->dst, REG_ITMP3);
988 store_reg_to_var_int(iptr->dst, d);
991 case ICMD_L2I: /* ..., value ==> ..., value */
993 var_to_reg_int(s1, src, REG_ITMP1);
994 d = reg_of_var(iptr->dst, REG_ITMP3);
995 M_ISLL_IMM(s1, 0, d );
996 store_reg_to_var_int(iptr->dst, d);
999 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1001 var_to_reg_int(s1, src, REG_ITMP1);
1002 d = reg_of_var(iptr->dst, REG_ITMP3);
1003 M_LSLL_IMM(s1, 56, d);
1004 M_LSRA_IMM( d, 56, d);
1005 store_reg_to_var_int(iptr->dst, d);
1008 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1010 var_to_reg_int(s1, src, REG_ITMP1);
1011 d = reg_of_var(iptr->dst, REG_ITMP3);
1013 store_reg_to_var_int(iptr->dst, d);
1016 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1018 var_to_reg_int(s1, src, REG_ITMP1);
1019 d = reg_of_var(iptr->dst, REG_ITMP3);
1020 M_LSLL_IMM(s1, 48, d);
1021 M_LSRA_IMM( d, 48, d);
1022 store_reg_to_var_int(iptr->dst, d);
1026 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1028 var_to_reg_int(s1, src->prev, REG_ITMP1);
1029 var_to_reg_int(s2, src, REG_ITMP2);
1030 d = reg_of_var(iptr->dst, REG_ITMP3);
1032 store_reg_to_var_int(iptr->dst, d);
1035 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1036 /* val.i = constant */
1038 var_to_reg_int(s1, src, REG_ITMP1);
1039 d = reg_of_var(iptr->dst, REG_ITMP3);
1040 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1041 M_IADD_IMM(s1, iptr->val.i, d);
1044 ICONST(REG_ITMP2, iptr->val.i);
1045 M_IADD(s1, REG_ITMP2, d);
1047 store_reg_to_var_int(iptr->dst, d);
1050 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1052 var_to_reg_int(s1, src->prev, REG_ITMP1);
1053 var_to_reg_int(s2, src, REG_ITMP2);
1054 d = reg_of_var(iptr->dst, REG_ITMP3);
1056 store_reg_to_var_int(iptr->dst, d);
1059 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1060 /* val.l = constant */
1062 var_to_reg_int(s1, src, REG_ITMP1);
1063 d = reg_of_var(iptr->dst, REG_ITMP3);
1064 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
1065 M_LADD_IMM(s1, iptr->val.l, d);
1068 LCONST(REG_ITMP2, iptr->val.l);
1069 M_LADD(s1, REG_ITMP2, d);
1071 store_reg_to_var_int(iptr->dst, d);
1074 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1076 var_to_reg_int(s1, src->prev, REG_ITMP1);
1077 var_to_reg_int(s2, src, REG_ITMP2);
1078 d = reg_of_var(iptr->dst, REG_ITMP3);
1080 store_reg_to_var_int(iptr->dst, d);
1083 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1084 /* val.i = constant */
1086 var_to_reg_int(s1, src, REG_ITMP1);
1087 d = reg_of_var(iptr->dst, REG_ITMP3);
1088 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
1089 M_IADD_IMM(s1, -iptr->val.i, d);
1092 ICONST(REG_ITMP2, iptr->val.i);
1093 M_ISUB(s1, REG_ITMP2, d);
1095 store_reg_to_var_int(iptr->dst, d);
1098 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1100 var_to_reg_int(s1, src->prev, REG_ITMP1);
1101 var_to_reg_int(s2, src, REG_ITMP2);
1102 d = reg_of_var(iptr->dst, REG_ITMP3);
1104 store_reg_to_var_int(iptr->dst, d);
1107 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1108 /* val.l = constant */
1110 var_to_reg_int(s1, src, REG_ITMP1);
1111 d = reg_of_var(iptr->dst, REG_ITMP3);
1112 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
1113 M_LADD_IMM(s1, -iptr->val.l, d);
1116 LCONST(REG_ITMP2, iptr->val.l);
1117 M_LSUB(s1, REG_ITMP2, d);
1119 store_reg_to_var_int(iptr->dst, d);
1122 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1124 var_to_reg_int(s1, src->prev, REG_ITMP1);
1125 var_to_reg_int(s2, src, REG_ITMP2);
1126 d = reg_of_var(iptr->dst, REG_ITMP3);
1131 store_reg_to_var_int(iptr->dst, d);
1134 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1135 /* val.i = constant */
1137 var_to_reg_int(s1, src, REG_ITMP1);
1138 d = reg_of_var(iptr->dst, REG_ITMP3);
1139 ICONST(REG_ITMP2, iptr->val.i);
1140 M_IMUL(s1, REG_ITMP2);
1144 store_reg_to_var_int(iptr->dst, d);
1147 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1149 var_to_reg_int(s1, src->prev, REG_ITMP1);
1150 var_to_reg_int(s2, src, REG_ITMP2);
1151 d = reg_of_var(iptr->dst, REG_ITMP3);
1156 store_reg_to_var_int(iptr->dst, d);
1159 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1160 /* val.l = constant */
1162 var_to_reg_int(s1, src, REG_ITMP1);
1163 d = reg_of_var(iptr->dst, REG_ITMP3);
1164 LCONST(REG_ITMP2, iptr->val.l);
1165 M_LMUL(s1, REG_ITMP2);
1169 store_reg_to_var_int(iptr->dst, d);
1172 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1174 var_to_reg_int(s1, src->prev, REG_ITMP1);
1175 var_to_reg_int(s2, src, REG_ITMP2);
1176 d = reg_of_var(iptr->dst, REG_ITMP3);
1181 store_reg_to_var_int(iptr->dst, d);
1184 case ICMD_IDIVCONST: /* ..., value ==> ..., value / constant */
1185 /* val.i = constant */
1187 var_to_reg_int(s1, src, REG_ITMP1);
1188 d = reg_of_var(iptr->dst, REG_ITMP3);
1189 ICONST(REG_ITMP2, iptr->val.i);
1190 M_IDIV(s1, REG_ITMP2);
1194 store_reg_to_var_int(iptr->dst, d);
1197 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1199 var_to_reg_int(s1, src->prev, REG_ITMP1);
1200 var_to_reg_int(s2, src, REG_ITMP2);
1201 d = reg_of_var(iptr->dst, REG_ITMP3);
1206 store_reg_to_var_int(iptr->dst, d);
1209 case ICMD_LDIVCONST: /* ..., value ==> ..., value / constant */
1210 /* val.l = constant */
1212 var_to_reg_int(s1, src, REG_ITMP1);
1213 d = reg_of_var(iptr->dst, REG_ITMP3);
1214 LCONST(REG_ITMP2, iptr->val.l);
1215 M_LDIV(s1, REG_ITMP2);
1219 store_reg_to_var_int(iptr->dst, d);
1222 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1224 var_to_reg_int(s1, src->prev, REG_ITMP1);
1225 var_to_reg_int(s2, src, REG_ITMP2);
1226 d = reg_of_var(iptr->dst, REG_ITMP3);
1231 store_reg_to_var_int(iptr->dst, d);
1234 case ICMD_IREMCONST: /* ..., value ==> ..., value % constant */
1235 /* val.i = constant */
1237 var_to_reg_int(s1, src, REG_ITMP1);
1238 d = reg_of_var(iptr->dst, REG_ITMP3);
1239 ICONST(REG_ITMP2, iptr->val.i);
1240 M_IDIV(s1, REG_ITMP2);
1244 store_reg_to_var_int(iptr->dst, d);
1247 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1249 var_to_reg_int(s1, src->prev, REG_ITMP1);
1250 var_to_reg_int(s2, src, REG_ITMP2);
1251 d = reg_of_var(iptr->dst, REG_ITMP3);
1256 store_reg_to_var_int(iptr->dst, d);
1259 case ICMD_LREMCONST: /* ..., value ==> ..., value % constant */
1260 /* val.l = constant */
1262 var_to_reg_int(s1, src, REG_ITMP1);
1263 d = reg_of_var(iptr->dst, REG_ITMP3);
1264 LCONST(REG_ITMP2, iptr->val.l);
1265 M_LDIV(s1, REG_ITMP2);
1269 store_reg_to_var_int(iptr->dst, d);
1272 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1273 case ICMD_LDIVPOW2: /* val.i = constant */
1275 var_to_reg_int(s1, src, REG_ITMP1);
1276 d = reg_of_var(iptr->dst, REG_ITMP3);
1277 M_LSRA_IMM(s1, 63, REG_ITMP2);
1278 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1279 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1280 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
1281 store_reg_to_var_int(iptr->dst, d);
1284 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1286 var_to_reg_int(s1, src->prev, REG_ITMP1);
1287 var_to_reg_int(s2, src, REG_ITMP2);
1288 d = reg_of_var(iptr->dst, REG_ITMP3);
1290 store_reg_to_var_int(iptr->dst, d);
1293 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1294 /* val.i = constant */
1296 var_to_reg_int(s1, src, REG_ITMP1);
1297 d = reg_of_var(iptr->dst, REG_ITMP3);
1298 M_ISLL_IMM(s1, iptr->val.i, d);
1299 store_reg_to_var_int(iptr->dst, d);
1302 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1304 var_to_reg_int(s1, src->prev, REG_ITMP1);
1305 var_to_reg_int(s2, src, REG_ITMP2);
1306 d = reg_of_var(iptr->dst, REG_ITMP3);
1308 store_reg_to_var_int(iptr->dst, d);
1311 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1312 /* val.i = constant */
1314 var_to_reg_int(s1, src, REG_ITMP1);
1315 d = reg_of_var(iptr->dst, REG_ITMP3);
1316 M_ISRA_IMM(s1, iptr->val.i, d);
1317 store_reg_to_var_int(iptr->dst, d);
1320 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1322 var_to_reg_int(s1, src->prev, REG_ITMP1);
1323 var_to_reg_int(s2, src, REG_ITMP2);
1324 d = reg_of_var(iptr->dst, REG_ITMP3);
1326 store_reg_to_var_int(iptr->dst, d);
1329 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1330 /* val.i = constant */
1332 var_to_reg_int(s1, src, REG_ITMP1);
1333 d = reg_of_var(iptr->dst, REG_ITMP3);
1334 M_ISRL_IMM(s1, iptr->val.i, d);
1335 store_reg_to_var_int(iptr->dst, d);
1338 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1340 var_to_reg_int(s1, src->prev, REG_ITMP1);
1341 var_to_reg_int(s2, src, REG_ITMP2);
1342 d = reg_of_var(iptr->dst, REG_ITMP3);
1344 store_reg_to_var_int(iptr->dst, d);
1347 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1348 /* val.i = constant */
1350 var_to_reg_int(s1, src, REG_ITMP1);
1351 d = reg_of_var(iptr->dst, REG_ITMP3);
1352 M_LSLL_IMM(s1, iptr->val.i, d);
1353 store_reg_to_var_int(iptr->dst, d);
1356 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1358 var_to_reg_int(s1, src->prev, REG_ITMP1);
1359 var_to_reg_int(s2, src, REG_ITMP2);
1360 d = reg_of_var(iptr->dst, REG_ITMP3);
1362 store_reg_to_var_int(iptr->dst, d);
1365 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1366 /* val.i = constant */
1368 var_to_reg_int(s1, src, REG_ITMP1);
1369 d = reg_of_var(iptr->dst, REG_ITMP3);
1370 M_LSRA_IMM(s1, iptr->val.i, d);
1371 store_reg_to_var_int(iptr->dst, d);
1374 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1376 var_to_reg_int(s1, src->prev, REG_ITMP1);
1377 var_to_reg_int(s2, src, REG_ITMP2);
1378 d = reg_of_var(iptr->dst, REG_ITMP3);
1380 store_reg_to_var_int(iptr->dst, d);
1383 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1384 /* val.i = constant */
1386 var_to_reg_int(s1, src, REG_ITMP1);
1387 d = reg_of_var(iptr->dst, REG_ITMP3);
1388 M_LSRL_IMM(s1, iptr->val.i, d);
1389 store_reg_to_var_int(iptr->dst, d);
1392 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1395 var_to_reg_int(s1, src->prev, REG_ITMP1);
1396 var_to_reg_int(s2, src, REG_ITMP2);
1397 d = reg_of_var(iptr->dst, REG_ITMP3);
1399 store_reg_to_var_int(iptr->dst, d);
1402 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1403 /* val.i = constant */
1405 var_to_reg_int(s1, src, REG_ITMP1);
1406 d = reg_of_var(iptr->dst, REG_ITMP3);
1407 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1408 M_AND_IMM(s1, iptr->val.i, d);
1411 ICONST(REG_ITMP2, iptr->val.i);
1412 M_AND(s1, REG_ITMP2, d);
1414 store_reg_to_var_int(iptr->dst, d);
1417 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1418 /* val.i = constant */
1420 var_to_reg_int(s1, src, REG_ITMP1);
1421 d = reg_of_var(iptr->dst, REG_ITMP3);
1423 M_MOV(s1, REG_ITMP1);
1426 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1427 M_AND_IMM(s1, iptr->val.i, d);
1430 M_ISUB(REG_ZERO, s1, d);
1431 M_AND_IMM(d, iptr->val.i, d);
1434 ICONST(REG_ITMP2, iptr->val.i);
1435 M_AND(s1, REG_ITMP2, d);
1438 M_ISUB(REG_ZERO, s1, d);
1439 M_AND(d, REG_ITMP2, d);
1441 M_ISUB(REG_ZERO, d, d);
1442 store_reg_to_var_int(iptr->dst, d);
1445 case ICMD_IREM0X10001: /* ..., value ==> ..., value % 0x100001 */
1447 /* b = value & 0xffff;
1449 a = ((b - a) & 0xffff) + (b < a);
1451 var_to_reg_int(s1, src, REG_ITMP1);
1452 d = reg_of_var(iptr->dst, REG_ITMP3);
1454 M_MOV(s1, REG_ITMP3);
1458 M_CZEXT(s1, REG_ITMP2); /* delay slot */
1459 M_ISRA_IMM(s1, 16, d);
1460 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1461 M_ISUB(REG_ITMP2, d, d);
1464 M_IADD(d, REG_ITMP1, d); /* delay slot */
1466 M_LUI(REG_ITMP2, 1);
1467 M_IADD_IMM(REG_ITMP2, 1, REG_ITMP2);
1468 M_IDIV(s1, REG_ITMP2);
1472 store_reg_to_var_int(iptr->dst, d);
1475 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1476 /* val.l = constant */
1478 var_to_reg_int(s1, src, REG_ITMP1);
1479 d = reg_of_var(iptr->dst, REG_ITMP3);
1480 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1481 M_AND_IMM(s1, iptr->val.l, d);
1484 LCONST(REG_ITMP2, iptr->val.l);
1485 M_AND(s1, REG_ITMP2, d);
1487 store_reg_to_var_int(iptr->dst, d);
1490 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1491 /* val.l = constant */
1493 var_to_reg_int(s1, src, REG_ITMP1);
1494 d = reg_of_var(iptr->dst, REG_ITMP3);
1496 M_MOV(s1, REG_ITMP1);
1499 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1500 M_AND_IMM(s1, iptr->val.l, d);
1503 M_LSUB(REG_ZERO, s1, d);
1504 M_AND_IMM(d, iptr->val.l, d);
1507 LCONST(REG_ITMP2, iptr->val.l);
1508 M_AND(s1, REG_ITMP2, d);
1511 M_LSUB(REG_ZERO, s1, d);
1512 M_AND(d, REG_ITMP2, d);
1514 M_LSUB(REG_ZERO, d, d);
1515 store_reg_to_var_int(iptr->dst, d);
1518 case ICMD_LREM0X10001:/* ..., value ==> ..., value % 0x10001 */
1520 var_to_reg_int(s1, src, REG_ITMP1);
1521 d = reg_of_var(iptr->dst, REG_ITMP3);
1522 M_LUI(REG_ITMP2, 1);
1523 M_LADD_IMM(REG_ITMP2, 1, REG_ITMP2);
1524 M_LDIV(s1, REG_ITMP2);
1528 store_reg_to_var_int(iptr->dst, d);
1531 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1534 var_to_reg_int(s1, src->prev, REG_ITMP1);
1535 var_to_reg_int(s2, src, REG_ITMP2);
1536 d = reg_of_var(iptr->dst, REG_ITMP3);
1538 store_reg_to_var_int(iptr->dst, d);
1541 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1542 /* val.i = constant */
1544 var_to_reg_int(s1, src, REG_ITMP1);
1545 d = reg_of_var(iptr->dst, REG_ITMP3);
1546 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1547 M_OR_IMM(s1, iptr->val.i, d);
1550 ICONST(REG_ITMP2, iptr->val.i);
1551 M_OR(s1, REG_ITMP2, d);
1553 store_reg_to_var_int(iptr->dst, d);
1556 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1557 /* val.l = constant */
1559 var_to_reg_int(s1, src, REG_ITMP1);
1560 d = reg_of_var(iptr->dst, REG_ITMP3);
1561 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1562 M_OR_IMM(s1, iptr->val.l, d);
1565 LCONST(REG_ITMP2, iptr->val.l);
1566 M_OR(s1, REG_ITMP2, d);
1568 store_reg_to_var_int(iptr->dst, d);
1571 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1574 var_to_reg_int(s1, src->prev, REG_ITMP1);
1575 var_to_reg_int(s2, src, REG_ITMP2);
1576 d = reg_of_var(iptr->dst, REG_ITMP3);
1578 store_reg_to_var_int(iptr->dst, d);
1581 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1582 /* val.i = constant */
1584 var_to_reg_int(s1, src, REG_ITMP1);
1585 d = reg_of_var(iptr->dst, REG_ITMP3);
1586 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1587 M_XOR_IMM(s1, iptr->val.i, d);
1590 ICONST(REG_ITMP2, iptr->val.i);
1591 M_XOR(s1, REG_ITMP2, d);
1593 store_reg_to_var_int(iptr->dst, d);
1596 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1597 /* val.l = constant */
1599 var_to_reg_int(s1, src, REG_ITMP1);
1600 d = reg_of_var(iptr->dst, REG_ITMP3);
1601 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1602 M_XOR_IMM(s1, iptr->val.l, d);
1605 LCONST(REG_ITMP2, iptr->val.l);
1606 M_XOR(s1, REG_ITMP2, d);
1608 store_reg_to_var_int(iptr->dst, d);
1612 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1614 var_to_reg_int(s1, src->prev, REG_ITMP1);
1615 var_to_reg_int(s2, src, REG_ITMP2);
1616 d = reg_of_var(iptr->dst, REG_ITMP3);
1617 M_CMPLT(s1, s2, REG_ITMP3);
1618 M_CMPLT(s2, s1, REG_ITMP1);
1619 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1620 store_reg_to_var_int(iptr->dst, d);
1624 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1625 /* op1 = variable, val.i = constant */
1627 var = &(locals[iptr->op1][TYPE_INT]);
1628 if (var->flags & INMEMORY) {
1630 M_LLD(s1, REG_SP, 8 * var->regoff);
1634 M_IADD_IMM(s1, iptr->val.i, s1);
1635 if (var->flags & INMEMORY)
1636 M_LST(s1, REG_SP, 8 * var->regoff);
1640 /* floating operations ************************************************/
1642 case ICMD_FNEG: /* ..., value ==> ..., - value */
1644 var_to_reg_flt(s1, src, REG_FTMP1);
1645 d = reg_of_var(iptr->dst, REG_FTMP3);
1647 store_reg_to_var_flt(iptr->dst, d);
1650 case ICMD_DNEG: /* ..., value ==> ..., - value */
1652 var_to_reg_flt(s1, src, REG_FTMP1);
1653 d = reg_of_var(iptr->dst, REG_FTMP3);
1655 store_reg_to_var_flt(iptr->dst, d);
1658 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1660 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1661 var_to_reg_flt(s2, src, REG_FTMP2);
1662 d = reg_of_var(iptr->dst, REG_FTMP3);
1664 store_reg_to_var_flt(iptr->dst, d);
1667 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1669 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1670 var_to_reg_flt(s2, src, REG_FTMP2);
1671 d = reg_of_var(iptr->dst, REG_FTMP3);
1673 store_reg_to_var_flt(iptr->dst, d);
1676 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1678 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1679 var_to_reg_flt(s2, src, REG_FTMP2);
1680 d = reg_of_var(iptr->dst, REG_FTMP3);
1682 store_reg_to_var_flt(iptr->dst, d);
1685 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1687 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1688 var_to_reg_flt(s2, src, REG_FTMP2);
1689 d = reg_of_var(iptr->dst, REG_FTMP3);
1691 store_reg_to_var_flt(iptr->dst, d);
1694 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1696 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1697 var_to_reg_flt(s2, src, REG_FTMP2);
1698 d = reg_of_var(iptr->dst, REG_FTMP3);
1700 store_reg_to_var_flt(iptr->dst, d);
1703 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1705 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1706 var_to_reg_flt(s2, src, REG_FTMP2);
1707 d = reg_of_var(iptr->dst, REG_FTMP3);
1709 store_reg_to_var_flt(iptr->dst, d);
1712 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1714 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1715 var_to_reg_flt(s2, src, REG_FTMP2);
1716 d = reg_of_var(iptr->dst, REG_FTMP3);
1718 store_reg_to_var_flt(iptr->dst, d);
1721 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1723 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1724 var_to_reg_flt(s2, src, REG_FTMP2);
1725 d = reg_of_var(iptr->dst, REG_FTMP3);
1727 store_reg_to_var_flt(iptr->dst, d);
1730 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1733 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1734 var_to_reg_flt(s2, src, REG_FTMP2);
1735 d = reg_of_var(iptr->dst, REG_FTMP3);
1736 M_FDIV(s1,s2, REG_FTMP3);
1737 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1738 M_CVTLF(REG_FTMP3, REG_FTMP3);
1739 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1740 M_FSUB(s1, REG_FTMP3, d);
1741 store_reg_to_var_flt(iptr->dst, d);
1744 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1746 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1747 var_to_reg_flt(s2, src, REG_FTMP2);
1748 d = reg_of_var(iptr->dst, REG_FTMP3);
1749 M_DDIV(s1,s2, REG_FTMP3);
1750 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1751 M_CVTLD(REG_FTMP3, REG_FTMP3);
1752 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1753 M_DSUB(s1, REG_FTMP3, d);
1754 store_reg_to_var_flt(iptr->dst, d);
1757 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1759 var_to_reg_int(s1, src, REG_ITMP1);
1760 d = reg_of_var(iptr->dst, REG_FTMP3);
1763 store_reg_to_var_flt(iptr->dst, d);
1766 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1768 var_to_reg_int(s1, src, REG_ITMP1);
1769 d = reg_of_var(iptr->dst, REG_FTMP3);
1772 store_reg_to_var_flt(iptr->dst, d);
1775 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1777 var_to_reg_flt(s1, src, REG_FTMP1);
1778 d = reg_of_var(iptr->dst, REG_ITMP3);
1779 M_TRUNCFI(s1, REG_FTMP1);
1780 M_MOVDI(REG_FTMP1, d);
1782 store_reg_to_var_int(iptr->dst, d);
1785 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1787 var_to_reg_flt(s1, src, REG_FTMP1);
1788 d = reg_of_var(iptr->dst, REG_ITMP3);
1789 M_TRUNCDI(s1, REG_FTMP1);
1790 M_MOVDI(REG_FTMP1, d);
1792 store_reg_to_var_int(iptr->dst, d);
1795 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1797 var_to_reg_flt(s1, src, REG_FTMP1);
1798 d = reg_of_var(iptr->dst, REG_ITMP3);
1799 M_TRUNCFL(s1, REG_FTMP1);
1800 M_MOVDL(REG_FTMP1, d);
1802 store_reg_to_var_int(iptr->dst, d);
1805 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1807 var_to_reg_flt(s1, src, REG_FTMP1);
1808 d = reg_of_var(iptr->dst, REG_ITMP3);
1809 M_TRUNCDL(s1, REG_FTMP1);
1810 M_MOVDL(REG_FTMP1, d);
1812 store_reg_to_var_int(iptr->dst, d);
1815 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1817 var_to_reg_flt(s1, src, REG_FTMP1);
1818 d = reg_of_var(iptr->dst, REG_FTMP3);
1820 store_reg_to_var_flt(iptr->dst, d);
1823 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1825 var_to_reg_flt(s1, src, REG_FTMP1);
1826 d = reg_of_var(iptr->dst, REG_FTMP3);
1828 store_reg_to_var_flt(iptr->dst, d);
1831 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1833 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1834 var_to_reg_flt(s2, src, REG_FTMP2);
1835 d = reg_of_var(iptr->dst, REG_ITMP3);
1838 M_LADD_IMM(REG_ZERO, 1, d);
1842 M_LSUB_IMM(REG_ZERO, 1, d);
1843 M_CMOVT(REG_ZERO, d);
1844 store_reg_to_var_int(iptr->dst, d);
1847 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1849 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1850 var_to_reg_flt(s2, src, REG_FTMP2);
1851 d = reg_of_var(iptr->dst, REG_ITMP3);
1854 M_LADD_IMM(REG_ZERO, 1, d);
1858 M_LSUB_IMM(REG_ZERO, 1, d);
1859 M_CMOVT(REG_ZERO, d);
1860 store_reg_to_var_int(iptr->dst, d);
1863 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1865 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1866 var_to_reg_flt(s2, src, REG_FTMP2);
1867 d = reg_of_var(iptr->dst, REG_ITMP3);
1870 M_LSUB_IMM(REG_ZERO, 1, d);
1874 M_LADD_IMM(REG_ZERO, 1, d);
1875 M_CMOVT(REG_ZERO, d);
1876 store_reg_to_var_int(iptr->dst, d);
1879 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1881 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1882 var_to_reg_flt(s2, src, REG_FTMP2);
1883 d = reg_of_var(iptr->dst, REG_ITMP3);
1886 M_LSUB_IMM(REG_ZERO, 1, d);
1890 M_LADD_IMM(REG_ZERO, 1, d);
1891 M_CMOVT(REG_ZERO, d);
1892 store_reg_to_var_int(iptr->dst, d);
1896 /* memory operations **************************************************/
1898 #define gen_bound_check \
1899 if (checkbounds) { \
1900 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size)); \
1901 M_CMPULT(s2, REG_ITMP3, REG_ITMP3); \
1902 M_BEQZ(REG_ITMP3, 0); \
1903 codegen_addxboundrefs(mcodeptr, s2); \
1907 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1909 var_to_reg_int(s1, src, REG_ITMP1);
1910 d = reg_of_var(iptr->dst, REG_ITMP3);
1911 gen_nullptr_check(s1);
1912 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1913 store_reg_to_var_int(iptr->dst, d);
1916 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1918 var_to_reg_int(s1, src->prev, REG_ITMP1);
1919 var_to_reg_int(s2, src, REG_ITMP2);
1920 d = reg_of_var(iptr->dst, REG_ITMP3);
1921 if (iptr->op1 == 0) {
1922 gen_nullptr_check(s1);
1925 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1926 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1927 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1928 store_reg_to_var_int(iptr->dst, d);
1931 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1933 var_to_reg_int(s1, src->prev, REG_ITMP1);
1934 var_to_reg_int(s2, src, REG_ITMP2);
1935 d = reg_of_var(iptr->dst, REG_ITMP3);
1936 if (iptr->op1 == 0) {
1937 gen_nullptr_check(s1);
1940 M_ASLL_IMM(s2, 2, REG_ITMP2);
1941 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1942 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1943 store_reg_to_var_int(iptr->dst, d);
1946 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1948 var_to_reg_int(s1, src->prev, REG_ITMP1);
1949 var_to_reg_int(s2, src, REG_ITMP2);
1950 d = reg_of_var(iptr->dst, REG_ITMP3);
1951 if (iptr->op1 == 0) {
1952 gen_nullptr_check(s1);
1955 M_ASLL_IMM(s2, 3, REG_ITMP2);
1956 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1957 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1958 store_reg_to_var_int(iptr->dst, d);
1961 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1963 var_to_reg_int(s1, src->prev, REG_ITMP1);
1964 var_to_reg_int(s2, src, REG_ITMP2);
1965 d = reg_of_var(iptr->dst, REG_FTMP3);
1966 if (iptr->op1 == 0) {
1967 gen_nullptr_check(s1);
1970 M_ASLL_IMM(s2, 2, REG_ITMP2);
1971 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1972 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1973 store_reg_to_var_flt(iptr->dst, d);
1976 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1978 var_to_reg_int(s1, src->prev, REG_ITMP1);
1979 var_to_reg_int(s2, src, REG_ITMP2);
1980 d = reg_of_var(iptr->dst, REG_FTMP3);
1981 if (iptr->op1 == 0) {
1982 gen_nullptr_check(s1);
1985 M_ASLL_IMM(s2, 3, REG_ITMP2);
1986 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1987 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1988 store_reg_to_var_flt(iptr->dst, d);
1991 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1993 var_to_reg_int(s1, src->prev, REG_ITMP1);
1994 var_to_reg_int(s2, src, REG_ITMP2);
1995 d = reg_of_var(iptr->dst, REG_ITMP3);
1996 if (iptr->op1 == 0) {
1997 gen_nullptr_check(s1);
2000 M_AADD(s2, s1, REG_ITMP1);
2001 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2002 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2003 store_reg_to_var_int(iptr->dst, d);
2006 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2008 var_to_reg_int(s1, src->prev, REG_ITMP1);
2009 var_to_reg_int(s2, src, REG_ITMP2);
2010 d = reg_of_var(iptr->dst, REG_ITMP3);
2011 if (iptr->op1 == 0) {
2012 gen_nullptr_check(s1);
2015 M_AADD(s2, s1, REG_ITMP1);
2016 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2017 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2018 store_reg_to_var_int(iptr->dst, d);
2021 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2023 var_to_reg_int(s1, src->prev, REG_ITMP1);
2024 var_to_reg_int(s2, src, REG_ITMP2);
2025 d = reg_of_var(iptr->dst, REG_ITMP3);
2026 if (iptr->op1 == 0) {
2027 gen_nullptr_check(s1);
2030 M_AADD(s2, s1, REG_ITMP1);
2031 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2032 store_reg_to_var_int(iptr->dst, d);
2036 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2038 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2039 var_to_reg_int(s2, src->prev, REG_ITMP2);
2040 if (iptr->op1 == 0) {
2041 gen_nullptr_check(s1);
2044 var_to_reg_int(s3, src, REG_ITMP3);
2045 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
2046 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2047 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2050 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2052 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2053 var_to_reg_int(s2, src->prev, REG_ITMP2);
2054 if (iptr->op1 == 0) {
2055 gen_nullptr_check(s1);
2058 var_to_reg_int(s3, src, REG_ITMP3);
2059 M_ASLL_IMM(s2, 2, REG_ITMP2);
2060 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2061 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
2064 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2066 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2067 var_to_reg_int(s2, src->prev, REG_ITMP2);
2068 if (iptr->op1 == 0) {
2069 gen_nullptr_check(s1);
2072 var_to_reg_int(s3, src, REG_ITMP3);
2073 M_ASLL_IMM(s2, 3, REG_ITMP2);
2074 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2075 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
2078 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2080 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2081 var_to_reg_int(s2, src->prev, REG_ITMP2);
2082 if (iptr->op1 == 0) {
2083 gen_nullptr_check(s1);
2086 var_to_reg_flt(s3, src, REG_FTMP3);
2087 M_ASLL_IMM(s2, 2, REG_ITMP2);
2088 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2089 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2092 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2094 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2095 var_to_reg_int(s2, src->prev, REG_ITMP2);
2096 if (iptr->op1 == 0) {
2097 gen_nullptr_check(s1);
2100 var_to_reg_flt(s3, src, REG_FTMP3);
2101 M_ASLL_IMM(s2, 3, REG_ITMP2);
2102 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2103 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2106 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2107 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2109 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2110 var_to_reg_int(s2, src->prev, REG_ITMP2);
2111 if (iptr->op1 == 0) {
2112 gen_nullptr_check(s1);
2115 var_to_reg_int(s3, src, REG_ITMP3);
2116 M_AADD(s2, s1, REG_ITMP1);
2117 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2118 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
2121 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2123 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2124 var_to_reg_int(s2, src->prev, REG_ITMP2);
2125 if (iptr->op1 == 0) {
2126 gen_nullptr_check(s1);
2129 var_to_reg_int(s3, src, REG_ITMP3);
2130 M_AADD(s2, s1, REG_ITMP1);
2131 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2135 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2136 /* op1 = type, val.a = field address */
2138 /* if class isn't yet initialized, do it */
2139 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2140 /* call helper function which patches this code */
2141 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
2142 M_ALD(REG_ITMP1, REG_PV, a);
2143 a = dseg_addaddress(asm_check_clinit);
2144 M_ALD(REG_ITMP3, REG_PV, a);
2145 M_JSR(REG_RA, REG_ITMP3);
2149 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
2151 M_LDA(REG_PV, REG_RA, -s1);
2156 s4 ml = -s1, mh = 0;
2157 while (ml < -32768) { ml += 65536; mh--; }
2159 M_IADD_IMM(REG_PV, ml, REG_PV);
2160 M_LADD(REG_PV, REG_RA, REG_PV);
2165 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2166 M_ALD(REG_ITMP1, REG_PV, a);
2167 switch (iptr->op1) {
2169 var_to_reg_int(s2, src, REG_ITMP2);
2170 M_IST(s2, REG_ITMP1, 0);
2173 var_to_reg_int(s2, src, REG_ITMP2);
2174 M_LST(s2, REG_ITMP1, 0);
2177 var_to_reg_int(s2, src, REG_ITMP2);
2178 M_AST(s2, REG_ITMP1, 0);
2181 var_to_reg_flt(s2, src, REG_FTMP2);
2182 M_FST(s2, REG_ITMP1, 0);
2185 var_to_reg_flt(s2, src, REG_FTMP2);
2186 M_DST(s2, REG_ITMP1, 0);
2188 default: panic ("internal error");
2192 case ICMD_GETSTATIC: /* ... ==> ..., value */
2193 /* op1 = type, val.a = field address */
2195 /* if class isn't yet initialized, do it */
2196 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2197 /* call helper function which patches this code */
2198 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
2199 M_ALD(REG_ITMP1, REG_PV, a);
2200 a = dseg_addaddress(asm_check_clinit);
2201 M_ALD(REG_ITMP3, REG_PV, a);
2202 M_JSR(REG_RA, REG_ITMP3);
2206 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
2208 M_LDA(REG_PV, REG_RA, -s1);
2213 s4 ml = -s1, mh = 0;
2214 while (ml < -32768) { ml += 65536; mh--; }
2216 M_IADD_IMM(REG_PV, ml, REG_PV);
2217 M_LADD(REG_PV, REG_RA, REG_PV);
2222 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2223 M_ALD(REG_ITMP1, REG_PV, a);
2224 switch (iptr->op1) {
2226 d = reg_of_var(iptr->dst, REG_ITMP3);
2227 M_ILD(d, REG_ITMP1, 0);
2228 store_reg_to_var_int(iptr->dst, d);
2231 d = reg_of_var(iptr->dst, REG_ITMP3);
2232 M_LLD(d, REG_ITMP1, 0);
2233 store_reg_to_var_int(iptr->dst, d);
2236 d = reg_of_var(iptr->dst, REG_ITMP3);
2237 M_ALD(d, REG_ITMP1, 0);
2238 store_reg_to_var_int(iptr->dst, d);
2241 d = reg_of_var(iptr->dst, REG_FTMP1);
2242 M_FLD(d, REG_ITMP1, 0);
2243 store_reg_to_var_flt(iptr->dst, d);
2246 d = reg_of_var(iptr->dst, REG_FTMP1);
2247 M_DLD(d, REG_ITMP1, 0);
2248 store_reg_to_var_flt(iptr->dst, d);
2250 default: panic ("internal error");
2255 case ICMD_PUTFIELD: /* ..., value ==> ... */
2256 /* op1 = type, val.i = field offset */
2258 a = ((fieldinfo *)(iptr->val.a))->offset;
2259 switch (iptr->op1) {
2261 var_to_reg_int(s1, src->prev, REG_ITMP1);
2262 var_to_reg_int(s2, src, REG_ITMP2);
2263 gen_nullptr_check(s1);
2267 var_to_reg_int(s1, src->prev, REG_ITMP1);
2268 var_to_reg_int(s2, src, REG_ITMP2);
2269 gen_nullptr_check(s1);
2273 var_to_reg_int(s1, src->prev, REG_ITMP1);
2274 var_to_reg_int(s2, src, REG_ITMP2);
2275 gen_nullptr_check(s1);
2279 var_to_reg_int(s1, src->prev, REG_ITMP1);
2280 var_to_reg_flt(s2, src, REG_FTMP2);
2281 gen_nullptr_check(s1);
2285 var_to_reg_int(s1, src->prev, REG_ITMP1);
2286 var_to_reg_flt(s2, src, REG_FTMP2);
2287 gen_nullptr_check(s1);
2290 default: panic ("internal error");
2294 case ICMD_GETFIELD: /* ... ==> ..., value */
2295 /* op1 = type, val.i = field offset */
2297 a = ((fieldinfo *)(iptr->val.a))->offset;
2298 switch (iptr->op1) {
2300 var_to_reg_int(s1, src, REG_ITMP1);
2301 d = reg_of_var(iptr->dst, REG_ITMP3);
2302 gen_nullptr_check(s1);
2304 store_reg_to_var_int(iptr->dst, d);
2307 var_to_reg_int(s1, src, REG_ITMP1);
2308 d = reg_of_var(iptr->dst, REG_ITMP3);
2309 gen_nullptr_check(s1);
2311 store_reg_to_var_int(iptr->dst, d);
2314 var_to_reg_int(s1, src, REG_ITMP1);
2315 d = reg_of_var(iptr->dst, REG_ITMP3);
2316 gen_nullptr_check(s1);
2318 store_reg_to_var_int(iptr->dst, d);
2321 var_to_reg_int(s1, src, REG_ITMP1);
2322 d = reg_of_var(iptr->dst, REG_FTMP1);
2323 gen_nullptr_check(s1);
2325 store_reg_to_var_flt(iptr->dst, d);
2328 var_to_reg_int(s1, src, REG_ITMP1);
2329 d = reg_of_var(iptr->dst, REG_FTMP1);
2330 gen_nullptr_check(s1);
2332 store_reg_to_var_flt(iptr->dst, d);
2334 default: panic ("internal error");
2339 /* branch operations **************************************************/
2341 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2343 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2345 var_to_reg_int(s1, src, REG_ITMP1);
2346 M_INTMOVE(s1, REG_ITMP1_XPTR);
2347 a = dseg_addaddress(asm_handle_exception);
2348 M_ALD(REG_ITMP2, REG_PV, a);
2349 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2351 M_NOP; /* nop ensures that XPC is less than the end */
2352 /* of basic block */
2356 case ICMD_GOTO: /* ... ==> ... */
2357 /* op1 = target JavaVM pc */
2359 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2364 case ICMD_JSR: /* ... ==> ... */
2365 /* op1 = target JavaVM pc */
2367 dseg_addtarget(BlockPtrOfPC(iptr->op1));
2368 M_ALD(REG_ITMP1, REG_PV, -dseglen);
2369 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2373 case ICMD_RET: /* ... ==> ... */
2374 /* op1 = local variable */
2375 var = &(locals[iptr->op1][TYPE_ADR]);
2376 if (var->flags & INMEMORY) {
2377 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2386 case ICMD_IFNULL: /* ..., value ==> ... */
2387 /* op1 = target JavaVM pc */
2389 var_to_reg_int(s1, src, REG_ITMP1);
2391 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2395 case ICMD_IFNONNULL: /* ..., value ==> ... */
2396 /* op1 = target JavaVM pc */
2398 var_to_reg_int(s1, src, REG_ITMP1);
2400 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2404 case ICMD_IFEQ: /* ..., value ==> ... */
2405 /* op1 = target JavaVM pc, val.i = constant */
2407 var_to_reg_int(s1, src, REG_ITMP1);
2408 if (iptr->val.i == 0) {
2412 ICONST(REG_ITMP2, iptr->val.i);
2413 M_BEQ(s1, REG_ITMP2, 0);
2415 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2419 case ICMD_IFLT: /* ..., value ==> ... */
2420 /* op1 = target JavaVM pc, val.i = constant */
2422 var_to_reg_int(s1, src, REG_ITMP1);
2423 if (iptr->val.i == 0) {
2427 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2428 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2431 ICONST(REG_ITMP2, iptr->val.i);
2432 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2434 M_BNEZ(REG_ITMP1, 0);
2436 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2440 case ICMD_IFLE: /* ..., value ==> ... */
2441 /* op1 = target JavaVM pc, val.i = constant */
2443 var_to_reg_int(s1, src, REG_ITMP1);
2444 if (iptr->val.i == 0) {
2448 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2449 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2450 M_BNEZ(REG_ITMP1, 0);
2453 ICONST(REG_ITMP2, iptr->val.i);
2454 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2455 M_BEQZ(REG_ITMP1, 0);
2458 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2462 case ICMD_IFNE: /* ..., value ==> ... */
2463 /* op1 = target JavaVM pc, val.i = constant */
2465 var_to_reg_int(s1, src, REG_ITMP1);
2466 if (iptr->val.i == 0) {
2470 ICONST(REG_ITMP2, iptr->val.i);
2471 M_BNE(s1, REG_ITMP2, 0);
2473 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2477 case ICMD_IFGT: /* ..., value ==> ... */
2478 /* op1 = target JavaVM pc, val.i = constant */
2480 var_to_reg_int(s1, src, REG_ITMP1);
2481 if (iptr->val.i == 0) {
2485 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2486 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2487 M_BEQZ(REG_ITMP1, 0);
2490 ICONST(REG_ITMP2, iptr->val.i);
2491 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2492 M_BNEZ(REG_ITMP1, 0);
2495 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2499 case ICMD_IFGE: /* ..., value ==> ... */
2500 /* op1 = target JavaVM pc, val.i = constant */
2502 var_to_reg_int(s1, src, REG_ITMP1);
2503 if (iptr->val.i == 0) {
2507 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2508 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2511 ICONST(REG_ITMP2, iptr->val.i);
2512 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2514 M_BEQZ(REG_ITMP1, 0);
2516 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2520 case ICMD_IF_LEQ: /* ..., value ==> ... */
2521 /* op1 = target JavaVM pc, val.l = constant */
2523 var_to_reg_int(s1, src, REG_ITMP1);
2524 if (iptr->val.l == 0) {
2528 LCONST(REG_ITMP2, iptr->val.l);
2529 M_BEQ(s1, REG_ITMP2, 0);
2531 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2535 case ICMD_IF_LLT: /* ..., value ==> ... */
2536 /* op1 = target JavaVM pc, val.l = constant */
2538 var_to_reg_int(s1, src, REG_ITMP1);
2539 if (iptr->val.l == 0) {
2543 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2544 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2547 LCONST(REG_ITMP2, iptr->val.l);
2548 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2550 M_BNEZ(REG_ITMP1, 0);
2552 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2556 case ICMD_IF_LLE: /* ..., value ==> ... */
2557 /* op1 = target JavaVM pc, val.l = constant */
2559 var_to_reg_int(s1, src, REG_ITMP1);
2560 if (iptr->val.l == 0) {
2564 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2565 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2566 M_BNEZ(REG_ITMP1, 0);
2569 LCONST(REG_ITMP2, iptr->val.l);
2570 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2571 M_BEQZ(REG_ITMP1, 0);
2574 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2578 case ICMD_IF_LNE: /* ..., value ==> ... */
2579 /* op1 = target JavaVM pc, val.l = constant */
2581 var_to_reg_int(s1, src, REG_ITMP1);
2582 if (iptr->val.l == 0) {
2586 LCONST(REG_ITMP2, iptr->val.l);
2587 M_BNE(s1, REG_ITMP2, 0);
2589 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2593 case ICMD_IF_LGT: /* ..., value ==> ... */
2594 /* op1 = target JavaVM pc, val.l = constant */
2596 var_to_reg_int(s1, src, REG_ITMP1);
2597 if (iptr->val.l == 0) {
2601 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2602 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2603 M_BEQZ(REG_ITMP1, 0);
2606 LCONST(REG_ITMP2, iptr->val.l);
2607 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2608 M_BNEZ(REG_ITMP1, 0);
2611 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2615 case ICMD_IF_LGE: /* ..., value ==> ... */
2616 /* op1 = target JavaVM pc, val.l = constant */
2618 var_to_reg_int(s1, src, REG_ITMP1);
2619 if (iptr->val.l == 0) {
2623 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2624 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2627 LCONST(REG_ITMP2, iptr->val.l);
2628 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2630 M_BEQZ(REG_ITMP1, 0);
2632 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2636 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2637 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2638 case ICMD_IF_ACMPEQ:
2640 var_to_reg_int(s1, src->prev, REG_ITMP1);
2641 var_to_reg_int(s2, src, REG_ITMP2);
2643 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2647 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2648 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2649 case ICMD_IF_ACMPNE:
2651 var_to_reg_int(s1, src->prev, REG_ITMP1);
2652 var_to_reg_int(s2, src, REG_ITMP2);
2654 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2658 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2659 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2661 var_to_reg_int(s1, src->prev, REG_ITMP1);
2662 var_to_reg_int(s2, src, REG_ITMP2);
2663 M_CMPLT(s1, s2, REG_ITMP1);
2664 M_BNEZ(REG_ITMP1, 0);
2665 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2669 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2670 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2672 var_to_reg_int(s1, src->prev, REG_ITMP1);
2673 var_to_reg_int(s2, src, REG_ITMP2);
2674 M_CMPGT(s1, s2, REG_ITMP1);
2675 M_BNEZ(REG_ITMP1, 0);
2676 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2680 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2681 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2683 var_to_reg_int(s1, src->prev, REG_ITMP1);
2684 var_to_reg_int(s2, src, REG_ITMP2);
2685 M_CMPGT(s1, s2, REG_ITMP1);
2686 M_BEQZ(REG_ITMP1, 0);
2687 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2691 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2692 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2694 var_to_reg_int(s1, src->prev, REG_ITMP1);
2695 var_to_reg_int(s2, src, REG_ITMP2);
2696 M_CMPLT(s1, s2, REG_ITMP1);
2697 M_BEQZ(REG_ITMP1, 0);
2698 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2702 #ifdef CONDITIONAL_LOADCONST
2703 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2705 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2708 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2709 /* val.i = constant */
2711 var_to_reg_int(s1, src, REG_ITMP1);
2712 d = reg_of_var(iptr->dst, REG_ITMP3);
2714 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2715 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2716 M_CMPEQ(s1, REG_ZERO, d);
2717 store_reg_to_var_int(iptr->dst, d);
2720 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2721 M_CMPEQ(s1, REG_ZERO, d);
2723 store_reg_to_var_int(iptr->dst, d);
2727 M_MOV(s1, REG_ITMP1);
2730 ICONST(d, iptr[1].val.i);
2732 if ((s3 >= 0) && (s3 <= 255)) {
2733 M_CMOVEQ_IMM(s1, s3, d);
2736 ICONST(REG_ITMP2, s3);
2737 M_CMOVEQ(s1, REG_ITMP2, d);
2739 store_reg_to_var_int(iptr->dst, d);
2742 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2743 /* val.i = constant */
2745 var_to_reg_int(s1, src, REG_ITMP1);
2746 d = reg_of_var(iptr->dst, REG_ITMP3);
2748 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2749 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2750 M_CMPEQ(s1, REG_ZERO, d);
2751 store_reg_to_var_int(iptr->dst, d);
2754 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2755 M_CMPEQ(s1, REG_ZERO, d);
2757 store_reg_to_var_int(iptr->dst, d);
2761 M_MOV(s1, REG_ITMP1);
2764 ICONST(d, iptr[1].val.i);
2766 if ((s3 >= 0) && (s3 <= 255)) {
2767 M_CMOVNE_IMM(s1, s3, d);
2770 ICONST(REG_ITMP2, s3);
2771 M_CMOVNE(s1, REG_ITMP2, d);
2773 store_reg_to_var_int(iptr->dst, d);
2776 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2777 /* val.i = constant */
2779 var_to_reg_int(s1, src, REG_ITMP1);
2780 d = reg_of_var(iptr->dst, REG_ITMP3);
2782 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2783 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2784 M_CMPLT(s1, REG_ZERO, d);
2785 store_reg_to_var_int(iptr->dst, d);
2788 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2789 M_CMPLE(REG_ZERO, s1, d);
2790 store_reg_to_var_int(iptr->dst, d);
2794 M_MOV(s1, REG_ITMP1);
2797 ICONST(d, iptr[1].val.i);
2799 if ((s3 >= 0) && (s3 <= 255)) {
2800 M_CMOVLT_IMM(s1, s3, d);
2803 ICONST(REG_ITMP2, s3);
2804 M_CMOVLT(s1, REG_ITMP2, d);
2806 store_reg_to_var_int(iptr->dst, d);
2809 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2810 /* val.i = constant */
2812 var_to_reg_int(s1, src, REG_ITMP1);
2813 d = reg_of_var(iptr->dst, REG_ITMP3);
2815 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2816 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2817 M_CMPLE(REG_ZERO, s1, d);
2818 store_reg_to_var_int(iptr->dst, d);
2821 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2822 M_CMPLT(s1, REG_ZERO, d);
2823 store_reg_to_var_int(iptr->dst, d);
2827 M_MOV(s1, REG_ITMP1);
2830 ICONST(d, iptr[1].val.i);
2832 if ((s3 >= 0) && (s3 <= 255)) {
2833 M_CMOVGE_IMM(s1, s3, d);
2836 ICONST(REG_ITMP2, s3);
2837 M_CMOVGE(s1, REG_ITMP2, d);
2839 store_reg_to_var_int(iptr->dst, d);
2842 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2843 /* val.i = constant */
2845 var_to_reg_int(s1, src, REG_ITMP1);
2846 d = reg_of_var(iptr->dst, REG_ITMP3);
2848 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2849 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2850 M_CMPLT(REG_ZERO, s1, d);
2851 store_reg_to_var_int(iptr->dst, d);
2854 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2855 M_CMPLE(s1, REG_ZERO, d);
2856 store_reg_to_var_int(iptr->dst, d);
2860 M_MOV(s1, REG_ITMP1);
2863 ICONST(d, iptr[1].val.i);
2865 if ((s3 >= 0) && (s3 <= 255)) {
2866 M_CMOVGT_IMM(s1, s3, d);
2869 ICONST(REG_ITMP2, s3);
2870 M_CMOVGT(s1, REG_ITMP2, d);
2872 store_reg_to_var_int(iptr->dst, d);
2875 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2876 /* val.i = constant */
2878 var_to_reg_int(s1, src, REG_ITMP1);
2879 d = reg_of_var(iptr->dst, REG_ITMP3);
2881 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2882 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2883 M_CMPLE(s1, REG_ZERO, d);
2884 store_reg_to_var_int(iptr->dst, d);
2887 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2888 M_CMPLT(REG_ZERO, s1, d);
2889 store_reg_to_var_int(iptr->dst, d);
2893 M_MOV(s1, REG_ITMP1);
2896 ICONST(d, iptr[1].val.i);
2898 if ((s3 >= 0) && (s3 <= 255)) {
2899 M_CMOVLE_IMM(s1, s3, d);
2902 ICONST(REG_ITMP2, s3);
2903 M_CMOVLE(s1, REG_ITMP2, d);
2905 store_reg_to_var_int(iptr->dst, d);
2910 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2914 #if defined(USE_THREADS)
2915 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2917 a = dseg_addaddress((void *) (builtin_monitorexit));
2918 M_ALD(REG_ITMP3, REG_PV, a);
2919 M_JSR(REG_RA, REG_ITMP3);
2920 M_ALD(argintregs[0], REG_SP, maxmemuse * 8); /* delay slot */
2921 disp = -(s4) ((u1 *) mcodeptr - mcodebase);
2922 M_LDA(REG_PV, REG_RA, disp);
2925 var_to_reg_int(s1, src, REG_RESULT);
2926 M_INTMOVE(s1, REG_RESULT);
2927 goto nowperformreturn;
2929 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2932 #if defined(USE_THREADS)
2933 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2935 a = dseg_addaddress((void *) (builtin_monitorexit));
2936 M_ALD(REG_ITMP3, REG_PV, a);
2937 M_JSR(REG_RA, REG_ITMP3);
2938 M_ALD(argintregs[0], REG_SP, maxmemuse * 8); /* delay slot */
2939 disp = -(s4) ((u1 *) mcodeptr - mcodebase);
2940 M_LDA(REG_PV, REG_RA, disp);
2943 var_to_reg_flt(s1, src, REG_FRESULT);
2945 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2946 M_TFLTMOVE(t, s1, REG_FRESULT);
2948 goto nowperformreturn;
2950 case ICMD_RETURN: /* ... ==> ... */
2952 #if defined(USE_THREADS)
2953 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2955 a = dseg_addaddress((void *) (builtin_monitorexit));
2956 M_ALD(REG_ITMP3, REG_PV, a);
2957 M_JSR(REG_RA, REG_ITMP3);
2958 M_ALD(argintregs[0], REG_SP, maxmemuse * 8); /* delay slot */
2959 disp = -(s4) ((u1 *) mcodeptr - mcodebase);
2960 M_LDA(REG_PV, REG_RA, disp);
2968 p = parentargs_base;
2970 /* restore return address */
2973 {p--; M_LLD (REG_RA, REG_SP, 8 * p);}
2975 /* restore saved registers */
2977 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
2978 {p--; M_LLD(savintregs[r], REG_SP, 8 * p);}
2979 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
2980 {p--; M_DLD(savfltregs[r], REG_SP, 8 * p);}
2982 /* call trace function */
2985 M_LDA (REG_SP, REG_SP, -24);
2986 M_LST(REG_RA, REG_SP, 0);
2987 M_LST(REG_RESULT, REG_SP, 8);
2988 M_DST(REG_FRESULT, REG_SP,16);
2989 a = dseg_addaddress (method);
2990 M_ALD(argintregs[0], REG_PV, a);
2991 M_MOV(REG_RESULT, argintregs[1]);
2992 M_FLTMOVE(REG_FRESULT, argfltregs[2]);
2993 M_FMOV(REG_FRESULT, argfltregs[3]);
2994 a = dseg_addaddress ((void*) (builtin_displaymethodstop));
2995 M_ALD(REG_ITMP3, REG_PV, a);
2996 M_JSR (REG_RA, REG_ITMP3);
2998 M_DLD(REG_FRESULT, REG_SP,16);
2999 M_LLD(REG_RESULT, REG_SP, 8);
3000 M_LLD(REG_RA, REG_SP, 0);
3001 M_LDA (REG_SP, REG_SP, 24);
3006 /* deallocate stack */
3008 if (parentargs_base)
3009 {M_LDA(REG_SP, REG_SP, parentargs_base*8);}
3017 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3022 tptr = (void **) iptr->target;
3024 s4ptr = iptr->val.a;
3025 l = s4ptr[1]; /* low */
3026 i = s4ptr[2]; /* high */
3028 var_to_reg_int(s1, src, REG_ITMP1);
3030 {M_INTMOVE(s1, REG_ITMP1);}
3031 else if (l <= 32768) {
3032 M_IADD_IMM(s1, -l, REG_ITMP1);
3035 ICONST(REG_ITMP2, l);
3036 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3042 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
3043 M_BEQZ(REG_ITMP2, 0);
3044 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3045 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
3047 /* build jump table top down and use address of lowest entry */
3049 /* s4ptr += 3 + i; */
3053 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3054 dseg_addtarget((basicblock *) tptr[0]);
3059 /* length of dataseg after last dseg_addtarget is used by load */
3061 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
3062 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
3069 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3071 s4 i, /*l, */val, *s4ptr;
3074 tptr = (void **) iptr->target;
3076 s4ptr = iptr->val.a;
3077 /*l = s4ptr[0];*/ /* default */
3078 i = s4ptr[1]; /* count */
3080 MCODECHECK((i<<2)+8);
3081 var_to_reg_int(s1, src, REG_ITMP1);
3087 ICONST(REG_ITMP2, val);
3088 M_BEQ(s1, REG_ITMP2, 0);
3089 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3094 tptr = (void **) iptr->target;
3095 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3102 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3103 /* op1 = return type, val.a = function pointer*/
3107 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3108 /* op1 = return type, val.a = function pointer*/
3112 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3113 /* op1 = return type, val.a = function pointer*/
3117 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3118 /* op1 = arg count, val.a = method pointer */
3120 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3121 /* op1 = arg count, val.a = method pointer */
3123 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3124 /* op1 = arg count, val.a = method pointer */
3126 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3127 /* op1 = arg count, val.a = method pointer */
3135 MCODECHECK((s3 << 1) + 64);
3137 /* copy arguments to registers or stack location */
3139 for (; --s3 >= 0; src = src->prev) {
3140 if (src->varkind == ARGVAR)
3142 if (IS_INT_LNG_TYPE(src->type)) {
3143 if (s3 < INT_ARG_CNT) {
3144 s1 = argintregs[s3];
3145 var_to_reg_int(d, src, s1);
3149 var_to_reg_int(d, src, REG_ITMP1);
3150 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3154 if (s3 < FLT_ARG_CNT) {
3155 s1 = argfltregs[s3];
3156 var_to_reg_flt(d, src, s1);
3157 M_TFLTMOVE(src->type,d, s1);
3160 var_to_reg_flt(d, src, REG_FTMP1);
3161 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3166 switch (iptr->opc) {
3170 a = dseg_addaddress ((void*) (m));
3171 M_ALD(REG_ITMP3, REG_PV, a); /* built-in-function pointer */
3172 M_JSR (REG_RA, REG_ITMP3);
3174 d = iptr->op1; /* return type */
3175 goto afteractualcall;
3177 case ICMD_INVOKESTATIC:
3178 case ICMD_INVOKESPECIAL:
3179 a = dseg_addaddress (m->stubroutine);
3181 M_ALD(REG_PV, REG_PV, a ); /* method pointer in pv */
3184 goto makeactualcall;
3186 case ICMD_INVOKEVIRTUAL:
3188 gen_nullptr_check(argintregs[0]);
3189 M_ALD(REG_METHODPTR, argintregs[0],
3190 OFFSET(java_objectheader, vftbl));
3191 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
3192 sizeof(methodptr) * m->vftblindex);
3195 goto makeactualcall;
3197 case ICMD_INVOKEINTERFACE:
3200 gen_nullptr_check(argintregs[0]);
3201 M_ALD(REG_METHODPTR, argintregs[0],
3202 OFFSET(java_objectheader, vftbl));
3203 M_ALD(REG_METHODPTR, REG_METHODPTR,
3204 OFFSET(vftbl, interfacetable[0]) -
3205 sizeof(methodptr*) * ci->index);
3206 M_ALD(REG_PV, REG_METHODPTR,
3207 sizeof(methodptr) * (m - ci->methods));
3210 goto makeactualcall;
3214 error ("Unkown ICMD-Command: %d", iptr->opc);
3219 M_JSR (REG_RA, REG_PV);
3226 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3227 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3229 s4 ml = -s1, mh = 0;
3230 while (ml < -32768) { ml += 65536; mh--; }
3232 M_IADD_IMM(REG_PV, ml, REG_PV);
3233 M_LADD(REG_PV, REG_RA, REG_PV);
3236 /* d contains return type */
3238 if (d != TYPE_VOID) {
3239 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3240 s1 = reg_of_var(iptr->dst, REG_RESULT);
3241 M_INTMOVE(REG_RESULT, s1);
3242 store_reg_to_var_int(iptr->dst, s1);
3245 s1 = reg_of_var(iptr->dst, REG_FRESULT);
3246 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3247 store_reg_to_var_flt(iptr->dst, s1);
3254 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3256 /* op1: 0 == array, 1 == class */
3257 /* val.a: (classinfo*) superclass */
3259 /* superclass is an interface:
3261 * return (sub != NULL) &&
3262 * (sub->vftbl->interfacetablelength > super->index) &&
3263 * (sub->vftbl->interfacetable[-super->index] != NULL);
3265 * superclass is a class:
3267 * return ((sub != NULL) && (0
3268 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3269 * super->vftbl->diffvall));
3273 classinfo *super = (classinfo*) iptr->val.a;
3275 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3276 codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
3278 var_to_reg_int(s1, src, REG_ITMP1);
3279 d = reg_of_var(iptr->dst, REG_ITMP3);
3281 M_MOV(s1, REG_ITMP1);
3285 if (iptr->op1) { /* class/interface */
3286 if (super->flags & ACC_INTERFACE) { /* interface */
3289 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3290 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3291 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3292 M_BLEZ(REG_ITMP2, 3);
3294 M_ALD(REG_ITMP1, REG_ITMP1,
3295 OFFSET(vftbl, interfacetable[0]) -
3296 super->index * sizeof(methodptr*));
3297 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3301 s2 = super->vftbl->diffval;
3304 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3305 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3306 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3307 M_CMPULT_IMM(REG_ITMP1, s2 + 1, d);
3312 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3313 a = dseg_addaddress ((void*) super->vftbl);
3314 M_ALD(REG_ITMP2, REG_PV, a);
3315 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3316 codegen_threadcritstart((u1*) mcodeptr - mcodebase);
3318 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3319 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3320 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3321 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3322 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
3324 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3325 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3331 panic ("internal error: no inlined array instanceof");
3333 store_reg_to_var_int(iptr->dst, d);
3336 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3338 /* op1: 0 == array, 1 == class */
3339 /* val.a: (classinfo*) superclass */
3341 /* superclass is an interface:
3343 * OK if ((sub == NULL) ||
3344 * (sub->vftbl->interfacetablelength > super->index) &&
3345 * (sub->vftbl->interfacetable[-super->index] != NULL));
3347 * superclass is a class:
3349 * OK if ((sub == NULL) || (0
3350 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3351 * super->vftbl->diffvall));
3355 classinfo *super = (classinfo*) iptr->val.a;
3357 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3358 codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
3361 d = reg_of_var(iptr->dst, REG_ITMP3);
3362 var_to_reg_int(s1, src, d);
3363 if (iptr->op1) { /* class/interface */
3364 if (super->flags & ACC_INTERFACE) { /* interface */
3367 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3368 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3369 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3370 M_BLEZ(REG_ITMP2, 0);
3371 codegen_addxcastrefs(mcodeptr);
3373 M_ALD(REG_ITMP2, REG_ITMP1,
3374 OFFSET(vftbl, interfacetable[0]) -
3375 super->index * sizeof(methodptr*));
3376 M_BEQZ(REG_ITMP2, 0);
3377 codegen_addxcastrefs(mcodeptr);
3383 s2 = super->vftbl->diffval;
3384 M_BEQZ(s1, 6 + (s2 != 0));
3386 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3387 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3388 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3390 M_BNEZ(REG_ITMP1, 0);
3393 M_CMPULT_IMM(REG_ITMP1, s2 + 1, REG_ITMP2);
3394 M_BEQZ(REG_ITMP2, 0);
3398 M_BEQZ(s1, 10 + (d == REG_ITMP3));
3400 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3401 a = dseg_addaddress ((void*) super->vftbl);
3402 M_ALD(REG_ITMP2, REG_PV, a);
3403 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3404 codegen_threadcritstart((u1*) mcodeptr - mcodebase);
3406 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3407 if (d != REG_ITMP3) {
3408 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3409 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3410 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3411 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
3413 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3415 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, baseval));
3416 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3417 M_ALD(REG_ITMP2, REG_PV, a);
3418 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3419 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3420 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
3423 M_CMPULT(REG_ITMP2, REG_ITMP1, REG_ITMP2);
3424 M_BNEZ(REG_ITMP2, 0);
3426 codegen_addxcastrefs(mcodeptr);
3431 panic ("internal error: no inlined array checkcast");
3434 store_reg_to_var_int(iptr->dst, d);
3437 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3439 var_to_reg_int(s1, src, REG_ITMP1);
3441 codegen_addxcheckarefs(mcodeptr);
3445 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3447 M_BEQZ(REG_RESULT, 0);
3448 codegen_addxexceptionrefs(mcodeptr);
3452 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3453 /* op1 = dimension, val.a = array descriptor */
3455 /* check for negative sizes and copy sizes to stack if necessary */
3457 MCODECHECK((iptr->op1 << 1) + 64);
3459 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3460 var_to_reg_int(s2, src, REG_ITMP1);
3462 codegen_addxcheckarefs(mcodeptr);
3465 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3467 if (src->varkind != ARGVAR) {
3468 M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
3472 /* a0 = dimension count */
3474 ICONST(argintregs[0], iptr->op1);
3476 /* a1 = arraydescriptor */
3478 a = dseg_addaddress(iptr->val.a);
3479 M_ALD(argintregs[1], REG_PV, a);
3481 /* a2 = pointer to dimensions = stack pointer */
3483 M_INTMOVE(REG_SP, argintregs[2]);
3485 a = dseg_addaddress((void*) (builtin_nmultianewarray));
3486 M_ALD(REG_ITMP3, REG_PV, a);
3487 M_JSR(REG_RA, REG_ITMP3);
3489 s1 = (int)((u1*) mcodeptr - mcodebase);
3491 M_LDA (REG_PV, REG_RA, -s1);
3495 s1 = reg_of_var(iptr->dst, REG_RESULT);
3496 M_INTMOVE(REG_RESULT, s1);
3497 store_reg_to_var_int(iptr->dst, s1);
3501 default: error ("Unknown pseudo command: %d", iptr->opc);
3507 } /* for instruction */
3509 /* copy values to interface registers */
3511 src = bptr->outstack;
3512 len = bptr->outdepth;
3516 if ((src->varkind != STACKVAR)) {
3518 if (IS_FLT_DBL_TYPE(s2)) {
3519 var_to_reg_flt(s1, src, REG_FTMP1);
3520 if (!(interfaces[len][s2].flags & INMEMORY)) {
3521 M_TFLTMOVE(s2,s1,interfaces[len][s2].regoff);
3524 M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3528 var_to_reg_int(s1, src, REG_ITMP1);
3529 if (!(interfaces[len][s2].flags & INMEMORY)) {
3530 M_INTMOVE(s1,interfaces[len][s2].regoff);
3533 M_LST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3539 } /* if (bptr -> flags >= BBREACHED) */
3540 } /* for basic block */
3542 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3545 /* generate bound check stubs */
3547 s4 *xcodeptr = NULL;
3549 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3550 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3551 xboundrefs->branchpos,
3552 (u1*) mcodeptr - mcodebase);
3556 M_MOV(xboundrefs->reg, REG_ITMP1);
3557 M_LADD_IMM(REG_PV, xboundrefs->branchpos - 4, REG_ITMP2_XPC);
3559 if (xcodeptr != NULL) {
3560 M_BR(xcodeptr - mcodeptr);
3564 xcodeptr = mcodeptr;
3566 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3567 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3569 a = dseg_addaddress(string_java_lang_ArrayIndexOutOfBoundsException);
3570 M_ALD(argintregs[0], REG_PV, a);
3571 M_MOV(REG_ITMP1, argintregs[1]);
3573 a = dseg_addaddress(new_exception_int);
3574 M_ALD(REG_ITMP3, REG_PV, a);
3575 M_JSR(REG_RA, REG_ITMP3);
3577 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3579 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3580 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3582 a = dseg_addaddress(asm_handle_exception);
3583 M_ALD(REG_ITMP3, REG_PV, a);
3589 /* generate negative array size check stubs */
3593 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3594 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3595 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3596 xcheckarefs->branchpos,
3597 (u1*) xcodeptr - (u1*) mcodebase - 4);
3601 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3602 xcheckarefs->branchpos,
3603 (u1*) mcodeptr - mcodebase);
3607 M_LADD_IMM(REG_PV, xcheckarefs->branchpos - 4, REG_ITMP2_XPC);
3609 if (xcodeptr != NULL) {
3610 M_BR(xcodeptr - mcodeptr);
3614 xcodeptr = mcodeptr;
3616 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3617 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3619 a = dseg_addaddress(string_java_lang_NegativeArraySizeException);
3620 M_ALD(argintregs[0], REG_PV, a);
3622 a = dseg_addaddress(new_exception);
3623 M_ALD(REG_ITMP3, REG_PV, a);
3624 M_JSR(REG_RA, REG_ITMP3);
3626 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3628 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3629 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3631 a = dseg_addaddress(asm_handle_exception);
3632 M_ALD(REG_ITMP3, REG_PV, a);
3638 /* generate cast check stubs */
3642 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3643 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3644 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3645 xcastrefs->branchpos,
3646 (u1*) xcodeptr - (u1*) mcodebase - 4);
3650 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3651 xcastrefs->branchpos,
3652 (u1*) mcodeptr - mcodebase);
3656 M_LADD_IMM(REG_PV, xcastrefs->branchpos - 4, REG_ITMP2_XPC);
3658 if (xcodeptr != NULL) {
3659 M_BR(xcodeptr - mcodeptr);
3663 xcodeptr = mcodeptr;
3665 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3666 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3668 a = dseg_addaddress(string_java_lang_ClassCastException);
3669 M_ALD(argintregs[0], REG_PV, a);
3671 a = dseg_addaddress(new_exception);
3672 M_ALD(REG_ITMP3, REG_PV, a);
3673 M_JSR(REG_RA, REG_ITMP3);
3675 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3677 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3678 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3680 a = dseg_addaddress(asm_handle_exception);
3681 M_ALD(REG_ITMP3, REG_PV, a);
3687 /* generate exception check stubs */
3691 for (; xexceptionrefs != NULL; xexceptionrefs = xexceptionrefs->next) {
3692 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3693 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
3694 xexceptionrefs->branchpos,
3695 (u1*) xcodeptr - (u1*) mcodebase - 4);
3699 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
3700 xexceptionrefs->branchpos,
3701 (u1*) mcodeptr - mcodebase);
3705 M_LADD_IMM(REG_PV, xexceptionrefs->branchpos - 4, REG_ITMP2_XPC);
3707 if (xcodeptr != NULL) {
3708 M_BR(xcodeptr - mcodeptr);
3712 xcodeptr = mcodeptr;
3714 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3715 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3716 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3718 a = dseg_addaddress(builtin_get_exceptionptrptr);
3719 M_ALD(REG_ITMP3, REG_PV, a);
3720 M_JSR(REG_RA, REG_ITMP3);
3722 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3724 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3725 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3727 a = dseg_addaddress(&_exceptionptr);
3728 M_ALD(REG_ITMP3, REG_PV, a);
3729 M_ALD(REG_ITMP1_XPTR, REG_ITMP3, 0);
3730 M_AST(REG_ZERO, REG_ITMP3, 0);
3733 a = dseg_addaddress(asm_handle_exception);
3734 M_ALD(REG_ITMP3, REG_PV, a);
3740 /* generate null pointer check stubs */
3744 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3745 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3746 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3747 xnullrefs->branchpos,
3748 (u1*) xcodeptr - (u1*) mcodebase - 4);
3752 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3753 xnullrefs->branchpos,
3754 (u1*) mcodeptr - mcodebase);
3758 M_LADD_IMM(REG_PV, xnullrefs->branchpos - 4, REG_ITMP2_XPC);
3760 if (xcodeptr != NULL) {
3761 M_BR(xcodeptr - mcodeptr);
3765 xcodeptr = mcodeptr;
3767 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3768 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3770 a = dseg_addaddress(string_java_lang_NullPointerException);
3771 M_ALD(argintregs[0], REG_PV, a);
3773 a = dseg_addaddress(new_exception);
3774 M_ALD(REG_ITMP3, REG_PV, a);
3775 M_JSR(REG_RA, REG_ITMP3);
3777 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3779 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3780 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3782 a = dseg_addaddress(asm_handle_exception);
3783 M_ALD(REG_ITMP3, REG_PV, a);
3790 codegen_finish((int)((u1*) mcodeptr - mcodebase));
3792 docacheflush((void*) method->entrypoint,
3793 ((u1*) mcodeptr - mcodebase));
3797 /* function createcompilerstub *************************************************
3799 creates a stub routine which calls the compiler
3801 *******************************************************************************/
3803 #define COMPSTUBSIZE 4
3805 u1 *createcompilerstub(methodinfo *m)
3807 u8 *s = CNEW(u8, COMPSTUBSIZE); /* memory to hold the stub */
3808 s4 *mcodeptr = (s4 *) s; /* code generation pointer */
3810 /* code for the stub */
3811 M_ALD(REG_PV, REG_PV, 24); /* load pointer to the compiler */
3813 M_JSR(REG_ITMP1, REG_PV); /* jump to the compiler, return address
3814 in itmp1 is used as method pointer */
3817 s[2] = (u8) m; /* literals to be adressed */
3818 s[3] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3820 (void) docacheflush((void*) s, (char*) mcodeptr - (char*) s);
3823 count_cstub_len += COMPSTUBSIZE * 8;
3830 /* function removecompilerstub *************************************************
3832 deletes a compilerstub from memory (simply by freeing it)
3834 *******************************************************************************/
3836 void removecompilerstub(u1 *stub)
3838 CFREE(stub, COMPSTUBSIZE * 8);
3842 /* function: createnativestub **************************************************
3844 creates a stub routine which calls a native method
3846 *******************************************************************************/
3848 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3849 #define NATIVESTUBSTACK 2
3850 #define NATIVESTUBTHREADEXTRA 5
3852 #define NATIVESTUBSTACK 1
3853 #define NATIVESTUBTHREADEXTRA 1
3856 #define NATIVESTUBSIZE (54 + 4 + NATIVESTUBTHREADEXTRA - 1)
3857 #define NATIVEVERBOSESIZE (50 + 17)
3858 #define NATIVESTUBOFFSET 9
3860 u1 *createnativestub(functionptr f, methodinfo *m)
3862 u8 *s; /* memory to hold the stub */
3864 s4 *mcodeptr; /* code generation pointer */
3865 s4 stackframesize = 0; /* size of stackframe if needed */
3870 descriptor2types(m); /* set paramcount and paramtypes */
3872 stubsize = runverbose ? NATIVESTUBSIZE + NATIVEVERBOSESIZE : NATIVESTUBSIZE;
3873 s = CNEW(u8, stubsize); /* memory to hold the stub */
3874 cs = s + NATIVESTUBOFFSET;
3875 mcodeptr = (s4 *) (cs); /* code generation pointer */
3877 *(cs-1) = (u8) f; /* address of native method */
3878 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3879 *(cs-2) = (u8) &builtin_get_exceptionptrptr;
3881 *(cs-2) = (u8) (&_exceptionptr); /* address of exceptionptr */
3883 *(cs-3) = (u8) asm_handle_nat_exception;/* addr of asm exception handler */
3884 *(cs-4) = (u8) (&env); /* addr of jni_environement */
3885 *(cs-5) = (u8) builtin_trace_args;
3887 *(cs-7) = (u8) builtin_displaymethodstop;
3888 *(cs-8) = (u8) m->class;
3889 *(cs-9) = (u8) asm_check_clinit;
3891 M_LDA(REG_SP, REG_SP, -NATIVESTUBSTACK * 8); /* build up stackframe */
3892 M_LST(REG_RA, REG_SP, 0); /* store return address */
3894 /* if function is static, check for initialized */
3896 if (m->flags & ACC_STATIC) {
3897 /* if class isn't yet initialized, do it */
3898 if (!m->class->initialized) {
3899 /* call helper function which patches this code */
3900 M_ALD(REG_ITMP1, REG_PV, -8 * 8); /* class */
3901 M_ALD(REG_ITMP3, REG_PV, -9 * 8); /* asm_check_clinit */
3902 M_JSR(REG_RA, REG_ITMP3);
3907 /* max. 50 instructions */
3912 M_LDA(REG_SP, REG_SP, -(18 * 8));
3913 M_AST(REG_RA, REG_SP, 1 * 8);
3915 /* save integer argument registers */
3916 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3917 M_LST(argintregs[p], REG_SP, (2 + p) * 8);
3920 /* save and copy float arguments into integer registers */
3921 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3922 t = m->paramtypes[p];
3924 if (IS_FLT_DBL_TYPE(t)) {
3925 if (IS_2_WORD_TYPE(t)) {
3926 M_DST(argfltregs[p], REG_SP, (10 + p) * 8);
3927 M_LLD(argintregs[p], REG_SP, (10 + p) * 8);
3930 M_FST(argfltregs[p], REG_SP, (10 + p) * 8);
3931 M_ILD(argintregs[p], REG_SP, (10 + p) * 8);
3935 M_DST(argfltregs[p], REG_SP, (10 + p) * 8);
3939 M_ALD(REG_ITMP1, REG_PV, -6 * 8); /* method address */
3940 M_AST(REG_ITMP1, REG_SP, 0);
3941 M_ALD(REG_ITMP3, REG_PV, -5 * 8); /* builtin_trace_args */
3942 M_JSR(REG_RA, REG_ITMP3);
3944 disp = -(int) (mcodeptr - (s4*) cs) * 4;
3945 M_LDA(REG_PV, REG_RA, disp);
3947 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3948 M_LLD(argintregs[p], REG_SP, (2 + p) * 8);
3951 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3952 t = m->paramtypes[p];
3954 if (IS_FLT_DBL_TYPE(t)) {
3955 if (IS_2_WORD_TYPE(t)) {
3956 M_DLD(argfltregs[p], REG_SP, (10 + p) * 8);
3959 M_FLD(argfltregs[p], REG_SP, (10 + p) * 8);
3963 M_DLD(argfltregs[p], REG_SP, (10 + p) * 8);
3967 M_ALD(REG_RA, REG_SP, 1 * 8);
3968 M_LDA(REG_SP, REG_SP, 18 * 8);
3971 /* save argument registers on stack -- if we have to */
3972 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
3974 int paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3975 int stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3977 stackframesize = stackparamcnt + paramshiftcnt;
3979 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
3981 /* copy stack arguments into new stack frame -- if any */
3982 for (i = 0; i < stackparamcnt; i++) {
3983 M_LLD(REG_ITMP1, REG_SP, (stackparamcnt + 1 + i) * 8);
3984 M_LST(REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
3987 if (m->flags & ACC_STATIC) {
3988 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
3989 M_DST(argfltregs[5], REG_SP, 1 * 8);
3991 M_LST(argintregs[5], REG_SP, 1 * 8);
3994 if (IS_FLT_DBL_TYPE(m->paramtypes[4])) {
3995 M_DST(argfltregs[4], REG_SP, 0 * 8);
3997 M_LST(argintregs[4], REG_SP, 0 * 8);
4001 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4002 M_DST(argfltregs[5], REG_SP, 0 * 8);
4004 M_LST(argintregs[5], REG_SP, 0 * 8);
4009 if (m->flags & ACC_STATIC) {
4010 M_MOV(argintregs[5], argintregs[7]);
4012 M_DMFC1(REG_ITMP1, argfltregs[5]);
4013 M_DMTC1(REG_ITMP1, argfltregs[7]);
4015 M_MOV(argintregs[4], argintregs[6]);
4017 M_DMFC1(REG_ITMP1, argfltregs[4]);
4018 M_DMTC1(REG_ITMP1, argfltregs[6]);
4020 M_MOV(argintregs[3], argintregs[5]);
4021 M_DMFC1(REG_ITMP1, argfltregs[3]);
4023 M_MOV(argintregs[2], argintregs[4]);
4024 M_DMTC1(REG_ITMP1, argfltregs[5]);
4026 M_MOV(argintregs[1], argintregs[3]);
4027 M_DMFC1(REG_ITMP1, argfltregs[2]);
4029 M_MOV(argintregs[0], argintregs[2]);
4030 M_DMTC1(REG_ITMP1, argfltregs[4]);
4032 M_DMFC1(REG_ITMP1, argfltregs[1]);
4033 M_DMTC1(REG_ITMP1, argfltregs[3]);
4035 M_DMFC1(REG_ITMP1, argfltregs[0]);
4036 M_DMTC1(REG_ITMP1, argfltregs[2]);
4038 M_ALD(argintregs[1], REG_PV, -8 * 8);
4041 M_MOV(argintregs[6], argintregs[7]);
4043 M_DMFC1(REG_ITMP1, argfltregs[6]);
4044 M_DMTC1(REG_ITMP1, argfltregs[7]);
4046 M_MOV(argintregs[5], argintregs[6]);
4048 M_DMFC1(REG_ITMP1, argfltregs[5]);
4049 M_DMTC1(REG_ITMP1, argfltregs[6]);
4051 M_MOV(argintregs[4], argintregs[5]);
4052 M_DMFC1(REG_ITMP1, argfltregs[4]);
4054 M_MOV(argintregs[3], argintregs[4]);
4055 M_DMTC1(REG_ITMP1, argfltregs[5]);
4057 M_MOV(argintregs[2], argintregs[3]);
4058 M_DMFC1(REG_ITMP1, argfltregs[3]);
4060 M_MOV(argintregs[1], argintregs[2]);
4061 M_DMTC1(REG_ITMP1, argfltregs[4]);
4063 M_MOV(argintregs[0], argintregs[1]);
4064 M_DMFC1(REG_ITMP1, argfltregs[2]);
4066 M_DMTC1(REG_ITMP1, argfltregs[3]);
4068 M_DMFC1(REG_ITMP1, argfltregs[1]);
4069 M_DMFC1(REG_ITMP2, argfltregs[0]);
4071 M_DMTC1(REG_ITMP1, argfltregs[2]);
4072 M_DMTC1(REG_ITMP2, argfltregs[1]);
4075 M_ALD(argintregs[0], REG_PV, -4 * 8); /* load adress of jni_environement */
4076 M_ALD(REG_ITMP3, REG_PV, -1 * 8); /* load adress of native method */
4077 M_JSR(REG_RA, REG_ITMP3); /* call native method */
4078 M_NOP; /* delay slot */
4080 /* remove stackframe if there is one */
4081 if (stackframesize) {
4082 M_LDA(REG_SP, REG_SP, stackframesize * 8);
4085 /* 17 instructions */
4087 M_LDA(REG_SP, REG_SP, -(3 * 8));
4088 M_AST(REG_RA, REG_SP, 0 * 8);
4089 M_LST(REG_RESULT, REG_SP, 1 * 8);
4090 M_DST(REG_FRESULT, REG_SP, 2 * 8);
4091 M_ALD(argintregs[0], REG_PV, -6 * 8);
4092 M_MOV(REG_RESULT, argintregs[1]);
4093 M_DMFC1(REG_ITMP1, REG_FRESULT);
4094 M_DMTC1(REG_ITMP1, argfltregs[2]);
4095 M_DMTC1(REG_ITMP1, argfltregs[3]);
4096 M_ALD(REG_ITMP3, REG_PV, -7 * 8);/* builtin_displaymethodstop */
4097 M_JSR(REG_RA, REG_ITMP3);
4099 disp = -(int) (mcodeptr - (s4*) cs) * 4;
4100 M_LDA(REG_PV, REG_RA, disp);
4101 M_ALD(REG_RA, REG_SP, 0 * 8);
4102 M_LLD(REG_RESULT, REG_SP, 1 * 8);
4103 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
4104 M_LDA(REG_SP, REG_SP, 3 * 8);
4107 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4108 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* builtin_get_exceptionptrptr */
4109 M_JSR(REG_RA, REG_ITMP3);
4112 if (IS_FLT_DBL_TYPE(m->returntype))
4113 M_DST(REG_FRESULT, REG_SP, 1 * 8);
4115 M_AST(REG_RESULT, REG_SP, 1 * 8);
4116 M_MOV(REG_RESULT, REG_ITMP3);
4117 if (IS_FLT_DBL_TYPE(m->returntype))
4118 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
4120 M_ALD(REG_RESULT, REG_SP, 1 * 8);
4122 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* get address of exceptionptr */
4125 M_LLD(REG_RA, REG_SP, 0); /* load return address */
4126 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4128 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
4129 M_LDA(REG_SP, REG_SP, NATIVESTUBSTACK * 8);/*remove stackframe, delay slot*/
4131 M_RET(REG_RA); /* return to caller */
4132 M_NOP; /* delay slot */
4134 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4135 M_ALD(REG_ITMP3, REG_PV, -3 * 8); /* load asm exception handler address */
4137 M_JMP(REG_ITMP3); /* jump to asm exception handler */
4138 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4141 (void) docacheflush((void*) cs, (char*) mcodeptr - (char*) cs);
4144 dolog_plain("stubsize: %d (for %d params)\n",
4145 (int) (mcodeptr - (s4*) s), m->paramcount);
4149 count_nstub_len += NATIVESTUBSIZE * 8;
4152 return (u1 *) (s + NATIVESTUBOFFSET);
4156 /* function: removenativestub **************************************************
4158 removes a previously created native-stub from memory
4160 *******************************************************************************/
4162 void removenativestub(u1 *stub)
4164 CFREE((u8*) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 8);
4168 void docacheflush(u1 *p, long bytelen)
4170 u1 *e = p + bytelen;
4171 long psize = sysconf(_SC_PAGESIZE);
4172 p -= (long) p & (psize-1);
4173 e += psize - ((((long) e - 1) & (psize-1)) + 1);
4175 mprotect(p, bytelen, PROT_READ|PROT_WRITE|PROT_EXEC);
4180 * These are local overrides for various environment variables in Emacs.
4181 * Please do not remove this and leave it at the end of the file, where
4182 * Emacs will automagically detect them.
4183 * ---------------------------------------------------------------------
4186 * indent-tabs-mode: t