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 564 2003-11-03 15:47:13Z twisti $
53 /* include independent code generation stuff */
54 #include "codegen.inc"
58 /* *****************************************************************************
60 Datatypes and Register Allocations:
61 -----------------------------------
63 On 64-bit-machines (like the MIPS) all operands are stored in the
64 registers in a 64-bit form, even when the correspondig JavaVM operands
65 only need 32 bits. This is done by a canonical representation:
67 32-bit integers are allways stored as sign-extended 64-bit values (this
68 approach is directly supported by the MIPS architecture and is very easy
71 32-bit-floats are stored in a 64-bit double precision register by simply
72 expanding the exponent and mantissa with zeroes. (also supported by the
78 The calling conventions and the layout of the stack is explained in detail
79 in the documention file: calling.doc
81 *******************************************************************************/
84 /* additional functions and macros to generate code ***************************/
86 /* #define BlockPtrOfPC(pc) block+block_index[pc] */
87 #define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
91 #define COUNT_SPILLS count_spills++
97 /* gen_nullptr_check(objreg) */
99 #ifdef SOFTNULLPTRCHECK
100 #define gen_nullptr_check(objreg) \
102 M_BEQZ((objreg), 0);\
103 codegen_addxnullrefs(mcodeptr);\
107 #define gen_nullptr_check(objreg)
111 /* MCODECHECK(icnt) */
113 #define MCODECHECK(icnt) \
114 if((mcodeptr+(icnt))>mcodeend)mcodeptr=codegen_increase((u1*)mcodeptr)
117 generates an integer-move from register a to b.
118 if a and b are the same int-register, no code will be generated.
121 #define M_INTMOVE(a,b) if(a!=b){M_MOV(a,b);}
125 generates a floating-point-move from register a to b.
126 if a and b are the same float-register, no code will be generated
129 #define M_FLTMOVE(a,b) {if(a!=b){M_DMOV(a,b);}}
131 #define M_TFLTMOVE(t,a,b) \
135 else {M_FMOV(a,b);} \
138 #define M_TFLD(t,a,b,disp) \
144 #define M_TFST(t,a,b,disp) \
150 #define M_CCFLTMOVE(t1,t2,a,b) \
152 {M_TFLTMOVE(t1,a,b);} \
154 if ((t1)==TYPE_DBL) \
159 #define M_CCFLD(t1,t2,a,b,disp) \
163 M_DLD(REG_FTMP1,b,disp); \
164 if ((t1)==TYPE_DBL) \
165 {M_CVTDF(REG_FTMP1,a);} \
167 {M_CVTFD(REG_FTMP1,a);} \
170 #define M_CCFST(t1,t2,a,b,disp) \
174 if ((t1)==TYPE_DBL) \
175 {M_CVTDF(a,REG_FTMP1);} \
177 {M_CVTFD(a,REG_FTMP1);} \
178 M_DST(REG_FTMP1,b,disp); \
183 this function generates code to fetch data from a pseudo-register
184 into a real register.
185 If the pseudo-register has actually been assigned to a real
186 register, no code will be emitted, since following operations
187 can use this register directly.
189 v: pseudoregister to be fetched from
190 tempregnum: temporary register to be used if v is actually spilled to ram
192 return: the register number, where the operand can be found after
193 fetching (this wil be either tempregnum or the register
194 number allready given to v)
197 #define var_to_reg_int(regnr,v,tempnr) { \
198 if ((v)->flags & INMEMORY) \
199 {COUNT_SPILLS;M_LLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
200 else regnr=(v)->regoff; \
204 #define var_to_reg_flt(regnr,v,tempnr) { \
205 if ((v)->flags & INMEMORY) \
206 {COUNT_SPILLS;M_DLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
207 else regnr=(v)->regoff; \
212 This function determines a register, to which the result of an operation
213 should go, when it is ultimatively intended to store the result in
215 If v is assigned to an actual register, this register will be returned.
216 Otherwise (when v is spilled) this function returns tempregnum.
217 If not already done, regoff and flags are set in the stack location.
220 static int reg_of_var(stackptr v, int tempregnum)
224 switch (v->varkind) {
226 if (!(v->flags & INMEMORY))
230 var = &(interfaces[v->varnum][v->type]);
231 v->regoff = var->regoff;
232 if (!(var->flags & INMEMORY))
236 var = &(locals[v->varnum][v->type]);
237 v->regoff = var->regoff;
238 if (!(var->flags & INMEMORY))
242 v->regoff = v->varnum;
243 if (IS_FLT_DBL_TYPE(v->type)) {
244 if (v->varnum < fltreg_argnum) {
245 v->regoff = argfltregs[v->varnum];
246 return(argfltregs[v->varnum]);
250 if (v->varnum < intreg_argnum) {
251 v->regoff = argintregs[v->varnum];
252 return(argintregs[v->varnum]);
254 v->regoff -= intreg_argnum;
257 v->flags |= INMEMORY;
262 /* store_reg_to_var_xxx:
263 This function generates the code to store the result of an operation
264 back into a spilled pseudo-variable.
265 If the pseudo-variable has not been spilled in the first place, this
266 function will generate nothing.
268 v ............ Pseudovariable
269 tempregnum ... Number of the temporary registers as returned by
273 #define store_reg_to_var_int(sptr, tempregnum) { \
274 if ((sptr)->flags & INMEMORY) { \
276 M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
280 #define store_reg_to_var_flt(sptr, tempregnum) { \
281 if ((sptr)->flags & INMEMORY) { \
283 M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
288 void docacheflush(u1 *p, long bytelen, int dummy);
290 /* NullPointerException handlers and exception handling initialisation */
292 /* NullPointerException signal handler for hardware null pointer check */
294 void catch_NullPointerException(int sig, int code, struct sigcontext *sigctx)
300 /* Reset signal handler - necessary for SysV, does no harm for BSD */
302 instr = *((int*)(sigctx->sc_pc));
303 faultaddr = sigctx->sc_regs[(instr >> 21) & 0x1f];
305 if (faultaddr == 0) {
307 sigaddset(&nsig, sig);
308 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
309 sigctx->sc_regs[REG_ITMP1_XPTR] =
310 (long) proto_java_lang_NullPointerException;
311 sigctx->sc_regs[REG_ITMP2_XPC] = sigctx->sc_pc;
312 sigctx->sc_pc = (long) asm_handle_exception;
315 faultaddr += (long) ((instr << 16) >> 16);
316 fprintf(stderr, "faulting address: 0x%lx at 0x%lx\n", (long) faultaddr, (long) sigctx->sc_pc);
317 panic("Stack overflow");
321 void createcalljava ();
324 void init_exceptions(void)
327 sigset_t unblockmask;
331 /* The Boehm GC initialization blocks the SIGSEGV signal. So we do a
332 dummy allocation here to ensure that the GC is initialized.
334 heap_allocate(1, 0, NULL);
336 /* install signal handlers we need to convert to exceptions */
338 sigemptyset(&unblockmask);
340 sa.sa_sigaction = catch_NullPointerException;
341 sigemptyset(&sa.sa_mask);
346 sigaction(SIGSEGV, &sa, NULL);
347 sigaddset(&unblockmask, SIGSEGV);
351 sigaction(SIGBUS, &sa, NULL);
352 sigaddset(&unblockmask, SIGBUS);
356 sigprocmask(SIG_UNBLOCK, &unblockmask, NULL);
360 /* function gen_mcode **********************************************************
362 generates machine code
364 *******************************************************************************/
366 #define MethodPointer -8
367 #define FrameSize -12
372 #define ExTableSize -32
373 #define ExTableStart -32
376 #define ExEntrySize -32
379 #define ExHandlerPC -24
380 #define ExCatchType -32
382 #define ExEntrySize -16
385 #define ExHandlerPC -12
386 #define ExCatchType -16
391 int len, s1, s2, s3, d, bbs;
403 savedregs_num = (isleafmethod) ? 0 : 1; /* space to save the RA */
405 /* space to save used callee saved registers */
407 savedregs_num += (savintregcnt - maxsavintreguse);
408 savedregs_num += (savfltregcnt - maxsavfltreguse);
410 parentargs_base = maxmemuse + savedregs_num;
412 #ifdef USE_THREADS /* space to save argument of monitor_enter */
414 if (checksync && (method->flags & ACC_SYNCHRONIZED))
419 /* adjust frame size for 16 byte alignment */
421 if (parentargs_base & 1)
424 /* create method header */
427 (void) dseg_addaddress(method); /* Filler */
429 (void) dseg_addaddress(method); /* MethodPointer */
430 (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
434 /* IsSync contains the offset relative to the stack pointer for the
435 argument of monitor_exit used in the exception handler. Since the
436 offset could be zero and give a wrong meaning of the flag it is
440 if (checksync && (method->flags & ACC_SYNCHRONIZED))
441 (void) dseg_adds4((maxmemuse + 1) * 8); /* IsSync */
446 (void) dseg_adds4(0); /* IsSync */
448 (void) dseg_adds4(isleafmethod); /* IsLeaf */
449 (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
450 (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
451 (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
453 /* create exception table */
455 for (ex = extable; ex != NULL; ex = ex->down) {
458 if (ex->start != NULL)
459 printf("adding start - %d - ", ex->start->debug_nr);
461 printf("PANIC - start is NULL");
466 dseg_addtarget(ex->start);
470 printf("adding end - %d - ", ex->end->debug_nr);
472 printf("PANIC - end is NULL");
477 dseg_addtarget(ex->end);
480 if (ex->handler != NULL)
481 printf("adding handler - %d\n", ex->handler->debug_nr);
483 printf("PANIC - handler is NULL");
488 dseg_addtarget(ex->handler);
490 (void) dseg_addaddress(ex->catchtype);
493 /* initialize mcode variables */
495 mcodeptr = (s4*) mcodebase;
496 mcodeend = (s4*) (mcodebase + mcodesize);
497 MCODECHECK(128 + mparamcount);
499 /* create stack frame (if necessary) */
502 {M_LDA (REG_SP, REG_SP, -parentargs_base * 8);}
504 /* save return address and used callee saved registers */
508 {p--; M_LST (REG_RA, REG_SP, 8*p);}
509 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
510 {p--; M_LST (savintregs[r], REG_SP, 8 * p);}
511 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
512 {p--; M_DST (savfltregs[r], REG_SP, 8 * p);}
514 /* save monitorenter argument */
517 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
518 if (method->flags & ACC_STATIC) {
519 p = dseg_addaddress (class);
520 M_ALD(REG_ITMP1, REG_PV, p);
521 M_AST(REG_ITMP1, REG_SP, 8 * maxmemuse);
524 M_AST (argintregs[0], REG_SP, 8 * maxmemuse);
529 /* copy argument registers to stack and call trace function with pointer
530 to arguments on stack. ToDo: save floating point registers !!!!!!!!!
534 M_LDA (REG_SP, REG_SP, -(18*8));
536 M_LST(REG_RA, REG_SP, 1*8);
538 M_LST(argintregs[0], REG_SP, 2*8);
539 M_LST(argintregs[1], REG_SP, 3*8);
540 M_LST(argintregs[2], REG_SP, 4*8);
541 M_LST(argintregs[3], REG_SP, 5*8);
542 M_LST(argintregs[4], REG_SP, 6*8);
543 M_LST(argintregs[5], REG_SP, 7*8);
544 M_LST(argintregs[6], REG_SP, 8*8);
545 M_LST(argintregs[7], REG_SP, 9*8);
547 M_DST(argfltregs[0], REG_SP, 10*8);
548 M_DST(argfltregs[1], REG_SP, 11*8);
549 M_DST(argfltregs[2], REG_SP, 12*8);
550 M_DST(argfltregs[3], REG_SP, 13*8);
551 M_DST(argfltregs[4], REG_SP, 14*8);
552 M_DST(argfltregs[5], REG_SP, 15*8);
553 M_DST(argfltregs[6], REG_SP, 16*8);
554 M_DST(argfltregs[7], REG_SP, 17*8);
556 p = dseg_addaddress (method);
557 M_ALD(REG_ITMP1, REG_PV, p);
558 M_LST(REG_ITMP1, REG_SP, 0);
559 p = dseg_addaddress ((void*) (builtin_trace_args));
560 M_ALD(REG_ITMP3, REG_PV, p);
561 M_JSR(REG_RA, REG_ITMP3);
564 M_LLD(REG_RA, REG_SP, 1*8);
566 M_LLD(argintregs[0], REG_SP, 2*8);
567 M_LLD(argintregs[1], REG_SP, 3*8);
568 M_LLD(argintregs[2], REG_SP, 4*8);
569 M_LLD(argintregs[3], REG_SP, 5*8);
570 M_LLD(argintregs[4], REG_SP, 6*8);
571 M_LLD(argintregs[5], REG_SP, 7*8);
572 M_LLD(argintregs[6], REG_SP, 8*8);
573 M_LLD(argintregs[7], REG_SP, 9*8);
575 M_DLD(argfltregs[0], REG_SP, 10*8);
576 M_DLD(argfltregs[1], REG_SP, 11*8);
577 M_DLD(argfltregs[2], REG_SP, 12*8);
578 M_DLD(argfltregs[3], REG_SP, 13*8);
579 M_DLD(argfltregs[4], REG_SP, 14*8);
580 M_DLD(argfltregs[5], REG_SP, 15*8);
581 M_DLD(argfltregs[6], REG_SP, 16*8);
582 M_DLD(argfltregs[7], REG_SP, 17*8);
584 M_LDA (REG_SP, REG_SP, 18*8);
587 /* take arguments out of register or stack frame */
589 for (p = 0, l = 0; p < mparamcount; p++) {
591 var = &(locals[l][t]);
593 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
598 if (IS_INT_LNG_TYPE(t)) { /* integer args */
599 if (p < INT_ARG_CNT) { /* register arguments */
600 if (!(var->flags & INMEMORY)) /* reg arg -> register */
601 {M_INTMOVE (argintregs[p], r);}
602 else /* reg arg -> spilled */
603 M_LST (argintregs[p], REG_SP, 8 * r);
605 else { /* stack arguments */
606 pa = p - INT_ARG_CNT;
607 if (!(var->flags & INMEMORY)) /* stack arg -> register */
608 M_LLD (r, REG_SP, 8 * (parentargs_base + pa));
609 else { /* stack arg -> spilled */
610 M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
611 M_LST (REG_ITMP1, REG_SP, 8 * r);
615 else { /* floating args */
616 if (p < FLT_ARG_CNT) { /* register arguments */
617 if (!(var->flags & INMEMORY)) /* reg arg -> register */
618 {M_TFLTMOVE (var->type, argfltregs[p], r);}
619 else /* reg arg -> spilled */
620 M_DST (argfltregs[p], REG_SP, 8 * r);
622 else { /* stack arguments */
623 pa = p - FLT_ARG_CNT;
624 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
625 M_DLD (r, REG_SP, 8 * (parentargs_base + pa) );
626 } else { /* stack-arg -> spilled */
627 M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
628 M_DST (REG_FTMP1, REG_SP, 8 * r);
634 /* call trace function */
637 if (runverbose && !isleafmethod) {
638 M_LDA (REG_SP, REG_SP, -8);
639 p = dseg_addaddress (method);
640 M_ALD(REG_ITMP1, REG_PV, p);
641 M_AST(REG_ITMP1, REG_SP, 0);
642 p = dseg_addaddress ((void*) (builtin_trace_args));
643 M_ALD(REG_ITMP3, REG_PV, p);
644 M_JSR(REG_RA, REG_ITMP3);
646 M_LDA(REG_SP, REG_SP, 8);
650 /* call monitorenter function */
653 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
655 p = dseg_addaddress ((void*) (builtin_monitorenter));
656 M_ALD(REG_ITMP3, REG_PV, p);
657 M_JSR(REG_RA, REG_ITMP3);
658 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
659 disp = -(int)((u1*) mcodeptr - mcodebase);
660 M_LDA(REG_PV, REG_RA, disp);
665 /* end of header generation */
667 /* walk through all basic blocks */
668 for (/* bbs = block_count, */ bptr = block; /* --bbs >= 0 */ bptr != NULL; bptr = bptr->next) {
670 bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
672 if (bptr->flags >= BBREACHED) {
674 /* branch resolving */
678 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
679 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
680 brefs->branchpos, bptr->mpc);
684 /* copy interface registers to their destination */
689 while (src != NULL) {
691 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
692 d = reg_of_var(src, REG_ITMP1);
693 M_INTMOVE(REG_ITMP1, d);
694 store_reg_to_var_int(src, d);
697 d = reg_of_var(src, REG_IFTMP);
698 if ((src->varkind != STACKVAR)) {
700 if (IS_FLT_DBL_TYPE(s2)) {
701 if (!(interfaces[len][s2].flags & INMEMORY)) {
702 s1 = interfaces[len][s2].regoff;
706 M_DLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
708 store_reg_to_var_flt(src, d);
711 if (!(interfaces[len][s2].flags & INMEMORY)) {
712 s1 = interfaces[len][s2].regoff;
716 M_LLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
718 store_reg_to_var_int(src, d);
725 /* walk through all instructions */
729 for (iptr = bptr->iinstr;
731 src = iptr->dst, len--, iptr++) {
733 MCODECHECK(64); /* an instruction usually needs < 64 words */
736 case ICMD_NOP: /* ... ==> ... */
739 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
741 var_to_reg_int(s1, src, REG_ITMP1);
743 codegen_addxnullrefs(mcodeptr);
747 /* constant operations ************************************************/
749 #define ICONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_IADD_IMM(REG_ZERO,c,r);} \
750 else if(((c)>=0)&&((c)<=0xffff)){M_OR_IMM(REG_ZERO,c,r);} \
751 else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
753 #define LCONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LADD_IMM(REG_ZERO,c,r);} \
754 else if(((c)>=0)&&((c)<=0xffff)){M_OR_IMM(REG_ZERO,c,r);} \
755 else{a=dseg_adds8(c);M_LLD(r,REG_PV,a);}
757 case ICMD_ICONST: /* ... ==> ..., constant */
758 /* op1 = 0, val.i = constant */
760 d = reg_of_var(iptr->dst, REG_ITMP1);
761 ICONST(d, iptr->val.i);
762 store_reg_to_var_int(iptr->dst, d);
765 case ICMD_LCONST: /* ... ==> ..., constant */
766 /* op1 = 0, val.l = constant */
768 d = reg_of_var(iptr->dst, REG_ITMP1);
769 LCONST(d, iptr->val.l);
770 store_reg_to_var_int(iptr->dst, d);
773 case ICMD_FCONST: /* ... ==> ..., constant */
774 /* op1 = 0, val.f = constant */
776 d = reg_of_var (iptr->dst, REG_FTMP1);
777 a = dseg_addfloat (iptr->val.f);
779 store_reg_to_var_flt (iptr->dst, d);
782 case ICMD_DCONST: /* ... ==> ..., constant */
783 /* op1 = 0, val.d = constant */
785 d = reg_of_var (iptr->dst, REG_FTMP1);
786 a = dseg_adddouble (iptr->val.d);
788 store_reg_to_var_flt (iptr->dst, d);
791 case ICMD_ACONST: /* ... ==> ..., constant */
792 /* op1 = 0, val.a = constant */
794 d = reg_of_var(iptr->dst, REG_ITMP1);
796 a = dseg_addaddress (iptr->val.a);
800 M_INTMOVE(REG_ZERO, d);
802 store_reg_to_var_int(iptr->dst, d);
806 /* load/store operations **********************************************/
808 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
809 case ICMD_LLOAD: /* op1 = local variable */
812 d = reg_of_var(iptr->dst, REG_ITMP1);
813 if ((iptr->dst->varkind == LOCALVAR) &&
814 (iptr->dst->varnum == iptr->op1))
816 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
817 if (var->flags & INMEMORY)
818 M_LLD(d, REG_SP, 8 * var->regoff);
820 {M_INTMOVE(var->regoff,d);}
821 store_reg_to_var_int(iptr->dst, d);
824 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
825 case ICMD_DLOAD: /* op1 = local variable */
827 d = reg_of_var(iptr->dst, REG_FTMP1);
828 if ((iptr->dst->varkind == LOCALVAR) &&
829 (iptr->dst->varnum == iptr->op1))
831 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
833 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
834 if (var->flags & INMEMORY)
835 {M_CCFLD(var->type,t2,d, REG_SP, 8 * var->regoff);}
837 {M_CCFLTMOVE(var->type,t2,var->regoff,d);}
839 store_reg_to_var_flt(iptr->dst, d);
843 case ICMD_ISTORE: /* ..., value ==> ... */
844 case ICMD_LSTORE: /* op1 = local variable */
847 if ((src->varkind == LOCALVAR) &&
848 (src->varnum == iptr->op1))
850 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
851 if (var->flags & INMEMORY) {
852 var_to_reg_int(s1, src, REG_ITMP1);
853 M_LST(s1, REG_SP, 8 * var->regoff);
856 var_to_reg_int(s1, src, var->regoff);
857 M_INTMOVE(s1, var->regoff);
861 case ICMD_FSTORE: /* ..., value ==> ... */
862 case ICMD_DSTORE: /* op1 = local variable */
864 if ((src->varkind == LOCALVAR) &&
865 (src->varnum == iptr->op1))
867 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
869 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
870 if (var->flags & INMEMORY) {
871 var_to_reg_flt(s1, src, REG_FTMP1);
872 M_CCFST(t1,var->type,s1, REG_SP, 8 * var->regoff);
875 var_to_reg_flt(s1, src, var->regoff);
876 M_CCFLTMOVE(t1,var->type,s1, var->regoff);
882 /* pop/dup/swap operations ********************************************/
884 /* attention: double and longs are only one entry in CACAO ICMDs */
886 case ICMD_POP: /* ..., value ==> ... */
887 case ICMD_POP2: /* ..., value, value ==> ... */
890 #define M_COPY(from,to) \
891 d = reg_of_var(to, REG_IFTMP); \
892 if ((from->regoff != to->regoff) || \
893 ((from->flags ^ to->flags) & INMEMORY)) { \
894 if (IS_FLT_DBL_TYPE(from->type)) { \
895 var_to_reg_flt(s1, from, d); \
896 M_TFLTMOVE(from->type,s1,d); \
897 store_reg_to_var_flt(to, d); \
900 var_to_reg_int(s1, from, d); \
902 store_reg_to_var_int(to, d); \
906 case ICMD_DUP: /* ..., a ==> ..., a, a */
907 M_COPY(src, iptr->dst);
910 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
912 M_COPY(src, iptr->dst->prev->prev);
914 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
916 M_COPY(src, iptr->dst);
917 M_COPY(src->prev, iptr->dst->prev);
920 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
922 M_COPY(src->prev, iptr->dst->prev->prev->prev);
924 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
926 M_COPY(src, iptr->dst);
927 M_COPY(src->prev, iptr->dst->prev);
928 M_COPY(src->prev->prev, iptr->dst->prev->prev);
929 M_COPY(src, iptr->dst->prev->prev->prev);
932 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
934 M_COPY(src, iptr->dst);
935 M_COPY(src->prev, iptr->dst->prev);
936 M_COPY(src->prev->prev, iptr->dst->prev->prev);
937 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
938 M_COPY(src, iptr->dst->prev->prev->prev->prev);
939 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
942 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
944 M_COPY(src, iptr->dst->prev);
945 M_COPY(src->prev, iptr->dst);
949 /* integer operations *************************************************/
951 case ICMD_INEG: /* ..., value ==> ..., - value */
953 var_to_reg_int(s1, src, REG_ITMP1);
954 d = reg_of_var(iptr->dst, REG_ITMP3);
955 M_ISUB(REG_ZERO, s1, d);
956 store_reg_to_var_int(iptr->dst, d);
959 case ICMD_LNEG: /* ..., value ==> ..., - value */
961 var_to_reg_int(s1, src, REG_ITMP1);
962 d = reg_of_var(iptr->dst, REG_ITMP3);
963 M_LSUB(REG_ZERO, s1, d);
964 store_reg_to_var_int(iptr->dst, d);
967 case ICMD_I2L: /* ..., value ==> ..., value */
969 var_to_reg_int(s1, src, REG_ITMP1);
970 d = reg_of_var(iptr->dst, REG_ITMP3);
972 store_reg_to_var_int(iptr->dst, d);
975 case ICMD_L2I: /* ..., value ==> ..., value */
977 var_to_reg_int(s1, src, REG_ITMP1);
978 d = reg_of_var(iptr->dst, REG_ITMP3);
979 M_ISLL_IMM(s1, 0, d );
980 store_reg_to_var_int(iptr->dst, d);
983 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
985 var_to_reg_int(s1, src, REG_ITMP1);
986 d = reg_of_var(iptr->dst, REG_ITMP3);
987 M_LSLL_IMM(s1, 56, d);
988 M_LSRA_IMM( d, 56, d);
989 store_reg_to_var_int(iptr->dst, d);
992 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
994 var_to_reg_int(s1, src, REG_ITMP1);
995 d = reg_of_var(iptr->dst, REG_ITMP3);
997 store_reg_to_var_int(iptr->dst, d);
1000 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1002 var_to_reg_int(s1, src, REG_ITMP1);
1003 d = reg_of_var(iptr->dst, REG_ITMP3);
1004 M_LSLL_IMM(s1, 48, d);
1005 M_LSRA_IMM( d, 48, d);
1006 store_reg_to_var_int(iptr->dst, d);
1010 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1012 var_to_reg_int(s1, src->prev, REG_ITMP1);
1013 var_to_reg_int(s2, src, REG_ITMP2);
1014 d = reg_of_var(iptr->dst, REG_ITMP3);
1016 store_reg_to_var_int(iptr->dst, d);
1019 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1020 /* val.i = constant */
1022 var_to_reg_int(s1, src, REG_ITMP1);
1023 d = reg_of_var(iptr->dst, REG_ITMP3);
1024 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1025 M_IADD_IMM(s1, iptr->val.i, d);
1028 ICONST(REG_ITMP2, iptr->val.i);
1029 M_IADD(s1, REG_ITMP2, d);
1031 store_reg_to_var_int(iptr->dst, d);
1034 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1036 var_to_reg_int(s1, src->prev, REG_ITMP1);
1037 var_to_reg_int(s2, src, REG_ITMP2);
1038 d = reg_of_var(iptr->dst, REG_ITMP3);
1040 store_reg_to_var_int(iptr->dst, d);
1043 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1044 /* val.l = constant */
1046 var_to_reg_int(s1, src, REG_ITMP1);
1047 d = reg_of_var(iptr->dst, REG_ITMP3);
1048 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
1049 M_LADD_IMM(s1, iptr->val.l, d);
1052 LCONST(REG_ITMP2, iptr->val.l);
1053 M_LADD(s1, REG_ITMP2, d);
1055 store_reg_to_var_int(iptr->dst, d);
1058 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1060 var_to_reg_int(s1, src->prev, REG_ITMP1);
1061 var_to_reg_int(s2, src, REG_ITMP2);
1062 d = reg_of_var(iptr->dst, REG_ITMP3);
1064 store_reg_to_var_int(iptr->dst, d);
1067 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1068 /* val.i = constant */
1070 var_to_reg_int(s1, src, REG_ITMP1);
1071 d = reg_of_var(iptr->dst, REG_ITMP3);
1072 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
1073 M_IADD_IMM(s1, -iptr->val.i, d);
1076 ICONST(REG_ITMP2, iptr->val.i);
1077 M_ISUB(s1, REG_ITMP2, d);
1079 store_reg_to_var_int(iptr->dst, d);
1082 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1084 var_to_reg_int(s1, src->prev, REG_ITMP1);
1085 var_to_reg_int(s2, src, REG_ITMP2);
1086 d = reg_of_var(iptr->dst, REG_ITMP3);
1088 store_reg_to_var_int(iptr->dst, d);
1091 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1092 /* val.l = constant */
1094 var_to_reg_int(s1, src, REG_ITMP1);
1095 d = reg_of_var(iptr->dst, REG_ITMP3);
1096 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
1097 M_LADD_IMM(s1, -iptr->val.l, d);
1100 LCONST(REG_ITMP2, iptr->val.l);
1101 M_LSUB(s1, REG_ITMP2, d);
1103 store_reg_to_var_int(iptr->dst, d);
1106 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1108 var_to_reg_int(s1, src->prev, REG_ITMP1);
1109 var_to_reg_int(s2, src, REG_ITMP2);
1110 d = reg_of_var(iptr->dst, REG_ITMP3);
1115 store_reg_to_var_int(iptr->dst, d);
1118 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1119 /* val.i = constant */
1121 var_to_reg_int(s1, src, REG_ITMP1);
1122 d = reg_of_var(iptr->dst, REG_ITMP3);
1123 ICONST(REG_ITMP2, iptr->val.i);
1124 M_IMUL(s1, REG_ITMP2);
1128 store_reg_to_var_int(iptr->dst, d);
1131 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1133 var_to_reg_int(s1, src->prev, REG_ITMP1);
1134 var_to_reg_int(s2, src, REG_ITMP2);
1135 d = reg_of_var(iptr->dst, REG_ITMP3);
1140 store_reg_to_var_int(iptr->dst, d);
1143 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1144 /* val.l = constant */
1146 var_to_reg_int(s1, src, REG_ITMP1);
1147 d = reg_of_var(iptr->dst, REG_ITMP3);
1148 LCONST(REG_ITMP2, iptr->val.l);
1149 M_LMUL(s1, REG_ITMP2);
1153 store_reg_to_var_int(iptr->dst, d);
1156 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1158 var_to_reg_int(s1, src->prev, REG_ITMP1);
1159 var_to_reg_int(s2, src, REG_ITMP2);
1160 d = reg_of_var(iptr->dst, REG_ITMP3);
1165 store_reg_to_var_int(iptr->dst, d);
1168 case ICMD_IDIVCONST: /* ..., value ==> ..., value / constant */
1169 /* val.i = constant */
1171 var_to_reg_int(s1, src, REG_ITMP1);
1172 d = reg_of_var(iptr->dst, REG_ITMP3);
1173 ICONST(REG_ITMP2, iptr->val.i);
1174 M_IDIV(s1, REG_ITMP2);
1178 store_reg_to_var_int(iptr->dst, d);
1181 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1183 var_to_reg_int(s1, src->prev, REG_ITMP1);
1184 var_to_reg_int(s2, src, REG_ITMP2);
1185 d = reg_of_var(iptr->dst, REG_ITMP3);
1190 store_reg_to_var_int(iptr->dst, d);
1193 case ICMD_LDIVCONST: /* ..., value ==> ..., value / constant */
1194 /* val.l = constant */
1196 var_to_reg_int(s1, src, REG_ITMP1);
1197 d = reg_of_var(iptr->dst, REG_ITMP3);
1198 LCONST(REG_ITMP2, iptr->val.l);
1199 M_LDIV(s1, REG_ITMP2);
1203 store_reg_to_var_int(iptr->dst, d);
1206 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1208 var_to_reg_int(s1, src->prev, REG_ITMP1);
1209 var_to_reg_int(s2, src, REG_ITMP2);
1210 d = reg_of_var(iptr->dst, REG_ITMP3);
1215 store_reg_to_var_int(iptr->dst, d);
1218 case ICMD_IREMCONST: /* ..., value ==> ..., value % constant */
1219 /* val.i = constant */
1221 var_to_reg_int(s1, src, REG_ITMP1);
1222 d = reg_of_var(iptr->dst, REG_ITMP3);
1223 ICONST(REG_ITMP2, iptr->val.i);
1224 M_IDIV(s1, REG_ITMP2);
1228 store_reg_to_var_int(iptr->dst, d);
1231 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1233 var_to_reg_int(s1, src->prev, REG_ITMP1);
1234 var_to_reg_int(s2, src, REG_ITMP2);
1235 d = reg_of_var(iptr->dst, REG_ITMP3);
1240 store_reg_to_var_int(iptr->dst, d);
1243 case ICMD_LREMCONST: /* ..., value ==> ..., value % constant */
1244 /* val.l = constant */
1246 var_to_reg_int(s1, src, REG_ITMP1);
1247 d = reg_of_var(iptr->dst, REG_ITMP3);
1248 LCONST(REG_ITMP2, iptr->val.l);
1249 M_LDIV(s1, REG_ITMP2);
1253 store_reg_to_var_int(iptr->dst, d);
1256 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1257 case ICMD_LDIVPOW2: /* val.i = constant */
1259 var_to_reg_int(s1, src, REG_ITMP1);
1260 d = reg_of_var(iptr->dst, REG_ITMP3);
1261 M_LSRA_IMM(s1, 63, REG_ITMP2);
1262 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1263 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1264 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
1265 store_reg_to_var_int(iptr->dst, d);
1268 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1270 var_to_reg_int(s1, src->prev, REG_ITMP1);
1271 var_to_reg_int(s2, src, REG_ITMP2);
1272 d = reg_of_var(iptr->dst, REG_ITMP3);
1274 store_reg_to_var_int(iptr->dst, d);
1277 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1278 /* val.i = constant */
1280 var_to_reg_int(s1, src, REG_ITMP1);
1281 d = reg_of_var(iptr->dst, REG_ITMP3);
1282 M_ISLL_IMM(s1, iptr->val.i, d);
1283 store_reg_to_var_int(iptr->dst, d);
1286 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1288 var_to_reg_int(s1, src->prev, REG_ITMP1);
1289 var_to_reg_int(s2, src, REG_ITMP2);
1290 d = reg_of_var(iptr->dst, REG_ITMP3);
1292 store_reg_to_var_int(iptr->dst, d);
1295 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1296 /* val.i = constant */
1298 var_to_reg_int(s1, src, REG_ITMP1);
1299 d = reg_of_var(iptr->dst, REG_ITMP3);
1300 M_ISRA_IMM(s1, iptr->val.i, d);
1301 store_reg_to_var_int(iptr->dst, d);
1304 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1306 var_to_reg_int(s1, src->prev, REG_ITMP1);
1307 var_to_reg_int(s2, src, REG_ITMP2);
1308 d = reg_of_var(iptr->dst, REG_ITMP3);
1310 store_reg_to_var_int(iptr->dst, d);
1313 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1314 /* val.i = constant */
1316 var_to_reg_int(s1, src, REG_ITMP1);
1317 d = reg_of_var(iptr->dst, REG_ITMP3);
1318 M_ISRL_IMM(s1, iptr->val.i, d);
1319 store_reg_to_var_int(iptr->dst, d);
1322 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1324 var_to_reg_int(s1, src->prev, REG_ITMP1);
1325 var_to_reg_int(s2, src, REG_ITMP2);
1326 d = reg_of_var(iptr->dst, REG_ITMP3);
1328 store_reg_to_var_int(iptr->dst, d);
1331 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1332 /* val.i = constant */
1334 var_to_reg_int(s1, src, REG_ITMP1);
1335 d = reg_of_var(iptr->dst, REG_ITMP3);
1336 M_LSLL_IMM(s1, iptr->val.i, d);
1337 store_reg_to_var_int(iptr->dst, d);
1340 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1342 var_to_reg_int(s1, src->prev, REG_ITMP1);
1343 var_to_reg_int(s2, src, REG_ITMP2);
1344 d = reg_of_var(iptr->dst, REG_ITMP3);
1346 store_reg_to_var_int(iptr->dst, d);
1349 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1350 /* val.i = constant */
1352 var_to_reg_int(s1, src, REG_ITMP1);
1353 d = reg_of_var(iptr->dst, REG_ITMP3);
1354 M_LSRA_IMM(s1, iptr->val.i, d);
1355 store_reg_to_var_int(iptr->dst, d);
1358 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1360 var_to_reg_int(s1, src->prev, REG_ITMP1);
1361 var_to_reg_int(s2, src, REG_ITMP2);
1362 d = reg_of_var(iptr->dst, REG_ITMP3);
1364 store_reg_to_var_int(iptr->dst, d);
1367 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1368 /* val.i = constant */
1370 var_to_reg_int(s1, src, REG_ITMP1);
1371 d = reg_of_var(iptr->dst, REG_ITMP3);
1372 M_LSRL_IMM(s1, iptr->val.i, d);
1373 store_reg_to_var_int(iptr->dst, d);
1376 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1379 var_to_reg_int(s1, src->prev, REG_ITMP1);
1380 var_to_reg_int(s2, src, REG_ITMP2);
1381 d = reg_of_var(iptr->dst, REG_ITMP3);
1383 store_reg_to_var_int(iptr->dst, d);
1386 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1387 /* val.i = constant */
1389 var_to_reg_int(s1, src, REG_ITMP1);
1390 d = reg_of_var(iptr->dst, REG_ITMP3);
1391 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1392 M_AND_IMM(s1, iptr->val.i, d);
1395 ICONST(REG_ITMP2, iptr->val.i);
1396 M_AND(s1, REG_ITMP2, d);
1398 store_reg_to_var_int(iptr->dst, d);
1401 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1402 /* val.i = constant */
1404 var_to_reg_int(s1, src, REG_ITMP1);
1405 d = reg_of_var(iptr->dst, REG_ITMP3);
1407 M_MOV(s1, REG_ITMP1);
1410 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1411 M_AND_IMM(s1, iptr->val.i, d);
1414 M_ISUB(REG_ZERO, s1, d);
1415 M_AND_IMM(d, iptr->val.i, d);
1418 ICONST(REG_ITMP2, iptr->val.i);
1419 M_AND(s1, REG_ITMP2, d);
1422 M_ISUB(REG_ZERO, s1, d);
1423 M_AND(d, REG_ITMP2, d);
1425 M_ISUB(REG_ZERO, d, d);
1426 store_reg_to_var_int(iptr->dst, d);
1429 case ICMD_IREM0X10001: /* ..., value ==> ..., value % 0x100001 */
1431 /* b = value & 0xffff;
1433 a = ((b - a) & 0xffff) + (b < a);
1435 var_to_reg_int(s1, src, REG_ITMP1);
1436 d = reg_of_var(iptr->dst, REG_ITMP3);
1438 M_MOV(s1, REG_ITMP3);
1442 M_CZEXT(s1, REG_ITMP2); /* delay slot */
1443 M_ISRA_IMM(s1, 16, d);
1444 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1445 M_ISUB(REG_ITMP2, d, d);
1448 M_IADD(d, REG_ITMP1, d); /* delay slot */
1450 M_LUI(REG_ITMP2, 1);
1451 M_IADD_IMM(REG_ITMP2, 1, REG_ITMP2);
1452 M_IDIV(s1, REG_ITMP2);
1456 store_reg_to_var_int(iptr->dst, d);
1459 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1460 /* val.l = constant */
1462 var_to_reg_int(s1, src, REG_ITMP1);
1463 d = reg_of_var(iptr->dst, REG_ITMP3);
1464 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1465 M_AND_IMM(s1, iptr->val.l, d);
1468 LCONST(REG_ITMP2, iptr->val.l);
1469 M_AND(s1, REG_ITMP2, d);
1471 store_reg_to_var_int(iptr->dst, d);
1474 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1475 /* val.l = constant */
1477 var_to_reg_int(s1, src, REG_ITMP1);
1478 d = reg_of_var(iptr->dst, REG_ITMP3);
1480 M_MOV(s1, REG_ITMP1);
1483 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1484 M_AND_IMM(s1, iptr->val.l, d);
1487 M_LSUB(REG_ZERO, s1, d);
1488 M_AND_IMM(d, iptr->val.l, d);
1491 LCONST(REG_ITMP2, iptr->val.l);
1492 M_AND(s1, REG_ITMP2, d);
1495 M_LSUB(REG_ZERO, s1, d);
1496 M_AND(d, REG_ITMP2, d);
1498 M_LSUB(REG_ZERO, d, d);
1499 store_reg_to_var_int(iptr->dst, d);
1502 case ICMD_LREM0X10001:/* ..., value ==> ..., value % 0x10001 */
1504 var_to_reg_int(s1, src, REG_ITMP1);
1505 d = reg_of_var(iptr->dst, REG_ITMP3);
1506 M_LUI(REG_ITMP2, 1);
1507 M_LADD_IMM(REG_ITMP2, 1, REG_ITMP2);
1508 M_LDIV(s1, REG_ITMP2);
1512 store_reg_to_var_int(iptr->dst, d);
1515 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1518 var_to_reg_int(s1, src->prev, REG_ITMP1);
1519 var_to_reg_int(s2, src, REG_ITMP2);
1520 d = reg_of_var(iptr->dst, REG_ITMP3);
1522 store_reg_to_var_int(iptr->dst, d);
1525 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1526 /* val.i = constant */
1528 var_to_reg_int(s1, src, REG_ITMP1);
1529 d = reg_of_var(iptr->dst, REG_ITMP3);
1530 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1531 M_OR_IMM(s1, iptr->val.i, d);
1534 ICONST(REG_ITMP2, iptr->val.i);
1535 M_OR(s1, REG_ITMP2, d);
1537 store_reg_to_var_int(iptr->dst, d);
1540 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1541 /* val.l = constant */
1543 var_to_reg_int(s1, src, REG_ITMP1);
1544 d = reg_of_var(iptr->dst, REG_ITMP3);
1545 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1546 M_OR_IMM(s1, iptr->val.l, d);
1549 LCONST(REG_ITMP2, iptr->val.l);
1550 M_OR(s1, REG_ITMP2, d);
1552 store_reg_to_var_int(iptr->dst, d);
1555 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1558 var_to_reg_int(s1, src->prev, REG_ITMP1);
1559 var_to_reg_int(s2, src, REG_ITMP2);
1560 d = reg_of_var(iptr->dst, REG_ITMP3);
1562 store_reg_to_var_int(iptr->dst, d);
1565 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1566 /* val.i = constant */
1568 var_to_reg_int(s1, src, REG_ITMP1);
1569 d = reg_of_var(iptr->dst, REG_ITMP3);
1570 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1571 M_XOR_IMM(s1, iptr->val.i, d);
1574 ICONST(REG_ITMP2, iptr->val.i);
1575 M_XOR(s1, REG_ITMP2, d);
1577 store_reg_to_var_int(iptr->dst, d);
1580 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1581 /* val.l = constant */
1583 var_to_reg_int(s1, src, REG_ITMP1);
1584 d = reg_of_var(iptr->dst, REG_ITMP3);
1585 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1586 M_XOR_IMM(s1, iptr->val.l, d);
1589 LCONST(REG_ITMP2, iptr->val.l);
1590 M_XOR(s1, REG_ITMP2, d);
1592 store_reg_to_var_int(iptr->dst, d);
1596 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1598 var_to_reg_int(s1, src->prev, REG_ITMP1);
1599 var_to_reg_int(s2, src, REG_ITMP2);
1600 d = reg_of_var(iptr->dst, REG_ITMP3);
1601 M_CMPLT(s1, s2, REG_ITMP3);
1602 M_CMPLT(s2, s1, REG_ITMP1);
1603 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1604 store_reg_to_var_int(iptr->dst, d);
1608 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1609 /* op1 = variable, val.i = constant */
1611 var = &(locals[iptr->op1][TYPE_INT]);
1612 if (var->flags & INMEMORY) {
1614 M_LLD(s1, REG_SP, 8 * var->regoff);
1618 M_IADD_IMM(s1, iptr->val.i, s1);
1619 if (var->flags & INMEMORY)
1620 M_LST(s1, REG_SP, 8 * var->regoff);
1624 /* floating operations ************************************************/
1626 case ICMD_FNEG: /* ..., value ==> ..., - value */
1628 var_to_reg_flt(s1, src, REG_FTMP1);
1629 d = reg_of_var(iptr->dst, REG_FTMP3);
1631 store_reg_to_var_flt(iptr->dst, d);
1634 case ICMD_DNEG: /* ..., value ==> ..., - value */
1636 var_to_reg_flt(s1, src, REG_FTMP1);
1637 d = reg_of_var(iptr->dst, REG_FTMP3);
1639 store_reg_to_var_flt(iptr->dst, d);
1642 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1644 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1645 var_to_reg_flt(s2, src, REG_FTMP2);
1646 d = reg_of_var(iptr->dst, REG_FTMP3);
1648 store_reg_to_var_flt(iptr->dst, d);
1651 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1653 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1654 var_to_reg_flt(s2, src, REG_FTMP2);
1655 d = reg_of_var(iptr->dst, REG_FTMP3);
1657 store_reg_to_var_flt(iptr->dst, d);
1660 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1662 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1663 var_to_reg_flt(s2, src, REG_FTMP2);
1664 d = reg_of_var(iptr->dst, REG_FTMP3);
1666 store_reg_to_var_flt(iptr->dst, d);
1669 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1671 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1672 var_to_reg_flt(s2, src, REG_FTMP2);
1673 d = reg_of_var(iptr->dst, REG_FTMP3);
1675 store_reg_to_var_flt(iptr->dst, d);
1678 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1680 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1681 var_to_reg_flt(s2, src, REG_FTMP2);
1682 d = reg_of_var(iptr->dst, REG_FTMP3);
1684 store_reg_to_var_flt(iptr->dst, d);
1687 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1689 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1690 var_to_reg_flt(s2, src, REG_FTMP2);
1691 d = reg_of_var(iptr->dst, REG_FTMP3);
1693 store_reg_to_var_flt(iptr->dst, d);
1696 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1698 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1699 var_to_reg_flt(s2, src, REG_FTMP2);
1700 d = reg_of_var(iptr->dst, REG_FTMP3);
1702 store_reg_to_var_flt(iptr->dst, d);
1705 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1707 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1708 var_to_reg_flt(s2, src, REG_FTMP2);
1709 d = reg_of_var(iptr->dst, REG_FTMP3);
1711 store_reg_to_var_flt(iptr->dst, d);
1714 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1717 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1718 var_to_reg_flt(s2, src, REG_FTMP2);
1719 d = reg_of_var(iptr->dst, REG_FTMP3);
1720 M_FDIV(s1,s2, REG_FTMP3);
1721 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1722 M_CVTLF(REG_FTMP3, REG_FTMP3);
1723 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1724 M_FSUB(s1, REG_FTMP3, d);
1725 store_reg_to_var_flt(iptr->dst, d);
1728 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1730 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1731 var_to_reg_flt(s2, src, REG_FTMP2);
1732 d = reg_of_var(iptr->dst, REG_FTMP3);
1733 M_DDIV(s1,s2, REG_FTMP3);
1734 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1735 M_CVTLD(REG_FTMP3, REG_FTMP3);
1736 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1737 M_DSUB(s1, REG_FTMP3, d);
1738 store_reg_to_var_flt(iptr->dst, d);
1741 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1743 var_to_reg_int(s1, src, REG_ITMP1);
1744 d = reg_of_var(iptr->dst, REG_FTMP3);
1747 store_reg_to_var_flt(iptr->dst, d);
1750 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1752 var_to_reg_int(s1, src, REG_ITMP1);
1753 d = reg_of_var(iptr->dst, REG_FTMP3);
1756 store_reg_to_var_flt(iptr->dst, d);
1759 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1761 var_to_reg_flt(s1, src, REG_FTMP1);
1762 d = reg_of_var(iptr->dst, REG_ITMP3);
1763 M_TRUNCFI(s1, REG_FTMP1);
1764 M_MOVDI(REG_FTMP1, d);
1766 store_reg_to_var_int(iptr->dst, d);
1769 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1771 var_to_reg_flt(s1, src, REG_FTMP1);
1772 d = reg_of_var(iptr->dst, REG_ITMP3);
1773 M_TRUNCDI(s1, REG_FTMP1);
1774 M_MOVDI(REG_FTMP1, d);
1776 store_reg_to_var_int(iptr->dst, d);
1779 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1781 var_to_reg_flt(s1, src, REG_FTMP1);
1782 d = reg_of_var(iptr->dst, REG_ITMP3);
1783 M_TRUNCFL(s1, REG_FTMP1);
1784 M_MOVDL(REG_FTMP1, d);
1786 store_reg_to_var_int(iptr->dst, d);
1789 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1791 var_to_reg_flt(s1, src, REG_FTMP1);
1792 d = reg_of_var(iptr->dst, REG_ITMP3);
1793 M_TRUNCDL(s1, REG_FTMP1);
1794 M_MOVDL(REG_FTMP1, d);
1796 store_reg_to_var_int(iptr->dst, d);
1799 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1801 var_to_reg_flt(s1, src, REG_FTMP1);
1802 d = reg_of_var(iptr->dst, REG_FTMP3);
1804 store_reg_to_var_flt(iptr->dst, d);
1807 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1809 var_to_reg_flt(s1, src, REG_FTMP1);
1810 d = reg_of_var(iptr->dst, REG_FTMP3);
1812 store_reg_to_var_flt(iptr->dst, d);
1815 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1817 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1818 var_to_reg_flt(s2, src, REG_FTMP2);
1819 d = reg_of_var(iptr->dst, REG_ITMP3);
1821 M_NOP; /* compare delay */
1822 M_FBF(2); /* jump over next instructions */
1823 M_LSUB_IMM(REG_ZERO, 1, d); /* delay slot */
1826 M_NOP; /* compare delay */
1827 M_FBF(2); /* jump over next instruction */
1829 M_LADD_IMM(REG_ZERO, 1, d);
1830 store_reg_to_var_int(iptr->dst, d);
1833 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1835 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1836 var_to_reg_flt(s2, src, REG_FTMP2);
1837 d = reg_of_var(iptr->dst, REG_ITMP3);
1839 M_NOP; /* compare delay */
1840 M_FBF(2); /* jump over next instructions */
1841 M_LSUB_IMM(REG_ZERO, 1, d); /* delay slot */
1844 M_NOP; /* compare delay */
1845 M_FBF(2); /* jump over next instruction */
1847 M_LADD_IMM(REG_ZERO, 1, d);
1848 store_reg_to_var_int(iptr->dst, d);
1851 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1853 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1854 var_to_reg_flt(s2, src, REG_FTMP2);
1855 d = reg_of_var(iptr->dst, REG_ITMP3);
1857 M_NOP; /* compare delay */
1858 M_FBF(2); /* jump over next instruction */
1859 M_LADD_IMM(REG_ZERO, 1, d); /* delay slot */
1862 M_NOP; /* compare delay */
1863 M_FBF(2); /* jump over next instruction */
1865 M_LSUB_IMM(REG_ZERO, 1, d);
1866 store_reg_to_var_int(iptr->dst, d);
1869 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1871 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1872 var_to_reg_flt(s2, src, REG_FTMP2);
1873 d = reg_of_var(iptr->dst, REG_ITMP3);
1875 M_NOP; /* compare delay */
1876 M_FBF(2); /* jump over next instruction */
1877 M_LADD_IMM(REG_ZERO, 1, d); /* delay slot */
1880 M_NOP; /* compare delay */
1881 M_FBF(2); /* jump over next instruction */
1883 M_LSUB_IMM(REG_ZERO, 1, d);
1884 store_reg_to_var_int(iptr->dst, d);
1888 /* memory operations **************************************************/
1890 #define gen_bound_check \
1892 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1893 M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
1894 M_BEQZ(REG_ITMP3, 0);\
1895 codegen_addxboundrefs(mcodeptr);\
1899 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1901 var_to_reg_int(s1, src, REG_ITMP1);
1902 d = reg_of_var(iptr->dst, REG_ITMP3);
1903 gen_nullptr_check(s1);
1904 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1905 store_reg_to_var_int(iptr->dst, d);
1908 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1910 var_to_reg_int(s1, src->prev, REG_ITMP1);
1911 var_to_reg_int(s2, src, REG_ITMP2);
1912 d = reg_of_var(iptr->dst, REG_ITMP3);
1913 if (iptr->op1 == 0) {
1914 gen_nullptr_check(s1);
1917 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1918 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1919 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1920 store_reg_to_var_int(iptr->dst, d);
1923 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1925 var_to_reg_int(s1, src->prev, REG_ITMP1);
1926 var_to_reg_int(s2, src, REG_ITMP2);
1927 d = reg_of_var(iptr->dst, REG_ITMP3);
1928 if (iptr->op1 == 0) {
1929 gen_nullptr_check(s1);
1932 M_ASLL_IMM(s2, 2, REG_ITMP2);
1933 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1934 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1935 store_reg_to_var_int(iptr->dst, d);
1938 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1940 var_to_reg_int(s1, src->prev, REG_ITMP1);
1941 var_to_reg_int(s2, src, REG_ITMP2);
1942 d = reg_of_var(iptr->dst, REG_ITMP3);
1943 if (iptr->op1 == 0) {
1944 gen_nullptr_check(s1);
1947 M_ASLL_IMM(s2, 3, REG_ITMP2);
1948 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1949 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1950 store_reg_to_var_int(iptr->dst, d);
1953 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1955 var_to_reg_int(s1, src->prev, REG_ITMP1);
1956 var_to_reg_int(s2, src, REG_ITMP2);
1957 d = reg_of_var(iptr->dst, REG_FTMP3);
1958 if (iptr->op1 == 0) {
1959 gen_nullptr_check(s1);
1962 M_ASLL_IMM(s2, 2, REG_ITMP2);
1963 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1964 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1965 store_reg_to_var_flt(iptr->dst, d);
1968 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1970 var_to_reg_int(s1, src->prev, REG_ITMP1);
1971 var_to_reg_int(s2, src, REG_ITMP2);
1972 d = reg_of_var(iptr->dst, REG_FTMP3);
1973 if (iptr->op1 == 0) {
1974 gen_nullptr_check(s1);
1977 M_ASLL_IMM(s2, 3, REG_ITMP2);
1978 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1979 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1980 store_reg_to_var_flt(iptr->dst, d);
1983 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1985 var_to_reg_int(s1, src->prev, REG_ITMP1);
1986 var_to_reg_int(s2, src, REG_ITMP2);
1987 d = reg_of_var(iptr->dst, REG_ITMP3);
1988 if (iptr->op1 == 0) {
1989 gen_nullptr_check(s1);
1992 M_AADD(s2, s1, REG_ITMP1);
1993 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1994 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1995 store_reg_to_var_int(iptr->dst, d);
1998 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2000 var_to_reg_int(s1, src->prev, REG_ITMP1);
2001 var_to_reg_int(s2, src, REG_ITMP2);
2002 d = reg_of_var(iptr->dst, REG_ITMP3);
2003 if (iptr->op1 == 0) {
2004 gen_nullptr_check(s1);
2007 M_AADD(s2, s1, REG_ITMP1);
2008 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2009 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2010 store_reg_to_var_int(iptr->dst, d);
2013 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2015 var_to_reg_int(s1, src->prev, REG_ITMP1);
2016 var_to_reg_int(s2, src, REG_ITMP2);
2017 d = reg_of_var(iptr->dst, REG_ITMP3);
2018 if (iptr->op1 == 0) {
2019 gen_nullptr_check(s1);
2022 M_AADD(s2, s1, REG_ITMP1);
2023 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2024 store_reg_to_var_int(iptr->dst, d);
2028 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2030 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2031 var_to_reg_int(s2, src->prev, REG_ITMP2);
2032 if (iptr->op1 == 0) {
2033 gen_nullptr_check(s1);
2036 var_to_reg_int(s3, src, REG_ITMP3);
2037 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
2038 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2039 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2042 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2044 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2045 var_to_reg_int(s2, src->prev, REG_ITMP2);
2046 if (iptr->op1 == 0) {
2047 gen_nullptr_check(s1);
2050 var_to_reg_int(s3, src, REG_ITMP3);
2051 M_ASLL_IMM(s2, 2, REG_ITMP2);
2052 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2053 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
2056 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2058 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2059 var_to_reg_int(s2, src->prev, REG_ITMP2);
2060 if (iptr->op1 == 0) {
2061 gen_nullptr_check(s1);
2064 var_to_reg_int(s3, src, REG_ITMP3);
2065 M_ASLL_IMM(s2, 3, REG_ITMP2);
2066 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2067 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
2070 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2072 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2073 var_to_reg_int(s2, src->prev, REG_ITMP2);
2074 if (iptr->op1 == 0) {
2075 gen_nullptr_check(s1);
2078 var_to_reg_flt(s3, src, REG_FTMP3);
2079 M_ASLL_IMM(s2, 2, REG_ITMP2);
2080 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2081 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2084 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2086 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2087 var_to_reg_int(s2, src->prev, REG_ITMP2);
2088 if (iptr->op1 == 0) {
2089 gen_nullptr_check(s1);
2092 var_to_reg_flt(s3, src, REG_FTMP3);
2093 M_ASLL_IMM(s2, 3, REG_ITMP2);
2094 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2095 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2098 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2099 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2101 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2102 var_to_reg_int(s2, src->prev, REG_ITMP2);
2103 if (iptr->op1 == 0) {
2104 gen_nullptr_check(s1);
2107 var_to_reg_int(s3, src, REG_ITMP3);
2108 M_AADD(s2, s1, REG_ITMP1);
2109 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2110 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
2113 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2115 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2116 var_to_reg_int(s2, src->prev, REG_ITMP2);
2117 if (iptr->op1 == 0) {
2118 gen_nullptr_check(s1);
2121 var_to_reg_int(s3, src, REG_ITMP3);
2122 M_AADD(s2, s1, REG_ITMP1);
2123 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2127 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2128 /* op1 = type, val.a = field address */
2130 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2131 M_ALD(REG_ITMP1, REG_PV, a);
2132 switch (iptr->op1) {
2134 var_to_reg_int(s2, src, REG_ITMP2);
2135 M_IST(s2, REG_ITMP1, 0);
2138 var_to_reg_int(s2, src, REG_ITMP2);
2139 M_LST(s2, REG_ITMP1, 0);
2142 var_to_reg_int(s2, src, REG_ITMP2);
2143 M_AST(s2, REG_ITMP1, 0);
2146 var_to_reg_flt(s2, src, REG_FTMP2);
2147 M_FST(s2, REG_ITMP1, 0);
2150 var_to_reg_flt(s2, src, REG_FTMP2);
2151 M_DST(s2, REG_ITMP1, 0);
2153 default: panic ("internal error");
2157 case ICMD_GETSTATIC: /* ... ==> ..., value */
2158 /* op1 = type, val.a = field address */
2160 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2161 M_ALD(REG_ITMP1, REG_PV, a);
2162 switch (iptr->op1) {
2164 d = reg_of_var(iptr->dst, REG_ITMP3);
2165 M_ILD(d, REG_ITMP1, 0);
2166 store_reg_to_var_int(iptr->dst, d);
2169 d = reg_of_var(iptr->dst, REG_ITMP3);
2170 M_LLD(d, REG_ITMP1, 0);
2171 store_reg_to_var_int(iptr->dst, d);
2174 d = reg_of_var(iptr->dst, REG_ITMP3);
2175 M_ALD(d, REG_ITMP1, 0);
2176 store_reg_to_var_int(iptr->dst, d);
2179 d = reg_of_var(iptr->dst, REG_FTMP1);
2180 M_FLD(d, REG_ITMP1, 0);
2181 store_reg_to_var_flt(iptr->dst, d);
2184 d = reg_of_var(iptr->dst, REG_FTMP1);
2185 M_DLD(d, REG_ITMP1, 0);
2186 store_reg_to_var_flt(iptr->dst, d);
2188 default: panic ("internal error");
2193 case ICMD_PUTFIELD: /* ..., value ==> ... */
2194 /* op1 = type, val.i = field offset */
2196 a = ((fieldinfo *)(iptr->val.a))->offset;
2197 switch (iptr->op1) {
2199 var_to_reg_int(s1, src->prev, REG_ITMP1);
2200 var_to_reg_int(s2, src, REG_ITMP2);
2201 gen_nullptr_check(s1);
2205 var_to_reg_int(s1, src->prev, REG_ITMP1);
2206 var_to_reg_int(s2, src, REG_ITMP2);
2207 gen_nullptr_check(s1);
2211 var_to_reg_int(s1, src->prev, REG_ITMP1);
2212 var_to_reg_int(s2, src, REG_ITMP2);
2213 gen_nullptr_check(s1);
2217 var_to_reg_int(s1, src->prev, REG_ITMP1);
2218 var_to_reg_flt(s2, src, REG_FTMP2);
2219 gen_nullptr_check(s1);
2223 var_to_reg_int(s1, src->prev, REG_ITMP1);
2224 var_to_reg_flt(s2, src, REG_FTMP2);
2225 gen_nullptr_check(s1);
2228 default: panic ("internal error");
2232 case ICMD_GETFIELD: /* ... ==> ..., value */
2233 /* op1 = type, val.i = field offset */
2235 a = ((fieldinfo *)(iptr->val.a))->offset;
2236 switch (iptr->op1) {
2238 var_to_reg_int(s1, src, REG_ITMP1);
2239 d = reg_of_var(iptr->dst, REG_ITMP3);
2240 gen_nullptr_check(s1);
2242 store_reg_to_var_int(iptr->dst, d);
2245 var_to_reg_int(s1, src, REG_ITMP1);
2246 d = reg_of_var(iptr->dst, REG_ITMP3);
2247 gen_nullptr_check(s1);
2249 store_reg_to_var_int(iptr->dst, d);
2252 var_to_reg_int(s1, src, REG_ITMP1);
2253 d = reg_of_var(iptr->dst, REG_ITMP3);
2254 gen_nullptr_check(s1);
2256 store_reg_to_var_int(iptr->dst, d);
2259 var_to_reg_int(s1, src, REG_ITMP1);
2260 d = reg_of_var(iptr->dst, REG_FTMP1);
2261 gen_nullptr_check(s1);
2263 store_reg_to_var_flt(iptr->dst, d);
2266 var_to_reg_int(s1, src, REG_ITMP1);
2267 d = reg_of_var(iptr->dst, REG_FTMP1);
2268 gen_nullptr_check(s1);
2270 store_reg_to_var_flt(iptr->dst, d);
2272 default: panic ("internal error");
2277 /* branch operations **************************************************/
2279 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2281 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2283 var_to_reg_int(s1, src, REG_ITMP1);
2284 M_INTMOVE(s1, REG_ITMP1_XPTR);
2285 a = dseg_addaddress(asm_handle_exception);
2286 M_ALD(REG_ITMP2, REG_PV, a);
2287 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2289 M_NOP; /* nop ensures that XPC is less than the end */
2290 /* of basic block */
2294 case ICMD_GOTO: /* ... ==> ... */
2295 /* op1 = target JavaVM pc */
2297 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2302 case ICMD_JSR: /* ... ==> ... */
2303 /* op1 = target JavaVM pc */
2305 dseg_addtarget(BlockPtrOfPC(iptr->op1));
2306 M_ALD(REG_ITMP1, REG_PV, -dseglen);
2307 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2311 case ICMD_RET: /* ... ==> ... */
2312 /* op1 = local variable */
2313 var = &(locals[iptr->op1][TYPE_ADR]);
2314 if (var->flags & INMEMORY) {
2315 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2324 case ICMD_IFNULL: /* ..., value ==> ... */
2325 /* op1 = target JavaVM pc */
2327 var_to_reg_int(s1, src, REG_ITMP1);
2329 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2333 case ICMD_IFNONNULL: /* ..., value ==> ... */
2334 /* op1 = target JavaVM pc */
2336 var_to_reg_int(s1, src, REG_ITMP1);
2338 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2342 case ICMD_IFEQ: /* ..., value ==> ... */
2343 /* op1 = target JavaVM pc, val.i = constant */
2345 var_to_reg_int(s1, src, REG_ITMP1);
2346 if (iptr->val.i == 0) {
2350 ICONST(REG_ITMP2, iptr->val.i);
2351 M_BEQ(s1, REG_ITMP2, 0);
2353 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2357 case ICMD_IFLT: /* ..., value ==> ... */
2358 /* op1 = target JavaVM pc, val.i = constant */
2360 var_to_reg_int(s1, src, REG_ITMP1);
2361 if (iptr->val.i == 0) {
2365 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2366 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2369 ICONST(REG_ITMP2, iptr->val.i);
2370 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2372 M_BNEZ(REG_ITMP1, 0);
2374 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2378 case ICMD_IFLE: /* ..., value ==> ... */
2379 /* op1 = target JavaVM pc, val.i = constant */
2381 var_to_reg_int(s1, src, REG_ITMP1);
2382 if (iptr->val.i == 0) {
2386 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2387 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2388 M_BNEZ(REG_ITMP1, 0);
2391 ICONST(REG_ITMP2, iptr->val.i);
2392 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2393 M_BEQZ(REG_ITMP1, 0);
2396 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2400 case ICMD_IFNE: /* ..., value ==> ... */
2401 /* op1 = target JavaVM pc, val.i = constant */
2403 var_to_reg_int(s1, src, REG_ITMP1);
2404 if (iptr->val.i == 0) {
2408 ICONST(REG_ITMP2, iptr->val.i);
2409 M_BNE(s1, REG_ITMP2, 0);
2411 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2415 case ICMD_IFGT: /* ..., value ==> ... */
2416 /* op1 = target JavaVM pc, val.i = constant */
2418 var_to_reg_int(s1, src, REG_ITMP1);
2419 if (iptr->val.i == 0) {
2423 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2424 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2425 M_BEQZ(REG_ITMP1, 0);
2428 ICONST(REG_ITMP2, iptr->val.i);
2429 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2430 M_BNEZ(REG_ITMP1, 0);
2433 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2437 case ICMD_IFGE: /* ..., value ==> ... */
2438 /* op1 = target JavaVM pc, val.i = constant */
2440 var_to_reg_int(s1, src, REG_ITMP1);
2441 if (iptr->val.i == 0) {
2445 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2446 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2449 ICONST(REG_ITMP2, iptr->val.i);
2450 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2452 M_BEQZ(REG_ITMP1, 0);
2454 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2458 case ICMD_IF_LEQ: /* ..., value ==> ... */
2459 /* op1 = target JavaVM pc, val.l = constant */
2461 var_to_reg_int(s1, src, REG_ITMP1);
2462 if (iptr->val.l == 0) {
2466 LCONST(REG_ITMP2, iptr->val.l);
2467 M_BEQ(s1, REG_ITMP2, 0);
2469 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2473 case ICMD_IF_LLT: /* ..., value ==> ... */
2474 /* op1 = target JavaVM pc, val.l = constant */
2476 var_to_reg_int(s1, src, REG_ITMP1);
2477 if (iptr->val.l == 0) {
2481 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2482 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2485 LCONST(REG_ITMP2, iptr->val.l);
2486 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2488 M_BNEZ(REG_ITMP1, 0);
2490 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2494 case ICMD_IF_LLE: /* ..., value ==> ... */
2495 /* op1 = target JavaVM pc, val.l = constant */
2497 var_to_reg_int(s1, src, REG_ITMP1);
2498 if (iptr->val.l == 0) {
2502 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2503 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2504 M_BNEZ(REG_ITMP1, 0);
2507 LCONST(REG_ITMP2, iptr->val.l);
2508 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2509 M_BEQZ(REG_ITMP1, 0);
2512 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2516 case ICMD_IF_LNE: /* ..., value ==> ... */
2517 /* op1 = target JavaVM pc, val.l = constant */
2519 var_to_reg_int(s1, src, REG_ITMP1);
2520 if (iptr->val.l == 0) {
2524 LCONST(REG_ITMP2, iptr->val.l);
2525 M_BNE(s1, REG_ITMP2, 0);
2527 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2531 case ICMD_IF_LGT: /* ..., value ==> ... */
2532 /* op1 = target JavaVM pc, val.l = constant */
2534 var_to_reg_int(s1, src, REG_ITMP1);
2535 if (iptr->val.l == 0) {
2539 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2540 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2541 M_BEQZ(REG_ITMP1, 0);
2544 LCONST(REG_ITMP2, iptr->val.l);
2545 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2546 M_BNEZ(REG_ITMP1, 0);
2549 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2553 case ICMD_IF_LGE: /* ..., value ==> ... */
2554 /* op1 = target JavaVM pc, val.l = constant */
2556 var_to_reg_int(s1, src, REG_ITMP1);
2557 if (iptr->val.l == 0) {
2561 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2562 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2565 LCONST(REG_ITMP2, iptr->val.l);
2566 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2568 M_BEQZ(REG_ITMP1, 0);
2570 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2574 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2575 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2576 case ICMD_IF_ACMPEQ:
2578 var_to_reg_int(s1, src->prev, REG_ITMP1);
2579 var_to_reg_int(s2, src, REG_ITMP2);
2581 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2585 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2586 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2587 case ICMD_IF_ACMPNE:
2589 var_to_reg_int(s1, src->prev, REG_ITMP1);
2590 var_to_reg_int(s2, src, REG_ITMP2);
2592 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2596 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2597 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2599 var_to_reg_int(s1, src->prev, REG_ITMP1);
2600 var_to_reg_int(s2, src, REG_ITMP2);
2601 M_CMPLT(s1, s2, REG_ITMP1);
2602 M_BNEZ(REG_ITMP1, 0);
2603 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2607 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2608 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2610 var_to_reg_int(s1, src->prev, REG_ITMP1);
2611 var_to_reg_int(s2, src, REG_ITMP2);
2612 M_CMPGT(s1, s2, REG_ITMP1);
2613 M_BNEZ(REG_ITMP1, 0);
2614 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2618 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2619 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2621 var_to_reg_int(s1, src->prev, REG_ITMP1);
2622 var_to_reg_int(s2, src, REG_ITMP2);
2623 M_CMPGT(s1, s2, REG_ITMP1);
2624 M_BEQZ(REG_ITMP1, 0);
2625 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2629 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2630 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2632 var_to_reg_int(s1, src->prev, REG_ITMP1);
2633 var_to_reg_int(s2, src, REG_ITMP2);
2634 M_CMPLT(s1, s2, REG_ITMP1);
2635 M_BEQZ(REG_ITMP1, 0);
2636 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2640 #ifdef CONDITIONAL_LOADCONST
2641 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2643 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2646 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2647 /* val.i = constant */
2649 var_to_reg_int(s1, src, REG_ITMP1);
2650 d = reg_of_var(iptr->dst, REG_ITMP3);
2652 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2653 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2654 M_CMPEQ(s1, REG_ZERO, d);
2655 store_reg_to_var_int(iptr->dst, d);
2658 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2659 M_CMPEQ(s1, REG_ZERO, d);
2661 store_reg_to_var_int(iptr->dst, d);
2665 M_MOV(s1, REG_ITMP1);
2668 ICONST(d, iptr[1].val.i);
2670 if ((s3 >= 0) && (s3 <= 255)) {
2671 M_CMOVEQ_IMM(s1, s3, d);
2674 ICONST(REG_ITMP2, s3);
2675 M_CMOVEQ(s1, REG_ITMP2, d);
2677 store_reg_to_var_int(iptr->dst, d);
2680 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2681 /* val.i = constant */
2683 var_to_reg_int(s1, src, REG_ITMP1);
2684 d = reg_of_var(iptr->dst, REG_ITMP3);
2686 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2687 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2688 M_CMPEQ(s1, REG_ZERO, d);
2689 store_reg_to_var_int(iptr->dst, d);
2692 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2693 M_CMPEQ(s1, REG_ZERO, d);
2695 store_reg_to_var_int(iptr->dst, d);
2699 M_MOV(s1, REG_ITMP1);
2702 ICONST(d, iptr[1].val.i);
2704 if ((s3 >= 0) && (s3 <= 255)) {
2705 M_CMOVNE_IMM(s1, s3, d);
2708 ICONST(REG_ITMP2, s3);
2709 M_CMOVNE(s1, REG_ITMP2, d);
2711 store_reg_to_var_int(iptr->dst, d);
2714 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2715 /* val.i = constant */
2717 var_to_reg_int(s1, src, REG_ITMP1);
2718 d = reg_of_var(iptr->dst, REG_ITMP3);
2720 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2721 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2722 M_CMPLT(s1, REG_ZERO, d);
2723 store_reg_to_var_int(iptr->dst, d);
2726 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2727 M_CMPLE(REG_ZERO, s1, d);
2728 store_reg_to_var_int(iptr->dst, d);
2732 M_MOV(s1, REG_ITMP1);
2735 ICONST(d, iptr[1].val.i);
2737 if ((s3 >= 0) && (s3 <= 255)) {
2738 M_CMOVLT_IMM(s1, s3, d);
2741 ICONST(REG_ITMP2, s3);
2742 M_CMOVLT(s1, REG_ITMP2, d);
2744 store_reg_to_var_int(iptr->dst, d);
2747 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2748 /* val.i = constant */
2750 var_to_reg_int(s1, src, REG_ITMP1);
2751 d = reg_of_var(iptr->dst, REG_ITMP3);
2753 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2754 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2755 M_CMPLE(REG_ZERO, s1, d);
2756 store_reg_to_var_int(iptr->dst, d);
2759 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2760 M_CMPLT(s1, REG_ZERO, d);
2761 store_reg_to_var_int(iptr->dst, d);
2765 M_MOV(s1, REG_ITMP1);
2768 ICONST(d, iptr[1].val.i);
2770 if ((s3 >= 0) && (s3 <= 255)) {
2771 M_CMOVGE_IMM(s1, s3, d);
2774 ICONST(REG_ITMP2, s3);
2775 M_CMOVGE(s1, REG_ITMP2, d);
2777 store_reg_to_var_int(iptr->dst, d);
2780 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2781 /* val.i = constant */
2783 var_to_reg_int(s1, src, REG_ITMP1);
2784 d = reg_of_var(iptr->dst, REG_ITMP3);
2786 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2787 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2788 M_CMPLT(REG_ZERO, s1, d);
2789 store_reg_to_var_int(iptr->dst, d);
2792 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2793 M_CMPLE(s1, REG_ZERO, d);
2794 store_reg_to_var_int(iptr->dst, d);
2798 M_MOV(s1, REG_ITMP1);
2801 ICONST(d, iptr[1].val.i);
2803 if ((s3 >= 0) && (s3 <= 255)) {
2804 M_CMOVGT_IMM(s1, s3, d);
2807 ICONST(REG_ITMP2, s3);
2808 M_CMOVGT(s1, REG_ITMP2, d);
2810 store_reg_to_var_int(iptr->dst, d);
2813 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2814 /* val.i = constant */
2816 var_to_reg_int(s1, src, REG_ITMP1);
2817 d = reg_of_var(iptr->dst, REG_ITMP3);
2819 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2820 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2821 M_CMPLE(s1, REG_ZERO, d);
2822 store_reg_to_var_int(iptr->dst, d);
2825 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2826 M_CMPLT(REG_ZERO, s1, d);
2827 store_reg_to_var_int(iptr->dst, d);
2831 M_MOV(s1, REG_ITMP1);
2834 ICONST(d, iptr[1].val.i);
2836 if ((s3 >= 0) && (s3 <= 255)) {
2837 M_CMOVLE_IMM(s1, s3, d);
2840 ICONST(REG_ITMP2, s3);
2841 M_CMOVLE(s1, REG_ITMP2, d);
2843 store_reg_to_var_int(iptr->dst, d);
2848 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2853 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2855 a = dseg_addaddress ((void*) (builtin_monitorexit));
2856 M_ALD(REG_ITMP3, REG_PV, a);
2857 M_JSR(REG_RA, REG_ITMP3);
2858 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse); /* delay slot */
2859 disp = -(int)((u1*) mcodeptr - mcodebase);
2860 M_LDA(REG_PV, REG_RA, disp);
2863 var_to_reg_int(s1, src, REG_RESULT);
2864 M_INTMOVE(s1, REG_RESULT);
2865 goto nowperformreturn;
2867 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2871 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2873 a = dseg_addaddress ((void*) (builtin_monitorexit));
2874 M_ALD(REG_ITMP3, REG_PV, a);
2875 M_JSR(REG_RA, REG_ITMP3);
2876 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse); /* delay slot */
2877 disp = -(int)((u1*) mcodeptr - mcodebase);
2878 M_LDA(REG_PV, REG_RA, disp);
2881 var_to_reg_flt(s1, src, REG_FRESULT);
2883 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2884 M_TFLTMOVE(t, s1, REG_FRESULT);
2886 goto nowperformreturn;
2888 case ICMD_RETURN: /* ... ==> ... */
2891 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2893 a = dseg_addaddress ((void*) (builtin_monitorexit));
2894 M_ALD(REG_ITMP3, REG_PV, a);
2895 M_JSR(REG_RA, REG_ITMP3);
2896 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse); /* delay slot */
2897 disp = -(int)((u1*) mcodeptr - mcodebase);
2898 M_LDA(REG_PV, REG_RA, disp);
2906 p = parentargs_base;
2908 /* restore return address */
2911 {p--; M_LLD (REG_RA, REG_SP, 8 * p);}
2913 /* restore saved registers */
2915 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
2916 {p--; M_LLD(savintregs[r], REG_SP, 8 * p);}
2917 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
2918 {p--; M_DLD(savfltregs[r], REG_SP, 8 * p);}
2920 /* call trace function */
2923 M_LDA (REG_SP, REG_SP, -24);
2924 M_LST(REG_RA, REG_SP, 0);
2925 M_LST(REG_RESULT, REG_SP, 8);
2926 M_DST(REG_FRESULT, REG_SP,16);
2927 a = dseg_addaddress (method);
2928 M_ALD(argintregs[0], REG_PV, a);
2929 M_MOV(REG_RESULT, argintregs[1]);
2930 M_FLTMOVE(REG_FRESULT, argfltregs[2]);
2931 M_FMOV(REG_FRESULT, argfltregs[3]);
2932 a = dseg_addaddress ((void*) (builtin_displaymethodstop));
2933 M_ALD(REG_ITMP3, REG_PV, a);
2934 M_JSR (REG_RA, REG_ITMP3);
2936 M_DLD(REG_FRESULT, REG_SP,16);
2937 M_LLD(REG_RESULT, REG_SP, 8);
2938 M_LLD(REG_RA, REG_SP, 0);
2939 M_LDA (REG_SP, REG_SP, 24);
2944 /* deallocate stack */
2946 if (parentargs_base)
2947 {M_LDA(REG_SP, REG_SP, parentargs_base*8);}
2955 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2960 tptr = (void **) iptr->target;
2962 s4ptr = iptr->val.a;
2963 l = s4ptr[1]; /* low */
2964 i = s4ptr[2]; /* high */
2966 var_to_reg_int(s1, src, REG_ITMP1);
2968 {M_INTMOVE(s1, REG_ITMP1);}
2969 else if (l <= 32768) {
2970 M_IADD_IMM(s1, -l, REG_ITMP1);
2973 ICONST(REG_ITMP2, l);
2974 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2980 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
2981 M_BEQZ(REG_ITMP2, 0);
2982 codegen_addreference((basicblock *) tptr[0], mcodeptr);
2983 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
2985 /* build jump table top down and use address of lowest entry */
2987 /* s4ptr += 3 + i; */
2991 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
2992 dseg_addtarget((basicblock *) tptr[0]);
2997 /* length of dataseg after last dseg_addtarget is used by load */
2999 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
3000 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
3007 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3009 s4 i, l, val, *s4ptr;
3012 tptr = (void **) iptr->target;
3014 s4ptr = iptr->val.a;
3015 l = s4ptr[0]; /* default */
3016 i = s4ptr[1]; /* count */
3018 MCODECHECK((i<<2)+8);
3019 var_to_reg_int(s1, src, REG_ITMP1);
3025 ICONST(REG_ITMP2, val);
3026 M_BEQ(s1, REG_ITMP2, 0);
3027 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3032 tptr = (void **) iptr->target;
3033 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3040 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3041 /* op1 = return type, val.a = function pointer*/
3045 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3046 /* op1 = return type, val.a = function pointer*/
3050 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3051 /* op1 = return type, val.a = function pointer*/
3055 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3056 /* op1 = arg count, val.a = method pointer */
3058 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3059 /* op1 = arg count, val.a = method pointer */
3061 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3062 /* op1 = arg count, val.a = method pointer */
3064 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3065 /* op1 = arg count, val.a = method pointer */
3073 MCODECHECK((s3 << 1) + 64);
3075 /* copy arguments to registers or stack location */
3077 for (; --s3 >= 0; src = src->prev) {
3078 if (src->varkind == ARGVAR)
3080 if (IS_INT_LNG_TYPE(src->type)) {
3081 if (s3 < INT_ARG_CNT) {
3082 s1 = argintregs[s3];
3083 var_to_reg_int(d, src, s1);
3087 var_to_reg_int(d, src, REG_ITMP1);
3088 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3092 if (s3 < FLT_ARG_CNT) {
3093 s1 = argfltregs[s3];
3094 var_to_reg_flt(d, src, s1);
3095 M_TFLTMOVE(src->type,d, s1);
3098 var_to_reg_flt(d, src, REG_FTMP1);
3099 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3104 switch (iptr->opc) {
3108 a = dseg_addaddress ((void*) (m));
3109 M_ALD(REG_ITMP3, REG_PV, a); /* built-in-function pointer */
3110 M_JSR (REG_RA, REG_ITMP3);
3112 d = iptr->op1; /* return type */
3113 goto afteractualcall;
3115 case ICMD_INVOKESTATIC:
3116 case ICMD_INVOKESPECIAL:
3117 a = dseg_addaddress (m->stubroutine);
3119 M_ALD(REG_PV, REG_PV, a ); /* method pointer in pv */
3122 goto makeactualcall;
3124 case ICMD_INVOKEVIRTUAL:
3126 gen_nullptr_check(argintregs[0]);
3127 M_ALD(REG_METHODPTR, argintregs[0],
3128 OFFSET(java_objectheader, vftbl));
3129 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
3130 sizeof(methodptr) * m->vftblindex);
3133 goto makeactualcall;
3135 case ICMD_INVOKEINTERFACE:
3138 gen_nullptr_check(argintregs[0]);
3139 M_ALD(REG_METHODPTR, argintregs[0],
3140 OFFSET(java_objectheader, vftbl));
3141 M_ALD(REG_METHODPTR, REG_METHODPTR,
3142 OFFSET(vftbl, interfacetable[0]) -
3143 sizeof(methodptr*) * ci->index);
3144 M_ALD(REG_PV, REG_METHODPTR,
3145 sizeof(methodptr) * (m - ci->methods));
3148 goto makeactualcall;
3152 sprintf (logtext, "Unkown ICMD-Command: %d", iptr->opc);
3158 M_JSR (REG_RA, REG_PV);
3165 s1 = (int)((u1*) mcodeptr - mcodebase);
3166 if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
3169 while (ml<-32768) { ml+=65536; mh--; }
3171 M_IADD_IMM(REG_PV, ml, REG_PV);
3172 M_LADD(REG_PV, REG_RA, REG_PV);
3175 /* d contains return type */
3177 if (d != TYPE_VOID) {
3178 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3179 s1 = reg_of_var(iptr->dst, REG_RESULT);
3180 M_INTMOVE(REG_RESULT, s1);
3181 store_reg_to_var_int(iptr->dst, s1);
3184 s1 = reg_of_var(iptr->dst, REG_FRESULT);
3185 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3186 store_reg_to_var_flt(iptr->dst, s1);
3193 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3195 /* op1: 0 == array, 1 == class */
3196 /* val.a: (classinfo*) superclass */
3198 /* superclass is an interface:
3200 * return (sub != NULL) &&
3201 * (sub->vftbl->interfacetablelength > super->index) &&
3202 * (sub->vftbl->interfacetable[-super->index] != NULL);
3204 * superclass is a class:
3206 * return ((sub != NULL) && (0
3207 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3208 * super->vftbl->diffvall));
3212 classinfo *super = (classinfo*) iptr->val.a;
3214 var_to_reg_int(s1, src, REG_ITMP1);
3215 d = reg_of_var(iptr->dst, REG_ITMP3);
3217 M_MOV(s1, REG_ITMP1);
3221 if (iptr->op1) { /* class/interface */
3222 if (super->flags & ACC_INTERFACE) { /* interface */
3225 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3226 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3227 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3228 M_BLEZ(REG_ITMP2, 3);
3230 M_ALD(REG_ITMP1, REG_ITMP1,
3231 OFFSET(vftbl, interfacetable[0]) -
3232 super->index * sizeof(methodptr*));
3233 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3237 s2 = super->vftbl->diffval;
3240 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3241 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3242 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3243 M_CMPULT_IMM(REG_ITMP1, s2 + 1, d);
3248 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3249 a = dseg_addaddress ((void*) super->vftbl);
3250 M_ALD(REG_ITMP2, REG_PV, a);
3251 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3252 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3253 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3254 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3255 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3261 panic ("internal error: no inlined array instanceof");
3263 store_reg_to_var_int(iptr->dst, d);
3266 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3268 /* op1: 0 == array, 1 == class */
3269 /* val.a: (classinfo*) superclass */
3271 /* superclass is an interface:
3273 * OK if ((sub == NULL) ||
3274 * (sub->vftbl->interfacetablelength > super->index) &&
3275 * (sub->vftbl->interfacetable[-super->index] != NULL));
3277 * superclass is a class:
3279 * OK if ((sub == NULL) || (0
3280 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3281 * super->vftbl->diffvall));
3285 classinfo *super = (classinfo*) iptr->val.a;
3287 d = reg_of_var(iptr->dst, REG_ITMP3);
3288 var_to_reg_int(s1, src, d);
3289 if (iptr->op1) { /* class/interface */
3290 if (super->flags & ACC_INTERFACE) { /* interface */
3293 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3294 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3295 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3296 M_BLEZ(REG_ITMP2, 0);
3297 codegen_addxcastrefs(mcodeptr);
3299 M_ALD(REG_ITMP2, REG_ITMP1,
3300 OFFSET(vftbl, interfacetable[0]) -
3301 super->index * sizeof(methodptr*));
3302 M_BEQZ(REG_ITMP2, 0);
3303 codegen_addxcastrefs(mcodeptr);
3309 s2 = super->vftbl->diffval;
3310 M_BEQZ(s1, 6 + (s2 != 0));
3312 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3313 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3314 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3316 M_BNEZ(REG_ITMP1, 0);
3319 M_CMPULT_IMM(REG_ITMP1, s2 + 1, REG_ITMP2);
3320 M_BEQZ(REG_ITMP2, 0);
3324 M_BEQZ(s1, 10 + (d == REG_ITMP3));
3326 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3327 a = dseg_addaddress ((void*) super->vftbl);
3328 M_ALD(REG_ITMP2, REG_PV, a);
3329 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3330 if (d != REG_ITMP3) {
3331 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3332 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3333 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3335 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, baseval));
3336 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3337 M_ALD(REG_ITMP2, REG_PV, a);
3338 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3340 M_CMPULT(REG_ITMP2, REG_ITMP1, REG_ITMP2);
3341 M_BNEZ(REG_ITMP2, 0);
3343 codegen_addxcastrefs(mcodeptr);
3348 panic ("internal error: no inlined array checkcast");
3351 store_reg_to_var_int(iptr->dst, d);
3354 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3356 var_to_reg_int(s1, src, REG_ITMP1);
3358 codegen_addxcheckarefs(mcodeptr);
3362 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3363 /* op1 = dimension, val.a = array descriptor */
3365 /* check for negative sizes and copy sizes to stack if necessary */
3367 MCODECHECK((iptr->op1 << 1) + 64);
3369 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3370 var_to_reg_int(s2, src, REG_ITMP1);
3372 codegen_addxcheckarefs(mcodeptr);
3375 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3377 if (src->varkind != ARGVAR) {
3378 M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
3382 /* a0 = dimension count */
3384 ICONST(argintregs[0], iptr->op1);
3386 /* a1 = arraydescriptor */
3388 a = dseg_addaddress(iptr->val.a);
3389 M_ALD(argintregs[1], REG_PV, a);
3391 /* a2 = pointer to dimensions = stack pointer */
3393 M_INTMOVE(REG_SP, argintregs[2]);
3395 a = dseg_addaddress((void*) (builtin_nmultianewarray));
3396 M_ALD(REG_ITMP3, REG_PV, a);
3397 M_JSR(REG_RA, REG_ITMP3);
3399 s1 = (int)((u1*) mcodeptr - mcodebase);
3401 M_LDA (REG_PV, REG_RA, -s1);
3405 s1 = reg_of_var(iptr->dst, REG_RESULT);
3406 M_INTMOVE(REG_RESULT, s1);
3407 store_reg_to_var_int(iptr->dst, s1);
3411 default: sprintf (logtext, "Unknown pseudo command: %d", iptr->opc);
3418 } /* for instruction */
3420 /* copy values to interface registers */
3422 src = bptr->outstack;
3423 len = bptr->outdepth;
3427 if ((src->varkind != STACKVAR)) {
3429 if (IS_FLT_DBL_TYPE(s2)) {
3430 var_to_reg_flt(s1, src, REG_FTMP1);
3431 if (!(interfaces[len][s2].flags & INMEMORY)) {
3432 M_TFLTMOVE(s2,s1,interfaces[len][s2].regoff);
3435 M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3439 var_to_reg_int(s1, src, REG_ITMP1);
3440 if (!(interfaces[len][s2].flags & INMEMORY)) {
3441 M_INTMOVE(s1,interfaces[len][s2].regoff);
3444 M_LST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3450 } /* if (bptr -> flags >= BBREACHED) */
3451 } /* for basic block */
3453 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3456 /* generate bound check stubs */
3458 s4 *xcodeptr = NULL;
3460 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3461 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3462 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3463 xboundrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3468 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3469 xboundrefs->branchpos, (u1*) mcodeptr - mcodebase);
3473 M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos - 4);
3475 if (xcodeptr != NULL) {
3476 int disp = xcodeptr-mcodeptr;
3481 xcodeptr = mcodeptr;
3483 a = dseg_addaddress(asm_handle_exception);
3484 M_ALD(REG_ITMP3, REG_PV, a);
3487 a = dseg_addaddress(proto_java_lang_ArrayIndexOutOfBoundsException);
3488 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3492 /* generate negative array size check stubs */
3496 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3497 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3498 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3499 xcheckarefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3503 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3504 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
3508 M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos - 4);
3510 if (xcodeptr != NULL) {
3511 int disp = xcodeptr-mcodeptr;
3516 xcodeptr = mcodeptr;
3518 a = dseg_addaddress(asm_handle_exception);
3519 M_ALD(REG_ITMP3, REG_PV, a);
3522 a = dseg_addaddress(proto_java_lang_NegativeArraySizeException);
3523 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3527 /* generate cast check stubs */
3531 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3532 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3533 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3534 xcastrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3538 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3539 xcastrefs->branchpos, (u1*) mcodeptr - mcodebase);
3543 M_LDA(REG_ITMP2_XPC, REG_PV, xcastrefs->branchpos - 4);
3545 if (xcodeptr != NULL) {
3546 int disp = xcodeptr-mcodeptr;
3551 xcodeptr = mcodeptr;
3553 a = dseg_addaddress(asm_handle_exception);
3554 M_ALD(REG_ITMP3, REG_PV, a);
3557 a = dseg_addaddress(proto_java_lang_ClassCastException);
3558 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3563 #ifdef SOFTNULLPTRCHECK
3565 /* generate null pointer check stubs */
3569 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3570 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3571 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3572 xnullrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3576 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3577 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
3581 M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
3583 if (xcodeptr != NULL) {
3584 int disp = xcodeptr-mcodeptr;
3589 xcodeptr = mcodeptr;
3591 a = dseg_addaddress(asm_handle_exception);
3592 M_ALD(REG_ITMP3, REG_PV, a);
3595 a = dseg_addaddress(proto_java_lang_NullPointerException);
3596 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3603 codegen_finish((int)((u1*) mcodeptr - mcodebase));
3605 docacheflush((void*) method->entrypoint,
3606 ((u1*) mcodeptr - mcodebase), ICACHE);
3610 /* redefinition of code generation macros (compiling into array) **************/
3613 These macros are newly defined to allow code generation into an array.
3614 This is necessary, because the original M_.. macros generate code by
3615 calling 'codegen_adds4' that uses an additional data structure to
3618 For a faster (but less flexible) version to generate code, these
3619 macros directly use the (s4* p) - pointer to put the code directly
3620 in a locally defined array.
3621 This makes sense only for the stub-generation-routines below.
3625 #define M_ITYPE(op, rs, rt, imm)\
3626 *(p++) = (((op)<<26)|((rs)<<21)|((rt)<<16)|((imm)&0xffff))
3629 #define M_JTYPE(op, imm)\
3630 *(p++) = (((op)<<26)|((off)&0x3ffffff))
3633 #define M_RTYPE(op, rs, rt, rd, sa, fu)\
3634 *(p++) = (((op)<<26)|((rs)<<21)|((rt)<<16)|((rd)<<11)|((sa)<<6)|(fu))
3637 /* function createcompilerstub *************************************************
3639 creates a stub routine which calls the compiler
3641 *******************************************************************************/
3643 #define COMPSTUBSIZE 4
3645 u1 *createcompilerstub (methodinfo *m)
3647 u8 *s = CNEW (u8, COMPSTUBSIZE); /* memory to hold the stub */
3648 s4 *p = (s4*) s; /* code generation pointer */
3650 /* code for the stub */
3651 M_ALD(REG_PV, REG_PV, 24); /* load pointer to the compiler */
3653 M_JSR(REG_ITMP1, REG_PV); /* jump to the compiler, return address
3654 in itmp1 is used as method pointer */
3657 s[2] = (u8) m; /* literals to be adressed */
3658 s[3] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3660 (void) docacheflush((void*) s, (char*) p - (char*) s, ICACHE);
3663 count_cstub_len += COMPSTUBSIZE * 8;
3670 /* function removecompilerstub *************************************************
3672 deletes a compilerstub from memory (simply by freeing it)
3674 *******************************************************************************/
3676 void removecompilerstub (u1 *stub)
3678 CFREE (stub, COMPSTUBSIZE * 8);
3681 /* function: createnativestub **************************************************
3683 creates a stub routine which calls a native method
3685 *******************************************************************************/
3687 #define NATIVESTUBSIZE 20
3689 u1 *createnativestub (functionptr f, methodinfo *m)
3691 u8 *s = CNEW (u8, NATIVESTUBSIZE); /* memory to hold the stub */
3692 s4 *p = (s4*) s; /* code generation pointer */
3696 M_MOV (argintregs[4], argintregs[5]);
3697 M_DMFC1 (REG_ITMP1, argfltregs[4]);
3699 M_MOV (argintregs[3], argintregs[4]);
3700 M_DMTC1 (REG_ITMP1, argfltregs[5]);
3702 M_MOV (argintregs[2], argintregs[3]);
3703 M_DMFC1 (REG_ITMP1, argfltregs[3]);
3705 M_MOV (argintregs[1], argintregs[2]);
3706 M_DMTC1 (REG_ITMP1, argfltregs[4]);
3708 M_MOV (argintregs[0], argintregs[1]);
3709 M_DMFC1 (REG_ITMP1, argfltregs[2]);
3711 M_ALD (argintregs[0], REG_PV, 19*8); /* load adress of jni_environement */
3712 M_DMTC1 (REG_ITMP1, argfltregs[3]);
3714 M_DMFC1 (REG_ITMP1, argfltregs[1]);
3715 M_DMFC1 (REG_ITMP2, argfltregs[0]);
3717 M_DMTC1 (REG_ITMP1, argfltregs[2]);
3718 M_DMTC1 (REG_ITMP2, argfltregs[1]);
3720 M_ALD (REG_ITMP3, REG_PV, 16*8); /* load adress of native method */
3721 M_LDA (REG_SP, REG_SP, -8); /* build up stackframe */
3723 M_LST (REG_RA, REG_SP, 0); /* store return address */
3724 M_JSR (REG_RA, REG_ITMP3); /* call native method */
3726 M_NOP; /* delay slot */
3727 M_ALD (REG_ITMP3, REG_PV, 17*8); /* get address of exceptionptr */
3729 M_LLD (REG_RA, REG_SP, 0); /* load return address */
3730 M_ALD (REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
3732 M_BNEZ (REG_ITMP1, 2); /* if no exception then return */
3733 M_LDA (REG_SP, REG_SP, 8); /* remove stackframe, delay slot */
3735 M_RET (REG_RA); /* return to caller */
3736 M_NOP; /* delay slot */
3738 M_AST (REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
3739 M_ALD (REG_ITMP3, REG_PV,18*8); /* load asm exception handler address */
3741 M_JMP (REG_ITMP3); /* jump to asm exception handler */
3742 M_LDA (REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
3745 s[16] = (u8) f; /* address of native method */
3746 s[17] = (u8) (&exceptionptr); /* address of exceptionptr */
3747 s[18]= (u8) (asm_handle_nat_exception); /* addr of asm exception handler */
3748 s[19] = (u8) (&env); /* addr of jni_environement */
3750 (void) docacheflush((void*) s, (char*) p - (char*) s, ICACHE);
3753 count_nstub_len += NATIVESTUBSIZE * 8;
3759 /* function: removenativestub **************************************************
3761 removes a previously created native-stub from memory
3763 *******************************************************************************/
3765 void removenativestub (u1 *stub)
3767 CFREE (stub, NATIVESTUBSIZE * 8);
3771 /* function: createcalljava ****************************************************
3773 creates the asm_calljavamethod (MIPS assembler does not like data in the
3774 text segment). Documentation can be found in asmpart.c.
3776 *******************************************************************************/
3785 #define CALL_JAVA_MEM_SIZE 60
3786 #define CALL_JAVA_ENTRY 20
3787 #define CALL_JAVA_XHANDLER 55
3789 static s4 calljavamem[CALL_JAVA_MEM_SIZE];
3791 void createcalljava ()
3795 *((void**)(calljavamem + 0)) = (void*) asm_call_jit_compiler;
3796 *((void**)(calljavamem + 2)) = (void*) builtin_throw_exception;
3798 *((void**)(calljavamem + 4)) = NULL;
3799 *((void**)(calljavamem + 6)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3800 *((void**)(calljavamem + 8)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3801 *((void**)(calljavamem +10)) = (void*) (calljavamem + CALL_JAVA_ENTRY);
3803 *((void**)(calljavamem + 8)) = NULL;
3804 *((void**)(calljavamem + 9)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3805 *((void**)(calljavamem +10)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3806 *((void**)(calljavamem +11)) = (void*) (calljavamem + CALL_JAVA_ENTRY);
3809 calljavamem[12] = 1; /* extable size */
3810 calljavamem[13] = 0; /* fltsave */
3811 calljavamem[14] = 0; /* intsave */
3812 calljavamem[15] = 0; /* isleaf */
3813 calljavamem[16] = 0; /* IsSync */
3814 calljavamem[17] = 80; /* frame size */
3815 calljavamem[18] = 0; /* method pointer (NULL) */
3816 calljavamem[19] = 0; /* method pointer (NULL) */
3818 p = calljavamem + CALL_JAVA_ENTRY; /* code generation pointer */
3821 M_LDA (REG_SP, REG_SP, -10*8); /* allocate stackframe */
3822 M_LST (REG_RA, REG_SP, 0); /* save return address */
3824 M_BRS(1); /* compute current program counter */
3825 M_LST (REG_PV, REG_SP, 3*8); /* save procedure vector */
3827 M_LDA (REG_PV, REG_RA, -4*4); /* compute procedure vector */
3828 M_DST (REG_FSS0, REG_SP, 4*8); /* save non JavaABI saved flt regs */
3830 M_DST (REG_FSS1, REG_SP, 5*8);
3831 M_DST (REG_FSS2, REG_SP, 6*8);
3833 M_DST (REG_FSS3, REG_SP, 7*8);
3834 M_DST (REG_FSS4, REG_SP, 8*8);
3836 M_DST (REG_FSS5, REG_SP, 9*8);
3837 M_LST (REG_ARG_0, REG_SP, 2*8); /* save method pointer for compiler */
3839 M_LDA (REG_ITMP1, REG_SP, 2*8); /* pass pointer to methodptr via itmp1*/
3840 M_MOV (REG_ARG_1, REG_ARG_0); /* pass the remaining parameters */
3842 M_MOV (REG_ARG_2, REG_ARG_1);
3843 M_MOV (REG_ARG_3, REG_ARG_2);
3845 M_MOV (REG_ARG_4, REG_ARG_3);
3846 M_ALD (REG_METHODPTR, REG_PV, -80); /* address of asm_call_jit_compiler */
3848 M_AST (REG_METHODPTR, REG_SP, 8); /* store function address */
3849 M_MOV (REG_SP, REG_METHODPTR); /* set method pointer */
3851 M_ALD (REG_PV, REG_METHODPTR, 8); /* method call as in Java */
3852 M_JSR (REG_RA, REG_PV); /* call JIT compiler */
3854 M_NOP; /* delay slot */
3855 M_LDA (REG_PV, REG_RA, -23*4); /* recompute procedure vector */
3859 M_CLR (REG_RESULT); /* clear return value (exception ptr) */
3863 /* calljava_return: */
3864 M_LLD (REG_RA, REG_SP, 0); /* restore return address */
3866 M_LLD (REG_PV, REG_SP, 3*8); /* restore procedure vector */
3867 M_DLD (REG_FSS0, REG_SP, 4*8); /* restore non JavaABI saved flt regs */
3869 M_DLD (REG_FSS1, REG_SP, 5*8);
3870 M_DLD (REG_FSS2, REG_SP, 6*8);
3872 M_DLD (REG_FSS3, REG_SP, 7*8);
3873 M_DLD (REG_FSS4, REG_SP, 8*8);
3875 M_DLD (REG_FSS5, REG_SP, 9*8);
3876 M_RET(REG_RA); /* return */
3878 M_LDA (REG_SP, REG_SP, 10*8); /* deallocate stackframe (delay slot) */
3881 /* calljava_xhandler: */
3883 M_ALD (REG_ITMP3, REG_PV, -72); /* address of builtin_throw_exception */
3885 M_JSR (REG_RA, REG_ITMP3); /* call builtin */
3886 M_MOV (REG_ITMP1, REG_ARG_0); /* pass parameter (delay slot) */
3888 M_BR(-14); /* branch calljava_return */
3889 M_NOP; /* delay slot */
3891 (void) cacheflush((void*)(calljavamem + CALL_JAVA_ENTRY),
3892 (CALL_JAVA_MEM_SIZE - CALL_JAVA_ENTRY) * (int) sizeof(s4), ICACHE);
3896 typedef java_objectheader* (*asm_fptr)(methodinfo*, void*, void*, void*, void*);
3898 java_objectheader *asm_calljavamethod (methodinfo *m, void *arg1, void *arg2,
3899 void *arg3, void *arg4)
3901 java_objectheader *r = ((asm_fptr)(calljavamem + 20))(m, arg1, arg2, arg3, arg4);
3902 return (exceptionptr ? r : NULL);
3905 java_objectheader *asm_calljavafunction (methodinfo *m, void *arg1, void *arg2,
3906 void *arg3, void *arg4)
3908 return ((asm_fptr)(calljavamem + 20))(m, arg1, arg2, arg3, arg4);
3916 void docacheflush(u1 *p, long bytelen, int dummy)
3918 u1 *e = p + bytelen;
3919 long psize = sysconf(_SC_PAGESIZE);
3920 p -= (long) p & (psize-1);
3921 e += psize - ((((long) e - 1) & (psize-1)) + 1);
3923 mprotect(p, bytelen, PROT_READ|PROT_WRITE|PROT_EXEC);
3928 * These are local overrides for various environment variables in Emacs.
3929 * Please do not remove this and leave it at the end of the file, where
3930 * Emacs will automagically detect them.
3931 * ---------------------------------------------------------------------
3934 * indent-tabs-mode: t