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 828 2004-01-03 16:20:06Z 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);
1878 M_LADD_IMM(REG_ZERO, 1, d);
1882 M_LSUB_IMM(REG_ZERO, 1, d);
1883 M_CMOVT(REG_ZERO, d);
1884 store_reg_to_var_int(iptr->dst, d);
1887 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1889 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1890 var_to_reg_flt(s2, src, REG_FTMP2);
1891 d = reg_of_var(iptr->dst, REG_ITMP3);
1894 M_LADD_IMM(REG_ZERO, 1, d);
1898 M_LSUB_IMM(REG_ZERO, 1, d);
1899 M_CMOVT(REG_ZERO, d);
1900 store_reg_to_var_int(iptr->dst, d);
1903 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1905 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1906 var_to_reg_flt(s2, src, REG_FTMP2);
1907 d = reg_of_var(iptr->dst, REG_ITMP3);
1910 M_LSUB_IMM(REG_ZERO, 1, d);
1914 M_LADD_IMM(REG_ZERO, 1, d);
1915 M_CMOVT(REG_ZERO, d);
1916 store_reg_to_var_int(iptr->dst, d);
1919 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1921 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1922 var_to_reg_flt(s2, src, REG_FTMP2);
1923 d = reg_of_var(iptr->dst, REG_ITMP3);
1926 M_LSUB_IMM(REG_ZERO, 1, d);
1930 M_LADD_IMM(REG_ZERO, 1, d);
1931 M_CMOVT(REG_ZERO, d);
1932 store_reg_to_var_int(iptr->dst, d);
1936 /* memory operations **************************************************/
1938 #define gen_bound_check \
1940 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1941 M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
1942 M_BEQZ(REG_ITMP3, 0);\
1943 codegen_addxboundrefs(mcodeptr);\
1947 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1949 var_to_reg_int(s1, src, REG_ITMP1);
1950 d = reg_of_var(iptr->dst, REG_ITMP3);
1951 gen_nullptr_check(s1);
1952 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1953 store_reg_to_var_int(iptr->dst, d);
1956 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1958 var_to_reg_int(s1, src->prev, REG_ITMP1);
1959 var_to_reg_int(s2, src, REG_ITMP2);
1960 d = reg_of_var(iptr->dst, REG_ITMP3);
1961 if (iptr->op1 == 0) {
1962 gen_nullptr_check(s1);
1965 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1966 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1967 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1968 store_reg_to_var_int(iptr->dst, d);
1971 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1973 var_to_reg_int(s1, src->prev, REG_ITMP1);
1974 var_to_reg_int(s2, src, REG_ITMP2);
1975 d = reg_of_var(iptr->dst, REG_ITMP3);
1976 if (iptr->op1 == 0) {
1977 gen_nullptr_check(s1);
1980 M_ASLL_IMM(s2, 2, REG_ITMP2);
1981 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1982 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1983 store_reg_to_var_int(iptr->dst, d);
1986 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1988 var_to_reg_int(s1, src->prev, REG_ITMP1);
1989 var_to_reg_int(s2, src, REG_ITMP2);
1990 d = reg_of_var(iptr->dst, REG_ITMP3);
1991 if (iptr->op1 == 0) {
1992 gen_nullptr_check(s1);
1995 M_ASLL_IMM(s2, 3, REG_ITMP2);
1996 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1997 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1998 store_reg_to_var_int(iptr->dst, d);
2001 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2003 var_to_reg_int(s1, src->prev, REG_ITMP1);
2004 var_to_reg_int(s2, src, REG_ITMP2);
2005 d = reg_of_var(iptr->dst, REG_FTMP3);
2006 if (iptr->op1 == 0) {
2007 gen_nullptr_check(s1);
2010 M_ASLL_IMM(s2, 2, REG_ITMP2);
2011 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2012 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2013 store_reg_to_var_flt(iptr->dst, d);
2016 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2018 var_to_reg_int(s1, src->prev, REG_ITMP1);
2019 var_to_reg_int(s2, src, REG_ITMP2);
2020 d = reg_of_var(iptr->dst, REG_FTMP3);
2021 if (iptr->op1 == 0) {
2022 gen_nullptr_check(s1);
2025 M_ASLL_IMM(s2, 3, REG_ITMP2);
2026 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2027 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2028 store_reg_to_var_flt(iptr->dst, d);
2031 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2033 var_to_reg_int(s1, src->prev, REG_ITMP1);
2034 var_to_reg_int(s2, src, REG_ITMP2);
2035 d = reg_of_var(iptr->dst, REG_ITMP3);
2036 if (iptr->op1 == 0) {
2037 gen_nullptr_check(s1);
2040 M_AADD(s2, s1, REG_ITMP1);
2041 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2042 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2043 store_reg_to_var_int(iptr->dst, d);
2046 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2048 var_to_reg_int(s1, src->prev, REG_ITMP1);
2049 var_to_reg_int(s2, src, REG_ITMP2);
2050 d = reg_of_var(iptr->dst, REG_ITMP3);
2051 if (iptr->op1 == 0) {
2052 gen_nullptr_check(s1);
2055 M_AADD(s2, s1, REG_ITMP1);
2056 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2057 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2058 store_reg_to_var_int(iptr->dst, d);
2061 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2063 var_to_reg_int(s1, src->prev, REG_ITMP1);
2064 var_to_reg_int(s2, src, REG_ITMP2);
2065 d = reg_of_var(iptr->dst, REG_ITMP3);
2066 if (iptr->op1 == 0) {
2067 gen_nullptr_check(s1);
2070 M_AADD(s2, s1, REG_ITMP1);
2071 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2072 store_reg_to_var_int(iptr->dst, d);
2076 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2078 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2079 var_to_reg_int(s2, src->prev, REG_ITMP2);
2080 if (iptr->op1 == 0) {
2081 gen_nullptr_check(s1);
2084 var_to_reg_int(s3, src, REG_ITMP3);
2085 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
2086 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2087 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2090 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2092 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2093 var_to_reg_int(s2, src->prev, REG_ITMP2);
2094 if (iptr->op1 == 0) {
2095 gen_nullptr_check(s1);
2098 var_to_reg_int(s3, src, REG_ITMP3);
2099 M_ASLL_IMM(s2, 2, REG_ITMP2);
2100 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2101 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
2104 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2106 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2107 var_to_reg_int(s2, src->prev, REG_ITMP2);
2108 if (iptr->op1 == 0) {
2109 gen_nullptr_check(s1);
2112 var_to_reg_int(s3, src, REG_ITMP3);
2113 M_ASLL_IMM(s2, 3, REG_ITMP2);
2114 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2115 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
2118 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2120 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2121 var_to_reg_int(s2, src->prev, REG_ITMP2);
2122 if (iptr->op1 == 0) {
2123 gen_nullptr_check(s1);
2126 var_to_reg_flt(s3, src, REG_FTMP3);
2127 M_ASLL_IMM(s2, 2, REG_ITMP2);
2128 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2129 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2132 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2134 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2135 var_to_reg_int(s2, src->prev, REG_ITMP2);
2136 if (iptr->op1 == 0) {
2137 gen_nullptr_check(s1);
2140 var_to_reg_flt(s3, src, REG_FTMP3);
2141 M_ASLL_IMM(s2, 3, REG_ITMP2);
2142 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2143 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2146 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2147 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2149 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2150 var_to_reg_int(s2, src->prev, REG_ITMP2);
2151 if (iptr->op1 == 0) {
2152 gen_nullptr_check(s1);
2155 var_to_reg_int(s3, src, REG_ITMP3);
2156 M_AADD(s2, s1, REG_ITMP1);
2157 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2158 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
2161 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2163 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2164 var_to_reg_int(s2, src->prev, REG_ITMP2);
2165 if (iptr->op1 == 0) {
2166 gen_nullptr_check(s1);
2169 var_to_reg_int(s3, src, REG_ITMP3);
2170 M_AADD(s2, s1, REG_ITMP1);
2171 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2175 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2176 /* op1 = type, val.a = field address */
2178 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2179 M_ALD(REG_ITMP1, REG_PV, a);
2180 switch (iptr->op1) {
2182 var_to_reg_int(s2, src, REG_ITMP2);
2183 M_IST(s2, REG_ITMP1, 0);
2186 var_to_reg_int(s2, src, REG_ITMP2);
2187 M_LST(s2, REG_ITMP1, 0);
2190 var_to_reg_int(s2, src, REG_ITMP2);
2191 M_AST(s2, REG_ITMP1, 0);
2194 var_to_reg_flt(s2, src, REG_FTMP2);
2195 M_FST(s2, REG_ITMP1, 0);
2198 var_to_reg_flt(s2, src, REG_FTMP2);
2199 M_DST(s2, REG_ITMP1, 0);
2201 default: panic ("internal error");
2205 case ICMD_GETSTATIC: /* ... ==> ..., value */
2206 /* op1 = type, val.a = field address */
2208 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2209 M_ALD(REG_ITMP1, REG_PV, a);
2210 switch (iptr->op1) {
2212 d = reg_of_var(iptr->dst, REG_ITMP3);
2213 M_ILD(d, REG_ITMP1, 0);
2214 store_reg_to_var_int(iptr->dst, d);
2217 d = reg_of_var(iptr->dst, REG_ITMP3);
2218 M_LLD(d, REG_ITMP1, 0);
2219 store_reg_to_var_int(iptr->dst, d);
2222 d = reg_of_var(iptr->dst, REG_ITMP3);
2223 M_ALD(d, REG_ITMP1, 0);
2224 store_reg_to_var_int(iptr->dst, d);
2227 d = reg_of_var(iptr->dst, REG_FTMP1);
2228 M_FLD(d, REG_ITMP1, 0);
2229 store_reg_to_var_flt(iptr->dst, d);
2232 d = reg_of_var(iptr->dst, REG_FTMP1);
2233 M_DLD(d, REG_ITMP1, 0);
2234 store_reg_to_var_flt(iptr->dst, d);
2236 default: panic ("internal error");
2241 case ICMD_PUTFIELD: /* ..., value ==> ... */
2242 /* op1 = type, val.i = field offset */
2244 a = ((fieldinfo *)(iptr->val.a))->offset;
2245 switch (iptr->op1) {
2247 var_to_reg_int(s1, src->prev, REG_ITMP1);
2248 var_to_reg_int(s2, src, REG_ITMP2);
2249 gen_nullptr_check(s1);
2253 var_to_reg_int(s1, src->prev, REG_ITMP1);
2254 var_to_reg_int(s2, src, REG_ITMP2);
2255 gen_nullptr_check(s1);
2259 var_to_reg_int(s1, src->prev, REG_ITMP1);
2260 var_to_reg_int(s2, src, REG_ITMP2);
2261 gen_nullptr_check(s1);
2265 var_to_reg_int(s1, src->prev, REG_ITMP1);
2266 var_to_reg_flt(s2, src, REG_FTMP2);
2267 gen_nullptr_check(s1);
2271 var_to_reg_int(s1, src->prev, REG_ITMP1);
2272 var_to_reg_flt(s2, src, REG_FTMP2);
2273 gen_nullptr_check(s1);
2276 default: panic ("internal error");
2280 case ICMD_GETFIELD: /* ... ==> ..., value */
2281 /* op1 = type, val.i = field offset */
2283 a = ((fieldinfo *)(iptr->val.a))->offset;
2284 switch (iptr->op1) {
2286 var_to_reg_int(s1, src, REG_ITMP1);
2287 d = reg_of_var(iptr->dst, REG_ITMP3);
2288 gen_nullptr_check(s1);
2290 store_reg_to_var_int(iptr->dst, d);
2293 var_to_reg_int(s1, src, REG_ITMP1);
2294 d = reg_of_var(iptr->dst, REG_ITMP3);
2295 gen_nullptr_check(s1);
2297 store_reg_to_var_int(iptr->dst, d);
2300 var_to_reg_int(s1, src, REG_ITMP1);
2301 d = reg_of_var(iptr->dst, REG_ITMP3);
2302 gen_nullptr_check(s1);
2304 store_reg_to_var_int(iptr->dst, d);
2307 var_to_reg_int(s1, src, REG_ITMP1);
2308 d = reg_of_var(iptr->dst, REG_FTMP1);
2309 gen_nullptr_check(s1);
2311 store_reg_to_var_flt(iptr->dst, d);
2314 var_to_reg_int(s1, src, REG_ITMP1);
2315 d = reg_of_var(iptr->dst, REG_FTMP1);
2316 gen_nullptr_check(s1);
2318 store_reg_to_var_flt(iptr->dst, d);
2320 default: panic ("internal error");
2325 /* branch operations **************************************************/
2327 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2329 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2331 var_to_reg_int(s1, src, REG_ITMP1);
2332 M_INTMOVE(s1, REG_ITMP1_XPTR);
2333 a = dseg_addaddress(asm_handle_exception);
2334 M_ALD(REG_ITMP2, REG_PV, a);
2335 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2337 M_NOP; /* nop ensures that XPC is less than the end */
2338 /* of basic block */
2342 case ICMD_GOTO: /* ... ==> ... */
2343 /* op1 = target JavaVM pc */
2345 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2350 case ICMD_JSR: /* ... ==> ... */
2351 /* op1 = target JavaVM pc */
2353 dseg_addtarget(BlockPtrOfPC(iptr->op1));
2354 M_ALD(REG_ITMP1, REG_PV, -dseglen);
2355 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2359 case ICMD_RET: /* ... ==> ... */
2360 /* op1 = local variable */
2361 var = &(locals[iptr->op1][TYPE_ADR]);
2362 if (var->flags & INMEMORY) {
2363 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2372 case ICMD_IFNULL: /* ..., value ==> ... */
2373 /* op1 = target JavaVM pc */
2375 var_to_reg_int(s1, src, REG_ITMP1);
2377 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2381 case ICMD_IFNONNULL: /* ..., value ==> ... */
2382 /* op1 = target JavaVM pc */
2384 var_to_reg_int(s1, src, REG_ITMP1);
2386 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2390 case ICMD_IFEQ: /* ..., value ==> ... */
2391 /* op1 = target JavaVM pc, val.i = constant */
2393 var_to_reg_int(s1, src, REG_ITMP1);
2394 if (iptr->val.i == 0) {
2398 ICONST(REG_ITMP2, iptr->val.i);
2399 M_BEQ(s1, REG_ITMP2, 0);
2401 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2405 case ICMD_IFLT: /* ..., value ==> ... */
2406 /* op1 = target JavaVM pc, val.i = constant */
2408 var_to_reg_int(s1, src, REG_ITMP1);
2409 if (iptr->val.i == 0) {
2413 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2414 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2417 ICONST(REG_ITMP2, iptr->val.i);
2418 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2420 M_BNEZ(REG_ITMP1, 0);
2422 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2426 case ICMD_IFLE: /* ..., value ==> ... */
2427 /* op1 = target JavaVM pc, val.i = constant */
2429 var_to_reg_int(s1, src, REG_ITMP1);
2430 if (iptr->val.i == 0) {
2434 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2435 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2436 M_BNEZ(REG_ITMP1, 0);
2439 ICONST(REG_ITMP2, iptr->val.i);
2440 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2441 M_BEQZ(REG_ITMP1, 0);
2444 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2448 case ICMD_IFNE: /* ..., value ==> ... */
2449 /* op1 = target JavaVM pc, val.i = constant */
2451 var_to_reg_int(s1, src, REG_ITMP1);
2452 if (iptr->val.i == 0) {
2456 ICONST(REG_ITMP2, iptr->val.i);
2457 M_BNE(s1, REG_ITMP2, 0);
2459 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2463 case ICMD_IFGT: /* ..., value ==> ... */
2464 /* op1 = target JavaVM pc, val.i = constant */
2466 var_to_reg_int(s1, src, REG_ITMP1);
2467 if (iptr->val.i == 0) {
2471 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2472 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2473 M_BEQZ(REG_ITMP1, 0);
2476 ICONST(REG_ITMP2, iptr->val.i);
2477 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2478 M_BNEZ(REG_ITMP1, 0);
2481 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2485 case ICMD_IFGE: /* ..., value ==> ... */
2486 /* op1 = target JavaVM pc, val.i = constant */
2488 var_to_reg_int(s1, src, REG_ITMP1);
2489 if (iptr->val.i == 0) {
2493 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2494 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2497 ICONST(REG_ITMP2, iptr->val.i);
2498 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2500 M_BEQZ(REG_ITMP1, 0);
2502 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2506 case ICMD_IF_LEQ: /* ..., value ==> ... */
2507 /* op1 = target JavaVM pc, val.l = constant */
2509 var_to_reg_int(s1, src, REG_ITMP1);
2510 if (iptr->val.l == 0) {
2514 LCONST(REG_ITMP2, iptr->val.l);
2515 M_BEQ(s1, REG_ITMP2, 0);
2517 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2521 case ICMD_IF_LLT: /* ..., value ==> ... */
2522 /* op1 = target JavaVM pc, val.l = constant */
2524 var_to_reg_int(s1, src, REG_ITMP1);
2525 if (iptr->val.l == 0) {
2529 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2530 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2533 LCONST(REG_ITMP2, iptr->val.l);
2534 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2536 M_BNEZ(REG_ITMP1, 0);
2538 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2542 case ICMD_IF_LLE: /* ..., value ==> ... */
2543 /* op1 = target JavaVM pc, val.l = constant */
2545 var_to_reg_int(s1, src, REG_ITMP1);
2546 if (iptr->val.l == 0) {
2550 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2551 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2552 M_BNEZ(REG_ITMP1, 0);
2555 LCONST(REG_ITMP2, iptr->val.l);
2556 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2557 M_BEQZ(REG_ITMP1, 0);
2560 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2564 case ICMD_IF_LNE: /* ..., value ==> ... */
2565 /* op1 = target JavaVM pc, val.l = constant */
2567 var_to_reg_int(s1, src, REG_ITMP1);
2568 if (iptr->val.l == 0) {
2572 LCONST(REG_ITMP2, iptr->val.l);
2573 M_BNE(s1, REG_ITMP2, 0);
2575 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2579 case ICMD_IF_LGT: /* ..., value ==> ... */
2580 /* op1 = target JavaVM pc, val.l = constant */
2582 var_to_reg_int(s1, src, REG_ITMP1);
2583 if (iptr->val.l == 0) {
2587 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2588 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2589 M_BEQZ(REG_ITMP1, 0);
2592 LCONST(REG_ITMP2, iptr->val.l);
2593 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2594 M_BNEZ(REG_ITMP1, 0);
2597 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2601 case ICMD_IF_LGE: /* ..., value ==> ... */
2602 /* op1 = target JavaVM pc, val.l = constant */
2604 var_to_reg_int(s1, src, REG_ITMP1);
2605 if (iptr->val.l == 0) {
2609 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2610 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2613 LCONST(REG_ITMP2, iptr->val.l);
2614 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2616 M_BEQZ(REG_ITMP1, 0);
2618 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2622 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2623 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2624 case ICMD_IF_ACMPEQ:
2626 var_to_reg_int(s1, src->prev, REG_ITMP1);
2627 var_to_reg_int(s2, src, REG_ITMP2);
2629 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2633 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2634 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2635 case ICMD_IF_ACMPNE:
2637 var_to_reg_int(s1, src->prev, REG_ITMP1);
2638 var_to_reg_int(s2, src, REG_ITMP2);
2640 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2644 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2645 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2647 var_to_reg_int(s1, src->prev, REG_ITMP1);
2648 var_to_reg_int(s2, src, REG_ITMP2);
2649 M_CMPLT(s1, s2, REG_ITMP1);
2650 M_BNEZ(REG_ITMP1, 0);
2651 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2655 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2656 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2658 var_to_reg_int(s1, src->prev, REG_ITMP1);
2659 var_to_reg_int(s2, src, REG_ITMP2);
2660 M_CMPGT(s1, s2, REG_ITMP1);
2661 M_BNEZ(REG_ITMP1, 0);
2662 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2666 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2667 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2669 var_to_reg_int(s1, src->prev, REG_ITMP1);
2670 var_to_reg_int(s2, src, REG_ITMP2);
2671 M_CMPGT(s1, s2, REG_ITMP1);
2672 M_BEQZ(REG_ITMP1, 0);
2673 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2677 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2678 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2680 var_to_reg_int(s1, src->prev, REG_ITMP1);
2681 var_to_reg_int(s2, src, REG_ITMP2);
2682 M_CMPLT(s1, s2, REG_ITMP1);
2683 M_BEQZ(REG_ITMP1, 0);
2684 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2688 #ifdef CONDITIONAL_LOADCONST
2689 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2691 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2694 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2695 /* val.i = constant */
2697 var_to_reg_int(s1, src, REG_ITMP1);
2698 d = reg_of_var(iptr->dst, REG_ITMP3);
2700 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2701 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2702 M_CMPEQ(s1, REG_ZERO, d);
2703 store_reg_to_var_int(iptr->dst, d);
2706 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2707 M_CMPEQ(s1, REG_ZERO, d);
2709 store_reg_to_var_int(iptr->dst, d);
2713 M_MOV(s1, REG_ITMP1);
2716 ICONST(d, iptr[1].val.i);
2718 if ((s3 >= 0) && (s3 <= 255)) {
2719 M_CMOVEQ_IMM(s1, s3, d);
2722 ICONST(REG_ITMP2, s3);
2723 M_CMOVEQ(s1, REG_ITMP2, d);
2725 store_reg_to_var_int(iptr->dst, d);
2728 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2729 /* val.i = constant */
2731 var_to_reg_int(s1, src, REG_ITMP1);
2732 d = reg_of_var(iptr->dst, REG_ITMP3);
2734 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2735 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2736 M_CMPEQ(s1, REG_ZERO, d);
2737 store_reg_to_var_int(iptr->dst, d);
2740 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2741 M_CMPEQ(s1, REG_ZERO, d);
2743 store_reg_to_var_int(iptr->dst, d);
2747 M_MOV(s1, REG_ITMP1);
2750 ICONST(d, iptr[1].val.i);
2752 if ((s3 >= 0) && (s3 <= 255)) {
2753 M_CMOVNE_IMM(s1, s3, d);
2756 ICONST(REG_ITMP2, s3);
2757 M_CMOVNE(s1, REG_ITMP2, d);
2759 store_reg_to_var_int(iptr->dst, d);
2762 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2763 /* val.i = constant */
2765 var_to_reg_int(s1, src, REG_ITMP1);
2766 d = reg_of_var(iptr->dst, REG_ITMP3);
2768 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2769 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2770 M_CMPLT(s1, REG_ZERO, d);
2771 store_reg_to_var_int(iptr->dst, d);
2774 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2775 M_CMPLE(REG_ZERO, s1, d);
2776 store_reg_to_var_int(iptr->dst, d);
2780 M_MOV(s1, REG_ITMP1);
2783 ICONST(d, iptr[1].val.i);
2785 if ((s3 >= 0) && (s3 <= 255)) {
2786 M_CMOVLT_IMM(s1, s3, d);
2789 ICONST(REG_ITMP2, s3);
2790 M_CMOVLT(s1, REG_ITMP2, d);
2792 store_reg_to_var_int(iptr->dst, d);
2795 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2796 /* val.i = constant */
2798 var_to_reg_int(s1, src, REG_ITMP1);
2799 d = reg_of_var(iptr->dst, REG_ITMP3);
2801 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2802 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2803 M_CMPLE(REG_ZERO, s1, d);
2804 store_reg_to_var_int(iptr->dst, d);
2807 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2808 M_CMPLT(s1, REG_ZERO, d);
2809 store_reg_to_var_int(iptr->dst, d);
2813 M_MOV(s1, REG_ITMP1);
2816 ICONST(d, iptr[1].val.i);
2818 if ((s3 >= 0) && (s3 <= 255)) {
2819 M_CMOVGE_IMM(s1, s3, d);
2822 ICONST(REG_ITMP2, s3);
2823 M_CMOVGE(s1, REG_ITMP2, d);
2825 store_reg_to_var_int(iptr->dst, d);
2828 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2829 /* val.i = constant */
2831 var_to_reg_int(s1, src, REG_ITMP1);
2832 d = reg_of_var(iptr->dst, REG_ITMP3);
2834 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2835 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2836 M_CMPLT(REG_ZERO, s1, d);
2837 store_reg_to_var_int(iptr->dst, d);
2840 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2841 M_CMPLE(s1, REG_ZERO, d);
2842 store_reg_to_var_int(iptr->dst, d);
2846 M_MOV(s1, REG_ITMP1);
2849 ICONST(d, iptr[1].val.i);
2851 if ((s3 >= 0) && (s3 <= 255)) {
2852 M_CMOVGT_IMM(s1, s3, d);
2855 ICONST(REG_ITMP2, s3);
2856 M_CMOVGT(s1, REG_ITMP2, d);
2858 store_reg_to_var_int(iptr->dst, d);
2861 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2862 /* val.i = constant */
2864 var_to_reg_int(s1, src, REG_ITMP1);
2865 d = reg_of_var(iptr->dst, REG_ITMP3);
2867 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2868 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2869 M_CMPLE(s1, REG_ZERO, d);
2870 store_reg_to_var_int(iptr->dst, d);
2873 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2874 M_CMPLT(REG_ZERO, s1, d);
2875 store_reg_to_var_int(iptr->dst, d);
2879 M_MOV(s1, REG_ITMP1);
2882 ICONST(d, iptr[1].val.i);
2884 if ((s3 >= 0) && (s3 <= 255)) {
2885 M_CMOVLE_IMM(s1, s3, d);
2888 ICONST(REG_ITMP2, s3);
2889 M_CMOVLE(s1, REG_ITMP2, d);
2891 store_reg_to_var_int(iptr->dst, d);
2896 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2901 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2903 a = dseg_addaddress ((void*) (builtin_monitorexit));
2904 M_ALD(REG_ITMP3, REG_PV, a);
2905 M_JSR(REG_RA, REG_ITMP3);
2906 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse); /* delay slot */
2907 disp = -(int)((u1*) mcodeptr - mcodebase);
2908 M_LDA(REG_PV, REG_RA, disp);
2911 var_to_reg_int(s1, src, REG_RESULT);
2912 M_INTMOVE(s1, REG_RESULT);
2913 goto nowperformreturn;
2915 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2919 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2921 a = dseg_addaddress ((void*) (builtin_monitorexit));
2922 M_ALD(REG_ITMP3, REG_PV, a);
2923 M_JSR(REG_RA, REG_ITMP3);
2924 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse); /* delay slot */
2925 disp = -(int)((u1*) mcodeptr - mcodebase);
2926 M_LDA(REG_PV, REG_RA, disp);
2929 var_to_reg_flt(s1, src, REG_FRESULT);
2931 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2932 M_TFLTMOVE(t, s1, REG_FRESULT);
2934 goto nowperformreturn;
2936 case ICMD_RETURN: /* ... ==> ... */
2939 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2941 a = dseg_addaddress ((void*) (builtin_monitorexit));
2942 M_ALD(REG_ITMP3, REG_PV, a);
2943 M_JSR(REG_RA, REG_ITMP3);
2944 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse); /* delay slot */
2945 disp = -(int)((u1*) mcodeptr - mcodebase);
2946 M_LDA(REG_PV, REG_RA, disp);
2954 p = parentargs_base;
2956 /* restore return address */
2959 {p--; M_LLD (REG_RA, REG_SP, 8 * p);}
2961 /* restore saved registers */
2963 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
2964 {p--; M_LLD(savintregs[r], REG_SP, 8 * p);}
2965 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
2966 {p--; M_DLD(savfltregs[r], REG_SP, 8 * p);}
2968 /* call trace function */
2971 M_LDA (REG_SP, REG_SP, -24);
2972 M_LST(REG_RA, REG_SP, 0);
2973 M_LST(REG_RESULT, REG_SP, 8);
2974 M_DST(REG_FRESULT, REG_SP,16);
2975 a = dseg_addaddress (method);
2976 M_ALD(argintregs[0], REG_PV, a);
2977 M_MOV(REG_RESULT, argintregs[1]);
2978 M_FLTMOVE(REG_FRESULT, argfltregs[2]);
2979 M_FMOV(REG_FRESULT, argfltregs[3]);
2980 a = dseg_addaddress ((void*) (builtin_displaymethodstop));
2981 M_ALD(REG_ITMP3, REG_PV, a);
2982 M_JSR (REG_RA, REG_ITMP3);
2984 M_DLD(REG_FRESULT, REG_SP,16);
2985 M_LLD(REG_RESULT, REG_SP, 8);
2986 M_LLD(REG_RA, REG_SP, 0);
2987 M_LDA (REG_SP, REG_SP, 24);
2992 /* deallocate stack */
2994 if (parentargs_base)
2995 {M_LDA(REG_SP, REG_SP, parentargs_base*8);}
3003 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3008 tptr = (void **) iptr->target;
3010 s4ptr = iptr->val.a;
3011 l = s4ptr[1]; /* low */
3012 i = s4ptr[2]; /* high */
3014 var_to_reg_int(s1, src, REG_ITMP1);
3016 {M_INTMOVE(s1, REG_ITMP1);}
3017 else if (l <= 32768) {
3018 M_IADD_IMM(s1, -l, REG_ITMP1);
3021 ICONST(REG_ITMP2, l);
3022 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3028 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
3029 M_BEQZ(REG_ITMP2, 0);
3030 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3031 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
3033 /* build jump table top down and use address of lowest entry */
3035 /* s4ptr += 3 + i; */
3039 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3040 dseg_addtarget((basicblock *) tptr[0]);
3045 /* length of dataseg after last dseg_addtarget is used by load */
3047 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
3048 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
3055 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3057 s4 i, l, val, *s4ptr;
3060 tptr = (void **) iptr->target;
3062 s4ptr = iptr->val.a;
3063 l = s4ptr[0]; /* default */
3064 i = s4ptr[1]; /* count */
3066 MCODECHECK((i<<2)+8);
3067 var_to_reg_int(s1, src, REG_ITMP1);
3073 ICONST(REG_ITMP2, val);
3074 M_BEQ(s1, REG_ITMP2, 0);
3075 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3080 tptr = (void **) iptr->target;
3081 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3088 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3089 /* op1 = return type, val.a = function pointer*/
3093 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3094 /* op1 = return type, val.a = function pointer*/
3098 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3099 /* op1 = return type, val.a = function pointer*/
3103 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3104 /* op1 = arg count, val.a = method pointer */
3106 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3107 /* op1 = arg count, val.a = method pointer */
3109 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3110 /* op1 = arg count, val.a = method pointer */
3112 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3113 /* op1 = arg count, val.a = method pointer */
3121 MCODECHECK((s3 << 1) + 64);
3123 /* copy arguments to registers or stack location */
3125 for (; --s3 >= 0; src = src->prev) {
3126 if (src->varkind == ARGVAR)
3128 if (IS_INT_LNG_TYPE(src->type)) {
3129 if (s3 < INT_ARG_CNT) {
3130 s1 = argintregs[s3];
3131 var_to_reg_int(d, src, s1);
3135 var_to_reg_int(d, src, REG_ITMP1);
3136 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3140 if (s3 < FLT_ARG_CNT) {
3141 s1 = argfltregs[s3];
3142 var_to_reg_flt(d, src, s1);
3143 M_TFLTMOVE(src->type,d, s1);
3146 var_to_reg_flt(d, src, REG_FTMP1);
3147 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3152 switch (iptr->opc) {
3156 a = dseg_addaddress ((void*) (m));
3157 M_ALD(REG_ITMP3, REG_PV, a); /* built-in-function pointer */
3158 M_JSR (REG_RA, REG_ITMP3);
3160 d = iptr->op1; /* return type */
3161 goto afteractualcall;
3163 case ICMD_INVOKESTATIC:
3164 case ICMD_INVOKESPECIAL:
3165 a = dseg_addaddress (m->stubroutine);
3167 M_ALD(REG_PV, REG_PV, a ); /* method pointer in pv */
3170 goto makeactualcall;
3172 case ICMD_INVOKEVIRTUAL:
3174 gen_nullptr_check(argintregs[0]);
3175 M_ALD(REG_METHODPTR, argintregs[0],
3176 OFFSET(java_objectheader, vftbl));
3177 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
3178 sizeof(methodptr) * m->vftblindex);
3181 goto makeactualcall;
3183 case ICMD_INVOKEINTERFACE:
3186 gen_nullptr_check(argintregs[0]);
3187 M_ALD(REG_METHODPTR, argintregs[0],
3188 OFFSET(java_objectheader, vftbl));
3189 M_ALD(REG_METHODPTR, REG_METHODPTR,
3190 OFFSET(vftbl, interfacetable[0]) -
3191 sizeof(methodptr*) * ci->index);
3192 M_ALD(REG_PV, REG_METHODPTR,
3193 sizeof(methodptr) * (m - ci->methods));
3196 goto makeactualcall;
3200 error ("Unkown ICMD-Command: %d", iptr->opc);
3205 M_JSR (REG_RA, REG_PV);
3212 s1 = (int)((u1*) mcodeptr - mcodebase);
3213 if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
3216 while (ml<-32768) { ml+=65536; mh--; }
3218 M_IADD_IMM(REG_PV, ml, REG_PV);
3219 M_LADD(REG_PV, REG_RA, REG_PV);
3222 /* d contains return type */
3224 if (d != TYPE_VOID) {
3225 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3226 s1 = reg_of_var(iptr->dst, REG_RESULT);
3227 M_INTMOVE(REG_RESULT, s1);
3228 store_reg_to_var_int(iptr->dst, s1);
3231 s1 = reg_of_var(iptr->dst, REG_FRESULT);
3232 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3233 store_reg_to_var_flt(iptr->dst, s1);
3240 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3242 /* op1: 0 == array, 1 == class */
3243 /* val.a: (classinfo*) superclass */
3245 /* superclass is an interface:
3247 * return (sub != NULL) &&
3248 * (sub->vftbl->interfacetablelength > super->index) &&
3249 * (sub->vftbl->interfacetable[-super->index] != NULL);
3251 * superclass is a class:
3253 * return ((sub != NULL) && (0
3254 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3255 * super->vftbl->diffvall));
3259 classinfo *super = (classinfo*) iptr->val.a;
3261 var_to_reg_int(s1, src, REG_ITMP1);
3262 d = reg_of_var(iptr->dst, REG_ITMP3);
3264 M_MOV(s1, REG_ITMP1);
3268 if (iptr->op1) { /* class/interface */
3269 if (super->flags & ACC_INTERFACE) { /* interface */
3272 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3273 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3274 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3275 M_BLEZ(REG_ITMP2, 3);
3277 M_ALD(REG_ITMP1, REG_ITMP1,
3278 OFFSET(vftbl, interfacetable[0]) -
3279 super->index * sizeof(methodptr*));
3280 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3284 s2 = super->vftbl->diffval;
3287 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3288 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3289 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3290 M_CMPULT_IMM(REG_ITMP1, s2 + 1, d);
3295 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3296 a = dseg_addaddress ((void*) super->vftbl);
3297 M_ALD(REG_ITMP2, REG_PV, a);
3298 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3299 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3300 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3301 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3302 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3308 panic ("internal error: no inlined array instanceof");
3310 store_reg_to_var_int(iptr->dst, d);
3313 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3315 /* op1: 0 == array, 1 == class */
3316 /* val.a: (classinfo*) superclass */
3318 /* superclass is an interface:
3320 * OK if ((sub == NULL) ||
3321 * (sub->vftbl->interfacetablelength > super->index) &&
3322 * (sub->vftbl->interfacetable[-super->index] != NULL));
3324 * superclass is a class:
3326 * OK if ((sub == NULL) || (0
3327 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3328 * super->vftbl->diffvall));
3332 classinfo *super = (classinfo*) iptr->val.a;
3334 d = reg_of_var(iptr->dst, REG_ITMP3);
3335 var_to_reg_int(s1, src, d);
3336 if (iptr->op1) { /* class/interface */
3337 if (super->flags & ACC_INTERFACE) { /* interface */
3340 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3341 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3342 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3343 M_BLEZ(REG_ITMP2, 0);
3344 codegen_addxcastrefs(mcodeptr);
3346 M_ALD(REG_ITMP2, REG_ITMP1,
3347 OFFSET(vftbl, interfacetable[0]) -
3348 super->index * sizeof(methodptr*));
3349 M_BEQZ(REG_ITMP2, 0);
3350 codegen_addxcastrefs(mcodeptr);
3356 s2 = super->vftbl->diffval;
3357 M_BEQZ(s1, 6 + (s2 != 0));
3359 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3360 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3361 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3363 M_BNEZ(REG_ITMP1, 0);
3366 M_CMPULT_IMM(REG_ITMP1, s2 + 1, REG_ITMP2);
3367 M_BEQZ(REG_ITMP2, 0);
3371 M_BEQZ(s1, 10 + (d == REG_ITMP3));
3373 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3374 a = dseg_addaddress ((void*) super->vftbl);
3375 M_ALD(REG_ITMP2, REG_PV, a);
3376 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3377 if (d != REG_ITMP3) {
3378 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3379 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3380 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3382 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, baseval));
3383 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3384 M_ALD(REG_ITMP2, REG_PV, a);
3385 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3387 M_CMPULT(REG_ITMP2, REG_ITMP1, REG_ITMP2);
3388 M_BNEZ(REG_ITMP2, 0);
3390 codegen_addxcastrefs(mcodeptr);
3395 panic ("internal error: no inlined array checkcast");
3398 store_reg_to_var_int(iptr->dst, d);
3401 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3403 var_to_reg_int(s1, src, REG_ITMP1);
3405 codegen_addxcheckarefs(mcodeptr);
3409 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3410 /* op1 = dimension, val.a = array descriptor */
3412 /* check for negative sizes and copy sizes to stack if necessary */
3414 MCODECHECK((iptr->op1 << 1) + 64);
3416 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3417 var_to_reg_int(s2, src, REG_ITMP1);
3419 codegen_addxcheckarefs(mcodeptr);
3422 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3424 if (src->varkind != ARGVAR) {
3425 M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
3429 /* a0 = dimension count */
3431 ICONST(argintregs[0], iptr->op1);
3433 /* a1 = arraydescriptor */
3435 a = dseg_addaddress(iptr->val.a);
3436 M_ALD(argintregs[1], REG_PV, a);
3438 /* a2 = pointer to dimensions = stack pointer */
3440 M_INTMOVE(REG_SP, argintregs[2]);
3442 a = dseg_addaddress((void*) (builtin_nmultianewarray));
3443 M_ALD(REG_ITMP3, REG_PV, a);
3444 M_JSR(REG_RA, REG_ITMP3);
3446 s1 = (int)((u1*) mcodeptr - mcodebase);
3448 M_LDA (REG_PV, REG_RA, -s1);
3452 s1 = reg_of_var(iptr->dst, REG_RESULT);
3453 M_INTMOVE(REG_RESULT, s1);
3454 store_reg_to_var_int(iptr->dst, s1);
3458 default: error ("Unknown pseudo command: %d", iptr->opc);
3464 } /* for instruction */
3466 /* copy values to interface registers */
3468 src = bptr->outstack;
3469 len = bptr->outdepth;
3473 if ((src->varkind != STACKVAR)) {
3475 if (IS_FLT_DBL_TYPE(s2)) {
3476 var_to_reg_flt(s1, src, REG_FTMP1);
3477 if (!(interfaces[len][s2].flags & INMEMORY)) {
3478 M_TFLTMOVE(s2,s1,interfaces[len][s2].regoff);
3481 M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3485 var_to_reg_int(s1, src, REG_ITMP1);
3486 if (!(interfaces[len][s2].flags & INMEMORY)) {
3487 M_INTMOVE(s1,interfaces[len][s2].regoff);
3490 M_LST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3496 } /* if (bptr -> flags >= BBREACHED) */
3497 } /* for basic block */
3499 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3502 /* generate bound check stubs */
3504 s4 *xcodeptr = NULL;
3506 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3507 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3508 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3509 xboundrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3514 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3515 xboundrefs->branchpos, (u1*) mcodeptr - mcodebase);
3519 M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos - 4);
3521 if (xcodeptr != NULL) {
3522 int disp = xcodeptr-mcodeptr;
3527 xcodeptr = mcodeptr;
3529 a = dseg_addaddress(asm_handle_exception);
3530 M_ALD(REG_ITMP3, REG_PV, a);
3533 a = dseg_addaddress(proto_java_lang_ArrayIndexOutOfBoundsException);
3534 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3538 /* generate negative array size check stubs */
3542 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3543 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3544 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3545 xcheckarefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3549 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3550 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
3554 M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos - 4);
3556 if (xcodeptr != NULL) {
3557 int disp = xcodeptr-mcodeptr;
3562 xcodeptr = mcodeptr;
3564 a = dseg_addaddress(asm_handle_exception);
3565 M_ALD(REG_ITMP3, REG_PV, a);
3568 a = dseg_addaddress(proto_java_lang_NegativeArraySizeException);
3569 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3573 /* generate cast check stubs */
3577 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3578 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3579 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3580 xcastrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3584 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3585 xcastrefs->branchpos, (u1*) mcodeptr - mcodebase);
3589 M_LDA(REG_ITMP2_XPC, REG_PV, xcastrefs->branchpos - 4);
3591 if (xcodeptr != NULL) {
3592 int disp = xcodeptr-mcodeptr;
3597 xcodeptr = mcodeptr;
3599 a = dseg_addaddress(asm_handle_exception);
3600 M_ALD(REG_ITMP3, REG_PV, a);
3603 a = dseg_addaddress(proto_java_lang_ClassCastException);
3604 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3609 #ifdef SOFTNULLPTRCHECK
3611 /* generate null pointer check stubs */
3615 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3616 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3617 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3618 xnullrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3622 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3623 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
3627 M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
3629 if (xcodeptr != NULL) {
3630 int disp = xcodeptr-mcodeptr;
3635 xcodeptr = mcodeptr;
3637 a = dseg_addaddress(asm_handle_exception);
3638 M_ALD(REG_ITMP3, REG_PV, a);
3641 a = dseg_addaddress(proto_java_lang_NullPointerException);
3642 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3649 codegen_finish((int)((u1*) mcodeptr - mcodebase));
3651 docacheflush((void*) method->entrypoint,
3652 ((u1*) mcodeptr - mcodebase));
3656 /* redefinition of code generation macros (compiling into array) **************/
3659 These macros are newly defined to allow code generation into an array.
3660 This is necessary, because the original M_.. macros generate code by
3661 calling 'codegen_adds4' that uses an additional data structure to
3664 For a faster (but less flexible) version to generate code, these
3665 macros directly use the (s4* p) - pointer to put the code directly
3666 in a locally defined array.
3667 This makes sense only for the stub-generation-routines below.
3671 #define M_ITYPE(op, rs, rt, imm)\
3672 *(p++) = (((op)<<26)|((rs)<<21)|((rt)<<16)|((imm)&0xffff))
3675 #define M_JTYPE(op, imm)\
3676 *(p++) = (((op)<<26)|((off)&0x3ffffff))
3679 #define M_RTYPE(op, rs, rt, rd, sa, fu)\
3680 *(p++) = (((op)<<26)|((rs)<<21)|((rt)<<16)|((rd)<<11)|((sa)<<6)|(fu))
3683 /* function createcompilerstub *************************************************
3685 creates a stub routine which calls the compiler
3687 *******************************************************************************/
3689 #define COMPSTUBSIZE 4
3691 u1 *createcompilerstub (methodinfo *m)
3693 u8 *s = CNEW(u8, COMPSTUBSIZE); /* memory to hold the stub */
3694 s4 *p = (s4*) s; /* code generation pointer */
3696 /* code for the stub */
3697 M_ALD(REG_PV, REG_PV, 24); /* load pointer to the compiler */
3699 M_JSR(REG_ITMP1, REG_PV); /* jump to the compiler, return address
3700 in itmp1 is used as method pointer */
3703 s[2] = (u8) m; /* literals to be adressed */
3704 s[3] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3706 (void) docacheflush((void*) s, (char*) p - (char*) s);
3709 count_cstub_len += COMPSTUBSIZE * 8;
3716 /* function removecompilerstub *************************************************
3718 deletes a compilerstub from memory (simply by freeing it)
3720 *******************************************************************************/
3722 void removecompilerstub (u1 *stub)
3724 CFREE(stub, COMPSTUBSIZE * 8);
3727 /* function: createnativestub **************************************************
3729 creates a stub routine which calls a native method
3731 *******************************************************************************/
3733 #define NATIVESTUBSIZE 20
3734 #define NATIVESTUBOFFSET 4
3736 u1 *createnativestub (functionptr f, methodinfo *m)
3738 u8 *s = CNEW(u8, NATIVESTUBSIZE); /* memory to hold the stub */
3739 u8 *cs = s + NATIVESTUBOFFSET;
3740 s4 *p = (s4*) (cs); /* code generation pointer */
3742 *(cs-1) = (u8) f; /* address of native method */
3743 *(cs-2) = (u8) (&exceptionptr); /* address of exceptionptr */
3744 *(cs-3) = (u8) (asm_handle_nat_exception);/* addr of asm exception handler*/
3745 *(cs-4) = (u8) (&env); /* addr of jni_environement */
3749 M_MOV (argintregs[4], argintregs[5]);
3750 M_DMFC1 (REG_ITMP1, argfltregs[4]);
3752 M_MOV (argintregs[3], argintregs[4]);
3753 M_DMTC1 (REG_ITMP1, argfltregs[5]);
3755 M_MOV (argintregs[2], argintregs[3]);
3756 M_DMFC1 (REG_ITMP1, argfltregs[3]);
3758 M_MOV (argintregs[1], argintregs[2]);
3759 M_DMTC1 (REG_ITMP1, argfltregs[4]);
3761 M_MOV (argintregs[0], argintregs[1]);
3762 M_DMFC1 (REG_ITMP1, argfltregs[2]);
3764 M_ALD (argintregs[0], REG_PV, -4*8); /* load adress of jni_environement */
3765 M_DMTC1 (REG_ITMP1, argfltregs[3]);
3767 M_DMFC1 (REG_ITMP1, argfltregs[1]);
3768 M_DMFC1 (REG_ITMP2, argfltregs[0]);
3770 M_DMTC1 (REG_ITMP1, argfltregs[2]);
3771 M_DMTC1 (REG_ITMP2, argfltregs[1]);
3773 M_ALD (REG_ITMP3, REG_PV, -1*8); /* load adress of native method */
3774 M_LDA (REG_SP, REG_SP, -8); /* build up stackframe */
3776 M_LST (REG_RA, REG_SP, 0); /* store return address */
3777 M_JSR (REG_RA, REG_ITMP3); /* call native method */
3779 M_NOP; /* delay slot */
3780 M_ALD (REG_ITMP3, REG_PV, -2*8); /* get address of exceptionptr */
3782 M_LLD (REG_RA, REG_SP, 0); /* load return address */
3783 M_ALD (REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
3785 M_BNEZ (REG_ITMP1, 2); /* if no exception then return */
3786 M_LDA (REG_SP, REG_SP, 8); /* remove stackframe, delay slot */
3788 M_RET (REG_RA); /* return to caller */
3789 M_NOP; /* delay slot */
3791 M_AST (REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
3792 M_ALD (REG_ITMP3, REG_PV,-3*8); /* load asm exception handler address */
3794 M_JMP (REG_ITMP3); /* jump to asm exception handler */
3795 M_LDA (REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
3798 (void) docacheflush((void*) cs, (char*) p - (char*) cs);
3801 count_nstub_len += NATIVESTUBSIZE * 8;
3804 return (u1*) (s + NATIVESTUBOFFSET);
3807 /* function: removenativestub **************************************************
3809 removes a previously created native-stub from memory
3811 *******************************************************************************/
3813 void removenativestub (u1 *stub)
3815 CFREE((u8*) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 8);
3819 /* function: createcalljava ****************************************************
3821 creates the asm_calljavamethod (MIPS assembler does not like data in the
3822 text segment). Documentation can be found in asmpart.c.
3824 *******************************************************************************/
3833 #define CALL_JAVA_MEM_SIZE 61
3834 #define CALL_JAVA2_MEM_SIZE 61
3835 #define CALL_JAVA_ENTRY 20
3836 #define CALL_JAVA_XHANDLER 55
3837 #define CALL_JAVA2_XHANDLER 108
3839 static s4 calljavamem[CALL_JAVA_MEM_SIZE];
3840 static s4 calljava2mem[CALL_JAVA2_MEM_SIZE];
3842 void asm_calljavafunction_asm();
3843 void asm_calljavafunction2_asm();
3845 void createcalljava ()
3849 *((void**)(calljavamem + 4)) = NULL;
3850 *((void**)(calljavamem + 6)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3851 *((void**)(calljavamem + 8)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3852 *((void**)(calljavamem +10)) = (void*) (calljavamem + CALL_JAVA_ENTRY);
3853 *((void**)(calljava2mem + 4)) = NULL;
3854 *((void**)(calljava2mem + 6)) = (void*) (calljava2mem + CALL_JAVA2_XHANDLER);
3855 *((void**)(calljava2mem + 8)) = (void*) (calljava2mem + CALL_JAVA2_XHANDLER);
3856 *((void**)(calljava2mem +10)) = (void*) (calljava2mem + CALL_JAVA_ENTRY);
3858 calljavamem[12] = 1; /* extable size */
3859 calljavamem[13] = 0; /* fltsave */
3860 calljavamem[14] = 0; /* intsave */
3861 calljavamem[15] = 0; /* isleaf */
3862 calljavamem[16] = 0; /* IsSync */
3863 calljavamem[17] = 80; /* frame size */
3864 calljavamem[18] = 0; /* method pointer (NULL) */
3865 calljavamem[19] = 0; /* method pointer (NULL) */
3867 calljava2mem[12] = 1; /* extable size */
3868 calljava2mem[13] = 0; /* fltsave */
3869 calljava2mem[14] = 1; /* intsave */
3870 calljava2mem[15] = 0; /* isleaf */
3871 calljava2mem[16] = 0; /* IsSync */
3872 calljava2mem[17] = 88; /* frame size */
3873 calljava2mem[18] = 0; /* method pointer (NULL) */
3874 calljava2mem[19] = 0; /* method pointer (NULL) */
3876 p = calljavamem + CALL_JAVA_ENTRY; /* code generation pointer */
3877 memcpy(p, asm_calljavafunction_asm,
3878 (CALL_JAVA_MEM_SIZE - CALL_JAVA_ENTRY) * (int) sizeof(s4));
3880 p = calljava2mem + CALL_JAVA_ENTRY; /* code generation pointer */
3881 memcpy(p, asm_calljavafunction2_asm,
3882 (CALL_JAVA2_MEM_SIZE - CALL_JAVA_ENTRY) * (int) sizeof(s4));
3884 (void) docacheflush((void*)(calljavamem + CALL_JAVA_ENTRY),
3885 (CALL_JAVA_MEM_SIZE - CALL_JAVA_ENTRY) * (int) sizeof(s4));
3886 (void) docacheflush((void*)(calljava2mem + CALL_JAVA_ENTRY),
3887 (CALL_JAVA2_MEM_SIZE - CALL_JAVA_ENTRY) * (int) sizeof(s4));
3891 typedef java_objectheader* (*asm_fptr)(methodinfo*, void*, void*, void*, void*);
3892 typedef java_objectheader* (*asm_fptr2)(methodinfo*, u4, u4, void*);
3893 typedef jdouble (*asm_fptr2double)(methodinfo*, u4, u4, void*);
3894 typedef jlong (*asm_fptr2long)(methodinfo*, u4, u4, void*);
3897 java_objectheader *asm_calljavafunction (methodinfo *m, void *arg1, void *arg2,
3898 void *arg3, void *arg4)
3900 return ((asm_fptr)(calljavamem + 20))(m, arg1, arg2, arg3, arg4);
3903 java_objectheader *asm_calljavafunction2(methodinfo *m, u4 count, u4 size , void *callblock)
3905 return ((asm_fptr2)(calljava2mem + 20))(m, count, size, callblock);
3908 jdouble asm_calljavafunction2double(methodinfo *m, u4 count, u4 size , void *callblock)
3910 return ((asm_fptr2double)(calljava2mem + 20))(m, count, size, callblock);
3913 jlong asm_calljavafunction2long(methodinfo *m, u4 count, u4 size , void *callblock)
3915 return ((asm_fptr2long)(calljava2mem + 20))(m, count, size, callblock);
3918 void docacheflush(u1 *p, long bytelen)
3920 u1 *e = p + bytelen;
3921 long psize = sysconf(_SC_PAGESIZE);
3922 p -= (long) p & (psize-1);
3923 e += psize - ((((long) e - 1) & (psize-1)) + 1);
3925 mprotect(p, bytelen, PROT_READ|PROT_WRITE|PROT_EXEC);
3930 * These are local overrides for various environment variables in Emacs.
3931 * Please do not remove this and leave it at the end of the file, where
3932 * Emacs will automagically detect them.
3933 * ---------------------------------------------------------------------
3936 * indent-tabs-mode: t