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 636 2003-11-14 20:19:21Z stefan $
55 /* include independent code generation stuff */
56 #include "codegen.inc"
60 /* *****************************************************************************
62 Datatypes and Register Allocations:
63 -----------------------------------
65 On 64-bit-machines (like the MIPS) all operands are stored in the
66 registers in a 64-bit form, even when the correspondig JavaVM operands
67 only need 32 bits. This is done by a canonical representation:
69 32-bit integers are allways stored as sign-extended 64-bit values (this
70 approach is directly supported by the MIPS architecture and is very easy
73 32-bit-floats are stored in a 64-bit double precision register by simply
74 expanding the exponent and mantissa with zeroes. (also supported by the
80 The calling conventions and the layout of the stack is explained in detail
81 in the documention file: calling.doc
83 *******************************************************************************/
86 /* register descripton - array ************************************************/
88 /* #define REG_RES 0 reserved register for OS or code generator */
89 /* #define REG_RET 1 return value register */
90 /* #define REG_EXC 2 exception value register (only old jit) */
91 /* #define REG_SAV 3 (callee) saved register */
92 /* #define REG_TMP 4 scratch temporary register (caller saved) */
93 /* #define REG_ARG 5 argument register (caller saved) */
95 /* #define REG_END -1 last entry in tables */
98 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
99 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
100 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
101 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
104 /* for use of reserved registers, see comment above */
106 int nregdescfloat[] = {
107 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
108 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
109 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
110 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
113 /* for use of reserved registers, see comment above */
116 /* parameter allocation mode */
118 int nreg_parammode = PARAMMODE_NUMBERED;
120 /* parameter-registers will be allocated by assigning the
121 1. parameter: int/float-reg a0
122 2. parameter: int/float-reg a1
123 3. parameter: int/float-reg a2 ....
127 /* stackframe-infos ***********************************************************/
129 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
131 /* -> see file 'calling.doc' */
134 /* additional functions and macros to generate code ***************************/
136 /* #define BlockPtrOfPC(pc) block+block_index[pc] */
137 #define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
141 #define COUNT_SPILLS count_spills++
147 /* gen_nullptr_check(objreg) */
149 #ifdef SOFTNULLPTRCHECK
150 #define gen_nullptr_check(objreg) \
152 M_BEQZ((objreg), 0);\
153 codegen_addxnullrefs(mcodeptr);\
157 #define gen_nullptr_check(objreg)
161 /* MCODECHECK(icnt) */
163 #define MCODECHECK(icnt) \
164 if((mcodeptr+(icnt))>mcodeend)mcodeptr=codegen_increase((u1*)mcodeptr)
167 generates an integer-move from register a to b.
168 if a and b are the same int-register, no code will be generated.
171 #define M_INTMOVE(a,b) if(a!=b){M_MOV(a,b);}
175 generates a floating-point-move from register a to b.
176 if a and b are the same float-register, no code will be generated
179 #define M_FLTMOVE(a,b) {if(a!=b){M_DMOV(a,b);}}
181 #define M_TFLTMOVE(t,a,b) \
185 else {M_FMOV(a,b);} \
188 #define M_TFLD(t,a,b,disp) \
194 #define M_TFST(t,a,b,disp) \
200 #define M_CCFLTMOVE(t1,t2,a,b) \
202 {M_TFLTMOVE(t1,a,b);} \
204 if ((t1)==TYPE_DBL) \
209 #define M_CCFLD(t1,t2,a,b,disp) \
213 M_DLD(REG_FTMP1,b,disp); \
214 if ((t1)==TYPE_DBL) \
215 {M_CVTDF(REG_FTMP1,a);} \
217 {M_CVTFD(REG_FTMP1,a);} \
220 #define M_CCFST(t1,t2,a,b,disp) \
224 if ((t1)==TYPE_DBL) \
225 {M_CVTDF(a,REG_FTMP1);} \
227 {M_CVTFD(a,REG_FTMP1);} \
228 M_DST(REG_FTMP1,b,disp); \
233 this function generates code to fetch data from a pseudo-register
234 into a real register.
235 If the pseudo-register has actually been assigned to a real
236 register, no code will be emitted, since following operations
237 can use this register directly.
239 v: pseudoregister to be fetched from
240 tempregnum: temporary register to be used if v is actually spilled to ram
242 return: the register number, where the operand can be found after
243 fetching (this wil be either tempregnum or the register
244 number allready given to v)
247 #define var_to_reg_int(regnr,v,tempnr) { \
248 if ((v)->flags & INMEMORY) \
249 {COUNT_SPILLS;M_LLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
250 else regnr=(v)->regoff; \
254 #define var_to_reg_flt(regnr,v,tempnr) { \
255 if ((v)->flags & INMEMORY) \
256 {COUNT_SPILLS;M_DLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
257 else regnr=(v)->regoff; \
262 This function determines a register, to which the result of an operation
263 should go, when it is ultimatively intended to store the result in
265 If v is assigned to an actual register, this register will be returned.
266 Otherwise (when v is spilled) this function returns tempregnum.
267 If not already done, regoff and flags are set in the stack location.
270 static int reg_of_var(stackptr v, int tempregnum)
274 switch (v->varkind) {
276 if (!(v->flags & INMEMORY))
280 var = &(interfaces[v->varnum][v->type]);
281 v->regoff = var->regoff;
282 if (!(var->flags & INMEMORY))
286 var = &(locals[v->varnum][v->type]);
287 v->regoff = var->regoff;
288 if (!(var->flags & INMEMORY))
292 v->regoff = v->varnum;
293 if (IS_FLT_DBL_TYPE(v->type)) {
294 if (v->varnum < fltreg_argnum) {
295 v->regoff = argfltregs[v->varnum];
296 return(argfltregs[v->varnum]);
300 if (v->varnum < intreg_argnum) {
301 v->regoff = argintregs[v->varnum];
302 return(argintregs[v->varnum]);
304 v->regoff -= intreg_argnum;
307 v->flags |= INMEMORY;
312 /* store_reg_to_var_xxx:
313 This function generates the code to store the result of an operation
314 back into a spilled pseudo-variable.
315 If the pseudo-variable has not been spilled in the first place, this
316 function will generate nothing.
318 v ............ Pseudovariable
319 tempregnum ... Number of the temporary registers as returned by
323 #define store_reg_to_var_int(sptr, tempregnum) { \
324 if ((sptr)->flags & INMEMORY) { \
326 M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
330 #define store_reg_to_var_flt(sptr, tempregnum) { \
331 if ((sptr)->flags & INMEMORY) { \
333 M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
338 /* NullPointerException handlers and exception handling initialisation */
340 /* NullPointerException signal handler for hardware null pointer check */
342 void catch_NullPointerException(int sig, int code, struct sigcontext *sigctx)
348 /* Reset signal handler - necessary for SysV, does no harm for BSD */
350 instr = *((int*)(sigctx->sc_pc));
351 faultaddr = sigctx->sc_regs[(instr >> 21) & 0x1f];
353 if (faultaddr == 0) {
355 sigaddset(&nsig, sig);
356 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
357 sigctx->sc_regs[REG_ITMP1_XPTR] =
358 (long) proto_java_lang_NullPointerException;
359 sigctx->sc_regs[REG_ITMP2_XPC] = sigctx->sc_pc;
360 sigctx->sc_pc = (long) asm_handle_exception;
363 faultaddr += (long) ((instr << 16) >> 16);
364 fprintf(stderr, "faulting address: 0x%lx at 0x%lx\n", (long) faultaddr, (long) sigctx->sc_pc);
365 panic("Stack overflow");
372 void init_exceptions(void)
375 sigset_t unblockmask;
379 /* The Boehm GC initialization blocks the SIGSEGV signal. So we do a
380 dummy allocation here to ensure that the GC is initialized.
382 heap_allocate(1, 0, NULL);
384 /* install signal handlers we need to convert to exceptions */
386 sigemptyset(&unblockmask);
388 sa.sa_sigaction = catch_NullPointerException;
389 sigemptyset(&sa.sa_mask);
394 sigaction(SIGSEGV, &sa, NULL);
395 sigaddset(&unblockmask, SIGSEGV);
399 sigaction(SIGBUS, &sa, NULL);
400 sigaddset(&unblockmask, SIGBUS);
404 sigprocmask(SIG_UNBLOCK, &unblockmask, NULL);
406 /* Turn off flush-to-zero */
409 n.fc_word = get_fpc_csr();
410 n.fc_struct.flush = 0;
411 set_fpc_csr(n.fc_word);
416 /* function gen_mcode **********************************************************
418 generates machine code
420 *******************************************************************************/
422 #define MethodPointer -8
423 #define FrameSize -12
428 #define ExTableSize -32
429 #define ExTableStart -32
432 #define ExEntrySize -32
435 #define ExHandlerPC -24
436 #define ExCatchType -32
438 #define ExEntrySize -16
441 #define ExHandlerPC -12
442 #define ExCatchType -16
447 int len, s1, s2, s3, d;
459 savedregs_num = (isleafmethod) ? 0 : 1; /* space to save the RA */
461 /* space to save used callee saved registers */
463 savedregs_num += (savintregcnt - maxsavintreguse);
464 savedregs_num += (savfltregcnt - maxsavfltreguse);
466 parentargs_base = maxmemuse + savedregs_num;
468 #ifdef USE_THREADS /* space to save argument of monitor_enter */
470 if (checksync && (method->flags & ACC_SYNCHRONIZED))
475 /* adjust frame size for 16 byte alignment */
477 if (parentargs_base & 1)
480 /* create method header */
483 (void) dseg_addaddress(method); /* Filler */
485 (void) dseg_addaddress(method); /* MethodPointer */
486 (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
490 /* IsSync contains the offset relative to the stack pointer for the
491 argument of monitor_exit used in the exception handler. Since the
492 offset could be zero and give a wrong meaning of the flag it is
496 if (checksync && (method->flags & ACC_SYNCHRONIZED))
497 (void) dseg_adds4((maxmemuse + 1) * 8); /* IsSync */
502 (void) dseg_adds4(0); /* IsSync */
504 (void) dseg_adds4(isleafmethod); /* IsLeaf */
505 (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
506 (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
507 (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
509 /* create exception table */
511 for (ex = extable; ex != NULL; ex = ex->down) {
514 if (ex->start != NULL)
515 printf("adding start - %d - ", ex->start->debug_nr);
517 printf("PANIC - start is NULL");
522 dseg_addtarget(ex->start);
526 printf("adding end - %d - ", ex->end->debug_nr);
528 printf("PANIC - end is NULL");
533 dseg_addtarget(ex->end);
536 if (ex->handler != NULL)
537 printf("adding handler - %d\n", ex->handler->debug_nr);
539 printf("PANIC - handler is NULL");
544 dseg_addtarget(ex->handler);
546 (void) dseg_addaddress(ex->catchtype);
549 /* initialize mcode variables */
551 mcodeptr = (s4*) mcodebase;
552 mcodeend = (s4*) (mcodebase + mcodesize);
553 MCODECHECK(128 + mparamcount);
555 /* create stack frame (if necessary) */
558 {M_LDA (REG_SP, REG_SP, -parentargs_base * 8);}
560 /* save return address and used callee saved registers */
564 {p--; M_LST (REG_RA, REG_SP, 8*p);}
565 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
566 {p--; M_LST (savintregs[r], REG_SP, 8 * p);}
567 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
568 {p--; M_DST (savfltregs[r], REG_SP, 8 * p);}
570 /* save monitorenter argument */
573 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
574 if (method->flags & ACC_STATIC) {
575 p = dseg_addaddress (class);
576 M_ALD(REG_ITMP1, REG_PV, p);
577 M_AST(REG_ITMP1, REG_SP, 8 * maxmemuse);
580 M_AST (argintregs[0], REG_SP, 8 * maxmemuse);
585 /* copy argument registers to stack and call trace function with pointer
586 to arguments on stack. ToDo: save floating point registers !!!!!!!!!
590 M_LDA (REG_SP, REG_SP, -(18*8));
592 M_LST(REG_RA, REG_SP, 1*8);
594 M_LST(argintregs[0], REG_SP, 2*8);
595 M_LST(argintregs[1], REG_SP, 3*8);
596 M_LST(argintregs[2], REG_SP, 4*8);
597 M_LST(argintregs[3], REG_SP, 5*8);
598 M_LST(argintregs[4], REG_SP, 6*8);
599 M_LST(argintregs[5], REG_SP, 7*8);
600 M_LST(argintregs[6], REG_SP, 8*8);
601 M_LST(argintregs[7], REG_SP, 9*8);
603 M_DST(argfltregs[0], REG_SP, 10*8);
604 M_DST(argfltregs[1], REG_SP, 11*8);
605 M_DST(argfltregs[2], REG_SP, 12*8);
606 M_DST(argfltregs[3], REG_SP, 13*8);
607 M_DST(argfltregs[4], REG_SP, 14*8);
608 M_DST(argfltregs[5], REG_SP, 15*8);
609 M_DST(argfltregs[6], REG_SP, 16*8);
610 M_DST(argfltregs[7], REG_SP, 17*8);
612 p = dseg_addaddress (method);
613 M_ALD(REG_ITMP1, REG_PV, p);
614 M_LST(REG_ITMP1, REG_SP, 0);
615 p = dseg_addaddress ((void*) (builtin_trace_args));
616 M_ALD(REG_ITMP3, REG_PV, p);
617 M_JSR(REG_RA, REG_ITMP3);
620 M_LLD(REG_RA, REG_SP, 1*8);
622 M_LLD(argintregs[0], REG_SP, 2*8);
623 M_LLD(argintregs[1], REG_SP, 3*8);
624 M_LLD(argintregs[2], REG_SP, 4*8);
625 M_LLD(argintregs[3], REG_SP, 5*8);
626 M_LLD(argintregs[4], REG_SP, 6*8);
627 M_LLD(argintregs[5], REG_SP, 7*8);
628 M_LLD(argintregs[6], REG_SP, 8*8);
629 M_LLD(argintregs[7], REG_SP, 9*8);
631 M_DLD(argfltregs[0], REG_SP, 10*8);
632 M_DLD(argfltregs[1], REG_SP, 11*8);
633 M_DLD(argfltregs[2], REG_SP, 12*8);
634 M_DLD(argfltregs[3], REG_SP, 13*8);
635 M_DLD(argfltregs[4], REG_SP, 14*8);
636 M_DLD(argfltregs[5], REG_SP, 15*8);
637 M_DLD(argfltregs[6], REG_SP, 16*8);
638 M_DLD(argfltregs[7], REG_SP, 17*8);
640 M_LDA (REG_SP, REG_SP, 18*8);
643 /* take arguments out of register or stack frame */
645 for (p = 0, l = 0; p < mparamcount; p++) {
647 var = &(locals[l][t]);
649 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
654 if (IS_INT_LNG_TYPE(t)) { /* integer args */
655 if (p < INT_ARG_CNT) { /* register arguments */
656 if (!(var->flags & INMEMORY)) /* reg arg -> register */
657 {M_INTMOVE (argintregs[p], r);}
658 else /* reg arg -> spilled */
659 M_LST (argintregs[p], REG_SP, 8 * r);
661 else { /* stack arguments */
662 pa = p - INT_ARG_CNT;
663 if (!(var->flags & INMEMORY)) /* stack arg -> register */
664 M_LLD (r, REG_SP, 8 * (parentargs_base + pa));
665 else { /* stack arg -> spilled */
666 M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
667 M_LST (REG_ITMP1, REG_SP, 8 * r);
671 else { /* floating args */
672 if (p < FLT_ARG_CNT) { /* register arguments */
673 if (!(var->flags & INMEMORY)) /* reg arg -> register */
674 {M_TFLTMOVE (var->type, argfltregs[p], r);}
675 else /* reg arg -> spilled */
676 M_DST (argfltregs[p], REG_SP, 8 * r);
678 else { /* stack arguments */
679 pa = p - FLT_ARG_CNT;
680 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
681 M_DLD (r, REG_SP, 8 * (parentargs_base + pa) );
682 } else { /* stack-arg -> spilled */
683 M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
684 M_DST (REG_FTMP1, REG_SP, 8 * r);
690 /* call trace function */
693 if (runverbose && !isleafmethod) {
694 M_LDA (REG_SP, REG_SP, -8);
695 p = dseg_addaddress (method);
696 M_ALD(REG_ITMP1, REG_PV, p);
697 M_AST(REG_ITMP1, REG_SP, 0);
698 p = dseg_addaddress ((void*) (builtin_trace_args));
699 M_ALD(REG_ITMP3, REG_PV, p);
700 M_JSR(REG_RA, REG_ITMP3);
702 M_LDA(REG_SP, REG_SP, 8);
706 /* call monitorenter function */
709 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
711 p = dseg_addaddress ((void*) (builtin_monitorenter));
712 M_ALD(REG_ITMP3, REG_PV, p);
713 M_JSR(REG_RA, REG_ITMP3);
714 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
715 disp = -(int)((u1*) mcodeptr - mcodebase);
716 M_LDA(REG_PV, REG_RA, disp);
721 /* end of header generation */
723 /* walk through all basic blocks */
724 for (bptr = block; bptr != NULL; bptr = bptr->next) {
726 bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
728 if (bptr->flags >= BBREACHED) {
730 /* branch resolving */
734 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
735 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
736 brefs->branchpos, bptr->mpc);
740 /* copy interface registers to their destination */
745 while (src != NULL) {
747 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
748 d = reg_of_var(src, REG_ITMP1);
749 M_INTMOVE(REG_ITMP1, d);
750 store_reg_to_var_int(src, d);
753 d = reg_of_var(src, REG_IFTMP);
754 if ((src->varkind != STACKVAR)) {
756 if (IS_FLT_DBL_TYPE(s2)) {
757 if (!(interfaces[len][s2].flags & INMEMORY)) {
758 s1 = interfaces[len][s2].regoff;
762 M_DLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
764 store_reg_to_var_flt(src, d);
767 if (!(interfaces[len][s2].flags & INMEMORY)) {
768 s1 = interfaces[len][s2].regoff;
772 M_LLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
774 store_reg_to_var_int(src, d);
781 /* walk through all instructions */
785 for (iptr = bptr->iinstr;
787 src = iptr->dst, len--, iptr++) {
789 MCODECHECK(64); /* an instruction usually needs < 64 words */
792 case ICMD_NOP: /* ... ==> ... */
795 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
797 var_to_reg_int(s1, src, REG_ITMP1);
799 codegen_addxnullrefs(mcodeptr);
803 /* constant operations ************************************************/
805 #define ICONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_IADD_IMM(REG_ZERO,c,r);} \
806 else if(((c)>=0)&&((c)<=0xffff)){M_OR_IMM(REG_ZERO,c,r);} \
807 else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
809 #define LCONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LADD_IMM(REG_ZERO,c,r);} \
810 else if(((c)>=0)&&((c)<=0xffff)){M_OR_IMM(REG_ZERO,c,r);} \
811 else{a=dseg_adds8(c);M_LLD(r,REG_PV,a);}
813 case ICMD_ICONST: /* ... ==> ..., constant */
814 /* op1 = 0, val.i = constant */
816 d = reg_of_var(iptr->dst, REG_ITMP1);
817 ICONST(d, iptr->val.i);
818 store_reg_to_var_int(iptr->dst, d);
821 case ICMD_LCONST: /* ... ==> ..., constant */
822 /* op1 = 0, val.l = constant */
824 d = reg_of_var(iptr->dst, REG_ITMP1);
825 LCONST(d, iptr->val.l);
826 store_reg_to_var_int(iptr->dst, d);
829 case ICMD_FCONST: /* ... ==> ..., constant */
830 /* op1 = 0, val.f = constant */
832 d = reg_of_var (iptr->dst, REG_FTMP1);
833 a = dseg_addfloat (iptr->val.f);
835 store_reg_to_var_flt (iptr->dst, d);
838 case ICMD_DCONST: /* ... ==> ..., constant */
839 /* op1 = 0, val.d = constant */
841 d = reg_of_var (iptr->dst, REG_FTMP1);
842 a = dseg_adddouble (iptr->val.d);
844 store_reg_to_var_flt (iptr->dst, d);
847 case ICMD_ACONST: /* ... ==> ..., constant */
848 /* op1 = 0, val.a = constant */
850 d = reg_of_var(iptr->dst, REG_ITMP1);
852 a = dseg_addaddress (iptr->val.a);
856 M_INTMOVE(REG_ZERO, d);
858 store_reg_to_var_int(iptr->dst, d);
862 /* load/store operations **********************************************/
864 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
865 case ICMD_LLOAD: /* op1 = local variable */
868 d = reg_of_var(iptr->dst, REG_ITMP1);
869 if ((iptr->dst->varkind == LOCALVAR) &&
870 (iptr->dst->varnum == iptr->op1))
872 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
873 if (var->flags & INMEMORY)
874 M_LLD(d, REG_SP, 8 * var->regoff);
876 {M_INTMOVE(var->regoff,d);}
877 store_reg_to_var_int(iptr->dst, d);
880 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
881 case ICMD_DLOAD: /* op1 = local variable */
883 d = reg_of_var(iptr->dst, REG_FTMP1);
884 if ((iptr->dst->varkind == LOCALVAR) &&
885 (iptr->dst->varnum == iptr->op1))
887 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
889 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
890 if (var->flags & INMEMORY)
891 {M_CCFLD(var->type,t2,d, REG_SP, 8 * var->regoff);}
893 {M_CCFLTMOVE(var->type,t2,var->regoff,d);}
895 store_reg_to_var_flt(iptr->dst, d);
899 case ICMD_ISTORE: /* ..., value ==> ... */
900 case ICMD_LSTORE: /* op1 = local variable */
903 if ((src->varkind == LOCALVAR) &&
904 (src->varnum == iptr->op1))
906 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
907 if (var->flags & INMEMORY) {
908 var_to_reg_int(s1, src, REG_ITMP1);
909 M_LST(s1, REG_SP, 8 * var->regoff);
912 var_to_reg_int(s1, src, var->regoff);
913 M_INTMOVE(s1, var->regoff);
917 case ICMD_FSTORE: /* ..., value ==> ... */
918 case ICMD_DSTORE: /* op1 = local variable */
920 if ((src->varkind == LOCALVAR) &&
921 (src->varnum == iptr->op1))
923 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
925 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
926 if (var->flags & INMEMORY) {
927 var_to_reg_flt(s1, src, REG_FTMP1);
928 M_CCFST(t1,var->type,s1, REG_SP, 8 * var->regoff);
931 var_to_reg_flt(s1, src, var->regoff);
932 M_CCFLTMOVE(t1,var->type,s1, var->regoff);
938 /* pop/dup/swap operations ********************************************/
940 /* attention: double and longs are only one entry in CACAO ICMDs */
942 case ICMD_POP: /* ..., value ==> ... */
943 case ICMD_POP2: /* ..., value, value ==> ... */
946 #define M_COPY(from,to) \
947 d = reg_of_var(to, REG_IFTMP); \
948 if ((from->regoff != to->regoff) || \
949 ((from->flags ^ to->flags) & INMEMORY)) { \
950 if (IS_FLT_DBL_TYPE(from->type)) { \
951 var_to_reg_flt(s1, from, d); \
952 M_TFLTMOVE(from->type,s1,d); \
953 store_reg_to_var_flt(to, d); \
956 var_to_reg_int(s1, from, d); \
958 store_reg_to_var_int(to, d); \
962 case ICMD_DUP: /* ..., a ==> ..., a, a */
963 M_COPY(src, iptr->dst);
966 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
968 M_COPY(src, iptr->dst->prev->prev);
970 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
972 M_COPY(src, iptr->dst);
973 M_COPY(src->prev, iptr->dst->prev);
976 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
978 M_COPY(src->prev, iptr->dst->prev->prev->prev);
980 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
982 M_COPY(src, iptr->dst);
983 M_COPY(src->prev, iptr->dst->prev);
984 M_COPY(src->prev->prev, iptr->dst->prev->prev);
985 M_COPY(src, iptr->dst->prev->prev->prev);
988 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
990 M_COPY(src, iptr->dst);
991 M_COPY(src->prev, iptr->dst->prev);
992 M_COPY(src->prev->prev, iptr->dst->prev->prev);
993 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
994 M_COPY(src, iptr->dst->prev->prev->prev->prev);
995 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
998 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1000 M_COPY(src, iptr->dst->prev);
1001 M_COPY(src->prev, iptr->dst);
1005 /* integer operations *************************************************/
1007 case ICMD_INEG: /* ..., value ==> ..., - value */
1009 var_to_reg_int(s1, src, REG_ITMP1);
1010 d = reg_of_var(iptr->dst, REG_ITMP3);
1011 M_ISUB(REG_ZERO, s1, d);
1012 store_reg_to_var_int(iptr->dst, d);
1015 case ICMD_LNEG: /* ..., value ==> ..., - value */
1017 var_to_reg_int(s1, src, REG_ITMP1);
1018 d = reg_of_var(iptr->dst, REG_ITMP3);
1019 M_LSUB(REG_ZERO, s1, d);
1020 store_reg_to_var_int(iptr->dst, d);
1023 case ICMD_I2L: /* ..., value ==> ..., value */
1025 var_to_reg_int(s1, src, REG_ITMP1);
1026 d = reg_of_var(iptr->dst, REG_ITMP3);
1028 store_reg_to_var_int(iptr->dst, d);
1031 case ICMD_L2I: /* ..., value ==> ..., value */
1033 var_to_reg_int(s1, src, REG_ITMP1);
1034 d = reg_of_var(iptr->dst, REG_ITMP3);
1035 M_ISLL_IMM(s1, 0, d );
1036 store_reg_to_var_int(iptr->dst, d);
1039 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1041 var_to_reg_int(s1, src, REG_ITMP1);
1042 d = reg_of_var(iptr->dst, REG_ITMP3);
1043 M_LSLL_IMM(s1, 56, d);
1044 M_LSRA_IMM( d, 56, d);
1045 store_reg_to_var_int(iptr->dst, d);
1048 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1050 var_to_reg_int(s1, src, REG_ITMP1);
1051 d = reg_of_var(iptr->dst, REG_ITMP3);
1053 store_reg_to_var_int(iptr->dst, d);
1056 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1058 var_to_reg_int(s1, src, REG_ITMP1);
1059 d = reg_of_var(iptr->dst, REG_ITMP3);
1060 M_LSLL_IMM(s1, 48, d);
1061 M_LSRA_IMM( d, 48, d);
1062 store_reg_to_var_int(iptr->dst, d);
1066 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1068 var_to_reg_int(s1, src->prev, REG_ITMP1);
1069 var_to_reg_int(s2, src, REG_ITMP2);
1070 d = reg_of_var(iptr->dst, REG_ITMP3);
1072 store_reg_to_var_int(iptr->dst, d);
1075 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1076 /* val.i = constant */
1078 var_to_reg_int(s1, src, REG_ITMP1);
1079 d = reg_of_var(iptr->dst, REG_ITMP3);
1080 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1081 M_IADD_IMM(s1, iptr->val.i, d);
1084 ICONST(REG_ITMP2, iptr->val.i);
1085 M_IADD(s1, REG_ITMP2, d);
1087 store_reg_to_var_int(iptr->dst, d);
1090 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1092 var_to_reg_int(s1, src->prev, REG_ITMP1);
1093 var_to_reg_int(s2, src, REG_ITMP2);
1094 d = reg_of_var(iptr->dst, REG_ITMP3);
1096 store_reg_to_var_int(iptr->dst, d);
1099 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1100 /* val.l = constant */
1102 var_to_reg_int(s1, src, REG_ITMP1);
1103 d = reg_of_var(iptr->dst, REG_ITMP3);
1104 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
1105 M_LADD_IMM(s1, iptr->val.l, d);
1108 LCONST(REG_ITMP2, iptr->val.l);
1109 M_LADD(s1, REG_ITMP2, d);
1111 store_reg_to_var_int(iptr->dst, d);
1114 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1116 var_to_reg_int(s1, src->prev, REG_ITMP1);
1117 var_to_reg_int(s2, src, REG_ITMP2);
1118 d = reg_of_var(iptr->dst, REG_ITMP3);
1120 store_reg_to_var_int(iptr->dst, d);
1123 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1124 /* val.i = constant */
1126 var_to_reg_int(s1, src, REG_ITMP1);
1127 d = reg_of_var(iptr->dst, REG_ITMP3);
1128 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
1129 M_IADD_IMM(s1, -iptr->val.i, d);
1132 ICONST(REG_ITMP2, iptr->val.i);
1133 M_ISUB(s1, REG_ITMP2, d);
1135 store_reg_to_var_int(iptr->dst, d);
1138 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1140 var_to_reg_int(s1, src->prev, REG_ITMP1);
1141 var_to_reg_int(s2, src, REG_ITMP2);
1142 d = reg_of_var(iptr->dst, REG_ITMP3);
1144 store_reg_to_var_int(iptr->dst, d);
1147 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1148 /* val.l = constant */
1150 var_to_reg_int(s1, src, REG_ITMP1);
1151 d = reg_of_var(iptr->dst, REG_ITMP3);
1152 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
1153 M_LADD_IMM(s1, -iptr->val.l, d);
1156 LCONST(REG_ITMP2, iptr->val.l);
1157 M_LSUB(s1, REG_ITMP2, d);
1159 store_reg_to_var_int(iptr->dst, d);
1162 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1164 var_to_reg_int(s1, src->prev, REG_ITMP1);
1165 var_to_reg_int(s2, src, REG_ITMP2);
1166 d = reg_of_var(iptr->dst, REG_ITMP3);
1171 store_reg_to_var_int(iptr->dst, d);
1174 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1175 /* val.i = constant */
1177 var_to_reg_int(s1, src, REG_ITMP1);
1178 d = reg_of_var(iptr->dst, REG_ITMP3);
1179 ICONST(REG_ITMP2, iptr->val.i);
1180 M_IMUL(s1, REG_ITMP2);
1184 store_reg_to_var_int(iptr->dst, d);
1187 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1189 var_to_reg_int(s1, src->prev, REG_ITMP1);
1190 var_to_reg_int(s2, src, REG_ITMP2);
1191 d = reg_of_var(iptr->dst, REG_ITMP3);
1196 store_reg_to_var_int(iptr->dst, d);
1199 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1200 /* val.l = constant */
1202 var_to_reg_int(s1, src, REG_ITMP1);
1203 d = reg_of_var(iptr->dst, REG_ITMP3);
1204 LCONST(REG_ITMP2, iptr->val.l);
1205 M_LMUL(s1, REG_ITMP2);
1209 store_reg_to_var_int(iptr->dst, d);
1212 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1214 var_to_reg_int(s1, src->prev, REG_ITMP1);
1215 var_to_reg_int(s2, src, REG_ITMP2);
1216 d = reg_of_var(iptr->dst, REG_ITMP3);
1221 store_reg_to_var_int(iptr->dst, d);
1224 case ICMD_IDIVCONST: /* ..., value ==> ..., value / constant */
1225 /* val.i = constant */
1227 var_to_reg_int(s1, src, REG_ITMP1);
1228 d = reg_of_var(iptr->dst, REG_ITMP3);
1229 ICONST(REG_ITMP2, iptr->val.i);
1230 M_IDIV(s1, REG_ITMP2);
1234 store_reg_to_var_int(iptr->dst, d);
1237 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1239 var_to_reg_int(s1, src->prev, REG_ITMP1);
1240 var_to_reg_int(s2, src, REG_ITMP2);
1241 d = reg_of_var(iptr->dst, REG_ITMP3);
1246 store_reg_to_var_int(iptr->dst, d);
1249 case ICMD_LDIVCONST: /* ..., value ==> ..., value / constant */
1250 /* val.l = constant */
1252 var_to_reg_int(s1, src, REG_ITMP1);
1253 d = reg_of_var(iptr->dst, REG_ITMP3);
1254 LCONST(REG_ITMP2, iptr->val.l);
1255 M_LDIV(s1, REG_ITMP2);
1259 store_reg_to_var_int(iptr->dst, d);
1262 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1264 var_to_reg_int(s1, src->prev, REG_ITMP1);
1265 var_to_reg_int(s2, src, REG_ITMP2);
1266 d = reg_of_var(iptr->dst, REG_ITMP3);
1271 store_reg_to_var_int(iptr->dst, d);
1274 case ICMD_IREMCONST: /* ..., value ==> ..., value % constant */
1275 /* val.i = constant */
1277 var_to_reg_int(s1, src, REG_ITMP1);
1278 d = reg_of_var(iptr->dst, REG_ITMP3);
1279 ICONST(REG_ITMP2, iptr->val.i);
1280 M_IDIV(s1, REG_ITMP2);
1284 store_reg_to_var_int(iptr->dst, d);
1287 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1289 var_to_reg_int(s1, src->prev, REG_ITMP1);
1290 var_to_reg_int(s2, src, REG_ITMP2);
1291 d = reg_of_var(iptr->dst, REG_ITMP3);
1296 store_reg_to_var_int(iptr->dst, d);
1299 case ICMD_LREMCONST: /* ..., value ==> ..., value % constant */
1300 /* val.l = constant */
1302 var_to_reg_int(s1, src, REG_ITMP1);
1303 d = reg_of_var(iptr->dst, REG_ITMP3);
1304 LCONST(REG_ITMP2, iptr->val.l);
1305 M_LDIV(s1, REG_ITMP2);
1309 store_reg_to_var_int(iptr->dst, d);
1312 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1313 case ICMD_LDIVPOW2: /* val.i = constant */
1315 var_to_reg_int(s1, src, REG_ITMP1);
1316 d = reg_of_var(iptr->dst, REG_ITMP3);
1317 M_LSRA_IMM(s1, 63, REG_ITMP2);
1318 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1319 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1320 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
1321 store_reg_to_var_int(iptr->dst, d);
1324 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1326 var_to_reg_int(s1, src->prev, REG_ITMP1);
1327 var_to_reg_int(s2, src, REG_ITMP2);
1328 d = reg_of_var(iptr->dst, REG_ITMP3);
1330 store_reg_to_var_int(iptr->dst, d);
1333 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1334 /* val.i = constant */
1336 var_to_reg_int(s1, src, REG_ITMP1);
1337 d = reg_of_var(iptr->dst, REG_ITMP3);
1338 M_ISLL_IMM(s1, iptr->val.i, d);
1339 store_reg_to_var_int(iptr->dst, d);
1342 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1344 var_to_reg_int(s1, src->prev, REG_ITMP1);
1345 var_to_reg_int(s2, src, REG_ITMP2);
1346 d = reg_of_var(iptr->dst, REG_ITMP3);
1348 store_reg_to_var_int(iptr->dst, d);
1351 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1352 /* val.i = constant */
1354 var_to_reg_int(s1, src, REG_ITMP1);
1355 d = reg_of_var(iptr->dst, REG_ITMP3);
1356 M_ISRA_IMM(s1, iptr->val.i, d);
1357 store_reg_to_var_int(iptr->dst, d);
1360 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1362 var_to_reg_int(s1, src->prev, REG_ITMP1);
1363 var_to_reg_int(s2, src, REG_ITMP2);
1364 d = reg_of_var(iptr->dst, REG_ITMP3);
1366 store_reg_to_var_int(iptr->dst, d);
1369 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1370 /* val.i = constant */
1372 var_to_reg_int(s1, src, REG_ITMP1);
1373 d = reg_of_var(iptr->dst, REG_ITMP3);
1374 M_ISRL_IMM(s1, iptr->val.i, d);
1375 store_reg_to_var_int(iptr->dst, d);
1378 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1380 var_to_reg_int(s1, src->prev, REG_ITMP1);
1381 var_to_reg_int(s2, src, REG_ITMP2);
1382 d = reg_of_var(iptr->dst, REG_ITMP3);
1384 store_reg_to_var_int(iptr->dst, d);
1387 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1388 /* val.i = constant */
1390 var_to_reg_int(s1, src, REG_ITMP1);
1391 d = reg_of_var(iptr->dst, REG_ITMP3);
1392 M_LSLL_IMM(s1, iptr->val.i, d);
1393 store_reg_to_var_int(iptr->dst, d);
1396 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1398 var_to_reg_int(s1, src->prev, REG_ITMP1);
1399 var_to_reg_int(s2, src, REG_ITMP2);
1400 d = reg_of_var(iptr->dst, REG_ITMP3);
1402 store_reg_to_var_int(iptr->dst, d);
1405 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1406 /* val.i = constant */
1408 var_to_reg_int(s1, src, REG_ITMP1);
1409 d = reg_of_var(iptr->dst, REG_ITMP3);
1410 M_LSRA_IMM(s1, iptr->val.i, d);
1411 store_reg_to_var_int(iptr->dst, d);
1414 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1416 var_to_reg_int(s1, src->prev, REG_ITMP1);
1417 var_to_reg_int(s2, src, REG_ITMP2);
1418 d = reg_of_var(iptr->dst, REG_ITMP3);
1420 store_reg_to_var_int(iptr->dst, d);
1423 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1424 /* val.i = constant */
1426 var_to_reg_int(s1, src, REG_ITMP1);
1427 d = reg_of_var(iptr->dst, REG_ITMP3);
1428 M_LSRL_IMM(s1, iptr->val.i, d);
1429 store_reg_to_var_int(iptr->dst, d);
1432 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1435 var_to_reg_int(s1, src->prev, REG_ITMP1);
1436 var_to_reg_int(s2, src, REG_ITMP2);
1437 d = reg_of_var(iptr->dst, REG_ITMP3);
1439 store_reg_to_var_int(iptr->dst, d);
1442 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1443 /* val.i = constant */
1445 var_to_reg_int(s1, src, REG_ITMP1);
1446 d = reg_of_var(iptr->dst, REG_ITMP3);
1447 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1448 M_AND_IMM(s1, iptr->val.i, d);
1451 ICONST(REG_ITMP2, iptr->val.i);
1452 M_AND(s1, REG_ITMP2, d);
1454 store_reg_to_var_int(iptr->dst, d);
1457 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1458 /* val.i = constant */
1460 var_to_reg_int(s1, src, REG_ITMP1);
1461 d = reg_of_var(iptr->dst, REG_ITMP3);
1463 M_MOV(s1, REG_ITMP1);
1466 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1467 M_AND_IMM(s1, iptr->val.i, d);
1470 M_ISUB(REG_ZERO, s1, d);
1471 M_AND_IMM(d, iptr->val.i, d);
1474 ICONST(REG_ITMP2, iptr->val.i);
1475 M_AND(s1, REG_ITMP2, d);
1478 M_ISUB(REG_ZERO, s1, d);
1479 M_AND(d, REG_ITMP2, d);
1481 M_ISUB(REG_ZERO, d, d);
1482 store_reg_to_var_int(iptr->dst, d);
1485 case ICMD_IREM0X10001: /* ..., value ==> ..., value % 0x100001 */
1487 /* b = value & 0xffff;
1489 a = ((b - a) & 0xffff) + (b < a);
1491 var_to_reg_int(s1, src, REG_ITMP1);
1492 d = reg_of_var(iptr->dst, REG_ITMP3);
1494 M_MOV(s1, REG_ITMP3);
1498 M_CZEXT(s1, REG_ITMP2); /* delay slot */
1499 M_ISRA_IMM(s1, 16, d);
1500 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1501 M_ISUB(REG_ITMP2, d, d);
1504 M_IADD(d, REG_ITMP1, d); /* delay slot */
1506 M_LUI(REG_ITMP2, 1);
1507 M_IADD_IMM(REG_ITMP2, 1, REG_ITMP2);
1508 M_IDIV(s1, REG_ITMP2);
1512 store_reg_to_var_int(iptr->dst, d);
1515 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1516 /* val.l = constant */
1518 var_to_reg_int(s1, src, REG_ITMP1);
1519 d = reg_of_var(iptr->dst, REG_ITMP3);
1520 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1521 M_AND_IMM(s1, iptr->val.l, d);
1524 LCONST(REG_ITMP2, iptr->val.l);
1525 M_AND(s1, REG_ITMP2, d);
1527 store_reg_to_var_int(iptr->dst, d);
1530 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1531 /* val.l = constant */
1533 var_to_reg_int(s1, src, REG_ITMP1);
1534 d = reg_of_var(iptr->dst, REG_ITMP3);
1536 M_MOV(s1, REG_ITMP1);
1539 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1540 M_AND_IMM(s1, iptr->val.l, d);
1543 M_LSUB(REG_ZERO, s1, d);
1544 M_AND_IMM(d, iptr->val.l, d);
1547 LCONST(REG_ITMP2, iptr->val.l);
1548 M_AND(s1, REG_ITMP2, d);
1551 M_LSUB(REG_ZERO, s1, d);
1552 M_AND(d, REG_ITMP2, d);
1554 M_LSUB(REG_ZERO, d, d);
1555 store_reg_to_var_int(iptr->dst, d);
1558 case ICMD_LREM0X10001:/* ..., value ==> ..., value % 0x10001 */
1560 var_to_reg_int(s1, src, REG_ITMP1);
1561 d = reg_of_var(iptr->dst, REG_ITMP3);
1562 M_LUI(REG_ITMP2, 1);
1563 M_LADD_IMM(REG_ITMP2, 1, REG_ITMP2);
1564 M_LDIV(s1, REG_ITMP2);
1568 store_reg_to_var_int(iptr->dst, d);
1571 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1574 var_to_reg_int(s1, src->prev, REG_ITMP1);
1575 var_to_reg_int(s2, src, REG_ITMP2);
1576 d = reg_of_var(iptr->dst, REG_ITMP3);
1578 store_reg_to_var_int(iptr->dst, d);
1581 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1582 /* val.i = constant */
1584 var_to_reg_int(s1, src, REG_ITMP1);
1585 d = reg_of_var(iptr->dst, REG_ITMP3);
1586 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1587 M_OR_IMM(s1, iptr->val.i, d);
1590 ICONST(REG_ITMP2, iptr->val.i);
1591 M_OR(s1, REG_ITMP2, d);
1593 store_reg_to_var_int(iptr->dst, d);
1596 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1597 /* val.l = constant */
1599 var_to_reg_int(s1, src, REG_ITMP1);
1600 d = reg_of_var(iptr->dst, REG_ITMP3);
1601 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1602 M_OR_IMM(s1, iptr->val.l, d);
1605 LCONST(REG_ITMP2, iptr->val.l);
1606 M_OR(s1, REG_ITMP2, d);
1608 store_reg_to_var_int(iptr->dst, d);
1611 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1614 var_to_reg_int(s1, src->prev, REG_ITMP1);
1615 var_to_reg_int(s2, src, REG_ITMP2);
1616 d = reg_of_var(iptr->dst, REG_ITMP3);
1618 store_reg_to_var_int(iptr->dst, d);
1621 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1622 /* val.i = constant */
1624 var_to_reg_int(s1, src, REG_ITMP1);
1625 d = reg_of_var(iptr->dst, REG_ITMP3);
1626 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1627 M_XOR_IMM(s1, iptr->val.i, d);
1630 ICONST(REG_ITMP2, iptr->val.i);
1631 M_XOR(s1, REG_ITMP2, d);
1633 store_reg_to_var_int(iptr->dst, d);
1636 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1637 /* val.l = constant */
1639 var_to_reg_int(s1, src, REG_ITMP1);
1640 d = reg_of_var(iptr->dst, REG_ITMP3);
1641 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1642 M_XOR_IMM(s1, iptr->val.l, d);
1645 LCONST(REG_ITMP2, iptr->val.l);
1646 M_XOR(s1, REG_ITMP2, d);
1648 store_reg_to_var_int(iptr->dst, d);
1652 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1654 var_to_reg_int(s1, src->prev, REG_ITMP1);
1655 var_to_reg_int(s2, src, REG_ITMP2);
1656 d = reg_of_var(iptr->dst, REG_ITMP3);
1657 M_CMPLT(s1, s2, REG_ITMP3);
1658 M_CMPLT(s2, s1, REG_ITMP1);
1659 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1660 store_reg_to_var_int(iptr->dst, d);
1664 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1665 /* op1 = variable, val.i = constant */
1667 var = &(locals[iptr->op1][TYPE_INT]);
1668 if (var->flags & INMEMORY) {
1670 M_LLD(s1, REG_SP, 8 * var->regoff);
1674 M_IADD_IMM(s1, iptr->val.i, s1);
1675 if (var->flags & INMEMORY)
1676 M_LST(s1, REG_SP, 8 * var->regoff);
1680 /* floating operations ************************************************/
1682 case ICMD_FNEG: /* ..., value ==> ..., - value */
1684 var_to_reg_flt(s1, src, REG_FTMP1);
1685 d = reg_of_var(iptr->dst, REG_FTMP3);
1687 store_reg_to_var_flt(iptr->dst, d);
1690 case ICMD_DNEG: /* ..., value ==> ..., - value */
1692 var_to_reg_flt(s1, src, REG_FTMP1);
1693 d = reg_of_var(iptr->dst, REG_FTMP3);
1695 store_reg_to_var_flt(iptr->dst, d);
1698 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1700 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1701 var_to_reg_flt(s2, src, REG_FTMP2);
1702 d = reg_of_var(iptr->dst, REG_FTMP3);
1704 store_reg_to_var_flt(iptr->dst, d);
1707 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1709 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1710 var_to_reg_flt(s2, src, REG_FTMP2);
1711 d = reg_of_var(iptr->dst, REG_FTMP3);
1713 store_reg_to_var_flt(iptr->dst, d);
1716 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1718 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1719 var_to_reg_flt(s2, src, REG_FTMP2);
1720 d = reg_of_var(iptr->dst, REG_FTMP3);
1722 store_reg_to_var_flt(iptr->dst, d);
1725 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1727 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1728 var_to_reg_flt(s2, src, REG_FTMP2);
1729 d = reg_of_var(iptr->dst, REG_FTMP3);
1731 store_reg_to_var_flt(iptr->dst, d);
1734 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1736 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1737 var_to_reg_flt(s2, src, REG_FTMP2);
1738 d = reg_of_var(iptr->dst, REG_FTMP3);
1740 store_reg_to_var_flt(iptr->dst, d);
1743 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1745 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1746 var_to_reg_flt(s2, src, REG_FTMP2);
1747 d = reg_of_var(iptr->dst, REG_FTMP3);
1749 store_reg_to_var_flt(iptr->dst, d);
1752 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1754 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1755 var_to_reg_flt(s2, src, REG_FTMP2);
1756 d = reg_of_var(iptr->dst, REG_FTMP3);
1758 store_reg_to_var_flt(iptr->dst, d);
1761 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1763 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1764 var_to_reg_flt(s2, src, REG_FTMP2);
1765 d = reg_of_var(iptr->dst, REG_FTMP3);
1767 store_reg_to_var_flt(iptr->dst, d);
1770 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1773 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1774 var_to_reg_flt(s2, src, REG_FTMP2);
1775 d = reg_of_var(iptr->dst, REG_FTMP3);
1776 M_FDIV(s1,s2, REG_FTMP3);
1777 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1778 M_CVTLF(REG_FTMP3, REG_FTMP3);
1779 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1780 M_FSUB(s1, REG_FTMP3, d);
1781 store_reg_to_var_flt(iptr->dst, d);
1784 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1786 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1787 var_to_reg_flt(s2, src, REG_FTMP2);
1788 d = reg_of_var(iptr->dst, REG_FTMP3);
1789 M_DDIV(s1,s2, REG_FTMP3);
1790 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1791 M_CVTLD(REG_FTMP3, REG_FTMP3);
1792 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1793 M_DSUB(s1, REG_FTMP3, d);
1794 store_reg_to_var_flt(iptr->dst, d);
1797 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1799 var_to_reg_int(s1, src, REG_ITMP1);
1800 d = reg_of_var(iptr->dst, REG_FTMP3);
1803 store_reg_to_var_flt(iptr->dst, d);
1806 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1808 var_to_reg_int(s1, src, REG_ITMP1);
1809 d = reg_of_var(iptr->dst, REG_FTMP3);
1812 store_reg_to_var_flt(iptr->dst, d);
1815 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1817 var_to_reg_flt(s1, src, REG_FTMP1);
1818 d = reg_of_var(iptr->dst, REG_ITMP3);
1819 M_TRUNCFI(s1, REG_FTMP1);
1820 M_MOVDI(REG_FTMP1, d);
1822 store_reg_to_var_int(iptr->dst, d);
1825 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1827 var_to_reg_flt(s1, src, REG_FTMP1);
1828 d = reg_of_var(iptr->dst, REG_ITMP3);
1829 M_TRUNCDI(s1, REG_FTMP1);
1830 M_MOVDI(REG_FTMP1, d);
1832 store_reg_to_var_int(iptr->dst, d);
1835 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1837 var_to_reg_flt(s1, src, REG_FTMP1);
1838 d = reg_of_var(iptr->dst, REG_ITMP3);
1839 M_TRUNCFL(s1, REG_FTMP1);
1840 M_MOVDL(REG_FTMP1, d);
1842 store_reg_to_var_int(iptr->dst, d);
1845 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1847 var_to_reg_flt(s1, src, REG_FTMP1);
1848 d = reg_of_var(iptr->dst, REG_ITMP3);
1849 M_TRUNCDL(s1, REG_FTMP1);
1850 M_MOVDL(REG_FTMP1, d);
1852 store_reg_to_var_int(iptr->dst, d);
1855 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1857 var_to_reg_flt(s1, src, REG_FTMP1);
1858 d = reg_of_var(iptr->dst, REG_FTMP3);
1860 store_reg_to_var_flt(iptr->dst, d);
1863 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1865 var_to_reg_flt(s1, src, REG_FTMP1);
1866 d = reg_of_var(iptr->dst, REG_FTMP3);
1868 store_reg_to_var_flt(iptr->dst, d);
1871 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1873 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1874 var_to_reg_flt(s2, src, REG_FTMP2);
1875 d = reg_of_var(iptr->dst, REG_ITMP3);
1877 M_NOP; /* compare delay */
1878 M_FBF(2); /* jump over next instructions */
1879 M_LSUB_IMM(REG_ZERO, 1, d); /* delay slot */
1882 M_NOP; /* compare delay */
1883 M_FBF(2); /* jump over next instruction */
1885 M_LADD_IMM(REG_ZERO, 1, d);
1886 store_reg_to_var_int(iptr->dst, d);
1889 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1891 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1892 var_to_reg_flt(s2, src, REG_FTMP2);
1893 d = reg_of_var(iptr->dst, REG_ITMP3);
1895 M_NOP; /* compare delay */
1896 M_FBF(2); /* jump over next instructions */
1897 M_LSUB_IMM(REG_ZERO, 1, d); /* delay slot */
1900 M_NOP; /* compare delay */
1901 M_FBF(2); /* jump over next instruction */
1903 M_LADD_IMM(REG_ZERO, 1, d);
1904 store_reg_to_var_int(iptr->dst, d);
1907 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1909 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1910 var_to_reg_flt(s2, src, REG_FTMP2);
1911 d = reg_of_var(iptr->dst, REG_ITMP3);
1913 M_NOP; /* compare delay */
1914 M_FBF(2); /* jump over next instruction */
1915 M_LADD_IMM(REG_ZERO, 1, d); /* delay slot */
1918 M_NOP; /* compare delay */
1919 M_FBF(2); /* jump over next instruction */
1921 M_LSUB_IMM(REG_ZERO, 1, d);
1922 store_reg_to_var_int(iptr->dst, d);
1925 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1927 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1928 var_to_reg_flt(s2, src, REG_FTMP2);
1929 d = reg_of_var(iptr->dst, REG_ITMP3);
1931 M_NOP; /* compare delay */
1932 M_FBF(2); /* jump over next instruction */
1933 M_LADD_IMM(REG_ZERO, 1, d); /* delay slot */
1936 M_NOP; /* compare delay */
1937 M_FBF(2); /* jump over next instruction */
1939 M_LSUB_IMM(REG_ZERO, 1, d);
1940 store_reg_to_var_int(iptr->dst, d);
1944 /* memory operations **************************************************/
1946 #define gen_bound_check \
1948 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1949 M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
1950 M_BEQZ(REG_ITMP3, 0);\
1951 codegen_addxboundrefs(mcodeptr);\
1955 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1957 var_to_reg_int(s1, src, REG_ITMP1);
1958 d = reg_of_var(iptr->dst, REG_ITMP3);
1959 gen_nullptr_check(s1);
1960 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1961 store_reg_to_var_int(iptr->dst, d);
1964 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1966 var_to_reg_int(s1, src->prev, REG_ITMP1);
1967 var_to_reg_int(s2, src, REG_ITMP2);
1968 d = reg_of_var(iptr->dst, REG_ITMP3);
1969 if (iptr->op1 == 0) {
1970 gen_nullptr_check(s1);
1973 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1974 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1975 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1976 store_reg_to_var_int(iptr->dst, d);
1979 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1981 var_to_reg_int(s1, src->prev, REG_ITMP1);
1982 var_to_reg_int(s2, src, REG_ITMP2);
1983 d = reg_of_var(iptr->dst, REG_ITMP3);
1984 if (iptr->op1 == 0) {
1985 gen_nullptr_check(s1);
1988 M_ASLL_IMM(s2, 2, REG_ITMP2);
1989 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1990 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1991 store_reg_to_var_int(iptr->dst, d);
1994 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1996 var_to_reg_int(s1, src->prev, REG_ITMP1);
1997 var_to_reg_int(s2, src, REG_ITMP2);
1998 d = reg_of_var(iptr->dst, REG_ITMP3);
1999 if (iptr->op1 == 0) {
2000 gen_nullptr_check(s1);
2003 M_ASLL_IMM(s2, 3, REG_ITMP2);
2004 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2005 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
2006 store_reg_to_var_int(iptr->dst, d);
2009 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2011 var_to_reg_int(s1, src->prev, REG_ITMP1);
2012 var_to_reg_int(s2, src, REG_ITMP2);
2013 d = reg_of_var(iptr->dst, REG_FTMP3);
2014 if (iptr->op1 == 0) {
2015 gen_nullptr_check(s1);
2018 M_ASLL_IMM(s2, 2, REG_ITMP2);
2019 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2020 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2021 store_reg_to_var_flt(iptr->dst, d);
2024 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2026 var_to_reg_int(s1, src->prev, REG_ITMP1);
2027 var_to_reg_int(s2, src, REG_ITMP2);
2028 d = reg_of_var(iptr->dst, REG_FTMP3);
2029 if (iptr->op1 == 0) {
2030 gen_nullptr_check(s1);
2033 M_ASLL_IMM(s2, 3, REG_ITMP2);
2034 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2035 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2036 store_reg_to_var_flt(iptr->dst, d);
2039 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2041 var_to_reg_int(s1, src->prev, REG_ITMP1);
2042 var_to_reg_int(s2, src, REG_ITMP2);
2043 d = reg_of_var(iptr->dst, REG_ITMP3);
2044 if (iptr->op1 == 0) {
2045 gen_nullptr_check(s1);
2048 M_AADD(s2, s1, REG_ITMP1);
2049 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2050 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2051 store_reg_to_var_int(iptr->dst, d);
2054 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2056 var_to_reg_int(s1, src->prev, REG_ITMP1);
2057 var_to_reg_int(s2, src, REG_ITMP2);
2058 d = reg_of_var(iptr->dst, REG_ITMP3);
2059 if (iptr->op1 == 0) {
2060 gen_nullptr_check(s1);
2063 M_AADD(s2, s1, REG_ITMP1);
2064 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2065 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2066 store_reg_to_var_int(iptr->dst, d);
2069 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2071 var_to_reg_int(s1, src->prev, REG_ITMP1);
2072 var_to_reg_int(s2, src, REG_ITMP2);
2073 d = reg_of_var(iptr->dst, REG_ITMP3);
2074 if (iptr->op1 == 0) {
2075 gen_nullptr_check(s1);
2078 M_AADD(s2, s1, REG_ITMP1);
2079 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2080 store_reg_to_var_int(iptr->dst, d);
2084 case ICMD_AASTORE: /* ..., 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_int(s3, src, REG_ITMP3);
2093 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
2094 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2095 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2098 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2100 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2101 var_to_reg_int(s2, src->prev, REG_ITMP2);
2102 if (iptr->op1 == 0) {
2103 gen_nullptr_check(s1);
2106 var_to_reg_int(s3, src, REG_ITMP3);
2107 M_ASLL_IMM(s2, 2, REG_ITMP2);
2108 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2109 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
2112 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2114 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2115 var_to_reg_int(s2, src->prev, REG_ITMP2);
2116 if (iptr->op1 == 0) {
2117 gen_nullptr_check(s1);
2120 var_to_reg_int(s3, src, REG_ITMP3);
2121 M_ASLL_IMM(s2, 3, REG_ITMP2);
2122 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2123 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
2126 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2128 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2129 var_to_reg_int(s2, src->prev, REG_ITMP2);
2130 if (iptr->op1 == 0) {
2131 gen_nullptr_check(s1);
2134 var_to_reg_flt(s3, src, REG_FTMP3);
2135 M_ASLL_IMM(s2, 2, REG_ITMP2);
2136 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2137 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2140 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2142 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2143 var_to_reg_int(s2, src->prev, REG_ITMP2);
2144 if (iptr->op1 == 0) {
2145 gen_nullptr_check(s1);
2148 var_to_reg_flt(s3, src, REG_FTMP3);
2149 M_ASLL_IMM(s2, 3, REG_ITMP2);
2150 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2151 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2154 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2155 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2157 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2158 var_to_reg_int(s2, src->prev, REG_ITMP2);
2159 if (iptr->op1 == 0) {
2160 gen_nullptr_check(s1);
2163 var_to_reg_int(s3, src, REG_ITMP3);
2164 M_AADD(s2, s1, REG_ITMP1);
2165 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2166 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
2169 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2171 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2172 var_to_reg_int(s2, src->prev, REG_ITMP2);
2173 if (iptr->op1 == 0) {
2174 gen_nullptr_check(s1);
2177 var_to_reg_int(s3, src, REG_ITMP3);
2178 M_AADD(s2, s1, REG_ITMP1);
2179 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2183 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2184 /* op1 = type, val.a = field address */
2186 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2187 M_ALD(REG_ITMP1, REG_PV, a);
2188 switch (iptr->op1) {
2190 var_to_reg_int(s2, src, REG_ITMP2);
2191 M_IST(s2, REG_ITMP1, 0);
2194 var_to_reg_int(s2, src, REG_ITMP2);
2195 M_LST(s2, REG_ITMP1, 0);
2198 var_to_reg_int(s2, src, REG_ITMP2);
2199 M_AST(s2, REG_ITMP1, 0);
2202 var_to_reg_flt(s2, src, REG_FTMP2);
2203 M_FST(s2, REG_ITMP1, 0);
2206 var_to_reg_flt(s2, src, REG_FTMP2);
2207 M_DST(s2, REG_ITMP1, 0);
2209 default: panic ("internal error");
2213 case ICMD_GETSTATIC: /* ... ==> ..., value */
2214 /* op1 = type, val.a = field address */
2216 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2217 M_ALD(REG_ITMP1, REG_PV, a);
2218 switch (iptr->op1) {
2220 d = reg_of_var(iptr->dst, REG_ITMP3);
2221 M_ILD(d, REG_ITMP1, 0);
2222 store_reg_to_var_int(iptr->dst, d);
2225 d = reg_of_var(iptr->dst, REG_ITMP3);
2226 M_LLD(d, REG_ITMP1, 0);
2227 store_reg_to_var_int(iptr->dst, d);
2230 d = reg_of_var(iptr->dst, REG_ITMP3);
2231 M_ALD(d, REG_ITMP1, 0);
2232 store_reg_to_var_int(iptr->dst, d);
2235 d = reg_of_var(iptr->dst, REG_FTMP1);
2236 M_FLD(d, REG_ITMP1, 0);
2237 store_reg_to_var_flt(iptr->dst, d);
2240 d = reg_of_var(iptr->dst, REG_FTMP1);
2241 M_DLD(d, REG_ITMP1, 0);
2242 store_reg_to_var_flt(iptr->dst, d);
2244 default: panic ("internal error");
2249 case ICMD_PUTFIELD: /* ..., value ==> ... */
2250 /* op1 = type, val.i = field offset */
2252 a = ((fieldinfo *)(iptr->val.a))->offset;
2253 switch (iptr->op1) {
2255 var_to_reg_int(s1, src->prev, REG_ITMP1);
2256 var_to_reg_int(s2, src, REG_ITMP2);
2257 gen_nullptr_check(s1);
2261 var_to_reg_int(s1, src->prev, REG_ITMP1);
2262 var_to_reg_int(s2, src, REG_ITMP2);
2263 gen_nullptr_check(s1);
2267 var_to_reg_int(s1, src->prev, REG_ITMP1);
2268 var_to_reg_int(s2, src, REG_ITMP2);
2269 gen_nullptr_check(s1);
2273 var_to_reg_int(s1, src->prev, REG_ITMP1);
2274 var_to_reg_flt(s2, src, REG_FTMP2);
2275 gen_nullptr_check(s1);
2279 var_to_reg_int(s1, src->prev, REG_ITMP1);
2280 var_to_reg_flt(s2, src, REG_FTMP2);
2281 gen_nullptr_check(s1);
2284 default: panic ("internal error");
2288 case ICMD_GETFIELD: /* ... ==> ..., value */
2289 /* op1 = type, val.i = field offset */
2291 a = ((fieldinfo *)(iptr->val.a))->offset;
2292 switch (iptr->op1) {
2294 var_to_reg_int(s1, src, REG_ITMP1);
2295 d = reg_of_var(iptr->dst, REG_ITMP3);
2296 gen_nullptr_check(s1);
2298 store_reg_to_var_int(iptr->dst, d);
2301 var_to_reg_int(s1, src, REG_ITMP1);
2302 d = reg_of_var(iptr->dst, REG_ITMP3);
2303 gen_nullptr_check(s1);
2305 store_reg_to_var_int(iptr->dst, d);
2308 var_to_reg_int(s1, src, REG_ITMP1);
2309 d = reg_of_var(iptr->dst, REG_ITMP3);
2310 gen_nullptr_check(s1);
2312 store_reg_to_var_int(iptr->dst, d);
2315 var_to_reg_int(s1, src, REG_ITMP1);
2316 d = reg_of_var(iptr->dst, REG_FTMP1);
2317 gen_nullptr_check(s1);
2319 store_reg_to_var_flt(iptr->dst, d);
2322 var_to_reg_int(s1, src, REG_ITMP1);
2323 d = reg_of_var(iptr->dst, REG_FTMP1);
2324 gen_nullptr_check(s1);
2326 store_reg_to_var_flt(iptr->dst, d);
2328 default: panic ("internal error");
2333 /* branch operations **************************************************/
2335 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2337 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2339 var_to_reg_int(s1, src, REG_ITMP1);
2340 M_INTMOVE(s1, REG_ITMP1_XPTR);
2341 a = dseg_addaddress(asm_handle_exception);
2342 M_ALD(REG_ITMP2, REG_PV, a);
2343 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2345 M_NOP; /* nop ensures that XPC is less than the end */
2346 /* of basic block */
2350 case ICMD_GOTO: /* ... ==> ... */
2351 /* op1 = target JavaVM pc */
2353 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2358 case ICMD_JSR: /* ... ==> ... */
2359 /* op1 = target JavaVM pc */
2361 dseg_addtarget(BlockPtrOfPC(iptr->op1));
2362 M_ALD(REG_ITMP1, REG_PV, -dseglen);
2363 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2367 case ICMD_RET: /* ... ==> ... */
2368 /* op1 = local variable */
2369 var = &(locals[iptr->op1][TYPE_ADR]);
2370 if (var->flags & INMEMORY) {
2371 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2380 case ICMD_IFNULL: /* ..., value ==> ... */
2381 /* op1 = target JavaVM pc */
2383 var_to_reg_int(s1, src, REG_ITMP1);
2385 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2389 case ICMD_IFNONNULL: /* ..., value ==> ... */
2390 /* op1 = target JavaVM pc */
2392 var_to_reg_int(s1, src, REG_ITMP1);
2394 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2398 case ICMD_IFEQ: /* ..., value ==> ... */
2399 /* op1 = target JavaVM pc, val.i = constant */
2401 var_to_reg_int(s1, src, REG_ITMP1);
2402 if (iptr->val.i == 0) {
2406 ICONST(REG_ITMP2, iptr->val.i);
2407 M_BEQ(s1, REG_ITMP2, 0);
2409 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2413 case ICMD_IFLT: /* ..., value ==> ... */
2414 /* op1 = target JavaVM pc, val.i = constant */
2416 var_to_reg_int(s1, src, REG_ITMP1);
2417 if (iptr->val.i == 0) {
2421 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2422 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2425 ICONST(REG_ITMP2, iptr->val.i);
2426 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2428 M_BNEZ(REG_ITMP1, 0);
2430 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2434 case ICMD_IFLE: /* ..., value ==> ... */
2435 /* op1 = target JavaVM pc, val.i = constant */
2437 var_to_reg_int(s1, src, REG_ITMP1);
2438 if (iptr->val.i == 0) {
2442 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2443 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2444 M_BNEZ(REG_ITMP1, 0);
2447 ICONST(REG_ITMP2, iptr->val.i);
2448 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2449 M_BEQZ(REG_ITMP1, 0);
2452 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2456 case ICMD_IFNE: /* ..., value ==> ... */
2457 /* op1 = target JavaVM pc, val.i = constant */
2459 var_to_reg_int(s1, src, REG_ITMP1);
2460 if (iptr->val.i == 0) {
2464 ICONST(REG_ITMP2, iptr->val.i);
2465 M_BNE(s1, REG_ITMP2, 0);
2467 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2471 case ICMD_IFGT: /* ..., value ==> ... */
2472 /* op1 = target JavaVM pc, val.i = constant */
2474 var_to_reg_int(s1, src, REG_ITMP1);
2475 if (iptr->val.i == 0) {
2479 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2480 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2481 M_BEQZ(REG_ITMP1, 0);
2484 ICONST(REG_ITMP2, iptr->val.i);
2485 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2486 M_BNEZ(REG_ITMP1, 0);
2489 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2493 case ICMD_IFGE: /* ..., value ==> ... */
2494 /* op1 = target JavaVM pc, val.i = constant */
2496 var_to_reg_int(s1, src, REG_ITMP1);
2497 if (iptr->val.i == 0) {
2501 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2502 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2505 ICONST(REG_ITMP2, iptr->val.i);
2506 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2508 M_BEQZ(REG_ITMP1, 0);
2510 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2514 case ICMD_IF_LEQ: /* ..., value ==> ... */
2515 /* op1 = target JavaVM pc, val.l = constant */
2517 var_to_reg_int(s1, src, REG_ITMP1);
2518 if (iptr->val.l == 0) {
2522 LCONST(REG_ITMP2, iptr->val.l);
2523 M_BEQ(s1, REG_ITMP2, 0);
2525 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2529 case ICMD_IF_LLT: /* ..., value ==> ... */
2530 /* op1 = target JavaVM pc, val.l = constant */
2532 var_to_reg_int(s1, src, REG_ITMP1);
2533 if (iptr->val.l == 0) {
2537 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2538 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2541 LCONST(REG_ITMP2, iptr->val.l);
2542 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2544 M_BNEZ(REG_ITMP1, 0);
2546 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2550 case ICMD_IF_LLE: /* ..., value ==> ... */
2551 /* op1 = target JavaVM pc, val.l = constant */
2553 var_to_reg_int(s1, src, REG_ITMP1);
2554 if (iptr->val.l == 0) {
2558 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2559 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2560 M_BNEZ(REG_ITMP1, 0);
2563 LCONST(REG_ITMP2, iptr->val.l);
2564 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2565 M_BEQZ(REG_ITMP1, 0);
2568 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2572 case ICMD_IF_LNE: /* ..., value ==> ... */
2573 /* op1 = target JavaVM pc, val.l = constant */
2575 var_to_reg_int(s1, src, REG_ITMP1);
2576 if (iptr->val.l == 0) {
2580 LCONST(REG_ITMP2, iptr->val.l);
2581 M_BNE(s1, REG_ITMP2, 0);
2583 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2587 case ICMD_IF_LGT: /* ..., value ==> ... */
2588 /* op1 = target JavaVM pc, val.l = constant */
2590 var_to_reg_int(s1, src, REG_ITMP1);
2591 if (iptr->val.l == 0) {
2595 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2596 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2597 M_BEQZ(REG_ITMP1, 0);
2600 LCONST(REG_ITMP2, iptr->val.l);
2601 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2602 M_BNEZ(REG_ITMP1, 0);
2605 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2609 case ICMD_IF_LGE: /* ..., value ==> ... */
2610 /* op1 = target JavaVM pc, val.l = constant */
2612 var_to_reg_int(s1, src, REG_ITMP1);
2613 if (iptr->val.l == 0) {
2617 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2618 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2621 LCONST(REG_ITMP2, iptr->val.l);
2622 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2624 M_BEQZ(REG_ITMP1, 0);
2626 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2630 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2631 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2632 case ICMD_IF_ACMPEQ:
2634 var_to_reg_int(s1, src->prev, REG_ITMP1);
2635 var_to_reg_int(s2, src, REG_ITMP2);
2637 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2641 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2642 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2643 case ICMD_IF_ACMPNE:
2645 var_to_reg_int(s1, src->prev, REG_ITMP1);
2646 var_to_reg_int(s2, src, REG_ITMP2);
2648 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2652 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2653 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2655 var_to_reg_int(s1, src->prev, REG_ITMP1);
2656 var_to_reg_int(s2, src, REG_ITMP2);
2657 M_CMPLT(s1, s2, REG_ITMP1);
2658 M_BNEZ(REG_ITMP1, 0);
2659 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2663 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2664 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2666 var_to_reg_int(s1, src->prev, REG_ITMP1);
2667 var_to_reg_int(s2, src, REG_ITMP2);
2668 M_CMPGT(s1, s2, REG_ITMP1);
2669 M_BNEZ(REG_ITMP1, 0);
2670 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2674 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2675 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2677 var_to_reg_int(s1, src->prev, REG_ITMP1);
2678 var_to_reg_int(s2, src, REG_ITMP2);
2679 M_CMPGT(s1, s2, REG_ITMP1);
2680 M_BEQZ(REG_ITMP1, 0);
2681 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2685 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2686 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2688 var_to_reg_int(s1, src->prev, REG_ITMP1);
2689 var_to_reg_int(s2, src, REG_ITMP2);
2690 M_CMPLT(s1, s2, REG_ITMP1);
2691 M_BEQZ(REG_ITMP1, 0);
2692 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2696 #ifdef CONDITIONAL_LOADCONST
2697 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2699 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2702 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2703 /* val.i = constant */
2705 var_to_reg_int(s1, src, REG_ITMP1);
2706 d = reg_of_var(iptr->dst, REG_ITMP3);
2708 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2709 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2710 M_CMPEQ(s1, REG_ZERO, d);
2711 store_reg_to_var_int(iptr->dst, d);
2714 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2715 M_CMPEQ(s1, REG_ZERO, d);
2717 store_reg_to_var_int(iptr->dst, d);
2721 M_MOV(s1, REG_ITMP1);
2724 ICONST(d, iptr[1].val.i);
2726 if ((s3 >= 0) && (s3 <= 255)) {
2727 M_CMOVEQ_IMM(s1, s3, d);
2730 ICONST(REG_ITMP2, s3);
2731 M_CMOVEQ(s1, REG_ITMP2, d);
2733 store_reg_to_var_int(iptr->dst, d);
2736 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2737 /* val.i = constant */
2739 var_to_reg_int(s1, src, REG_ITMP1);
2740 d = reg_of_var(iptr->dst, REG_ITMP3);
2742 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2743 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2744 M_CMPEQ(s1, REG_ZERO, d);
2745 store_reg_to_var_int(iptr->dst, d);
2748 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2749 M_CMPEQ(s1, REG_ZERO, d);
2751 store_reg_to_var_int(iptr->dst, d);
2755 M_MOV(s1, REG_ITMP1);
2758 ICONST(d, iptr[1].val.i);
2760 if ((s3 >= 0) && (s3 <= 255)) {
2761 M_CMOVNE_IMM(s1, s3, d);
2764 ICONST(REG_ITMP2, s3);
2765 M_CMOVNE(s1, REG_ITMP2, d);
2767 store_reg_to_var_int(iptr->dst, d);
2770 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2771 /* val.i = constant */
2773 var_to_reg_int(s1, src, REG_ITMP1);
2774 d = reg_of_var(iptr->dst, REG_ITMP3);
2776 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2777 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2778 M_CMPLT(s1, REG_ZERO, d);
2779 store_reg_to_var_int(iptr->dst, d);
2782 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2783 M_CMPLE(REG_ZERO, s1, d);
2784 store_reg_to_var_int(iptr->dst, d);
2788 M_MOV(s1, REG_ITMP1);
2791 ICONST(d, iptr[1].val.i);
2793 if ((s3 >= 0) && (s3 <= 255)) {
2794 M_CMOVLT_IMM(s1, s3, d);
2797 ICONST(REG_ITMP2, s3);
2798 M_CMOVLT(s1, REG_ITMP2, d);
2800 store_reg_to_var_int(iptr->dst, d);
2803 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2804 /* val.i = constant */
2806 var_to_reg_int(s1, src, REG_ITMP1);
2807 d = reg_of_var(iptr->dst, REG_ITMP3);
2809 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2810 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2811 M_CMPLE(REG_ZERO, s1, d);
2812 store_reg_to_var_int(iptr->dst, d);
2815 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2816 M_CMPLT(s1, REG_ZERO, d);
2817 store_reg_to_var_int(iptr->dst, d);
2821 M_MOV(s1, REG_ITMP1);
2824 ICONST(d, iptr[1].val.i);
2826 if ((s3 >= 0) && (s3 <= 255)) {
2827 M_CMOVGE_IMM(s1, s3, d);
2830 ICONST(REG_ITMP2, s3);
2831 M_CMOVGE(s1, REG_ITMP2, d);
2833 store_reg_to_var_int(iptr->dst, d);
2836 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2837 /* val.i = constant */
2839 var_to_reg_int(s1, src, REG_ITMP1);
2840 d = reg_of_var(iptr->dst, REG_ITMP3);
2842 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2843 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2844 M_CMPLT(REG_ZERO, s1, d);
2845 store_reg_to_var_int(iptr->dst, d);
2848 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2849 M_CMPLE(s1, REG_ZERO, d);
2850 store_reg_to_var_int(iptr->dst, d);
2854 M_MOV(s1, REG_ITMP1);
2857 ICONST(d, iptr[1].val.i);
2859 if ((s3 >= 0) && (s3 <= 255)) {
2860 M_CMOVGT_IMM(s1, s3, d);
2863 ICONST(REG_ITMP2, s3);
2864 M_CMOVGT(s1, REG_ITMP2, d);
2866 store_reg_to_var_int(iptr->dst, d);
2869 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2870 /* val.i = constant */
2872 var_to_reg_int(s1, src, REG_ITMP1);
2873 d = reg_of_var(iptr->dst, REG_ITMP3);
2875 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2876 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2877 M_CMPLE(s1, REG_ZERO, d);
2878 store_reg_to_var_int(iptr->dst, d);
2881 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2882 M_CMPLT(REG_ZERO, s1, d);
2883 store_reg_to_var_int(iptr->dst, d);
2887 M_MOV(s1, REG_ITMP1);
2890 ICONST(d, iptr[1].val.i);
2892 if ((s3 >= 0) && (s3 <= 255)) {
2893 M_CMOVLE_IMM(s1, s3, d);
2896 ICONST(REG_ITMP2, s3);
2897 M_CMOVLE(s1, REG_ITMP2, d);
2899 store_reg_to_var_int(iptr->dst, d);
2904 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2909 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2911 a = dseg_addaddress ((void*) (builtin_monitorexit));
2912 M_ALD(REG_ITMP3, REG_PV, a);
2913 M_JSR(REG_RA, REG_ITMP3);
2914 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse); /* delay slot */
2915 disp = -(int)((u1*) mcodeptr - mcodebase);
2916 M_LDA(REG_PV, REG_RA, disp);
2919 var_to_reg_int(s1, src, REG_RESULT);
2920 M_INTMOVE(s1, REG_RESULT);
2921 goto nowperformreturn;
2923 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2927 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2929 a = dseg_addaddress ((void*) (builtin_monitorexit));
2930 M_ALD(REG_ITMP3, REG_PV, a);
2931 M_JSR(REG_RA, REG_ITMP3);
2932 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse); /* delay slot */
2933 disp = -(int)((u1*) mcodeptr - mcodebase);
2934 M_LDA(REG_PV, REG_RA, disp);
2937 var_to_reg_flt(s1, src, REG_FRESULT);
2939 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2940 M_TFLTMOVE(t, s1, REG_FRESULT);
2942 goto nowperformreturn;
2944 case ICMD_RETURN: /* ... ==> ... */
2947 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2949 a = dseg_addaddress ((void*) (builtin_monitorexit));
2950 M_ALD(REG_ITMP3, REG_PV, a);
2951 M_JSR(REG_RA, REG_ITMP3);
2952 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse); /* delay slot */
2953 disp = -(int)((u1*) mcodeptr - mcodebase);
2954 M_LDA(REG_PV, REG_RA, disp);
2962 p = parentargs_base;
2964 /* restore return address */
2967 {p--; M_LLD (REG_RA, REG_SP, 8 * p);}
2969 /* restore saved registers */
2971 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
2972 {p--; M_LLD(savintregs[r], REG_SP, 8 * p);}
2973 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
2974 {p--; M_DLD(savfltregs[r], REG_SP, 8 * p);}
2976 /* call trace function */
2979 M_LDA (REG_SP, REG_SP, -24);
2980 M_LST(REG_RA, REG_SP, 0);
2981 M_LST(REG_RESULT, REG_SP, 8);
2982 M_DST(REG_FRESULT, REG_SP,16);
2983 a = dseg_addaddress (method);
2984 M_ALD(argintregs[0], REG_PV, a);
2985 M_MOV(REG_RESULT, argintregs[1]);
2986 M_FLTMOVE(REG_FRESULT, argfltregs[2]);
2987 M_FMOV(REG_FRESULT, argfltregs[3]);
2988 a = dseg_addaddress ((void*) (builtin_displaymethodstop));
2989 M_ALD(REG_ITMP3, REG_PV, a);
2990 M_JSR (REG_RA, REG_ITMP3);
2992 M_DLD(REG_FRESULT, REG_SP,16);
2993 M_LLD(REG_RESULT, REG_SP, 8);
2994 M_LLD(REG_RA, REG_SP, 0);
2995 M_LDA (REG_SP, REG_SP, 24);
3000 /* deallocate stack */
3002 if (parentargs_base)
3003 {M_LDA(REG_SP, REG_SP, parentargs_base*8);}
3011 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3016 tptr = (void **) iptr->target;
3018 s4ptr = iptr->val.a;
3019 l = s4ptr[1]; /* low */
3020 i = s4ptr[2]; /* high */
3022 var_to_reg_int(s1, src, REG_ITMP1);
3024 {M_INTMOVE(s1, REG_ITMP1);}
3025 else if (l <= 32768) {
3026 M_IADD_IMM(s1, -l, REG_ITMP1);
3029 ICONST(REG_ITMP2, l);
3030 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3036 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
3037 M_BEQZ(REG_ITMP2, 0);
3038 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3039 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
3041 /* build jump table top down and use address of lowest entry */
3043 /* s4ptr += 3 + i; */
3047 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3048 dseg_addtarget((basicblock *) tptr[0]);
3053 /* length of dataseg after last dseg_addtarget is used by load */
3055 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
3056 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
3063 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3065 s4 i, l, val, *s4ptr;
3068 tptr = (void **) iptr->target;
3070 s4ptr = iptr->val.a;
3071 l = s4ptr[0]; /* default */
3072 i = s4ptr[1]; /* count */
3074 MCODECHECK((i<<2)+8);
3075 var_to_reg_int(s1, src, REG_ITMP1);
3081 ICONST(REG_ITMP2, val);
3082 M_BEQ(s1, REG_ITMP2, 0);
3083 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3088 tptr = (void **) iptr->target;
3089 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3096 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3097 /* op1 = return type, val.a = function pointer*/
3101 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3102 /* op1 = return type, val.a = function pointer*/
3106 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3107 /* op1 = return type, val.a = function pointer*/
3111 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3112 /* op1 = arg count, val.a = method pointer */
3114 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3115 /* op1 = arg count, val.a = method pointer */
3117 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3118 /* op1 = arg count, val.a = method pointer */
3120 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3121 /* op1 = arg count, val.a = method pointer */
3129 MCODECHECK((s3 << 1) + 64);
3131 /* copy arguments to registers or stack location */
3133 for (; --s3 >= 0; src = src->prev) {
3134 if (src->varkind == ARGVAR)
3136 if (IS_INT_LNG_TYPE(src->type)) {
3137 if (s3 < INT_ARG_CNT) {
3138 s1 = argintregs[s3];
3139 var_to_reg_int(d, src, s1);
3143 var_to_reg_int(d, src, REG_ITMP1);
3144 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3148 if (s3 < FLT_ARG_CNT) {
3149 s1 = argfltregs[s3];
3150 var_to_reg_flt(d, src, s1);
3151 M_TFLTMOVE(src->type,d, s1);
3154 var_to_reg_flt(d, src, REG_FTMP1);
3155 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3160 switch (iptr->opc) {
3164 a = dseg_addaddress ((void*) (m));
3165 M_ALD(REG_ITMP3, REG_PV, a); /* built-in-function pointer */
3166 M_JSR (REG_RA, REG_ITMP3);
3168 d = iptr->op1; /* return type */
3169 goto afteractualcall;
3171 case ICMD_INVOKESTATIC:
3172 case ICMD_INVOKESPECIAL:
3173 a = dseg_addaddress (m->stubroutine);
3175 M_ALD(REG_PV, REG_PV, a ); /* method pointer in pv */
3178 goto makeactualcall;
3180 case ICMD_INVOKEVIRTUAL:
3182 gen_nullptr_check(argintregs[0]);
3183 M_ALD(REG_METHODPTR, argintregs[0],
3184 OFFSET(java_objectheader, vftbl));
3185 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
3186 sizeof(methodptr) * m->vftblindex);
3189 goto makeactualcall;
3191 case ICMD_INVOKEINTERFACE:
3194 gen_nullptr_check(argintregs[0]);
3195 M_ALD(REG_METHODPTR, argintregs[0],
3196 OFFSET(java_objectheader, vftbl));
3197 M_ALD(REG_METHODPTR, REG_METHODPTR,
3198 OFFSET(vftbl, interfacetable[0]) -
3199 sizeof(methodptr*) * ci->index);
3200 M_ALD(REG_PV, REG_METHODPTR,
3201 sizeof(methodptr) * (m - ci->methods));
3204 goto makeactualcall;
3208 sprintf (logtext, "Unkown ICMD-Command: %d", iptr->opc);
3214 M_JSR (REG_RA, REG_PV);
3221 s1 = (int)((u1*) mcodeptr - mcodebase);
3222 if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
3225 while (ml<-32768) { ml+=65536; mh--; }
3227 M_IADD_IMM(REG_PV, ml, REG_PV);
3228 M_LADD(REG_PV, REG_RA, REG_PV);
3231 /* d contains return type */
3233 if (d != TYPE_VOID) {
3234 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3235 s1 = reg_of_var(iptr->dst, REG_RESULT);
3236 M_INTMOVE(REG_RESULT, s1);
3237 store_reg_to_var_int(iptr->dst, s1);
3240 s1 = reg_of_var(iptr->dst, REG_FRESULT);
3241 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3242 store_reg_to_var_flt(iptr->dst, s1);
3249 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3251 /* op1: 0 == array, 1 == class */
3252 /* val.a: (classinfo*) superclass */
3254 /* superclass is an interface:
3256 * return (sub != NULL) &&
3257 * (sub->vftbl->interfacetablelength > super->index) &&
3258 * (sub->vftbl->interfacetable[-super->index] != NULL);
3260 * superclass is a class:
3262 * return ((sub != NULL) && (0
3263 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3264 * super->vftbl->diffvall));
3268 classinfo *super = (classinfo*) iptr->val.a;
3270 var_to_reg_int(s1, src, REG_ITMP1);
3271 d = reg_of_var(iptr->dst, REG_ITMP3);
3273 M_MOV(s1, REG_ITMP1);
3277 if (iptr->op1) { /* class/interface */
3278 if (super->flags & ACC_INTERFACE) { /* interface */
3281 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3282 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3283 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3284 M_BLEZ(REG_ITMP2, 3);
3286 M_ALD(REG_ITMP1, REG_ITMP1,
3287 OFFSET(vftbl, interfacetable[0]) -
3288 super->index * sizeof(methodptr*));
3289 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3293 s2 = super->vftbl->diffval;
3296 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3297 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3298 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3299 M_CMPULT_IMM(REG_ITMP1, s2 + 1, d);
3304 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3305 a = dseg_addaddress ((void*) super->vftbl);
3306 M_ALD(REG_ITMP2, REG_PV, a);
3307 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3308 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3309 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3310 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3311 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3317 panic ("internal error: no inlined array instanceof");
3319 store_reg_to_var_int(iptr->dst, d);
3322 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3324 /* op1: 0 == array, 1 == class */
3325 /* val.a: (classinfo*) superclass */
3327 /* superclass is an interface:
3329 * OK if ((sub == NULL) ||
3330 * (sub->vftbl->interfacetablelength > super->index) &&
3331 * (sub->vftbl->interfacetable[-super->index] != NULL));
3333 * superclass is a class:
3335 * OK if ((sub == NULL) || (0
3336 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3337 * super->vftbl->diffvall));
3341 classinfo *super = (classinfo*) iptr->val.a;
3343 d = reg_of_var(iptr->dst, REG_ITMP3);
3344 var_to_reg_int(s1, src, d);
3345 if (iptr->op1) { /* class/interface */
3346 if (super->flags & ACC_INTERFACE) { /* interface */
3349 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3350 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3351 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3352 M_BLEZ(REG_ITMP2, 0);
3353 codegen_addxcastrefs(mcodeptr);
3355 M_ALD(REG_ITMP2, REG_ITMP1,
3356 OFFSET(vftbl, interfacetable[0]) -
3357 super->index * sizeof(methodptr*));
3358 M_BEQZ(REG_ITMP2, 0);
3359 codegen_addxcastrefs(mcodeptr);
3365 s2 = super->vftbl->diffval;
3366 M_BEQZ(s1, 6 + (s2 != 0));
3368 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3369 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3370 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3372 M_BNEZ(REG_ITMP1, 0);
3375 M_CMPULT_IMM(REG_ITMP1, s2 + 1, REG_ITMP2);
3376 M_BEQZ(REG_ITMP2, 0);
3380 M_BEQZ(s1, 10 + (d == REG_ITMP3));
3382 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3383 a = dseg_addaddress ((void*) super->vftbl);
3384 M_ALD(REG_ITMP2, REG_PV, a);
3385 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3386 if (d != REG_ITMP3) {
3387 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3388 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3389 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3391 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, baseval));
3392 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3393 M_ALD(REG_ITMP2, REG_PV, a);
3394 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3396 M_CMPULT(REG_ITMP2, REG_ITMP1, REG_ITMP2);
3397 M_BNEZ(REG_ITMP2, 0);
3399 codegen_addxcastrefs(mcodeptr);
3404 panic ("internal error: no inlined array checkcast");
3407 store_reg_to_var_int(iptr->dst, d);
3410 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3412 var_to_reg_int(s1, src, REG_ITMP1);
3414 codegen_addxcheckarefs(mcodeptr);
3418 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3419 /* op1 = dimension, val.a = array descriptor */
3421 /* check for negative sizes and copy sizes to stack if necessary */
3423 MCODECHECK((iptr->op1 << 1) + 64);
3425 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3426 var_to_reg_int(s2, src, REG_ITMP1);
3428 codegen_addxcheckarefs(mcodeptr);
3431 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3433 if (src->varkind != ARGVAR) {
3434 M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
3438 /* a0 = dimension count */
3440 ICONST(argintregs[0], iptr->op1);
3442 /* a1 = arraydescriptor */
3444 a = dseg_addaddress(iptr->val.a);
3445 M_ALD(argintregs[1], REG_PV, a);
3447 /* a2 = pointer to dimensions = stack pointer */
3449 M_INTMOVE(REG_SP, argintregs[2]);
3451 a = dseg_addaddress((void*) (builtin_nmultianewarray));
3452 M_ALD(REG_ITMP3, REG_PV, a);
3453 M_JSR(REG_RA, REG_ITMP3);
3455 s1 = (int)((u1*) mcodeptr - mcodebase);
3457 M_LDA (REG_PV, REG_RA, -s1);
3461 s1 = reg_of_var(iptr->dst, REG_RESULT);
3462 M_INTMOVE(REG_RESULT, s1);
3463 store_reg_to_var_int(iptr->dst, s1);
3467 default: sprintf (logtext, "Unknown pseudo command: %d", iptr->opc);
3474 } /* for instruction */
3476 /* copy values to interface registers */
3478 src = bptr->outstack;
3479 len = bptr->outdepth;
3483 if ((src->varkind != STACKVAR)) {
3485 if (IS_FLT_DBL_TYPE(s2)) {
3486 var_to_reg_flt(s1, src, REG_FTMP1);
3487 if (!(interfaces[len][s2].flags & INMEMORY)) {
3488 M_TFLTMOVE(s2,s1,interfaces[len][s2].regoff);
3491 M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3495 var_to_reg_int(s1, src, REG_ITMP1);
3496 if (!(interfaces[len][s2].flags & INMEMORY)) {
3497 M_INTMOVE(s1,interfaces[len][s2].regoff);
3500 M_LST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3506 } /* if (bptr -> flags >= BBREACHED) */
3507 } /* for basic block */
3509 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3512 /* generate bound check stubs */
3514 s4 *xcodeptr = NULL;
3516 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3517 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3518 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3519 xboundrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3524 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3525 xboundrefs->branchpos, (u1*) mcodeptr - mcodebase);
3529 M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos - 4);
3531 if (xcodeptr != NULL) {
3532 int disp = xcodeptr-mcodeptr;
3537 xcodeptr = mcodeptr;
3539 a = dseg_addaddress(asm_handle_exception);
3540 M_ALD(REG_ITMP3, REG_PV, a);
3543 a = dseg_addaddress(proto_java_lang_ArrayIndexOutOfBoundsException);
3544 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3548 /* generate negative array size check stubs */
3552 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3553 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3554 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3555 xcheckarefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3559 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3560 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
3564 M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos - 4);
3566 if (xcodeptr != NULL) {
3567 int disp = xcodeptr-mcodeptr;
3572 xcodeptr = mcodeptr;
3574 a = dseg_addaddress(asm_handle_exception);
3575 M_ALD(REG_ITMP3, REG_PV, a);
3578 a = dseg_addaddress(proto_java_lang_NegativeArraySizeException);
3579 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3583 /* generate cast check stubs */
3587 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3588 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3589 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3590 xcastrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3594 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3595 xcastrefs->branchpos, (u1*) mcodeptr - mcodebase);
3599 M_LDA(REG_ITMP2_XPC, REG_PV, xcastrefs->branchpos - 4);
3601 if (xcodeptr != NULL) {
3602 int disp = xcodeptr-mcodeptr;
3607 xcodeptr = mcodeptr;
3609 a = dseg_addaddress(asm_handle_exception);
3610 M_ALD(REG_ITMP3, REG_PV, a);
3613 a = dseg_addaddress(proto_java_lang_ClassCastException);
3614 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3619 #ifdef SOFTNULLPTRCHECK
3621 /* generate null pointer check stubs */
3625 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3626 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3627 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3628 xnullrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3632 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3633 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
3637 M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
3639 if (xcodeptr != NULL) {
3640 int disp = xcodeptr-mcodeptr;
3645 xcodeptr = mcodeptr;
3647 a = dseg_addaddress(asm_handle_exception);
3648 M_ALD(REG_ITMP3, REG_PV, a);
3651 a = dseg_addaddress(proto_java_lang_NullPointerException);
3652 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3659 codegen_finish((int)((u1*) mcodeptr - mcodebase));
3661 docacheflush((void*) method->entrypoint,
3662 ((u1*) mcodeptr - mcodebase));
3666 /* redefinition of code generation macros (compiling into array) **************/
3669 These macros are newly defined to allow code generation into an array.
3670 This is necessary, because the original M_.. macros generate code by
3671 calling 'codegen_adds4' that uses an additional data structure to
3674 For a faster (but less flexible) version to generate code, these
3675 macros directly use the (s4* p) - pointer to put the code directly
3676 in a locally defined array.
3677 This makes sense only for the stub-generation-routines below.
3681 #define M_ITYPE(op, rs, rt, imm)\
3682 *(p++) = (((op)<<26)|((rs)<<21)|((rt)<<16)|((imm)&0xffff))
3685 #define M_JTYPE(op, imm)\
3686 *(p++) = (((op)<<26)|((off)&0x3ffffff))
3689 #define M_RTYPE(op, rs, rt, rd, sa, fu)\
3690 *(p++) = (((op)<<26)|((rs)<<21)|((rt)<<16)|((rd)<<11)|((sa)<<6)|(fu))
3693 /* function createcompilerstub *************************************************
3695 creates a stub routine which calls the compiler
3697 *******************************************************************************/
3699 #define COMPSTUBSIZE 4
3701 u1 *createcompilerstub (methodinfo *m)
3703 u8 *s = CNEW(u8, COMPSTUBSIZE); /* memory to hold the stub */
3704 s4 *p = (s4*) s; /* code generation pointer */
3706 /* code for the stub */
3707 M_ALD(REG_PV, REG_PV, 24); /* load pointer to the compiler */
3709 M_JSR(REG_ITMP1, REG_PV); /* jump to the compiler, return address
3710 in itmp1 is used as method pointer */
3713 s[2] = (u8) m; /* literals to be adressed */
3714 s[3] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3716 (void) docacheflush((void*) s, (char*) p - (char*) s);
3719 count_cstub_len += COMPSTUBSIZE * 8;
3726 /* function removecompilerstub *************************************************
3728 deletes a compilerstub from memory (simply by freeing it)
3730 *******************************************************************************/
3732 void removecompilerstub (u1 *stub)
3734 CFREE(stub, COMPSTUBSIZE * 8);
3737 /* function: createnativestub **************************************************
3739 creates a stub routine which calls a native method
3741 *******************************************************************************/
3743 #define NATIVESTUBSIZE 20
3745 u1 *createnativestub (functionptr f, methodinfo *m)
3747 u8 *s = CNEW(u8, NATIVESTUBSIZE); /* memory to hold the stub */
3748 s4 *p = (s4*) s; /* code generation pointer */
3752 M_MOV (argintregs[4], argintregs[5]);
3753 M_DMFC1 (REG_ITMP1, argfltregs[4]);
3755 M_MOV (argintregs[3], argintregs[4]);
3756 M_DMTC1 (REG_ITMP1, argfltregs[5]);
3758 M_MOV (argintregs[2], argintregs[3]);
3759 M_DMFC1 (REG_ITMP1, argfltregs[3]);
3761 M_MOV (argintregs[1], argintregs[2]);
3762 M_DMTC1 (REG_ITMP1, argfltregs[4]);
3764 M_MOV (argintregs[0], argintregs[1]);
3765 M_DMFC1 (REG_ITMP1, argfltregs[2]);
3767 M_ALD (argintregs[0], REG_PV, 19*8); /* load adress of jni_environement */
3768 M_DMTC1 (REG_ITMP1, argfltregs[3]);
3770 M_DMFC1 (REG_ITMP1, argfltregs[1]);
3771 M_DMFC1 (REG_ITMP2, argfltregs[0]);
3773 M_DMTC1 (REG_ITMP1, argfltregs[2]);
3774 M_DMTC1 (REG_ITMP2, argfltregs[1]);
3776 M_ALD (REG_ITMP3, REG_PV, 16*8); /* load adress of native method */
3777 M_LDA (REG_SP, REG_SP, -8); /* build up stackframe */
3779 M_LST (REG_RA, REG_SP, 0); /* store return address */
3780 M_JSR (REG_RA, REG_ITMP3); /* call native method */
3782 M_NOP; /* delay slot */
3783 M_ALD (REG_ITMP3, REG_PV, 17*8); /* get address of exceptionptr */
3785 M_LLD (REG_RA, REG_SP, 0); /* load return address */
3786 M_ALD (REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
3788 M_BNEZ (REG_ITMP1, 2); /* if no exception then return */
3789 M_LDA (REG_SP, REG_SP, 8); /* remove stackframe, delay slot */
3791 M_RET (REG_RA); /* return to caller */
3792 M_NOP; /* delay slot */
3794 M_AST (REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
3795 M_ALD (REG_ITMP3, REG_PV,18*8); /* load asm exception handler address */
3797 M_JMP (REG_ITMP3); /* jump to asm exception handler */
3798 M_LDA (REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
3801 s[16] = (u8) f; /* address of native method */
3802 s[17] = (u8) (&exceptionptr); /* address of exceptionptr */
3803 s[18]= (u8) (asm_handle_nat_exception); /* addr of asm exception handler */
3804 s[19] = (u8) (&env); /* addr of jni_environement */
3806 (void) docacheflush((void*) s, (char*) p - (char*) s);
3809 count_nstub_len += NATIVESTUBSIZE * 8;
3815 /* function: removenativestub **************************************************
3817 removes a previously created native-stub from memory
3819 *******************************************************************************/
3821 void removenativestub (u1 *stub)
3823 CFREE(stub, NATIVESTUBSIZE * 8);
3827 /* function: createcalljava ****************************************************
3829 creates the asm_calljavamethod (MIPS assembler does not like data in the
3830 text segment). Documentation can be found in asmpart.c.
3832 *******************************************************************************/
3841 #define CALL_JAVA_MEM_SIZE 60
3842 #define CALL_JAVA_ENTRY 20
3843 #define CALL_JAVA_XHANDLER 55
3845 static s4 calljavamem[CALL_JAVA_MEM_SIZE];
3847 void createcalljava ()
3851 *((void**)(calljavamem + 0)) = (void*) asm_call_jit_compiler;
3852 *((void**)(calljavamem + 2)) = (void*) builtin_throw_exception;
3854 *((void**)(calljavamem + 4)) = NULL;
3855 *((void**)(calljavamem + 6)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3856 *((void**)(calljavamem + 8)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3857 *((void**)(calljavamem +10)) = (void*) (calljavamem + CALL_JAVA_ENTRY);
3859 *((void**)(calljavamem + 8)) = NULL;
3860 *((void**)(calljavamem + 9)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3861 *((void**)(calljavamem +10)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3862 *((void**)(calljavamem +11)) = (void*) (calljavamem + CALL_JAVA_ENTRY);
3865 calljavamem[12] = 1; /* extable size */
3866 calljavamem[13] = 0; /* fltsave */
3867 calljavamem[14] = 0; /* intsave */
3868 calljavamem[15] = 0; /* isleaf */
3869 calljavamem[16] = 0; /* IsSync */
3870 calljavamem[17] = 80; /* frame size */
3871 calljavamem[18] = 0; /* method pointer (NULL) */
3872 calljavamem[19] = 0; /* method pointer (NULL) */
3874 p = calljavamem + CALL_JAVA_ENTRY; /* code generation pointer */
3877 M_LDA (REG_SP, REG_SP, -10*8); /* allocate stackframe */
3878 M_LST (REG_RA, REG_SP, 0); /* save return address */
3880 M_BRS(1); /* compute current program counter */
3881 M_LST (REG_PV, REG_SP, 3*8); /* save procedure vector */
3883 M_LDA (REG_PV, REG_RA, -4*4); /* compute procedure vector */
3884 M_DST (REG_FSS0, REG_SP, 4*8); /* save non JavaABI saved flt regs */
3886 M_DST (REG_FSS1, REG_SP, 5*8);
3887 M_DST (REG_FSS2, REG_SP, 6*8);
3889 M_DST (REG_FSS3, REG_SP, 7*8);
3890 M_DST (REG_FSS4, REG_SP, 8*8);
3892 M_DST (REG_FSS5, REG_SP, 9*8);
3893 M_LST (REG_ARG_0, REG_SP, 2*8); /* save method pointer for compiler */
3895 M_LDA (REG_ITMP1, REG_SP, 2*8); /* pass pointer to methodptr via itmp1*/
3896 M_MOV (REG_ARG_1, REG_ARG_0); /* pass the remaining parameters */
3898 M_MOV (REG_ARG_2, REG_ARG_1);
3899 M_MOV (REG_ARG_3, REG_ARG_2);
3901 M_MOV (REG_ARG_4, REG_ARG_3);
3902 M_ALD (REG_METHODPTR, REG_PV, -80); /* address of asm_call_jit_compiler */
3904 M_AST (REG_METHODPTR, REG_SP, 8); /* store function address */
3905 M_MOV (REG_SP, REG_METHODPTR); /* set method pointer */
3907 M_ALD (REG_PV, REG_METHODPTR, 8); /* method call as in Java */
3908 M_JSR (REG_RA, REG_PV); /* call JIT compiler */
3910 M_NOP; /* delay slot */
3911 M_LDA (REG_PV, REG_RA, -23*4); /* recompute procedure vector */
3915 M_CLR (REG_RESULT); /* clear return value (exception ptr) */
3919 /* calljava_return: */
3920 M_LLD (REG_RA, REG_SP, 0); /* restore return address */
3922 M_LLD (REG_PV, REG_SP, 3*8); /* restore procedure vector */
3923 M_DLD (REG_FSS0, REG_SP, 4*8); /* restore non JavaABI saved flt regs */
3925 M_DLD (REG_FSS1, REG_SP, 5*8);
3926 M_DLD (REG_FSS2, REG_SP, 6*8);
3928 M_DLD (REG_FSS3, REG_SP, 7*8);
3929 M_DLD (REG_FSS4, REG_SP, 8*8);
3931 M_DLD (REG_FSS5, REG_SP, 9*8);
3932 M_RET(REG_RA); /* return */
3934 M_LDA (REG_SP, REG_SP, 10*8); /* deallocate stackframe (delay slot) */
3937 /* calljava_xhandler: */
3939 M_ALD (REG_ITMP3, REG_PV, -72); /* address of builtin_throw_exception */
3941 M_JSR (REG_RA, REG_ITMP3); /* call builtin */
3942 M_MOV (REG_ITMP1, REG_ARG_0); /* pass parameter (delay slot) */
3944 M_BR(-14); /* branch calljava_return */
3945 M_NOP; /* delay slot */
3947 (void) docacheflush((void*)(calljavamem + CALL_JAVA_ENTRY),
3948 (CALL_JAVA_MEM_SIZE - CALL_JAVA_ENTRY) * (int) sizeof(s4));
3952 typedef java_objectheader* (*asm_fptr)(methodinfo*, void*, void*, void*, void*);
3955 java_objectheader *asm_calljavamethod (methodinfo *m, void *arg1, void *arg2,
3956 void *arg3, void *arg4)
3958 java_objectheader *r = ((asm_fptr)(calljavamem + 20))(m, arg1, arg2, arg3, arg4);
3959 return (exceptionptr ? r : NULL);
3963 java_objectheader *asm_calljavafunction (methodinfo *m, void *arg1, void *arg2,
3964 void *arg3, void *arg4)
3966 return ((asm_fptr)(calljavamem + 20))(m, arg1, arg2, arg3, arg4);
3970 void docacheflush(u1 *p, long bytelen)
3972 u1 *e = p + bytelen;
3973 long psize = sysconf(_SC_PAGESIZE);
3974 p -= (long) p & (psize-1);
3975 e += psize - ((((long) e - 1) & (psize-1)) + 1);
3977 mprotect(p, bytelen, PROT_READ|PROT_WRITE|PROT_EXEC);
3982 * These are local overrides for various environment variables in Emacs.
3983 * Please do not remove this and leave it at the end of the file, where
3984 * Emacs will automagically detect them.
3985 * ---------------------------------------------------------------------
3988 * indent-tabs-mode: t