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 1118 2004-06-02 11:10:17Z twisti $
56 /* include independent code generation stuff */
57 #include "codegen.inc"
61 /* *****************************************************************************
63 Datatypes and Register Allocations:
64 -----------------------------------
66 On 64-bit-machines (like the MIPS) all operands are stored in the
67 registers in a 64-bit form, even when the correspondig JavaVM operands
68 only need 32 bits. This is done by a canonical representation:
70 32-bit integers are allways stored as sign-extended 64-bit values (this
71 approach is directly supported by the MIPS architecture and is very easy
74 32-bit-floats are stored in a 64-bit double precision register by simply
75 expanding the exponent and mantissa with zeroes. (also supported by the
81 The calling conventions and the layout of the stack is explained in detail
82 in the documention file: calling.doc
84 *******************************************************************************/
87 /* register descripton - array ************************************************/
89 /* #define REG_RES 0 reserved register for OS or code generator */
90 /* #define REG_RET 1 return value register */
91 /* #define REG_EXC 2 exception value register (only old jit) */
92 /* #define REG_SAV 3 (callee) saved register */
93 /* #define REG_TMP 4 scratch temporary register (caller saved) */
94 /* #define REG_ARG 5 argument register (caller saved) */
96 /* #define REG_END -1 last entry in tables */
99 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
100 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
101 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
102 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
105 /* for use of reserved registers, see comment above */
107 int nregdescfloat[] = {
108 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
109 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
110 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
111 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
114 /* for use of reserved registers, see comment above */
117 /* parameter allocation mode */
119 int nreg_parammode = PARAMMODE_NUMBERED;
121 /* parameter-registers will be allocated by assigning the
122 1. parameter: int/float-reg a0
123 2. parameter: int/float-reg a1
124 3. parameter: int/float-reg a2 ....
128 /* stackframe-infos ***********************************************************/
130 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
132 /* -> see file 'calling.doc' */
135 /* additional functions and macros to generate code ***************************/
137 /* #define BlockPtrOfPC(pc) block+block_index[pc] */
138 #define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
142 #define COUNT_SPILLS count_spills++
148 /* gen_nullptr_check(objreg) */
150 #define gen_nullptr_check(objreg) \
152 M_BEQZ((objreg), 0); \
153 codegen_addxnullrefs(mcodeptr); \
158 /* MCODECHECK(icnt) */
160 #define MCODECHECK(icnt) \
161 if ((mcodeptr + (icnt)) > mcodeend) mcodeptr = codegen_increase((u1 *) mcodeptr)
164 generates an integer-move from register a to b.
165 if a and b are the same int-register, no code will be generated.
168 #define M_INTMOVE(a,b) if (a != b) { M_MOV(a, b); }
172 generates a floating-point-move from register a to b.
173 if a and b are the same float-register, no code will be generated
176 #define M_FLTMOVE(a,b) if (a != b) { M_DMOV(a, b); }
178 #define M_TFLTMOVE(t,a,b) \
182 else {M_FMOV(a,b);} \
185 #define M_TFLD(t,a,b,disp) \
191 #define M_TFST(t,a,b,disp) \
197 #define M_CCFLTMOVE(t1,t2,a,b) \
199 {M_TFLTMOVE(t1,a,b);} \
201 if ((t1)==TYPE_DBL) \
206 #define M_CCFLD(t1,t2,a,b,disp) \
210 M_DLD(REG_FTMP1,b,disp); \
211 if ((t1)==TYPE_DBL) \
212 {M_CVTDF(REG_FTMP1,a);} \
214 {M_CVTFD(REG_FTMP1,a);} \
217 #define M_CCFST(t1,t2,a,b,disp) \
221 if ((t1)==TYPE_DBL) \
222 {M_CVTDF(a,REG_FTMP1);} \
224 {M_CVTFD(a,REG_FTMP1);} \
225 M_DST(REG_FTMP1,b,disp); \
230 this function generates code to fetch data from a pseudo-register
231 into a real register.
232 If the pseudo-register has actually been assigned to a real
233 register, no code will be emitted, since following operations
234 can use this register directly.
236 v: pseudoregister to be fetched from
237 tempregnum: temporary register to be used if v is actually spilled to ram
239 return: the register number, where the operand can be found after
240 fetching (this wil be either tempregnum or the register
241 number allready given to v)
244 #define var_to_reg_int(regnr,v,tempnr) { \
245 if ((v)->flags & INMEMORY) \
246 {COUNT_SPILLS;M_LLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
247 else regnr=(v)->regoff; \
251 #define var_to_reg_flt(regnr,v,tempnr) { \
252 if ((v)->flags & INMEMORY) \
253 {COUNT_SPILLS;M_DLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
254 else regnr=(v)->regoff; \
259 This function determines a register, to which the result of an operation
260 should go, when it is ultimatively intended to store the result in
262 If v is assigned to an actual register, this register will be returned.
263 Otherwise (when v is spilled) this function returns tempregnum.
264 If not already done, regoff and flags are set in the stack location.
267 static int reg_of_var(stackptr v, int tempregnum)
271 switch (v->varkind) {
273 if (!(v->flags & INMEMORY))
277 var = &(interfaces[v->varnum][v->type]);
278 v->regoff = var->regoff;
279 if (!(var->flags & INMEMORY))
283 var = &(locals[v->varnum][v->type]);
284 v->regoff = var->regoff;
285 if (!(var->flags & INMEMORY))
289 v->regoff = v->varnum;
290 if (IS_FLT_DBL_TYPE(v->type)) {
291 if (v->varnum < fltreg_argnum) {
292 v->regoff = argfltregs[v->varnum];
293 return(argfltregs[v->varnum]);
297 if (v->varnum < intreg_argnum) {
298 v->regoff = argintregs[v->varnum];
299 return(argintregs[v->varnum]);
301 v->regoff -= intreg_argnum;
304 v->flags |= INMEMORY;
309 /* store_reg_to_var_xxx:
310 This function generates the code to store the result of an operation
311 back into a spilled pseudo-variable.
312 If the pseudo-variable has not been spilled in the first place, this
313 function will generate nothing.
315 v ............ Pseudovariable
316 tempregnum ... Number of the temporary registers as returned by
320 #define store_reg_to_var_int(sptr, tempregnum) { \
321 if ((sptr)->flags & INMEMORY) { \
323 M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
327 #define store_reg_to_var_flt(sptr, tempregnum) { \
328 if ((sptr)->flags & INMEMORY) { \
330 M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
335 /* NullPointerException handlers and exception handling initialisation */
337 /* NullPointerException signal handler for hardware null pointer check */
339 void catch_NullPointerException(int sig, int code, struct sigcontext *sigctx)
344 java_objectheader *xptr;
346 /* Reset signal handler - necessary for SysV, does no harm for BSD */
348 instr = *((int*)(sigctx->sc_pc));
349 faultaddr = sigctx->sc_regs[(instr >> 21) & 0x1f];
351 if (faultaddr == 0) {
353 sigaddset(&nsig, sig);
354 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
356 xptr = new_exception(string_java_lang_NullPointerException);
359 sigctx->sc_regs[REG_ITMP1_XPTR] = (u8) xptr;
360 sigctx->sc_regs[REG_ITMP2_XPC] = sigctx->sc_pc;
361 sigctx->sc_pc = (u8) asm_handle_exception;
364 faultaddr += (long) ((instr << 16) >> 16);
365 fprintf(stderr, "faulting address: 0x%lx at 0x%lx\n", (long) faultaddr, (long) sigctx->sc_pc);
366 panic("Stack overflow");
373 void init_exceptions(void)
376 sigset_t unblockmask;
378 /* The Boehm GC initialization blocks the SIGSEGV signal. So we do a
379 dummy allocation here to ensure that the GC is initialized.
381 heap_allocate(1, 0, NULL);
383 /* install signal handlers we need to convert to exceptions */
385 sigemptyset(&unblockmask);
387 sa.sa_sigaction = catch_NullPointerException;
388 sigemptyset(&sa.sa_mask);
392 sigaction(SIGSEGV, &sa, NULL);
393 sigaddset(&unblockmask, SIGSEGV);
397 sigaction(SIGBUS, &sa, NULL);
398 sigaddset(&unblockmask, SIGBUS);
402 sigprocmask(SIG_UNBLOCK, &unblockmask, NULL);
404 /* Turn off flush-to-zero */
407 n.fc_word = get_fpc_csr();
408 n.fc_struct.flush = 0;
409 set_fpc_csr(n.fc_word);
414 /* function gen_mcode **********************************************************
416 generates machine code
418 *******************************************************************************/
422 int len, s1, s2, s3, d;
434 savedregs_num = (isleafmethod) ? 0 : 1; /* space to save the RA */
436 /* space to save used callee saved registers */
438 savedregs_num += (savintregcnt - maxsavintreguse);
439 savedregs_num += (savfltregcnt - maxsavfltreguse);
441 parentargs_base = maxmemuse + savedregs_num;
443 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
445 if (checksync && (method->flags & ACC_SYNCHRONIZED))
450 /* adjust frame size for 16 byte alignment */
452 if (parentargs_base & 1)
455 /* create method header */
458 (void) dseg_addaddress(method); /* Filler */
460 (void) dseg_addaddress(method); /* MethodPointer */
461 (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
463 #if defined(USE_THREADS)
465 /* IsSync contains the offset relative to the stack pointer for the
466 argument of monitor_exit used in the exception handler. Since the
467 offset could be zero and give a wrong meaning of the flag it is
471 if (checksync && (method->flags & ACC_SYNCHRONIZED))
472 (void) dseg_adds4((maxmemuse + 1) * 8); /* IsSync */
477 (void) dseg_adds4(0); /* IsSync */
479 (void) dseg_adds4(isleafmethod); /* IsLeaf */
480 (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
481 (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
482 (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
484 /* create exception table */
486 for (ex = extable; ex != NULL; ex = ex->down) {
487 dseg_addtarget(ex->start);
488 dseg_addtarget(ex->end);
489 dseg_addtarget(ex->handler);
490 (void) dseg_addaddress(ex->catchtype);
493 /* initialize mcode variables */
495 mcodeptr = (s4*) mcodebase;
496 mcodeend = (s4*) (mcodebase + mcodesize);
497 MCODECHECK(128 + mparamcount);
499 /* create stack frame (if necessary) */
502 {M_LDA(REG_SP, REG_SP, -parentargs_base * 8);}
504 /* save return address and used callee saved registers */
508 {p--; M_LST(REG_RA, REG_SP, 8*p);}
509 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
510 {p--; M_LST(savintregs[r], REG_SP, 8 * p);}
511 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
512 {p--; M_DST(savfltregs[r], REG_SP, 8 * p);}
514 /* save monitorenter argument */
516 #if defined(USE_THREADS)
517 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
518 if (method->flags & ACC_STATIC) {
519 p = dseg_addaddress(class);
520 M_ALD(REG_ITMP1, REG_PV, p);
521 M_AST(REG_ITMP1, REG_SP, maxmemuse * 8);
524 M_AST(argintregs[0], REG_SP, maxmemuse * 8);
529 /* copy argument registers to stack and call trace function with pointer
530 to arguments on stack. ToDo: save floating point registers !!!!!!!!!
534 M_LDA(REG_SP, REG_SP, -(18 * 8));
535 M_LST(REG_RA, REG_SP, 1 * 8);
537 /* save integer argument registers */
538 for (p = 0; p < mparamcount && p < INT_ARG_CNT; p++) {
539 M_LST(argintregs[p], REG_SP, (2 + p) * 8);
542 /* save and copy float arguments into integer registers */
543 for (p = 0; p < mparamcount && p < FLT_ARG_CNT; p++) {
546 if (IS_FLT_DBL_TYPE(t)) {
547 if (IS_2_WORD_TYPE(t)) {
548 M_DST(argfltregs[p], REG_SP, (10 + p) * 8);
549 M_LLD(argintregs[p], REG_SP, (10 + p) * 8);
552 M_FST(argfltregs[p], REG_SP, (10 + p) * 8);
553 M_ILD(argintregs[p], REG_SP, (10 + p) * 8);
557 M_DST(argfltregs[p], REG_SP, (10 + p) * 8);
561 p = dseg_addaddress(method);
562 M_ALD(REG_ITMP1, REG_PV, p);
563 M_LST(REG_ITMP1, REG_SP, 0);
564 p = dseg_addaddress((void *) builtin_trace_args);
565 M_ALD(REG_ITMP3, REG_PV, p);
566 M_JSR(REG_RA, REG_ITMP3);
569 M_LLD(REG_RA, REG_SP, 1 * 8);
571 for (p = 0; p < mparamcount && p < INT_ARG_CNT; p++) {
572 M_LLD(argintregs[p], REG_SP, (2 + p) * 8);
575 for (p = 0; p < mparamcount && p < FLT_ARG_CNT; p++) {
578 if (IS_FLT_DBL_TYPE(t)) {
579 if (IS_2_WORD_TYPE(t)) {
580 M_DLD(argfltregs[p], REG_SP, (10 + p) * 8);
582 M_FLD(argfltregs[p], REG_SP, (10 + p) * 8);
585 M_DLD(argfltregs[p], REG_SP, (10 + p) * 8);
589 M_LDA(REG_SP, REG_SP, 18 * 8);
592 /* take arguments out of register or stack frame */
594 for (p = 0, l = 0; p < mparamcount; p++) {
596 var = &(locals[l][t]);
598 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
603 if (IS_INT_LNG_TYPE(t)) { /* integer args */
604 if (p < INT_ARG_CNT) { /* register arguments */
605 if (!(var->flags & INMEMORY)) /* reg arg -> register */
606 {M_INTMOVE (argintregs[p], r);}
607 else /* reg arg -> spilled */
608 M_LST (argintregs[p], REG_SP, 8 * r);
610 else { /* stack arguments */
611 pa = p - INT_ARG_CNT;
612 if (!(var->flags & INMEMORY)) /* stack arg -> register */
613 M_LLD (r, REG_SP, 8 * (parentargs_base + pa));
614 else { /* stack arg -> spilled */
615 M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
616 M_LST (REG_ITMP1, REG_SP, 8 * r);
620 else { /* floating args */
621 if (p < FLT_ARG_CNT) { /* register arguments */
622 if (!(var->flags & INMEMORY)) /* reg arg -> register */
623 {M_TFLTMOVE (var->type, argfltregs[p], r);}
624 else /* reg arg -> spilled */
625 M_DST (argfltregs[p], REG_SP, 8 * r);
627 else { /* stack arguments */
628 pa = p - FLT_ARG_CNT;
629 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
630 M_DLD (r, REG_SP, 8 * (parentargs_base + pa) );
631 } else { /* stack-arg -> spilled */
632 M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
633 M_DST (REG_FTMP1, REG_SP, 8 * r);
639 /* call trace function */
642 if (runverbose && !isleafmethod) {
643 M_LDA (REG_SP, REG_SP, -8);
644 p = dseg_addaddress (method);
645 M_ALD(REG_ITMP1, REG_PV, p);
646 M_AST(REG_ITMP1, REG_SP, 0);
647 p = dseg_addaddress ((void*) (builtin_trace_args));
648 M_ALD(REG_ITMP3, REG_PV, p);
649 M_JSR(REG_RA, REG_ITMP3);
651 M_LDA(REG_SP, REG_SP, 8);
655 /* call monitorenter function */
657 #if defined(USE_THREADS)
658 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
660 p = dseg_addaddress((void *) (builtin_monitorenter));
661 M_ALD(REG_ITMP3, REG_PV, p);
662 M_JSR(REG_RA, REG_ITMP3);
663 M_ALD(argintregs[0], REG_SP, maxmemuse * 8);
664 disp = -(s4)((u1 *) mcodeptr - mcodebase);
665 M_LDA(REG_PV, REG_RA, disp);
670 /* end of header generation */
672 /* walk through all basic blocks */
673 for (bptr = block; bptr != NULL; bptr = bptr->next) {
675 bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
677 if (bptr->flags >= BBREACHED) {
679 /* branch resolving */
683 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
684 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
685 brefs->branchpos, bptr->mpc);
689 /* copy interface registers to their destination */
694 while (src != NULL) {
696 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
697 d = reg_of_var(src, REG_ITMP1);
698 M_INTMOVE(REG_ITMP1, d);
699 store_reg_to_var_int(src, d);
702 d = reg_of_var(src, REG_IFTMP);
703 if ((src->varkind != STACKVAR)) {
705 if (IS_FLT_DBL_TYPE(s2)) {
706 if (!(interfaces[len][s2].flags & INMEMORY)) {
707 s1 = interfaces[len][s2].regoff;
711 M_DLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
713 store_reg_to_var_flt(src, d);
716 if (!(interfaces[len][s2].flags & INMEMORY)) {
717 s1 = interfaces[len][s2].regoff;
721 M_LLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
723 store_reg_to_var_int(src, d);
730 /* walk through all instructions */
734 for (iptr = bptr->iinstr;
736 src = iptr->dst, len--, iptr++) {
738 MCODECHECK(64); /* an instruction usually needs < 64 words */
741 case ICMD_NOP: /* ... ==> ... */
744 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
746 var_to_reg_int(s1, src, REG_ITMP1);
748 codegen_addxnullrefs(mcodeptr);
752 /* constant operations ************************************************/
754 #define ICONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_IADD_IMM(REG_ZERO,c,r);} \
755 else if(((c)>=0)&&((c)<=0xffff)){M_OR_IMM(REG_ZERO,c,r);} \
756 else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
758 #define LCONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LADD_IMM(REG_ZERO,c,r);} \
759 else if(((c)>=0)&&((c)<=0xffff)){M_OR_IMM(REG_ZERO,c,r);} \
760 else{a=dseg_adds8(c);M_LLD(r,REG_PV,a);}
762 case ICMD_ICONST: /* ... ==> ..., constant */
763 /* op1 = 0, val.i = constant */
765 d = reg_of_var(iptr->dst, REG_ITMP1);
766 ICONST(d, iptr->val.i);
767 store_reg_to_var_int(iptr->dst, d);
770 case ICMD_LCONST: /* ... ==> ..., constant */
771 /* op1 = 0, val.l = constant */
773 d = reg_of_var(iptr->dst, REG_ITMP1);
774 LCONST(d, iptr->val.l);
775 store_reg_to_var_int(iptr->dst, d);
778 case ICMD_FCONST: /* ... ==> ..., constant */
779 /* op1 = 0, val.f = constant */
781 d = reg_of_var (iptr->dst, REG_FTMP1);
782 a = dseg_addfloat (iptr->val.f);
784 store_reg_to_var_flt (iptr->dst, d);
787 case ICMD_DCONST: /* ... ==> ..., constant */
788 /* op1 = 0, val.d = constant */
790 d = reg_of_var (iptr->dst, REG_FTMP1);
791 a = dseg_adddouble (iptr->val.d);
793 store_reg_to_var_flt (iptr->dst, d);
796 case ICMD_ACONST: /* ... ==> ..., constant */
797 /* op1 = 0, val.a = constant */
799 d = reg_of_var(iptr->dst, REG_ITMP1);
801 a = dseg_addaddress (iptr->val.a);
805 M_INTMOVE(REG_ZERO, d);
807 store_reg_to_var_int(iptr->dst, d);
811 /* load/store operations **********************************************/
813 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
814 case ICMD_LLOAD: /* op1 = local variable */
817 d = reg_of_var(iptr->dst, REG_ITMP1);
818 if ((iptr->dst->varkind == LOCALVAR) &&
819 (iptr->dst->varnum == iptr->op1))
821 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
822 if (var->flags & INMEMORY)
823 M_LLD(d, REG_SP, 8 * var->regoff);
825 {M_INTMOVE(var->regoff,d);}
826 store_reg_to_var_int(iptr->dst, d);
829 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
830 case ICMD_DLOAD: /* op1 = local variable */
832 d = reg_of_var(iptr->dst, REG_FTMP1);
833 if ((iptr->dst->varkind == LOCALVAR) &&
834 (iptr->dst->varnum == iptr->op1))
836 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
838 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
839 if (var->flags & INMEMORY)
840 {M_CCFLD(var->type,t2,d, REG_SP, 8 * var->regoff);}
842 {M_CCFLTMOVE(var->type,t2,var->regoff,d);}
844 store_reg_to_var_flt(iptr->dst, d);
848 case ICMD_ISTORE: /* ..., value ==> ... */
849 case ICMD_LSTORE: /* op1 = local variable */
852 if ((src->varkind == LOCALVAR) &&
853 (src->varnum == iptr->op1))
855 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
856 if (var->flags & INMEMORY) {
857 var_to_reg_int(s1, src, REG_ITMP1);
858 M_LST(s1, REG_SP, 8 * var->regoff);
861 var_to_reg_int(s1, src, var->regoff);
862 M_INTMOVE(s1, var->regoff);
866 case ICMD_FSTORE: /* ..., value ==> ... */
867 case ICMD_DSTORE: /* op1 = local variable */
869 if ((src->varkind == LOCALVAR) &&
870 (src->varnum == iptr->op1))
872 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
874 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
875 if (var->flags & INMEMORY) {
876 var_to_reg_flt(s1, src, REG_FTMP1);
877 M_CCFST(t1,var->type,s1, REG_SP, 8 * var->regoff);
880 var_to_reg_flt(s1, src, var->regoff);
881 M_CCFLTMOVE(t1,var->type,s1, var->regoff);
887 /* pop/dup/swap operations ********************************************/
889 /* attention: double and longs are only one entry in CACAO ICMDs */
891 case ICMD_POP: /* ..., value ==> ... */
892 case ICMD_POP2: /* ..., value, value ==> ... */
895 #define M_COPY(from,to) \
896 d = reg_of_var(to, REG_IFTMP); \
897 if ((from->regoff != to->regoff) || \
898 ((from->flags ^ to->flags) & INMEMORY)) { \
899 if (IS_FLT_DBL_TYPE(from->type)) { \
900 var_to_reg_flt(s1, from, d); \
901 M_TFLTMOVE(from->type,s1,d); \
902 store_reg_to_var_flt(to, d); \
905 var_to_reg_int(s1, from, d); \
907 store_reg_to_var_int(to, d); \
911 case ICMD_DUP: /* ..., a ==> ..., a, a */
912 M_COPY(src, iptr->dst);
915 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
917 M_COPY(src, iptr->dst->prev->prev);
919 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
921 M_COPY(src, iptr->dst);
922 M_COPY(src->prev, iptr->dst->prev);
925 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
927 M_COPY(src->prev, iptr->dst->prev->prev->prev);
929 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
931 M_COPY(src, iptr->dst);
932 M_COPY(src->prev, iptr->dst->prev);
933 M_COPY(src->prev->prev, iptr->dst->prev->prev);
934 M_COPY(src, iptr->dst->prev->prev->prev);
937 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
939 M_COPY(src, iptr->dst);
940 M_COPY(src->prev, iptr->dst->prev);
941 M_COPY(src->prev->prev, iptr->dst->prev->prev);
942 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
943 M_COPY(src, iptr->dst->prev->prev->prev->prev);
944 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
947 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
949 M_COPY(src, iptr->dst->prev);
950 M_COPY(src->prev, iptr->dst);
954 /* integer operations *************************************************/
956 case ICMD_INEG: /* ..., value ==> ..., - value */
958 var_to_reg_int(s1, src, REG_ITMP1);
959 d = reg_of_var(iptr->dst, REG_ITMP3);
960 M_ISUB(REG_ZERO, s1, d);
961 store_reg_to_var_int(iptr->dst, d);
964 case ICMD_LNEG: /* ..., value ==> ..., - value */
966 var_to_reg_int(s1, src, REG_ITMP1);
967 d = reg_of_var(iptr->dst, REG_ITMP3);
968 M_LSUB(REG_ZERO, s1, d);
969 store_reg_to_var_int(iptr->dst, d);
972 case ICMD_I2L: /* ..., value ==> ..., value */
974 var_to_reg_int(s1, src, REG_ITMP1);
975 d = reg_of_var(iptr->dst, REG_ITMP3);
977 store_reg_to_var_int(iptr->dst, d);
980 case ICMD_L2I: /* ..., value ==> ..., value */
982 var_to_reg_int(s1, src, REG_ITMP1);
983 d = reg_of_var(iptr->dst, REG_ITMP3);
984 M_ISLL_IMM(s1, 0, d );
985 store_reg_to_var_int(iptr->dst, d);
988 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
990 var_to_reg_int(s1, src, REG_ITMP1);
991 d = reg_of_var(iptr->dst, REG_ITMP3);
992 M_LSLL_IMM(s1, 56, d);
993 M_LSRA_IMM( d, 56, d);
994 store_reg_to_var_int(iptr->dst, d);
997 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
999 var_to_reg_int(s1, src, REG_ITMP1);
1000 d = reg_of_var(iptr->dst, REG_ITMP3);
1002 store_reg_to_var_int(iptr->dst, d);
1005 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1007 var_to_reg_int(s1, src, REG_ITMP1);
1008 d = reg_of_var(iptr->dst, REG_ITMP3);
1009 M_LSLL_IMM(s1, 48, d);
1010 M_LSRA_IMM( d, 48, d);
1011 store_reg_to_var_int(iptr->dst, d);
1015 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1017 var_to_reg_int(s1, src->prev, REG_ITMP1);
1018 var_to_reg_int(s2, src, REG_ITMP2);
1019 d = reg_of_var(iptr->dst, REG_ITMP3);
1021 store_reg_to_var_int(iptr->dst, d);
1024 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1025 /* val.i = constant */
1027 var_to_reg_int(s1, src, REG_ITMP1);
1028 d = reg_of_var(iptr->dst, REG_ITMP3);
1029 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1030 M_IADD_IMM(s1, iptr->val.i, d);
1033 ICONST(REG_ITMP2, iptr->val.i);
1034 M_IADD(s1, REG_ITMP2, d);
1036 store_reg_to_var_int(iptr->dst, d);
1039 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1041 var_to_reg_int(s1, src->prev, REG_ITMP1);
1042 var_to_reg_int(s2, src, REG_ITMP2);
1043 d = reg_of_var(iptr->dst, REG_ITMP3);
1045 store_reg_to_var_int(iptr->dst, d);
1048 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1049 /* val.l = constant */
1051 var_to_reg_int(s1, src, REG_ITMP1);
1052 d = reg_of_var(iptr->dst, REG_ITMP3);
1053 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
1054 M_LADD_IMM(s1, iptr->val.l, d);
1057 LCONST(REG_ITMP2, iptr->val.l);
1058 M_LADD(s1, REG_ITMP2, d);
1060 store_reg_to_var_int(iptr->dst, d);
1063 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1065 var_to_reg_int(s1, src->prev, REG_ITMP1);
1066 var_to_reg_int(s2, src, REG_ITMP2);
1067 d = reg_of_var(iptr->dst, REG_ITMP3);
1069 store_reg_to_var_int(iptr->dst, d);
1072 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1073 /* val.i = constant */
1075 var_to_reg_int(s1, src, REG_ITMP1);
1076 d = reg_of_var(iptr->dst, REG_ITMP3);
1077 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
1078 M_IADD_IMM(s1, -iptr->val.i, d);
1081 ICONST(REG_ITMP2, iptr->val.i);
1082 M_ISUB(s1, REG_ITMP2, d);
1084 store_reg_to_var_int(iptr->dst, d);
1087 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1089 var_to_reg_int(s1, src->prev, REG_ITMP1);
1090 var_to_reg_int(s2, src, REG_ITMP2);
1091 d = reg_of_var(iptr->dst, REG_ITMP3);
1093 store_reg_to_var_int(iptr->dst, d);
1096 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1097 /* val.l = constant */
1099 var_to_reg_int(s1, src, REG_ITMP1);
1100 d = reg_of_var(iptr->dst, REG_ITMP3);
1101 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
1102 M_LADD_IMM(s1, -iptr->val.l, d);
1105 LCONST(REG_ITMP2, iptr->val.l);
1106 M_LSUB(s1, REG_ITMP2, d);
1108 store_reg_to_var_int(iptr->dst, d);
1111 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1113 var_to_reg_int(s1, src->prev, REG_ITMP1);
1114 var_to_reg_int(s2, src, REG_ITMP2);
1115 d = reg_of_var(iptr->dst, REG_ITMP3);
1120 store_reg_to_var_int(iptr->dst, d);
1123 case ICMD_IMULCONST: /* ..., 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 ICONST(REG_ITMP2, iptr->val.i);
1129 M_IMUL(s1, REG_ITMP2);
1133 store_reg_to_var_int(iptr->dst, d);
1136 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1138 var_to_reg_int(s1, src->prev, REG_ITMP1);
1139 var_to_reg_int(s2, src, REG_ITMP2);
1140 d = reg_of_var(iptr->dst, REG_ITMP3);
1145 store_reg_to_var_int(iptr->dst, d);
1148 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1149 /* val.l = constant */
1151 var_to_reg_int(s1, src, REG_ITMP1);
1152 d = reg_of_var(iptr->dst, REG_ITMP3);
1153 LCONST(REG_ITMP2, iptr->val.l);
1154 M_LMUL(s1, REG_ITMP2);
1158 store_reg_to_var_int(iptr->dst, d);
1161 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1163 var_to_reg_int(s1, src->prev, REG_ITMP1);
1164 var_to_reg_int(s2, src, REG_ITMP2);
1165 d = reg_of_var(iptr->dst, REG_ITMP3);
1170 store_reg_to_var_int(iptr->dst, d);
1173 case ICMD_IDIVCONST: /* ..., value ==> ..., value / constant */
1174 /* val.i = constant */
1176 var_to_reg_int(s1, src, REG_ITMP1);
1177 d = reg_of_var(iptr->dst, REG_ITMP3);
1178 ICONST(REG_ITMP2, iptr->val.i);
1179 M_IDIV(s1, REG_ITMP2);
1183 store_reg_to_var_int(iptr->dst, d);
1186 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1188 var_to_reg_int(s1, src->prev, REG_ITMP1);
1189 var_to_reg_int(s2, src, REG_ITMP2);
1190 d = reg_of_var(iptr->dst, REG_ITMP3);
1195 store_reg_to_var_int(iptr->dst, d);
1198 case ICMD_LDIVCONST: /* ..., value ==> ..., value / constant */
1199 /* val.l = constant */
1201 var_to_reg_int(s1, src, REG_ITMP1);
1202 d = reg_of_var(iptr->dst, REG_ITMP3);
1203 LCONST(REG_ITMP2, iptr->val.l);
1204 M_LDIV(s1, REG_ITMP2);
1208 store_reg_to_var_int(iptr->dst, d);
1211 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1213 var_to_reg_int(s1, src->prev, REG_ITMP1);
1214 var_to_reg_int(s2, src, REG_ITMP2);
1215 d = reg_of_var(iptr->dst, REG_ITMP3);
1220 store_reg_to_var_int(iptr->dst, d);
1223 case ICMD_IREMCONST: /* ..., value ==> ..., value % constant */
1224 /* val.i = constant */
1226 var_to_reg_int(s1, src, REG_ITMP1);
1227 d = reg_of_var(iptr->dst, REG_ITMP3);
1228 ICONST(REG_ITMP2, iptr->val.i);
1229 M_IDIV(s1, REG_ITMP2);
1233 store_reg_to_var_int(iptr->dst, d);
1236 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1238 var_to_reg_int(s1, src->prev, REG_ITMP1);
1239 var_to_reg_int(s2, src, REG_ITMP2);
1240 d = reg_of_var(iptr->dst, REG_ITMP3);
1245 store_reg_to_var_int(iptr->dst, d);
1248 case ICMD_LREMCONST: /* ..., value ==> ..., value % constant */
1249 /* val.l = constant */
1251 var_to_reg_int(s1, src, REG_ITMP1);
1252 d = reg_of_var(iptr->dst, REG_ITMP3);
1253 LCONST(REG_ITMP2, iptr->val.l);
1254 M_LDIV(s1, REG_ITMP2);
1258 store_reg_to_var_int(iptr->dst, d);
1261 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1262 case ICMD_LDIVPOW2: /* val.i = constant */
1264 var_to_reg_int(s1, src, REG_ITMP1);
1265 d = reg_of_var(iptr->dst, REG_ITMP3);
1266 M_LSRA_IMM(s1, 63, REG_ITMP2);
1267 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1268 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1269 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
1270 store_reg_to_var_int(iptr->dst, d);
1273 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1275 var_to_reg_int(s1, src->prev, REG_ITMP1);
1276 var_to_reg_int(s2, src, REG_ITMP2);
1277 d = reg_of_var(iptr->dst, REG_ITMP3);
1279 store_reg_to_var_int(iptr->dst, d);
1282 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1283 /* val.i = constant */
1285 var_to_reg_int(s1, src, REG_ITMP1);
1286 d = reg_of_var(iptr->dst, REG_ITMP3);
1287 M_ISLL_IMM(s1, iptr->val.i, d);
1288 store_reg_to_var_int(iptr->dst, d);
1291 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1293 var_to_reg_int(s1, src->prev, REG_ITMP1);
1294 var_to_reg_int(s2, src, REG_ITMP2);
1295 d = reg_of_var(iptr->dst, REG_ITMP3);
1297 store_reg_to_var_int(iptr->dst, d);
1300 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1301 /* val.i = constant */
1303 var_to_reg_int(s1, src, REG_ITMP1);
1304 d = reg_of_var(iptr->dst, REG_ITMP3);
1305 M_ISRA_IMM(s1, iptr->val.i, d);
1306 store_reg_to_var_int(iptr->dst, d);
1309 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1311 var_to_reg_int(s1, src->prev, REG_ITMP1);
1312 var_to_reg_int(s2, src, REG_ITMP2);
1313 d = reg_of_var(iptr->dst, REG_ITMP3);
1315 store_reg_to_var_int(iptr->dst, d);
1318 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1319 /* val.i = constant */
1321 var_to_reg_int(s1, src, REG_ITMP1);
1322 d = reg_of_var(iptr->dst, REG_ITMP3);
1323 M_ISRL_IMM(s1, iptr->val.i, d);
1324 store_reg_to_var_int(iptr->dst, d);
1327 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1329 var_to_reg_int(s1, src->prev, REG_ITMP1);
1330 var_to_reg_int(s2, src, REG_ITMP2);
1331 d = reg_of_var(iptr->dst, REG_ITMP3);
1333 store_reg_to_var_int(iptr->dst, d);
1336 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1337 /* val.i = constant */
1339 var_to_reg_int(s1, src, REG_ITMP1);
1340 d = reg_of_var(iptr->dst, REG_ITMP3);
1341 M_LSLL_IMM(s1, iptr->val.i, d);
1342 store_reg_to_var_int(iptr->dst, d);
1345 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1347 var_to_reg_int(s1, src->prev, REG_ITMP1);
1348 var_to_reg_int(s2, src, REG_ITMP2);
1349 d = reg_of_var(iptr->dst, REG_ITMP3);
1351 store_reg_to_var_int(iptr->dst, d);
1354 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1355 /* val.i = constant */
1357 var_to_reg_int(s1, src, REG_ITMP1);
1358 d = reg_of_var(iptr->dst, REG_ITMP3);
1359 M_LSRA_IMM(s1, iptr->val.i, d);
1360 store_reg_to_var_int(iptr->dst, d);
1363 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1365 var_to_reg_int(s1, src->prev, REG_ITMP1);
1366 var_to_reg_int(s2, src, REG_ITMP2);
1367 d = reg_of_var(iptr->dst, REG_ITMP3);
1369 store_reg_to_var_int(iptr->dst, d);
1372 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1373 /* val.i = constant */
1375 var_to_reg_int(s1, src, REG_ITMP1);
1376 d = reg_of_var(iptr->dst, REG_ITMP3);
1377 M_LSRL_IMM(s1, iptr->val.i, d);
1378 store_reg_to_var_int(iptr->dst, d);
1381 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1384 var_to_reg_int(s1, src->prev, REG_ITMP1);
1385 var_to_reg_int(s2, src, REG_ITMP2);
1386 d = reg_of_var(iptr->dst, REG_ITMP3);
1388 store_reg_to_var_int(iptr->dst, d);
1391 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1392 /* val.i = constant */
1394 var_to_reg_int(s1, src, REG_ITMP1);
1395 d = reg_of_var(iptr->dst, REG_ITMP3);
1396 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1397 M_AND_IMM(s1, iptr->val.i, d);
1400 ICONST(REG_ITMP2, iptr->val.i);
1401 M_AND(s1, REG_ITMP2, d);
1403 store_reg_to_var_int(iptr->dst, d);
1406 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1407 /* val.i = constant */
1409 var_to_reg_int(s1, src, REG_ITMP1);
1410 d = reg_of_var(iptr->dst, REG_ITMP3);
1412 M_MOV(s1, REG_ITMP1);
1415 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1416 M_AND_IMM(s1, iptr->val.i, d);
1419 M_ISUB(REG_ZERO, s1, d);
1420 M_AND_IMM(d, iptr->val.i, d);
1423 ICONST(REG_ITMP2, iptr->val.i);
1424 M_AND(s1, REG_ITMP2, d);
1427 M_ISUB(REG_ZERO, s1, d);
1428 M_AND(d, REG_ITMP2, d);
1430 M_ISUB(REG_ZERO, d, d);
1431 store_reg_to_var_int(iptr->dst, d);
1434 case ICMD_IREM0X10001: /* ..., value ==> ..., value % 0x100001 */
1436 /* b = value & 0xffff;
1438 a = ((b - a) & 0xffff) + (b < a);
1440 var_to_reg_int(s1, src, REG_ITMP1);
1441 d = reg_of_var(iptr->dst, REG_ITMP3);
1443 M_MOV(s1, REG_ITMP3);
1447 M_CZEXT(s1, REG_ITMP2); /* delay slot */
1448 M_ISRA_IMM(s1, 16, d);
1449 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1450 M_ISUB(REG_ITMP2, d, d);
1453 M_IADD(d, REG_ITMP1, d); /* delay slot */
1455 M_LUI(REG_ITMP2, 1);
1456 M_IADD_IMM(REG_ITMP2, 1, REG_ITMP2);
1457 M_IDIV(s1, REG_ITMP2);
1461 store_reg_to_var_int(iptr->dst, d);
1464 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1465 /* val.l = constant */
1467 var_to_reg_int(s1, src, REG_ITMP1);
1468 d = reg_of_var(iptr->dst, REG_ITMP3);
1469 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1470 M_AND_IMM(s1, iptr->val.l, d);
1473 LCONST(REG_ITMP2, iptr->val.l);
1474 M_AND(s1, REG_ITMP2, d);
1476 store_reg_to_var_int(iptr->dst, d);
1479 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1480 /* val.l = constant */
1482 var_to_reg_int(s1, src, REG_ITMP1);
1483 d = reg_of_var(iptr->dst, REG_ITMP3);
1485 M_MOV(s1, REG_ITMP1);
1488 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1489 M_AND_IMM(s1, iptr->val.l, d);
1492 M_LSUB(REG_ZERO, s1, d);
1493 M_AND_IMM(d, iptr->val.l, d);
1496 LCONST(REG_ITMP2, iptr->val.l);
1497 M_AND(s1, REG_ITMP2, d);
1500 M_LSUB(REG_ZERO, s1, d);
1501 M_AND(d, REG_ITMP2, d);
1503 M_LSUB(REG_ZERO, d, d);
1504 store_reg_to_var_int(iptr->dst, d);
1507 case ICMD_LREM0X10001:/* ..., value ==> ..., value % 0x10001 */
1509 var_to_reg_int(s1, src, REG_ITMP1);
1510 d = reg_of_var(iptr->dst, REG_ITMP3);
1511 M_LUI(REG_ITMP2, 1);
1512 M_LADD_IMM(REG_ITMP2, 1, REG_ITMP2);
1513 M_LDIV(s1, REG_ITMP2);
1517 store_reg_to_var_int(iptr->dst, d);
1520 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1523 var_to_reg_int(s1, src->prev, REG_ITMP1);
1524 var_to_reg_int(s2, src, REG_ITMP2);
1525 d = reg_of_var(iptr->dst, REG_ITMP3);
1527 store_reg_to_var_int(iptr->dst, d);
1530 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1531 /* val.i = constant */
1533 var_to_reg_int(s1, src, REG_ITMP1);
1534 d = reg_of_var(iptr->dst, REG_ITMP3);
1535 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1536 M_OR_IMM(s1, iptr->val.i, d);
1539 ICONST(REG_ITMP2, iptr->val.i);
1540 M_OR(s1, REG_ITMP2, d);
1542 store_reg_to_var_int(iptr->dst, d);
1545 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1546 /* val.l = constant */
1548 var_to_reg_int(s1, src, REG_ITMP1);
1549 d = reg_of_var(iptr->dst, REG_ITMP3);
1550 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1551 M_OR_IMM(s1, iptr->val.l, d);
1554 LCONST(REG_ITMP2, iptr->val.l);
1555 M_OR(s1, REG_ITMP2, d);
1557 store_reg_to_var_int(iptr->dst, d);
1560 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1563 var_to_reg_int(s1, src->prev, REG_ITMP1);
1564 var_to_reg_int(s2, src, REG_ITMP2);
1565 d = reg_of_var(iptr->dst, REG_ITMP3);
1567 store_reg_to_var_int(iptr->dst, d);
1570 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1571 /* val.i = constant */
1573 var_to_reg_int(s1, src, REG_ITMP1);
1574 d = reg_of_var(iptr->dst, REG_ITMP3);
1575 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1576 M_XOR_IMM(s1, iptr->val.i, d);
1579 ICONST(REG_ITMP2, iptr->val.i);
1580 M_XOR(s1, REG_ITMP2, d);
1582 store_reg_to_var_int(iptr->dst, d);
1585 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1586 /* val.l = constant */
1588 var_to_reg_int(s1, src, REG_ITMP1);
1589 d = reg_of_var(iptr->dst, REG_ITMP3);
1590 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1591 M_XOR_IMM(s1, iptr->val.l, d);
1594 LCONST(REG_ITMP2, iptr->val.l);
1595 M_XOR(s1, REG_ITMP2, d);
1597 store_reg_to_var_int(iptr->dst, d);
1601 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1603 var_to_reg_int(s1, src->prev, REG_ITMP1);
1604 var_to_reg_int(s2, src, REG_ITMP2);
1605 d = reg_of_var(iptr->dst, REG_ITMP3);
1606 M_CMPLT(s1, s2, REG_ITMP3);
1607 M_CMPLT(s2, s1, REG_ITMP1);
1608 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1609 store_reg_to_var_int(iptr->dst, d);
1613 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1614 /* op1 = variable, val.i = constant */
1616 var = &(locals[iptr->op1][TYPE_INT]);
1617 if (var->flags & INMEMORY) {
1619 M_LLD(s1, REG_SP, 8 * var->regoff);
1623 M_IADD_IMM(s1, iptr->val.i, s1);
1624 if (var->flags & INMEMORY)
1625 M_LST(s1, REG_SP, 8 * var->regoff);
1629 /* floating operations ************************************************/
1631 case ICMD_FNEG: /* ..., value ==> ..., - value */
1633 var_to_reg_flt(s1, src, REG_FTMP1);
1634 d = reg_of_var(iptr->dst, REG_FTMP3);
1636 store_reg_to_var_flt(iptr->dst, d);
1639 case ICMD_DNEG: /* ..., value ==> ..., - value */
1641 var_to_reg_flt(s1, src, REG_FTMP1);
1642 d = reg_of_var(iptr->dst, REG_FTMP3);
1644 store_reg_to_var_flt(iptr->dst, d);
1647 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1649 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1650 var_to_reg_flt(s2, src, REG_FTMP2);
1651 d = reg_of_var(iptr->dst, REG_FTMP3);
1653 store_reg_to_var_flt(iptr->dst, d);
1656 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1658 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1659 var_to_reg_flt(s2, src, REG_FTMP2);
1660 d = reg_of_var(iptr->dst, REG_FTMP3);
1662 store_reg_to_var_flt(iptr->dst, d);
1665 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1667 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1668 var_to_reg_flt(s2, src, REG_FTMP2);
1669 d = reg_of_var(iptr->dst, REG_FTMP3);
1671 store_reg_to_var_flt(iptr->dst, d);
1674 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1676 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1677 var_to_reg_flt(s2, src, REG_FTMP2);
1678 d = reg_of_var(iptr->dst, REG_FTMP3);
1680 store_reg_to_var_flt(iptr->dst, d);
1683 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1685 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1686 var_to_reg_flt(s2, src, REG_FTMP2);
1687 d = reg_of_var(iptr->dst, REG_FTMP3);
1689 store_reg_to_var_flt(iptr->dst, d);
1692 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1694 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1695 var_to_reg_flt(s2, src, REG_FTMP2);
1696 d = reg_of_var(iptr->dst, REG_FTMP3);
1698 store_reg_to_var_flt(iptr->dst, d);
1701 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1703 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1704 var_to_reg_flt(s2, src, REG_FTMP2);
1705 d = reg_of_var(iptr->dst, REG_FTMP3);
1707 store_reg_to_var_flt(iptr->dst, d);
1710 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1712 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1713 var_to_reg_flt(s2, src, REG_FTMP2);
1714 d = reg_of_var(iptr->dst, REG_FTMP3);
1716 store_reg_to_var_flt(iptr->dst, d);
1719 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1722 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1723 var_to_reg_flt(s2, src, REG_FTMP2);
1724 d = reg_of_var(iptr->dst, REG_FTMP3);
1725 M_FDIV(s1,s2, REG_FTMP3);
1726 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1727 M_CVTLF(REG_FTMP3, REG_FTMP3);
1728 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1729 M_FSUB(s1, REG_FTMP3, d);
1730 store_reg_to_var_flt(iptr->dst, d);
1733 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1735 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1736 var_to_reg_flt(s2, src, REG_FTMP2);
1737 d = reg_of_var(iptr->dst, REG_FTMP3);
1738 M_DDIV(s1,s2, REG_FTMP3);
1739 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1740 M_CVTLD(REG_FTMP3, REG_FTMP3);
1741 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1742 M_DSUB(s1, REG_FTMP3, d);
1743 store_reg_to_var_flt(iptr->dst, d);
1746 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1748 var_to_reg_int(s1, src, REG_ITMP1);
1749 d = reg_of_var(iptr->dst, REG_FTMP3);
1752 store_reg_to_var_flt(iptr->dst, d);
1755 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1757 var_to_reg_int(s1, src, REG_ITMP1);
1758 d = reg_of_var(iptr->dst, REG_FTMP3);
1761 store_reg_to_var_flt(iptr->dst, d);
1764 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1766 var_to_reg_flt(s1, src, REG_FTMP1);
1767 d = reg_of_var(iptr->dst, REG_ITMP3);
1768 M_TRUNCFI(s1, REG_FTMP1);
1769 M_MOVDI(REG_FTMP1, d);
1771 store_reg_to_var_int(iptr->dst, d);
1774 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1776 var_to_reg_flt(s1, src, REG_FTMP1);
1777 d = reg_of_var(iptr->dst, REG_ITMP3);
1778 M_TRUNCDI(s1, REG_FTMP1);
1779 M_MOVDI(REG_FTMP1, d);
1781 store_reg_to_var_int(iptr->dst, d);
1784 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1786 var_to_reg_flt(s1, src, REG_FTMP1);
1787 d = reg_of_var(iptr->dst, REG_ITMP3);
1788 M_TRUNCFL(s1, REG_FTMP1);
1789 M_MOVDL(REG_FTMP1, d);
1791 store_reg_to_var_int(iptr->dst, d);
1794 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1796 var_to_reg_flt(s1, src, REG_FTMP1);
1797 d = reg_of_var(iptr->dst, REG_ITMP3);
1798 M_TRUNCDL(s1, REG_FTMP1);
1799 M_MOVDL(REG_FTMP1, d);
1801 store_reg_to_var_int(iptr->dst, d);
1804 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1806 var_to_reg_flt(s1, src, REG_FTMP1);
1807 d = reg_of_var(iptr->dst, REG_FTMP3);
1809 store_reg_to_var_flt(iptr->dst, d);
1812 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1814 var_to_reg_flt(s1, src, REG_FTMP1);
1815 d = reg_of_var(iptr->dst, REG_FTMP3);
1817 store_reg_to_var_flt(iptr->dst, d);
1820 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1822 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1823 var_to_reg_flt(s2, src, REG_FTMP2);
1824 d = reg_of_var(iptr->dst, REG_ITMP3);
1827 M_LADD_IMM(REG_ZERO, 1, d);
1831 M_LSUB_IMM(REG_ZERO, 1, d);
1832 M_CMOVT(REG_ZERO, d);
1833 store_reg_to_var_int(iptr->dst, d);
1836 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1838 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1839 var_to_reg_flt(s2, src, REG_FTMP2);
1840 d = reg_of_var(iptr->dst, REG_ITMP3);
1843 M_LADD_IMM(REG_ZERO, 1, d);
1847 M_LSUB_IMM(REG_ZERO, 1, d);
1848 M_CMOVT(REG_ZERO, d);
1849 store_reg_to_var_int(iptr->dst, d);
1852 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1854 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1855 var_to_reg_flt(s2, src, REG_FTMP2);
1856 d = reg_of_var(iptr->dst, REG_ITMP3);
1859 M_LSUB_IMM(REG_ZERO, 1, d);
1863 M_LADD_IMM(REG_ZERO, 1, d);
1864 M_CMOVT(REG_ZERO, d);
1865 store_reg_to_var_int(iptr->dst, d);
1868 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1870 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1871 var_to_reg_flt(s2, src, REG_FTMP2);
1872 d = reg_of_var(iptr->dst, REG_ITMP3);
1875 M_LSUB_IMM(REG_ZERO, 1, d);
1879 M_LADD_IMM(REG_ZERO, 1, d);
1880 M_CMOVT(REG_ZERO, d);
1881 store_reg_to_var_int(iptr->dst, d);
1885 /* memory operations **************************************************/
1887 #define gen_bound_check \
1888 if (checkbounds) { \
1889 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size)); \
1890 M_CMPULT(s2, REG_ITMP3, REG_ITMP3); \
1891 M_BEQZ(REG_ITMP3, 0); \
1892 codegen_addxboundrefs(mcodeptr, s2); \
1896 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1898 var_to_reg_int(s1, src, REG_ITMP1);
1899 d = reg_of_var(iptr->dst, REG_ITMP3);
1900 gen_nullptr_check(s1);
1901 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1902 store_reg_to_var_int(iptr->dst, d);
1905 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1907 var_to_reg_int(s1, src->prev, REG_ITMP1);
1908 var_to_reg_int(s2, src, REG_ITMP2);
1909 d = reg_of_var(iptr->dst, REG_ITMP3);
1910 if (iptr->op1 == 0) {
1911 gen_nullptr_check(s1);
1914 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1915 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1916 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1917 store_reg_to_var_int(iptr->dst, d);
1920 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1922 var_to_reg_int(s1, src->prev, REG_ITMP1);
1923 var_to_reg_int(s2, src, REG_ITMP2);
1924 d = reg_of_var(iptr->dst, REG_ITMP3);
1925 if (iptr->op1 == 0) {
1926 gen_nullptr_check(s1);
1929 M_ASLL_IMM(s2, 2, REG_ITMP2);
1930 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1931 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1932 store_reg_to_var_int(iptr->dst, d);
1935 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1937 var_to_reg_int(s1, src->prev, REG_ITMP1);
1938 var_to_reg_int(s2, src, REG_ITMP2);
1939 d = reg_of_var(iptr->dst, REG_ITMP3);
1940 if (iptr->op1 == 0) {
1941 gen_nullptr_check(s1);
1944 M_ASLL_IMM(s2, 3, REG_ITMP2);
1945 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1946 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1947 store_reg_to_var_int(iptr->dst, d);
1950 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1952 var_to_reg_int(s1, src->prev, REG_ITMP1);
1953 var_to_reg_int(s2, src, REG_ITMP2);
1954 d = reg_of_var(iptr->dst, REG_FTMP3);
1955 if (iptr->op1 == 0) {
1956 gen_nullptr_check(s1);
1959 M_ASLL_IMM(s2, 2, REG_ITMP2);
1960 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1961 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1962 store_reg_to_var_flt(iptr->dst, d);
1965 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1967 var_to_reg_int(s1, src->prev, REG_ITMP1);
1968 var_to_reg_int(s2, src, REG_ITMP2);
1969 d = reg_of_var(iptr->dst, REG_FTMP3);
1970 if (iptr->op1 == 0) {
1971 gen_nullptr_check(s1);
1974 M_ASLL_IMM(s2, 3, REG_ITMP2);
1975 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1976 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1977 store_reg_to_var_flt(iptr->dst, d);
1980 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1982 var_to_reg_int(s1, src->prev, REG_ITMP1);
1983 var_to_reg_int(s2, src, REG_ITMP2);
1984 d = reg_of_var(iptr->dst, REG_ITMP3);
1985 if (iptr->op1 == 0) {
1986 gen_nullptr_check(s1);
1989 M_AADD(s2, s1, REG_ITMP1);
1990 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1991 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1992 store_reg_to_var_int(iptr->dst, d);
1995 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1997 var_to_reg_int(s1, src->prev, REG_ITMP1);
1998 var_to_reg_int(s2, src, REG_ITMP2);
1999 d = reg_of_var(iptr->dst, REG_ITMP3);
2000 if (iptr->op1 == 0) {
2001 gen_nullptr_check(s1);
2004 M_AADD(s2, s1, REG_ITMP1);
2005 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2006 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2007 store_reg_to_var_int(iptr->dst, d);
2010 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2012 var_to_reg_int(s1, src->prev, REG_ITMP1);
2013 var_to_reg_int(s2, src, REG_ITMP2);
2014 d = reg_of_var(iptr->dst, REG_ITMP3);
2015 if (iptr->op1 == 0) {
2016 gen_nullptr_check(s1);
2019 M_AADD(s2, s1, REG_ITMP1);
2020 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2021 store_reg_to_var_int(iptr->dst, d);
2025 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2027 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2028 var_to_reg_int(s2, src->prev, REG_ITMP2);
2029 if (iptr->op1 == 0) {
2030 gen_nullptr_check(s1);
2033 var_to_reg_int(s3, src, REG_ITMP3);
2034 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
2035 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2036 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2039 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2041 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2042 var_to_reg_int(s2, src->prev, REG_ITMP2);
2043 if (iptr->op1 == 0) {
2044 gen_nullptr_check(s1);
2047 var_to_reg_int(s3, src, REG_ITMP3);
2048 M_ASLL_IMM(s2, 2, REG_ITMP2);
2049 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2050 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
2053 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2055 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2056 var_to_reg_int(s2, src->prev, REG_ITMP2);
2057 if (iptr->op1 == 0) {
2058 gen_nullptr_check(s1);
2061 var_to_reg_int(s3, src, REG_ITMP3);
2062 M_ASLL_IMM(s2, 3, REG_ITMP2);
2063 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2064 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
2067 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2069 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2070 var_to_reg_int(s2, src->prev, REG_ITMP2);
2071 if (iptr->op1 == 0) {
2072 gen_nullptr_check(s1);
2075 var_to_reg_flt(s3, src, REG_FTMP3);
2076 M_ASLL_IMM(s2, 2, REG_ITMP2);
2077 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2078 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2081 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2083 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2084 var_to_reg_int(s2, src->prev, REG_ITMP2);
2085 if (iptr->op1 == 0) {
2086 gen_nullptr_check(s1);
2089 var_to_reg_flt(s3, src, REG_FTMP3);
2090 M_ASLL_IMM(s2, 3, REG_ITMP2);
2091 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2092 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2095 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2096 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2098 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2099 var_to_reg_int(s2, src->prev, REG_ITMP2);
2100 if (iptr->op1 == 0) {
2101 gen_nullptr_check(s1);
2104 var_to_reg_int(s3, src, REG_ITMP3);
2105 M_AADD(s2, s1, REG_ITMP1);
2106 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2107 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
2110 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2112 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2113 var_to_reg_int(s2, src->prev, REG_ITMP2);
2114 if (iptr->op1 == 0) {
2115 gen_nullptr_check(s1);
2118 var_to_reg_int(s3, src, REG_ITMP3);
2119 M_AADD(s2, s1, REG_ITMP1);
2120 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2124 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2125 /* op1 = type, val.a = field address */
2127 /* if class isn't yet initialized, do it */
2128 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2129 /* call helper function which patches this code */
2130 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
2131 M_ALD(REG_ITMP1, REG_PV, a);
2132 a = dseg_addaddress(asm_check_clinit);
2133 M_ALD(REG_ITMP3, REG_PV, a);
2134 M_JSR(REG_RA, REG_ITMP3);
2138 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
2140 M_LDA(REG_PV, REG_RA, -s1);
2145 s4 ml = -s1, mh = 0;
2146 while (ml < -32768) { ml += 65536; mh--; }
2148 M_IADD_IMM(REG_PV, ml, REG_PV);
2149 M_LADD(REG_PV, REG_RA, REG_PV);
2154 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2155 M_ALD(REG_ITMP1, REG_PV, a);
2156 switch (iptr->op1) {
2158 var_to_reg_int(s2, src, REG_ITMP2);
2159 M_IST(s2, REG_ITMP1, 0);
2162 var_to_reg_int(s2, src, REG_ITMP2);
2163 M_LST(s2, REG_ITMP1, 0);
2166 var_to_reg_int(s2, src, REG_ITMP2);
2167 M_AST(s2, REG_ITMP1, 0);
2170 var_to_reg_flt(s2, src, REG_FTMP2);
2171 M_FST(s2, REG_ITMP1, 0);
2174 var_to_reg_flt(s2, src, REG_FTMP2);
2175 M_DST(s2, REG_ITMP1, 0);
2177 default: panic ("internal error");
2181 case ICMD_GETSTATIC: /* ... ==> ..., value */
2182 /* op1 = type, val.a = field address */
2184 /* if class isn't yet initialized, do it */
2185 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2186 /* call helper function which patches this code */
2187 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
2188 M_ALD(REG_ITMP1, REG_PV, a);
2189 a = dseg_addaddress(asm_check_clinit);
2190 M_ALD(REG_ITMP3, REG_PV, a);
2191 M_JSR(REG_RA, REG_ITMP3);
2195 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
2197 M_LDA(REG_PV, REG_RA, -s1);
2202 s4 ml = -s1, mh = 0;
2203 while (ml < -32768) { ml += 65536; mh--; }
2205 M_IADD_IMM(REG_PV, ml, REG_PV);
2206 M_LADD(REG_PV, REG_RA, REG_PV);
2211 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2212 M_ALD(REG_ITMP1, REG_PV, a);
2213 switch (iptr->op1) {
2215 d = reg_of_var(iptr->dst, REG_ITMP3);
2216 M_ILD(d, REG_ITMP1, 0);
2217 store_reg_to_var_int(iptr->dst, d);
2220 d = reg_of_var(iptr->dst, REG_ITMP3);
2221 M_LLD(d, REG_ITMP1, 0);
2222 store_reg_to_var_int(iptr->dst, d);
2225 d = reg_of_var(iptr->dst, REG_ITMP3);
2226 M_ALD(d, REG_ITMP1, 0);
2227 store_reg_to_var_int(iptr->dst, d);
2230 d = reg_of_var(iptr->dst, REG_FTMP1);
2231 M_FLD(d, REG_ITMP1, 0);
2232 store_reg_to_var_flt(iptr->dst, d);
2235 d = reg_of_var(iptr->dst, REG_FTMP1);
2236 M_DLD(d, REG_ITMP1, 0);
2237 store_reg_to_var_flt(iptr->dst, d);
2239 default: panic ("internal error");
2244 case ICMD_PUTFIELD: /* ..., value ==> ... */
2245 /* op1 = type, val.i = field offset */
2247 a = ((fieldinfo *)(iptr->val.a))->offset;
2248 switch (iptr->op1) {
2250 var_to_reg_int(s1, src->prev, REG_ITMP1);
2251 var_to_reg_int(s2, src, REG_ITMP2);
2252 gen_nullptr_check(s1);
2256 var_to_reg_int(s1, src->prev, REG_ITMP1);
2257 var_to_reg_int(s2, src, REG_ITMP2);
2258 gen_nullptr_check(s1);
2262 var_to_reg_int(s1, src->prev, REG_ITMP1);
2263 var_to_reg_int(s2, src, REG_ITMP2);
2264 gen_nullptr_check(s1);
2268 var_to_reg_int(s1, src->prev, REG_ITMP1);
2269 var_to_reg_flt(s2, src, REG_FTMP2);
2270 gen_nullptr_check(s1);
2274 var_to_reg_int(s1, src->prev, REG_ITMP1);
2275 var_to_reg_flt(s2, src, REG_FTMP2);
2276 gen_nullptr_check(s1);
2279 default: panic ("internal error");
2283 case ICMD_GETFIELD: /* ... ==> ..., value */
2284 /* op1 = type, val.i = field offset */
2286 a = ((fieldinfo *)(iptr->val.a))->offset;
2287 switch (iptr->op1) {
2289 var_to_reg_int(s1, src, REG_ITMP1);
2290 d = reg_of_var(iptr->dst, REG_ITMP3);
2291 gen_nullptr_check(s1);
2293 store_reg_to_var_int(iptr->dst, d);
2296 var_to_reg_int(s1, src, REG_ITMP1);
2297 d = reg_of_var(iptr->dst, REG_ITMP3);
2298 gen_nullptr_check(s1);
2300 store_reg_to_var_int(iptr->dst, d);
2303 var_to_reg_int(s1, src, REG_ITMP1);
2304 d = reg_of_var(iptr->dst, REG_ITMP3);
2305 gen_nullptr_check(s1);
2307 store_reg_to_var_int(iptr->dst, d);
2310 var_to_reg_int(s1, src, REG_ITMP1);
2311 d = reg_of_var(iptr->dst, REG_FTMP1);
2312 gen_nullptr_check(s1);
2314 store_reg_to_var_flt(iptr->dst, d);
2317 var_to_reg_int(s1, src, REG_ITMP1);
2318 d = reg_of_var(iptr->dst, REG_FTMP1);
2319 gen_nullptr_check(s1);
2321 store_reg_to_var_flt(iptr->dst, d);
2323 default: panic ("internal error");
2328 /* branch operations **************************************************/
2330 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2332 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2334 var_to_reg_int(s1, src, REG_ITMP1);
2335 M_INTMOVE(s1, REG_ITMP1_XPTR);
2336 a = dseg_addaddress(asm_handle_exception);
2337 M_ALD(REG_ITMP2, REG_PV, a);
2338 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2340 M_NOP; /* nop ensures that XPC is less than the end */
2341 /* of basic block */
2345 case ICMD_GOTO: /* ... ==> ... */
2346 /* op1 = target JavaVM pc */
2348 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2353 case ICMD_JSR: /* ... ==> ... */
2354 /* op1 = target JavaVM pc */
2356 dseg_addtarget(BlockPtrOfPC(iptr->op1));
2357 M_ALD(REG_ITMP1, REG_PV, -dseglen);
2358 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2362 case ICMD_RET: /* ... ==> ... */
2363 /* op1 = local variable */
2364 var = &(locals[iptr->op1][TYPE_ADR]);
2365 if (var->flags & INMEMORY) {
2366 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2375 case ICMD_IFNULL: /* ..., value ==> ... */
2376 /* op1 = target JavaVM pc */
2378 var_to_reg_int(s1, src, REG_ITMP1);
2380 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2384 case ICMD_IFNONNULL: /* ..., value ==> ... */
2385 /* op1 = target JavaVM pc */
2387 var_to_reg_int(s1, src, REG_ITMP1);
2389 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2393 case ICMD_IFEQ: /* ..., value ==> ... */
2394 /* op1 = target JavaVM pc, val.i = constant */
2396 var_to_reg_int(s1, src, REG_ITMP1);
2397 if (iptr->val.i == 0) {
2401 ICONST(REG_ITMP2, iptr->val.i);
2402 M_BEQ(s1, REG_ITMP2, 0);
2404 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2408 case ICMD_IFLT: /* ..., value ==> ... */
2409 /* op1 = target JavaVM pc, val.i = constant */
2411 var_to_reg_int(s1, src, REG_ITMP1);
2412 if (iptr->val.i == 0) {
2416 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2417 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2420 ICONST(REG_ITMP2, iptr->val.i);
2421 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2423 M_BNEZ(REG_ITMP1, 0);
2425 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2429 case ICMD_IFLE: /* ..., value ==> ... */
2430 /* op1 = target JavaVM pc, val.i = constant */
2432 var_to_reg_int(s1, src, REG_ITMP1);
2433 if (iptr->val.i == 0) {
2437 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2438 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2439 M_BNEZ(REG_ITMP1, 0);
2442 ICONST(REG_ITMP2, iptr->val.i);
2443 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2444 M_BEQZ(REG_ITMP1, 0);
2447 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2451 case ICMD_IFNE: /* ..., value ==> ... */
2452 /* op1 = target JavaVM pc, val.i = constant */
2454 var_to_reg_int(s1, src, REG_ITMP1);
2455 if (iptr->val.i == 0) {
2459 ICONST(REG_ITMP2, iptr->val.i);
2460 M_BNE(s1, REG_ITMP2, 0);
2462 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2466 case ICMD_IFGT: /* ..., value ==> ... */
2467 /* op1 = target JavaVM pc, val.i = constant */
2469 var_to_reg_int(s1, src, REG_ITMP1);
2470 if (iptr->val.i == 0) {
2474 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2475 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2476 M_BEQZ(REG_ITMP1, 0);
2479 ICONST(REG_ITMP2, iptr->val.i);
2480 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2481 M_BNEZ(REG_ITMP1, 0);
2484 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2488 case ICMD_IFGE: /* ..., value ==> ... */
2489 /* op1 = target JavaVM pc, val.i = constant */
2491 var_to_reg_int(s1, src, REG_ITMP1);
2492 if (iptr->val.i == 0) {
2496 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2497 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2500 ICONST(REG_ITMP2, iptr->val.i);
2501 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2503 M_BEQZ(REG_ITMP1, 0);
2505 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2509 case ICMD_IF_LEQ: /* ..., value ==> ... */
2510 /* op1 = target JavaVM pc, val.l = constant */
2512 var_to_reg_int(s1, src, REG_ITMP1);
2513 if (iptr->val.l == 0) {
2517 LCONST(REG_ITMP2, iptr->val.l);
2518 M_BEQ(s1, REG_ITMP2, 0);
2520 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2524 case ICMD_IF_LLT: /* ..., value ==> ... */
2525 /* op1 = target JavaVM pc, val.l = constant */
2527 var_to_reg_int(s1, src, REG_ITMP1);
2528 if (iptr->val.l == 0) {
2532 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2533 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2536 LCONST(REG_ITMP2, iptr->val.l);
2537 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2539 M_BNEZ(REG_ITMP1, 0);
2541 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2545 case ICMD_IF_LLE: /* ..., value ==> ... */
2546 /* op1 = target JavaVM pc, val.l = constant */
2548 var_to_reg_int(s1, src, REG_ITMP1);
2549 if (iptr->val.l == 0) {
2553 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2554 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2555 M_BNEZ(REG_ITMP1, 0);
2558 LCONST(REG_ITMP2, iptr->val.l);
2559 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2560 M_BEQZ(REG_ITMP1, 0);
2563 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2567 case ICMD_IF_LNE: /* ..., value ==> ... */
2568 /* op1 = target JavaVM pc, val.l = constant */
2570 var_to_reg_int(s1, src, REG_ITMP1);
2571 if (iptr->val.l == 0) {
2575 LCONST(REG_ITMP2, iptr->val.l);
2576 M_BNE(s1, REG_ITMP2, 0);
2578 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2582 case ICMD_IF_LGT: /* ..., value ==> ... */
2583 /* op1 = target JavaVM pc, val.l = constant */
2585 var_to_reg_int(s1, src, REG_ITMP1);
2586 if (iptr->val.l == 0) {
2590 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2591 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2592 M_BEQZ(REG_ITMP1, 0);
2595 LCONST(REG_ITMP2, iptr->val.l);
2596 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2597 M_BNEZ(REG_ITMP1, 0);
2600 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2604 case ICMD_IF_LGE: /* ..., value ==> ... */
2605 /* op1 = target JavaVM pc, val.l = constant */
2607 var_to_reg_int(s1, src, REG_ITMP1);
2608 if (iptr->val.l == 0) {
2612 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2613 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2616 LCONST(REG_ITMP2, iptr->val.l);
2617 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2619 M_BEQZ(REG_ITMP1, 0);
2621 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2625 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2626 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2627 case ICMD_IF_ACMPEQ:
2629 var_to_reg_int(s1, src->prev, REG_ITMP1);
2630 var_to_reg_int(s2, src, REG_ITMP2);
2632 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2636 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2637 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2638 case ICMD_IF_ACMPNE:
2640 var_to_reg_int(s1, src->prev, REG_ITMP1);
2641 var_to_reg_int(s2, src, REG_ITMP2);
2643 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2647 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2648 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2650 var_to_reg_int(s1, src->prev, REG_ITMP1);
2651 var_to_reg_int(s2, src, REG_ITMP2);
2652 M_CMPLT(s1, s2, REG_ITMP1);
2653 M_BNEZ(REG_ITMP1, 0);
2654 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2658 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2659 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2661 var_to_reg_int(s1, src->prev, REG_ITMP1);
2662 var_to_reg_int(s2, src, REG_ITMP2);
2663 M_CMPGT(s1, s2, REG_ITMP1);
2664 M_BNEZ(REG_ITMP1, 0);
2665 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2669 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2670 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2672 var_to_reg_int(s1, src->prev, REG_ITMP1);
2673 var_to_reg_int(s2, src, REG_ITMP2);
2674 M_CMPGT(s1, s2, REG_ITMP1);
2675 M_BEQZ(REG_ITMP1, 0);
2676 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2680 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2681 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2683 var_to_reg_int(s1, src->prev, REG_ITMP1);
2684 var_to_reg_int(s2, src, REG_ITMP2);
2685 M_CMPLT(s1, s2, REG_ITMP1);
2686 M_BEQZ(REG_ITMP1, 0);
2687 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2691 #ifdef CONDITIONAL_LOADCONST
2692 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2694 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2697 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2698 /* val.i = constant */
2700 var_to_reg_int(s1, src, REG_ITMP1);
2701 d = reg_of_var(iptr->dst, REG_ITMP3);
2703 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2704 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2705 M_CMPEQ(s1, REG_ZERO, d);
2706 store_reg_to_var_int(iptr->dst, d);
2709 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2710 M_CMPEQ(s1, REG_ZERO, d);
2712 store_reg_to_var_int(iptr->dst, d);
2716 M_MOV(s1, REG_ITMP1);
2719 ICONST(d, iptr[1].val.i);
2721 if ((s3 >= 0) && (s3 <= 255)) {
2722 M_CMOVEQ_IMM(s1, s3, d);
2725 ICONST(REG_ITMP2, s3);
2726 M_CMOVEQ(s1, REG_ITMP2, d);
2728 store_reg_to_var_int(iptr->dst, d);
2731 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2732 /* val.i = constant */
2734 var_to_reg_int(s1, src, REG_ITMP1);
2735 d = reg_of_var(iptr->dst, REG_ITMP3);
2737 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2738 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2739 M_CMPEQ(s1, REG_ZERO, d);
2740 store_reg_to_var_int(iptr->dst, d);
2743 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2744 M_CMPEQ(s1, REG_ZERO, d);
2746 store_reg_to_var_int(iptr->dst, d);
2750 M_MOV(s1, REG_ITMP1);
2753 ICONST(d, iptr[1].val.i);
2755 if ((s3 >= 0) && (s3 <= 255)) {
2756 M_CMOVNE_IMM(s1, s3, d);
2759 ICONST(REG_ITMP2, s3);
2760 M_CMOVNE(s1, REG_ITMP2, d);
2762 store_reg_to_var_int(iptr->dst, d);
2765 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2766 /* val.i = constant */
2768 var_to_reg_int(s1, src, REG_ITMP1);
2769 d = reg_of_var(iptr->dst, REG_ITMP3);
2771 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2772 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2773 M_CMPLT(s1, REG_ZERO, d);
2774 store_reg_to_var_int(iptr->dst, d);
2777 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2778 M_CMPLE(REG_ZERO, s1, d);
2779 store_reg_to_var_int(iptr->dst, d);
2783 M_MOV(s1, REG_ITMP1);
2786 ICONST(d, iptr[1].val.i);
2788 if ((s3 >= 0) && (s3 <= 255)) {
2789 M_CMOVLT_IMM(s1, s3, d);
2792 ICONST(REG_ITMP2, s3);
2793 M_CMOVLT(s1, REG_ITMP2, d);
2795 store_reg_to_var_int(iptr->dst, d);
2798 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2799 /* val.i = constant */
2801 var_to_reg_int(s1, src, REG_ITMP1);
2802 d = reg_of_var(iptr->dst, REG_ITMP3);
2804 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2805 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2806 M_CMPLE(REG_ZERO, s1, d);
2807 store_reg_to_var_int(iptr->dst, d);
2810 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2811 M_CMPLT(s1, REG_ZERO, d);
2812 store_reg_to_var_int(iptr->dst, d);
2816 M_MOV(s1, REG_ITMP1);
2819 ICONST(d, iptr[1].val.i);
2821 if ((s3 >= 0) && (s3 <= 255)) {
2822 M_CMOVGE_IMM(s1, s3, d);
2825 ICONST(REG_ITMP2, s3);
2826 M_CMOVGE(s1, REG_ITMP2, d);
2828 store_reg_to_var_int(iptr->dst, d);
2831 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2832 /* val.i = constant */
2834 var_to_reg_int(s1, src, REG_ITMP1);
2835 d = reg_of_var(iptr->dst, REG_ITMP3);
2837 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2838 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2839 M_CMPLT(REG_ZERO, s1, d);
2840 store_reg_to_var_int(iptr->dst, d);
2843 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2844 M_CMPLE(s1, REG_ZERO, d);
2845 store_reg_to_var_int(iptr->dst, d);
2849 M_MOV(s1, REG_ITMP1);
2852 ICONST(d, iptr[1].val.i);
2854 if ((s3 >= 0) && (s3 <= 255)) {
2855 M_CMOVGT_IMM(s1, s3, d);
2858 ICONST(REG_ITMP2, s3);
2859 M_CMOVGT(s1, REG_ITMP2, d);
2861 store_reg_to_var_int(iptr->dst, d);
2864 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2865 /* val.i = constant */
2867 var_to_reg_int(s1, src, REG_ITMP1);
2868 d = reg_of_var(iptr->dst, REG_ITMP3);
2870 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2871 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2872 M_CMPLE(s1, REG_ZERO, d);
2873 store_reg_to_var_int(iptr->dst, d);
2876 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2877 M_CMPLT(REG_ZERO, s1, d);
2878 store_reg_to_var_int(iptr->dst, d);
2882 M_MOV(s1, REG_ITMP1);
2885 ICONST(d, iptr[1].val.i);
2887 if ((s3 >= 0) && (s3 <= 255)) {
2888 M_CMOVLE_IMM(s1, s3, d);
2891 ICONST(REG_ITMP2, s3);
2892 M_CMOVLE(s1, REG_ITMP2, d);
2894 store_reg_to_var_int(iptr->dst, d);
2899 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2903 #if defined(USE_THREADS)
2904 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2906 a = dseg_addaddress((void *) (builtin_monitorexit));
2907 M_ALD(REG_ITMP3, REG_PV, a);
2908 M_JSR(REG_RA, REG_ITMP3);
2909 M_ALD(argintregs[0], REG_SP, maxmemuse * 8); /* delay slot */
2910 disp = -(s4) ((u1 *) mcodeptr - mcodebase);
2911 M_LDA(REG_PV, REG_RA, disp);
2914 var_to_reg_int(s1, src, REG_RESULT);
2915 M_INTMOVE(s1, REG_RESULT);
2916 goto nowperformreturn;
2918 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2921 #if defined(USE_THREADS)
2922 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2924 a = dseg_addaddress((void *) (builtin_monitorexit));
2925 M_ALD(REG_ITMP3, REG_PV, a);
2926 M_JSR(REG_RA, REG_ITMP3);
2927 M_ALD(argintregs[0], REG_SP, maxmemuse * 8); /* delay slot */
2928 disp = -(s4) ((u1 *) mcodeptr - mcodebase);
2929 M_LDA(REG_PV, REG_RA, disp);
2932 var_to_reg_flt(s1, src, REG_FRESULT);
2934 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2935 M_TFLTMOVE(t, s1, REG_FRESULT);
2937 goto nowperformreturn;
2939 case ICMD_RETURN: /* ... ==> ... */
2941 #if defined(USE_THREADS)
2942 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2944 a = dseg_addaddress((void *) (builtin_monitorexit));
2945 M_ALD(REG_ITMP3, REG_PV, a);
2946 M_JSR(REG_RA, REG_ITMP3);
2947 M_ALD(argintregs[0], REG_SP, maxmemuse * 8); /* delay slot */
2948 disp = -(s4) ((u1 *) mcodeptr - mcodebase);
2949 M_LDA(REG_PV, REG_RA, disp);
2957 p = parentargs_base;
2959 /* restore return address */
2962 {p--; M_LLD (REG_RA, REG_SP, 8 * p);}
2964 /* restore saved registers */
2966 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
2967 {p--; M_LLD(savintregs[r], REG_SP, 8 * p);}
2968 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
2969 {p--; M_DLD(savfltregs[r], REG_SP, 8 * p);}
2971 /* call trace function */
2974 M_LDA (REG_SP, REG_SP, -24);
2975 M_LST(REG_RA, REG_SP, 0);
2976 M_LST(REG_RESULT, REG_SP, 8);
2977 M_DST(REG_FRESULT, REG_SP,16);
2978 a = dseg_addaddress (method);
2979 M_ALD(argintregs[0], REG_PV, a);
2980 M_MOV(REG_RESULT, argintregs[1]);
2981 M_FLTMOVE(REG_FRESULT, argfltregs[2]);
2982 M_FMOV(REG_FRESULT, argfltregs[3]);
2983 a = dseg_addaddress ((void*) (builtin_displaymethodstop));
2984 M_ALD(REG_ITMP3, REG_PV, a);
2985 M_JSR (REG_RA, REG_ITMP3);
2987 M_DLD(REG_FRESULT, REG_SP,16);
2988 M_LLD(REG_RESULT, REG_SP, 8);
2989 M_LLD(REG_RA, REG_SP, 0);
2990 M_LDA (REG_SP, REG_SP, 24);
2995 /* deallocate stack */
2997 if (parentargs_base)
2998 {M_LDA(REG_SP, REG_SP, parentargs_base*8);}
3006 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3011 tptr = (void **) iptr->target;
3013 s4ptr = iptr->val.a;
3014 l = s4ptr[1]; /* low */
3015 i = s4ptr[2]; /* high */
3017 var_to_reg_int(s1, src, REG_ITMP1);
3019 {M_INTMOVE(s1, REG_ITMP1);}
3020 else if (l <= 32768) {
3021 M_IADD_IMM(s1, -l, REG_ITMP1);
3024 ICONST(REG_ITMP2, l);
3025 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3031 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
3032 M_BEQZ(REG_ITMP2, 0);
3033 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3034 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
3036 /* build jump table top down and use address of lowest entry */
3038 /* s4ptr += 3 + i; */
3042 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3043 dseg_addtarget((basicblock *) tptr[0]);
3048 /* length of dataseg after last dseg_addtarget is used by load */
3050 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
3051 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
3058 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3060 s4 i, /*l, */val, *s4ptr;
3063 tptr = (void **) iptr->target;
3065 s4ptr = iptr->val.a;
3066 /*l = s4ptr[0];*/ /* default */
3067 i = s4ptr[1]; /* count */
3069 MCODECHECK((i<<2)+8);
3070 var_to_reg_int(s1, src, REG_ITMP1);
3076 ICONST(REG_ITMP2, val);
3077 M_BEQ(s1, REG_ITMP2, 0);
3078 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3083 tptr = (void **) iptr->target;
3084 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3091 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3092 /* op1 = return type, val.a = function pointer*/
3096 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3097 /* op1 = return type, val.a = function pointer*/
3101 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3102 /* op1 = return type, val.a = function pointer*/
3106 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3107 /* op1 = arg count, val.a = method pointer */
3109 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3110 /* op1 = arg count, val.a = method pointer */
3112 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3113 /* op1 = arg count, val.a = method pointer */
3115 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3116 /* op1 = arg count, val.a = method pointer */
3124 MCODECHECK((s3 << 1) + 64);
3126 /* copy arguments to registers or stack location */
3128 for (; --s3 >= 0; src = src->prev) {
3129 if (src->varkind == ARGVAR)
3131 if (IS_INT_LNG_TYPE(src->type)) {
3132 if (s3 < INT_ARG_CNT) {
3133 s1 = argintregs[s3];
3134 var_to_reg_int(d, src, s1);
3138 var_to_reg_int(d, src, REG_ITMP1);
3139 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3143 if (s3 < FLT_ARG_CNT) {
3144 s1 = argfltregs[s3];
3145 var_to_reg_flt(d, src, s1);
3146 M_TFLTMOVE(src->type,d, s1);
3149 var_to_reg_flt(d, src, REG_FTMP1);
3150 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3155 switch (iptr->opc) {
3159 a = dseg_addaddress ((void*) (m));
3160 M_ALD(REG_ITMP3, REG_PV, a); /* built-in-function pointer */
3161 M_JSR (REG_RA, REG_ITMP3);
3163 d = iptr->op1; /* return type */
3164 goto afteractualcall;
3166 case ICMD_INVOKESTATIC:
3167 case ICMD_INVOKESPECIAL:
3168 a = dseg_addaddress (m->stubroutine);
3170 M_ALD(REG_PV, REG_PV, a ); /* method pointer in pv */
3173 goto makeactualcall;
3175 case ICMD_INVOKEVIRTUAL:
3177 gen_nullptr_check(argintregs[0]);
3178 M_ALD(REG_METHODPTR, argintregs[0],
3179 OFFSET(java_objectheader, vftbl));
3180 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
3181 sizeof(methodptr) * m->vftblindex);
3184 goto makeactualcall;
3186 case ICMD_INVOKEINTERFACE:
3189 gen_nullptr_check(argintregs[0]);
3190 M_ALD(REG_METHODPTR, argintregs[0],
3191 OFFSET(java_objectheader, vftbl));
3192 M_ALD(REG_METHODPTR, REG_METHODPTR,
3193 OFFSET(vftbl, interfacetable[0]) -
3194 sizeof(methodptr*) * ci->index);
3195 M_ALD(REG_PV, REG_METHODPTR,
3196 sizeof(methodptr) * (m - ci->methods));
3199 goto makeactualcall;
3203 error ("Unkown ICMD-Command: %d", iptr->opc);
3208 M_JSR (REG_RA, REG_PV);
3215 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3216 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3218 s4 ml = -s1, mh = 0;
3219 while (ml < -32768) { ml += 65536; mh--; }
3221 M_IADD_IMM(REG_PV, ml, REG_PV);
3222 M_LADD(REG_PV, REG_RA, REG_PV);
3225 /* d contains return type */
3227 if (d != TYPE_VOID) {
3228 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3229 s1 = reg_of_var(iptr->dst, REG_RESULT);
3230 M_INTMOVE(REG_RESULT, s1);
3231 store_reg_to_var_int(iptr->dst, s1);
3234 s1 = reg_of_var(iptr->dst, REG_FRESULT);
3235 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3236 store_reg_to_var_flt(iptr->dst, s1);
3243 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3245 /* op1: 0 == array, 1 == class */
3246 /* val.a: (classinfo*) superclass */
3248 /* superclass is an interface:
3250 * return (sub != NULL) &&
3251 * (sub->vftbl->interfacetablelength > super->index) &&
3252 * (sub->vftbl->interfacetable[-super->index] != NULL);
3254 * superclass is a class:
3256 * return ((sub != NULL) && (0
3257 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3258 * super->vftbl->diffvall));
3262 classinfo *super = (classinfo*) iptr->val.a;
3264 var_to_reg_int(s1, src, REG_ITMP1);
3265 d = reg_of_var(iptr->dst, REG_ITMP3);
3267 M_MOV(s1, REG_ITMP1);
3271 if (iptr->op1) { /* class/interface */
3272 if (super->flags & ACC_INTERFACE) { /* interface */
3275 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3276 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3277 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3278 M_BLEZ(REG_ITMP2, 3);
3280 M_ALD(REG_ITMP1, REG_ITMP1,
3281 OFFSET(vftbl, interfacetable[0]) -
3282 super->index * sizeof(methodptr*));
3283 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3287 s2 = super->vftbl->diffval;
3290 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3291 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3292 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3293 M_CMPULT_IMM(REG_ITMP1, s2 + 1, d);
3298 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3299 a = dseg_addaddress ((void*) super->vftbl);
3300 M_ALD(REG_ITMP2, REG_PV, a);
3301 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3302 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3303 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3304 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3305 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3311 panic ("internal error: no inlined array instanceof");
3313 store_reg_to_var_int(iptr->dst, d);
3316 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3318 /* op1: 0 == array, 1 == class */
3319 /* val.a: (classinfo*) superclass */
3321 /* superclass is an interface:
3323 * OK if ((sub == NULL) ||
3324 * (sub->vftbl->interfacetablelength > super->index) &&
3325 * (sub->vftbl->interfacetable[-super->index] != NULL));
3327 * superclass is a class:
3329 * OK if ((sub == NULL) || (0
3330 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3331 * super->vftbl->diffvall));
3335 classinfo *super = (classinfo*) iptr->val.a;
3337 d = reg_of_var(iptr->dst, REG_ITMP3);
3338 var_to_reg_int(s1, src, d);
3339 if (iptr->op1) { /* class/interface */
3340 if (super->flags & ACC_INTERFACE) { /* interface */
3343 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3344 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3345 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3346 M_BLEZ(REG_ITMP2, 0);
3347 codegen_addxcastrefs(mcodeptr);
3349 M_ALD(REG_ITMP2, REG_ITMP1,
3350 OFFSET(vftbl, interfacetable[0]) -
3351 super->index * sizeof(methodptr*));
3352 M_BEQZ(REG_ITMP2, 0);
3353 codegen_addxcastrefs(mcodeptr);
3359 s2 = super->vftbl->diffval;
3360 M_BEQZ(s1, 6 + (s2 != 0));
3362 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3363 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3364 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3366 M_BNEZ(REG_ITMP1, 0);
3369 M_CMPULT_IMM(REG_ITMP1, s2 + 1, REG_ITMP2);
3370 M_BEQZ(REG_ITMP2, 0);
3374 M_BEQZ(s1, 10 + (d == REG_ITMP3));
3376 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3377 a = dseg_addaddress ((void*) super->vftbl);
3378 M_ALD(REG_ITMP2, REG_PV, a);
3379 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3380 if (d != REG_ITMP3) {
3381 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3382 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3383 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3385 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, baseval));
3386 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3387 M_ALD(REG_ITMP2, REG_PV, a);
3388 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3390 M_CMPULT(REG_ITMP2, REG_ITMP1, REG_ITMP2);
3391 M_BNEZ(REG_ITMP2, 0);
3393 codegen_addxcastrefs(mcodeptr);
3398 panic ("internal error: no inlined array checkcast");
3401 store_reg_to_var_int(iptr->dst, d);
3404 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3406 var_to_reg_int(s1, src, REG_ITMP1);
3408 codegen_addxcheckarefs(mcodeptr);
3412 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3414 M_BEQZ(REG_RESULT, 0);
3415 codegen_addxexceptionrefs(mcodeptr);
3419 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3420 /* op1 = dimension, val.a = array descriptor */
3422 /* check for negative sizes and copy sizes to stack if necessary */
3424 MCODECHECK((iptr->op1 << 1) + 64);
3426 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3427 var_to_reg_int(s2, src, REG_ITMP1);
3429 codegen_addxcheckarefs(mcodeptr);
3432 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3434 if (src->varkind != ARGVAR) {
3435 M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
3439 /* a0 = dimension count */
3441 ICONST(argintregs[0], iptr->op1);
3443 /* a1 = arraydescriptor */
3445 a = dseg_addaddress(iptr->val.a);
3446 M_ALD(argintregs[1], REG_PV, a);
3448 /* a2 = pointer to dimensions = stack pointer */
3450 M_INTMOVE(REG_SP, argintregs[2]);
3452 a = dseg_addaddress((void*) (builtin_nmultianewarray));
3453 M_ALD(REG_ITMP3, REG_PV, a);
3454 M_JSR(REG_RA, REG_ITMP3);
3456 s1 = (int)((u1*) mcodeptr - mcodebase);
3458 M_LDA (REG_PV, REG_RA, -s1);
3462 s1 = reg_of_var(iptr->dst, REG_RESULT);
3463 M_INTMOVE(REG_RESULT, s1);
3464 store_reg_to_var_int(iptr->dst, s1);
3468 default: error ("Unknown pseudo command: %d", iptr->opc);
3474 } /* for instruction */
3476 /* copy values to interface registers */
3478 src = bptr->outstack;
3479 len = bptr->outdepth;
3483 if ((src->varkind != STACKVAR)) {
3485 if (IS_FLT_DBL_TYPE(s2)) {
3486 var_to_reg_flt(s1, src, REG_FTMP1);
3487 if (!(interfaces[len][s2].flags & INMEMORY)) {
3488 M_TFLTMOVE(s2,s1,interfaces[len][s2].regoff);
3491 M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3495 var_to_reg_int(s1, src, REG_ITMP1);
3496 if (!(interfaces[len][s2].flags & INMEMORY)) {
3497 M_INTMOVE(s1,interfaces[len][s2].regoff);
3500 M_LST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3506 } /* if (bptr -> flags >= BBREACHED) */
3507 } /* for basic block */
3509 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3512 /* generate bound check stubs */
3514 s4 *xcodeptr = NULL;
3516 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3517 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3518 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3519 xboundrefs->branchpos,
3520 (u1*) xcodeptr - (u1*) mcodebase - (4 + 4));
3525 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3526 xboundrefs->branchpos,
3527 (u1*) mcodeptr - mcodebase);
3531 M_MOV(xboundrefs->reg, REG_ITMP1);
3532 M_LADD_IMM(REG_PV, xboundrefs->branchpos - 4, REG_ITMP2_XPC);
3534 if (xcodeptr != NULL) {
3535 M_BR(xcodeptr - mcodeptr);
3539 xcodeptr = mcodeptr;
3541 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3542 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3544 a = dseg_addaddress(string_java_lang_ArrayIndexOutOfBoundsException);
3545 M_ALD(argintregs[0], REG_PV, a);
3546 M_MOV(REG_ITMP1, argintregs[1]);
3548 a = dseg_addaddress(new_exception_int);
3549 M_ALD(REG_ITMP3, REG_PV, a);
3550 M_JSR(REG_RA, REG_ITMP3);
3552 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3554 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3555 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3557 a = dseg_addaddress(asm_handle_exception);
3558 M_ALD(REG_ITMP3, REG_PV, a);
3564 /* generate negative array size check stubs */
3568 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3569 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3570 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3571 xcheckarefs->branchpos,
3572 (u1*) xcodeptr - (u1*) mcodebase - 4);
3576 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3577 xcheckarefs->branchpos,
3578 (u1*) mcodeptr - mcodebase);
3582 M_LADD_IMM(REG_PV, xcheckarefs->branchpos - 4, REG_ITMP2_XPC);
3584 if (xcodeptr != NULL) {
3585 M_BR(xcodeptr - mcodeptr);
3589 xcodeptr = mcodeptr;
3591 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3592 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3594 a = dseg_addaddress(string_java_lang_NegativeArraySizeException);
3595 M_ALD(argintregs[0], REG_PV, a);
3597 a = dseg_addaddress(new_exception);
3598 M_ALD(REG_ITMP3, REG_PV, a);
3599 M_JSR(REG_RA, REG_ITMP3);
3601 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3603 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3604 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3606 a = dseg_addaddress(asm_handle_exception);
3607 M_ALD(REG_ITMP3, REG_PV, a);
3613 /* generate cast check stubs */
3617 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3618 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3619 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3620 xcastrefs->branchpos,
3621 (u1*) xcodeptr - (u1*) mcodebase - 4);
3625 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3626 xcastrefs->branchpos,
3627 (u1*) mcodeptr - mcodebase);
3631 M_LADD_IMM(REG_PV, xcastrefs->branchpos - 4, REG_ITMP2_XPC);
3633 if (xcodeptr != NULL) {
3634 M_BR(xcodeptr - mcodeptr);
3638 xcodeptr = mcodeptr;
3640 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3641 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3643 a = dseg_addaddress(string_java_lang_ClassCastException);
3644 M_ALD(argintregs[0], REG_PV, a);
3646 a = dseg_addaddress(new_exception);
3647 M_ALD(REG_ITMP3, REG_PV, a);
3648 M_JSR(REG_RA, REG_ITMP3);
3650 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3652 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3653 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3655 a = dseg_addaddress(asm_handle_exception);
3656 M_ALD(REG_ITMP3, REG_PV, a);
3662 /* generate exception check stubs */
3666 for (; xexceptionrefs != NULL; xexceptionrefs = xexceptionrefs->next) {
3667 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3668 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
3669 xexceptionrefs->branchpos,
3670 (u1*) xcodeptr - (u1*) mcodebase - 4);
3674 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
3675 xexceptionrefs->branchpos,
3676 (u1*) mcodeptr - mcodebase);
3680 M_LADD_IMM(REG_PV, xexceptionrefs->branchpos - 4, REG_ITMP2_XPC);
3682 if (xcodeptr != NULL) {
3683 M_BR(xcodeptr - mcodeptr);
3687 xcodeptr = mcodeptr;
3689 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3690 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3691 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3693 a = dseg_addaddress(builtin_get_exceptionptrptr);
3694 M_ALD(REG_ITMP3, REG_PV, a);
3695 M_JSR(REG_RA, REG_ITMP3);
3697 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3699 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3700 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3702 a = dseg_addaddress(&_exceptionptr);
3703 M_ALD(REG_ITMP3, REG_PV, a);
3704 M_ALD(REG_ITMP1_XPTR, REG_ITMP3, 0);
3705 M_AST(REG_ZERO, REG_ITMP3, 0);
3708 a = dseg_addaddress(asm_handle_exception);
3709 M_ALD(REG_ITMP3, REG_PV, a);
3715 /* generate null pointer check stubs */
3719 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3720 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3721 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3722 xnullrefs->branchpos,
3723 (u1*) xcodeptr - (u1*) mcodebase - 4);
3727 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3728 xnullrefs->branchpos,
3729 (u1*) mcodeptr - mcodebase);
3733 M_LADD_IMM(REG_PV, xnullrefs->branchpos - 4, REG_ITMP2_XPC);
3735 if (xcodeptr != NULL) {
3736 M_BR(xcodeptr - mcodeptr);
3740 xcodeptr = mcodeptr;
3742 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3743 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3745 a = dseg_addaddress(string_java_lang_NullPointerException);
3746 M_ALD(argintregs[0], REG_PV, a);
3748 a = dseg_addaddress(new_exception);
3749 M_ALD(REG_ITMP3, REG_PV, a);
3750 M_JSR(REG_RA, REG_ITMP3);
3752 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3754 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3755 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3757 a = dseg_addaddress(asm_handle_exception);
3758 M_ALD(REG_ITMP3, REG_PV, a);
3765 codegen_finish((int)((u1*) mcodeptr - mcodebase));
3767 docacheflush((void*) method->entrypoint,
3768 ((u1*) mcodeptr - mcodebase));
3772 /* function createcompilerstub *************************************************
3774 creates a stub routine which calls the compiler
3776 *******************************************************************************/
3778 #define COMPSTUBSIZE 4
3780 u1 *createcompilerstub(methodinfo *m)
3782 u8 *s = CNEW(u8, COMPSTUBSIZE); /* memory to hold the stub */
3783 s4 *mcodeptr = (s4 *) s; /* code generation pointer */
3785 /* code for the stub */
3786 M_ALD(REG_PV, REG_PV, 24); /* load pointer to the compiler */
3788 M_JSR(REG_ITMP1, REG_PV); /* jump to the compiler, return address
3789 in itmp1 is used as method pointer */
3792 s[2] = (u8) m; /* literals to be adressed */
3793 s[3] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3795 (void) docacheflush((void*) s, (char*) mcodeptr - (char*) s);
3798 count_cstub_len += COMPSTUBSIZE * 8;
3805 /* function removecompilerstub *************************************************
3807 deletes a compilerstub from memory (simply by freeing it)
3809 *******************************************************************************/
3811 void removecompilerstub(u1 *stub)
3813 CFREE(stub, COMPSTUBSIZE * 8);
3817 /* function: createnativestub **************************************************
3819 creates a stub routine which calls a native method
3821 *******************************************************************************/
3823 #define NATIVESTUBSIZE 54 + 4
3824 #define NATIVEVERBOSESIZE 50 + 17
3825 #define NATIVESTUBOFFSET 9
3827 u1 *createnativestub(functionptr f, methodinfo *m)
3829 u8 *s; /* memory to hold the stub */
3831 s4 *mcodeptr; /* code generation pointer */
3832 s4 stackframesize = 0; /* size of stackframe if needed */
3837 descriptor2types(m); /* set paramcount and paramtypes */
3839 stubsize = runverbose ? NATIVESTUBSIZE + NATIVEVERBOSESIZE : NATIVESTUBSIZE;
3840 s = CNEW(u8, stubsize); /* memory to hold the stub */
3841 cs = s + NATIVESTUBOFFSET;
3842 mcodeptr = (s4 *) (cs); /* code generation pointer */
3844 *(cs-1) = (u8) f; /* address of native method */
3845 *(cs-2) = (u8) (&_exceptionptr); /* address of exceptionptr */
3846 *(cs-3) = (u8) asm_handle_nat_exception;/* addr of asm exception handler */
3847 *(cs-4) = (u8) (&env); /* addr of jni_environement */
3848 *(cs-5) = (u8) builtin_trace_args;
3850 *(cs-7) = (u8) builtin_displaymethodstop;
3851 *(cs-8) = (u8) m->class;
3852 *(cs-9) = (u8) asm_check_clinit;
3854 M_LDA(REG_SP, REG_SP, -8); /* build up stackframe */
3855 M_LST(REG_RA, REG_SP, 0); /* store return address */
3857 /* if function is static, check for initialized */
3859 if (m->flags & ACC_STATIC) {
3860 /* if class isn't yet initialized, do it */
3861 if (!m->class->initialized) {
3862 /* call helper function which patches this code */
3863 M_ALD(REG_ITMP1, REG_PV, -8 * 8); /* class */
3864 M_ALD(REG_ITMP3, REG_PV, -9 * 8); /* asm_check_clinit */
3865 M_JSR(REG_RA, REG_ITMP3);
3870 /* max. 50 instructions */
3875 M_LDA(REG_SP, REG_SP, -(18 * 8));
3876 M_AST(REG_RA, REG_SP, 1 * 8);
3878 /* save integer argument registers */
3879 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3880 M_LST(argintregs[p], REG_SP, (2 + p) * 8);
3883 /* save and copy float arguments into integer registers */
3884 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3885 t = m->paramtypes[p];
3887 if (IS_FLT_DBL_TYPE(t)) {
3888 if (IS_2_WORD_TYPE(t)) {
3889 M_DST(argfltregs[p], REG_SP, (10 + p) * 8);
3890 M_LLD(argintregs[p], REG_SP, (10 + p) * 8);
3893 M_FST(argfltregs[p], REG_SP, (10 + p) * 8);
3894 M_ILD(argintregs[p], REG_SP, (10 + p) * 8);
3898 M_DST(argfltregs[p], REG_SP, (10 + p) * 8);
3902 M_ALD(REG_ITMP1, REG_PV, -6 * 8); /* method address */
3903 M_AST(REG_ITMP1, REG_SP, 0);
3904 M_ALD(REG_ITMP3, REG_PV, -5 * 8); /* builtin_trace_args */
3905 M_JSR(REG_RA, REG_ITMP3);
3907 disp = -(int) (mcodeptr - (s4*) cs) * 4;
3908 M_LDA(REG_PV, REG_RA, disp);
3910 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3911 M_LLD(argintregs[p], REG_SP, (2 + p) * 8);
3914 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3915 t = m->paramtypes[p];
3917 if (IS_FLT_DBL_TYPE(t)) {
3918 if (IS_2_WORD_TYPE(t)) {
3919 M_DLD(argfltregs[p], REG_SP, (10 + p) * 8);
3922 M_FLD(argfltregs[p], REG_SP, (10 + p) * 8);
3926 M_DLD(argfltregs[p], REG_SP, (10 + p) * 8);
3930 M_ALD(REG_RA, REG_SP, 1 * 8);
3931 M_LDA(REG_SP, REG_SP, 18 * 8);
3934 /* save argument registers on stack -- if we have to */
3935 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
3937 int paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3938 int stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3940 stackframesize = stackparamcnt + paramshiftcnt;
3942 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
3944 /* copy stack arguments into new stack frame -- if any */
3945 for (i = 0; i < stackparamcnt; i++) {
3946 M_LLD(REG_ITMP1, REG_SP, (stackparamcnt + 1 + i) * 8);
3947 M_LST(REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
3950 if (m->flags & ACC_STATIC) {
3951 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
3952 M_DST(argfltregs[5], REG_SP, 1 * 8);
3954 M_LST(argintregs[5], REG_SP, 1 * 8);
3957 if (IS_FLT_DBL_TYPE(m->paramtypes[4])) {
3958 M_DST(argfltregs[4], REG_SP, 0 * 8);
3960 M_LST(argintregs[4], REG_SP, 0 * 8);
3964 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
3965 M_DST(argfltregs[5], REG_SP, 0 * 8);
3967 M_LST(argintregs[5], REG_SP, 0 * 8);
3972 if (m->flags & ACC_STATIC) {
3973 M_MOV(argintregs[5], argintregs[7]);
3975 M_DMFC1(REG_ITMP1, argfltregs[5]);
3976 M_DMTC1(REG_ITMP1, argfltregs[7]);
3978 M_MOV(argintregs[4], argintregs[6]);
3980 M_DMFC1(REG_ITMP1, argfltregs[4]);
3981 M_DMTC1(REG_ITMP1, argfltregs[6]);
3983 M_MOV(argintregs[3], argintregs[5]);
3984 M_DMFC1(REG_ITMP1, argfltregs[3]);
3986 M_MOV(argintregs[2], argintregs[4]);
3987 M_DMTC1(REG_ITMP1, argfltregs[5]);
3989 M_MOV(argintregs[1], argintregs[3]);
3990 M_DMFC1(REG_ITMP1, argfltregs[2]);
3992 M_MOV(argintregs[0], argintregs[2]);
3993 M_DMTC1(REG_ITMP1, argfltregs[4]);
3995 M_DMFC1(REG_ITMP1, argfltregs[1]);
3996 M_DMTC1(REG_ITMP1, argfltregs[3]);
3998 M_DMFC1(REG_ITMP1, argfltregs[0]);
3999 M_DMTC1(REG_ITMP1, argfltregs[2]);
4001 M_ALD(argintregs[1], REG_PV, -8 * 8);
4004 M_MOV(argintregs[6], argintregs[7]);
4006 M_DMFC1(REG_ITMP1, argfltregs[6]);
4007 M_DMTC1(REG_ITMP1, argfltregs[7]);
4009 M_MOV(argintregs[5], argintregs[6]);
4011 M_DMFC1(REG_ITMP1, argfltregs[5]);
4012 M_DMTC1(REG_ITMP1, argfltregs[6]);
4014 M_MOV(argintregs[4], argintregs[5]);
4015 M_DMFC1(REG_ITMP1, argfltregs[4]);
4017 M_MOV(argintregs[3], argintregs[4]);
4018 M_DMTC1(REG_ITMP1, argfltregs[5]);
4020 M_MOV(argintregs[2], argintregs[3]);
4021 M_DMFC1(REG_ITMP1, argfltregs[3]);
4023 M_MOV(argintregs[1], argintregs[2]);
4024 M_DMTC1(REG_ITMP1, argfltregs[4]);
4026 M_MOV(argintregs[0], argintregs[1]);
4027 M_DMFC1(REG_ITMP1, argfltregs[2]);
4029 M_DMTC1(REG_ITMP1, argfltregs[3]);
4031 M_DMFC1(REG_ITMP1, argfltregs[1]);
4032 M_DMFC1(REG_ITMP2, argfltregs[0]);
4034 M_DMTC1(REG_ITMP1, argfltregs[2]);
4035 M_DMTC1(REG_ITMP2, argfltregs[1]);
4038 M_ALD(argintregs[0], REG_PV, -4 * 8); /* load adress of jni_environement */
4039 M_ALD(REG_ITMP3, REG_PV, -1 * 8); /* load adress of native method */
4040 M_JSR(REG_RA, REG_ITMP3); /* call native method */
4041 M_NOP; /* delay slot */
4043 /* remove stackframe if there is one */
4044 if (stackframesize) {
4045 M_LDA(REG_SP, REG_SP, stackframesize * 8);
4048 /* 17 instructions */
4050 M_LDA(REG_SP, REG_SP, -(3 * 8));
4051 M_AST(REG_RA, REG_SP, 0 * 8);
4052 M_LST(REG_RESULT, REG_SP, 1 * 8);
4053 M_DST(REG_FRESULT, REG_SP, 2 * 8);
4054 M_ALD(argintregs[0], REG_PV, -6 * 8);
4055 M_MOV(REG_RESULT, argintregs[1]);
4056 M_DMFC1(REG_ITMP1, REG_FRESULT);
4057 M_DMTC1(REG_ITMP1, argfltregs[2]);
4058 M_DMTC1(REG_ITMP1, argfltregs[3]);
4059 M_ALD(REG_ITMP3, REG_PV, -7 * 8);/* builtin_displaymethodstop */
4060 M_JSR(REG_RA, REG_ITMP3);
4062 disp = -(int) (mcodeptr - (s4*) cs) * 4;
4063 M_LDA(REG_PV, REG_RA, disp);
4064 M_ALD(REG_RA, REG_SP, 0 * 8);
4065 M_LLD(REG_RESULT, REG_SP, 1 * 8);
4066 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
4067 M_LDA(REG_SP, REG_SP, 3 * 8);
4070 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* get address of exceptionptr */
4072 M_LLD(REG_RA, REG_SP, 0); /* load return address */
4073 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4075 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
4076 M_LDA(REG_SP, REG_SP, 8); /* remove stackframe, delay slot */
4078 M_RET(REG_RA); /* return to caller */
4079 M_NOP; /* delay slot */
4081 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4082 M_ALD(REG_ITMP3, REG_PV, -3 * 8); /* load asm exception handler address */
4084 M_JMP(REG_ITMP3); /* jump to asm exception handler */
4085 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4088 (void) docacheflush((void*) cs, (char*) mcodeptr - (char*) cs);
4091 dolog_plain("stubsize: %d (for %d params)\n",
4092 (int) (mcodeptr - (s4*) s), m->paramcount);
4096 count_nstub_len += NATIVESTUBSIZE * 8;
4099 return (u1 *) (s + NATIVESTUBOFFSET);
4103 /* function: removenativestub **************************************************
4105 removes a previously created native-stub from memory
4107 *******************************************************************************/
4109 void removenativestub(u1 *stub)
4111 CFREE((u8*) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 8);
4115 void docacheflush(u1 *p, long bytelen)
4117 u1 *e = p + bytelen;
4118 long psize = sysconf(_SC_PAGESIZE);
4119 p -= (long) p & (psize-1);
4120 e += psize - ((((long) e - 1) & (psize-1)) + 1);
4122 mprotect(p, bytelen, PROT_READ|PROT_WRITE|PROT_EXEC);
4127 * These are local overrides for various environment variables in Emacs.
4128 * Please do not remove this and leave it at the end of the file, where
4129 * Emacs will automagically detect them.
4130 * ---------------------------------------------------------------------
4133 * indent-tabs-mode: t