1 /* jit/alpha/codegen.c - machine code generator for alpha
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 $Id: codegen.c 691 2003-12-05 18:17:22Z stefan $
49 /* include independent code generation stuff */
50 #include "codegen.inc"
54 /* *****************************************************************************
56 Datatypes and Register Allocations:
57 -----------------------------------
59 On 64-bit-machines (like the Alpha) all operands are stored in the
60 registers in a 64-bit form, even when the correspondig JavaVM operands
61 only need 32 bits. This is done by a canonical representation:
63 32-bit integers are allways stored as sign-extended 64-bit values (this
64 approach is directly supported by the Alpha architecture and is very easy
67 32-bit-floats are stored in a 64-bit doubleprecision register by simply
68 expanding the exponent and mantissa with zeroes. (also supported by the
74 The calling conventions and the layout of the stack is explained in detail
75 in the documention file: calling.doc
77 *******************************************************************************/
80 /* register descripton - array ************************************************/
82 /* #define REG_RES 0 reserved register for OS or code generator */
83 /* #define REG_RET 1 return value register */
84 /* #define REG_EXC 2 exception value register (only old jit) */
85 /* #define REG_SAV 3 (callee) saved register */
86 /* #define REG_TMP 4 scratch temporary register (caller saved) */
87 /* #define REG_ARG 5 argument register (caller saved) */
89 /* #define REG_END -1 last entry in tables */
92 REG_RET, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
93 REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
94 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
95 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
98 /* for use of reserved registers, see comment above */
100 int nregdescfloat[] = {
101 REG_RET, REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
102 REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
103 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
104 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES,
107 /* for use of reserved registers, see comment above */
110 /* parameter allocation mode */
112 int nreg_parammode = PARAMMODE_NUMBERED;
114 /* parameter-registers will be allocated by assigning the
115 1. parameter: int/float-reg 16
116 2. parameter: int/float-reg 17
117 3. parameter: int/float-reg 18 ....
121 /* stackframe-infos ***********************************************************/
123 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
125 /* -> see file 'calling.doc' */
128 /* additional functions and macros to generate code ***************************/
130 /* #define BlockPtrOfPC(pc) block+block_index[pc] */
131 #define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
135 #define COUNT_SPILLS count_spills++
141 /* gen_nullptr_check(objreg) */
143 #ifdef SOFTNULLPTRCHECK
144 #define gen_nullptr_check(objreg) \
146 M_BEQZ((objreg), 0);\
147 codegen_addxnullrefs(mcodeptr);\
150 #define gen_nullptr_check(objreg)
154 /* MCODECHECK(icnt) */
156 #define MCODECHECK(icnt) \
157 if((mcodeptr + (icnt)) > mcodeend) mcodeptr = codegen_increase((u1*) mcodeptr)
160 generates an integer-move from register a to b.
161 if a and b are the same int-register, no code will be generated.
164 #define M_INTMOVE(a,b) if(a!=b){M_MOV(a,b);}
168 generates a floating-point-move from register a to b.
169 if a and b are the same float-register, no code will be generated
172 #define M_FLTMOVE(a,b) if(a!=b){M_FMOV(a,b);}
176 this function generates code to fetch data from a pseudo-register
177 into a real register.
178 If the pseudo-register has actually been assigned to a real
179 register, no code will be emitted, since following operations
180 can use this register directly.
182 v: pseudoregister to be fetched from
183 tempregnum: temporary register to be used if v is actually spilled to ram
185 return: the register number, where the operand can be found after
186 fetching (this wil be either tempregnum or the register
187 number allready given to v)
190 #define var_to_reg_int(regnr,v,tempnr) { \
191 if ((v)->flags & INMEMORY) \
192 {COUNT_SPILLS;M_LLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
193 else regnr=(v)->regoff; \
197 #define var_to_reg_flt(regnr,v,tempnr) { \
198 if ((v)->flags & INMEMORY) \
199 {COUNT_SPILLS;M_DLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
200 else regnr=(v)->regoff; \
205 This function determines a register, to which the result of an operation
206 should go, when it is ultimatively intended to store the result in
208 If v is assigned to an actual register, this register will be returned.
209 Otherwise (when v is spilled) this function returns tempregnum.
210 If not already done, regoff and flags are set in the stack location.
213 static int reg_of_var(stackptr v, int tempregnum)
217 switch (v->varkind) {
219 if (!(v->flags & INMEMORY))
223 var = &(interfaces[v->varnum][v->type]);
224 v->regoff = var->regoff;
225 if (!(var->flags & INMEMORY))
229 var = &(locals[v->varnum][v->type]);
230 v->regoff = var->regoff;
231 if (!(var->flags & INMEMORY))
235 v->regoff = v->varnum;
236 if (IS_FLT_DBL_TYPE(v->type)) {
237 if (v->varnum < fltreg_argnum) {
238 v->regoff = argfltregs[v->varnum];
239 return(argfltregs[v->varnum]);
243 if (v->varnum < intreg_argnum) {
244 v->regoff = argintregs[v->varnum];
245 return(argintregs[v->varnum]);
247 v->regoff -= intreg_argnum;
250 v->flags |= INMEMORY;
255 /* store_reg_to_var_xxx:
256 This function generates the code to store the result of an operation
257 back into a spilled pseudo-variable.
258 If the pseudo-variable has not been spilled in the first place, this
259 function will generate nothing.
261 v ............ Pseudovariable
262 tempregnum ... Number of the temporary registers as returned by
266 #define store_reg_to_var_int(sptr, tempregnum) { \
267 if ((sptr)->flags & INMEMORY) { \
269 M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
273 #define store_reg_to_var_flt(sptr, tempregnum) { \
274 if ((sptr)->flags & INMEMORY) { \
276 M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
281 /* NullPointerException handlers and exception handling initialisation */
283 typedef struct sigctx_struct {
285 long sc_onstack; /* sigstack state to restore */
286 long sc_mask; /* signal mask to restore */
287 long sc_pc; /* pc at time of signal */
288 long sc_ps; /* psl to retore */
289 long sc_regs[32]; /* processor regs 0 to 31 */
290 long sc_ownedfp; /* fp has been used */
291 long sc_fpregs[32]; /* fp regs 0 to 31 */
292 unsigned long sc_fpcr; /* floating point control register */
293 unsigned long sc_fp_control; /* software fpcr */
295 unsigned long sc_reserved1, sc_reserved2;
296 unsigned long sc_ssize;
298 unsigned long sc_traparg_a0;
299 unsigned long sc_traparg_a1;
300 unsigned long sc_traparg_a2;
301 unsigned long sc_fp_trap_pc;
302 unsigned long sc_fp_trigger_sum;
303 unsigned long sc_fp_trigger_inst;
304 unsigned long sc_retcode[2];
308 /* NullPointerException signal handler for hardware null pointer check */
310 void catch_NullPointerException(int sig, int code, sigctx_struct *sigctx)
316 /* Reset signal handler - necessary for SysV, does no harm for BSD */
318 instr = *((int*)(sigctx->sc_pc));
319 faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f];
321 if (faultaddr == 0) {
322 signal(sig, (void*) catch_NullPointerException); /* reinstall handler */
324 sigaddset(&nsig, sig);
325 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
326 sigctx->sc_regs[REG_ITMP1_XPTR] =
327 (long) proto_java_lang_NullPointerException;
328 sigctx->sc_regs[REG_ITMP2_XPC] = sigctx->sc_pc;
329 sigctx->sc_pc = (long) asm_handle_exception;
333 faultaddr += (long) ((instr << 16) >> 16);
334 fprintf(stderr, "faulting address: 0x%16lx\n", faultaddr);
335 panic("Stack overflow");
342 void init_exceptions(void)
347 /* Linux on Digital Alpha needs an initialisation of the ieee floating point
348 control for IEEE compliant arithmetic (option -mieee of GCC). Under
349 Digital Unix this is done automatically.
354 extern unsigned long ieee_get_fp_control();
355 extern void ieee_set_fp_control(unsigned long fp_control);
357 void init_exceptions(void)
359 /* initialize floating point control */
361 ieee_set_fp_control(ieee_get_fp_control()
362 & ~IEEE_TRAP_ENABLE_INV
363 & ~IEEE_TRAP_ENABLE_DZE
364 /* & ~IEEE_TRAP_ENABLE_UNF we dont want underflow */
365 & ~IEEE_TRAP_ENABLE_OVF);
368 /* install signal handlers we need to convert to exceptions */
373 signal(SIGSEGV, (void*) catch_NullPointerException);
377 signal(SIGBUS, (void*) catch_NullPointerException);
383 /* function gen_mcode **********************************************************
385 generates machine code
387 *******************************************************************************/
389 #define MethodPointer -8
390 #define FrameSize -12
395 #define ExTableSize -32
396 #define ExTableStart -32
398 #define ExEntrySize -32
401 #define ExHandlerPC -24
402 #define ExCatchType -32
406 int len, s1, s2, s3, d, bbs;
418 savedregs_num = (isleafmethod) ? 0 : 1; /* space to save the RA */
420 /* space to save used callee saved registers */
422 savedregs_num += (savintregcnt - maxsavintreguse);
423 savedregs_num += (savfltregcnt - maxsavfltreguse);
425 parentargs_base = maxmemuse + savedregs_num;
427 #ifdef USE_THREADS /* space to save argument of monitor_enter */
429 if (checksync && (method->flags & ACC_SYNCHRONIZED))
434 /* create method header */
436 (void) dseg_addaddress(method); /* MethodPointer */
437 (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
441 /* IsSync contains the offset relative to the stack pointer for the
442 argument of monitor_exit used in the exception handler. Since the
443 offset could be zero and give a wrong meaning of the flag it is
447 if (checksync && (method->flags & ACC_SYNCHRONIZED))
448 (void) dseg_adds4((maxmemuse + 1) * 8); /* IsSync */
453 (void) dseg_adds4(0); /* IsSync */
455 (void) dseg_adds4(isleafmethod); /* IsLeaf */
456 (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
457 (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
458 (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
460 /* create exception table */
462 for (ex = extable; ex != NULL; ex = ex->down) {
465 if (ex->start != NULL)
466 printf("adding start - %d - ", ex->start->debug_nr);
468 printf("PANIC - start is NULL");
473 dseg_addtarget(ex->start);
477 printf("adding end - %d - ", ex->end->debug_nr);
479 printf("PANIC - end is NULL");
484 dseg_addtarget(ex->end);
487 if (ex->handler != NULL)
488 printf("adding handler - %d\n", ex->handler->debug_nr);
490 printf("PANIC - handler is NULL");
495 dseg_addtarget(ex->handler);
497 (void) dseg_addaddress(ex->catchtype);
500 /* initialize mcode variables */
502 mcodeptr = (s4*) mcodebase;
503 mcodeend = (s4*) (mcodebase + mcodesize);
504 MCODECHECK(128 + mparamcount);
506 /* create stack frame (if necessary) */
509 {M_LDA (REG_SP, REG_SP, -parentargs_base * 8);}
511 /* save return address and used callee saved registers */
515 {p--; M_AST (REG_RA, REG_SP, 8*p);}
516 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
517 {p--; M_LST (savintregs[r], REG_SP, 8 * p);}
518 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
519 {p--; M_DST (savfltregs[r], REG_SP, 8 * p);}
521 /* save monitorenter argument */
524 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
525 if (method->flags & ACC_STATIC) {
526 p = dseg_addaddress (class);
527 M_ALD(REG_ITMP1, REG_PV, p);
528 M_AST(REG_ITMP1, REG_SP, 8 * maxmemuse);
531 M_AST (argintregs[0], REG_SP, 8 * maxmemuse);
536 /* copy argument registers to stack and call trace function with pointer
537 to arguments on stack. ToDo: save floating point registers !!!!!!!!!
542 M_LDA (REG_SP, REG_SP, -(14*8));
543 M_AST(REG_RA, REG_SP, 1*8);
545 M_LST(argintregs[0], REG_SP, 2*8);
546 M_LST(argintregs[1], REG_SP, 3*8);
547 M_LST(argintregs[2], REG_SP, 4*8);
548 M_LST(argintregs[3], REG_SP, 5*8);
549 M_LST(argintregs[4], REG_SP, 6*8);
550 M_LST(argintregs[5], REG_SP, 7*8);
552 M_DST(argfltregs[0], REG_SP, 8*8);
553 M_DST(argfltregs[1], REG_SP, 9*8);
554 M_DST(argfltregs[2], REG_SP, 10*8);
555 M_DST(argfltregs[3], REG_SP, 11*8);
556 M_DST(argfltregs[4], REG_SP, 12*8);
557 M_DST(argfltregs[5], REG_SP, 13*8);
559 p = dseg_addaddress (method);
560 M_ALD(REG_ITMP1, REG_PV, p);
561 M_AST(REG_ITMP1, REG_SP, 0);
562 p = dseg_addaddress ((void*) (builtin_trace_args));
563 M_ALD(REG_PV, REG_PV, p);
564 M_JSR(REG_RA, REG_PV);
565 disp = -(int)((u1*) mcodeptr - mcodebase);
566 M_LDA(REG_PV, REG_RA, disp);
567 M_ALD(REG_RA, REG_SP, 1*8);
569 M_LLD(argintregs[0], REG_SP, 2*8);
570 M_LLD(argintregs[1], REG_SP, 3*8);
571 M_LLD(argintregs[2], REG_SP, 4*8);
572 M_LLD(argintregs[3], REG_SP, 5*8);
573 M_LLD(argintregs[4], REG_SP, 6*8);
574 M_LLD(argintregs[5], REG_SP, 7*8);
576 M_DLD(argfltregs[0], REG_SP, 8*8);
577 M_DLD(argfltregs[1], REG_SP, 9*8);
578 M_DLD(argfltregs[2], REG_SP, 10*8);
579 M_DLD(argfltregs[3], REG_SP, 11*8);
580 M_DLD(argfltregs[4], REG_SP, 12*8);
581 M_DLD(argfltregs[5], REG_SP, 13*8);
583 M_LDA (REG_SP, REG_SP, 14*8);
586 /* take arguments out of register or stack frame */
588 for (p = 0, l = 0; p < mparamcount; p++) {
590 var = &(locals[l][t]);
592 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
597 if (IS_INT_LNG_TYPE(t)) { /* integer args */
598 if (p < INT_ARG_CNT) { /* register arguments */
599 if (!(var->flags & INMEMORY)) /* reg arg -> register */
600 {M_INTMOVE (argintregs[p], r);}
601 else /* reg arg -> spilled */
602 M_LST (argintregs[p], REG_SP, 8 * r);
604 else { /* stack arguments */
605 pa = p - INT_ARG_CNT;
606 if (!(var->flags & INMEMORY)) /* stack arg -> register */
607 M_LLD (r, REG_SP, 8 * (parentargs_base + pa));
608 else { /* stack arg -> spilled */
609 M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
610 M_LST (REG_ITMP1, REG_SP, 8 * r);
614 else { /* floating args */
615 if (p < FLT_ARG_CNT) { /* register arguments */
616 if (!(var->flags & INMEMORY)) /* reg arg -> register */
617 {M_FLTMOVE (argfltregs[p], r);}
618 else /* reg arg -> spilled */
619 M_DST (argfltregs[p], REG_SP, 8 * r);
621 else { /* stack arguments */
622 pa = p - FLT_ARG_CNT;
623 if (!(var->flags & INMEMORY)) /* stack-arg -> register */
624 M_DLD (r, REG_SP, 8 * (parentargs_base + pa) );
625 else { /* stack-arg -> spilled */
626 M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
627 M_DST (REG_FTMP1, REG_SP, 8 * r);
633 /* call trace function */
636 if (runverbose && !isleafmethod) {
637 M_LDA (REG_SP, REG_SP, -8);
638 p = dseg_addaddress (method);
639 M_ALD(REG_ITMP1, REG_PV, p);
640 M_AST(REG_ITMP1, REG_SP, 0);
641 p = dseg_addaddress ((void*) (builtin_trace_args));
642 M_ALD(REG_PV, REG_PV, p);
643 M_JSR(REG_RA, REG_PV);
644 M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
645 M_LDA(REG_SP, REG_SP, 8);
649 /* call monitorenter function */
652 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
654 p = dseg_addaddress ((void*) (builtin_monitorenter));
655 M_ALD(REG_PV, REG_PV, p);
656 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
657 M_JSR(REG_RA, REG_PV);
658 disp = -(int)((u1*) mcodeptr - mcodebase);
659 M_LDA(REG_PV, REG_RA, disp);
664 /* end of header generation */
666 /* walk through all basic blocks */
667 for (/* bbs = block_count, */ bptr = block; /* --bbs >= 0 */ bptr != NULL; bptr = bptr->next) {
669 bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
671 if (bptr->flags >= BBREACHED) {
673 /* branch resolving */
677 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
678 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
679 brefs->branchpos, bptr->mpc);
683 /* copy interface registers to their destination */
688 while (src != NULL) {
690 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
691 d = reg_of_var(src, REG_ITMP1);
692 M_INTMOVE(REG_ITMP1, d);
693 store_reg_to_var_int(src, d);
696 d = reg_of_var(src, REG_IFTMP);
697 if ((src->varkind != STACKVAR)) {
699 if (IS_FLT_DBL_TYPE(s2)) {
700 if (!(interfaces[len][s2].flags & INMEMORY)) {
701 s1 = interfaces[len][s2].regoff;
705 M_DLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
707 store_reg_to_var_flt(src, d);
710 if (!(interfaces[len][s2].flags & INMEMORY)) {
711 s1 = interfaces[len][s2].regoff;
715 M_LLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
717 store_reg_to_var_int(src, d);
724 /* walk through all instructions */
728 for (iptr = bptr->iinstr;
730 src = iptr->dst, len--, iptr++) {
732 MCODECHECK(64); /* an instruction usually needs < 64 words */
735 case ICMD_NOP: /* ... ==> ... */
738 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
740 var_to_reg_int(s1, src, REG_ITMP1);
742 codegen_addxnullrefs(mcodeptr);
745 /* constant operations ************************************************/
747 #define ICONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LDA(r,REG_ZERO,c);} \
748 else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
750 #define LCONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LDA(r,REG_ZERO,c);} \
751 else{a=dseg_adds8(c);M_LLD(r,REG_PV,a);}
753 case ICMD_ICONST: /* ... ==> ..., constant */
754 /* op1 = 0, val.i = constant */
756 d = reg_of_var(iptr->dst, REG_ITMP1);
757 ICONST(d, iptr->val.i);
758 store_reg_to_var_int(iptr->dst, d);
761 case ICMD_LCONST: /* ... ==> ..., constant */
762 /* op1 = 0, val.l = constant */
764 d = reg_of_var(iptr->dst, REG_ITMP1);
765 LCONST(d, iptr->val.l);
766 store_reg_to_var_int(iptr->dst, d);
769 case ICMD_FCONST: /* ... ==> ..., constant */
770 /* op1 = 0, val.f = constant */
772 d = reg_of_var (iptr->dst, REG_FTMP1);
773 a = dseg_addfloat (iptr->val.f);
775 store_reg_to_var_flt (iptr->dst, d);
778 case ICMD_DCONST: /* ... ==> ..., constant */
779 /* op1 = 0, val.d = constant */
781 d = reg_of_var (iptr->dst, REG_FTMP1);
782 a = dseg_adddouble (iptr->val.d);
784 store_reg_to_var_flt (iptr->dst, d);
787 case ICMD_ACONST: /* ... ==> ..., constant */
788 /* op1 = 0, val.a = constant */
790 d = reg_of_var(iptr->dst, REG_ITMP1);
792 a = dseg_addaddress (iptr->val.a);
796 M_INTMOVE(REG_ZERO, d);
798 store_reg_to_var_int(iptr->dst, d);
802 /* load/store operations **********************************************/
804 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
805 case ICMD_LLOAD: /* op1 = local variable */
808 d = reg_of_var(iptr->dst, REG_ITMP1);
809 if ((iptr->dst->varkind == LOCALVAR) &&
810 (iptr->dst->varnum == iptr->op1))
812 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
813 if (var->flags & INMEMORY)
814 M_LLD(d, REG_SP, 8 * var->regoff);
816 {M_INTMOVE(var->regoff,d);}
817 store_reg_to_var_int(iptr->dst, d);
820 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
821 case ICMD_DLOAD: /* op1 = local variable */
823 d = reg_of_var(iptr->dst, REG_FTMP1);
824 if ((iptr->dst->varkind == LOCALVAR) &&
825 (iptr->dst->varnum == iptr->op1))
827 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
828 if (var->flags & INMEMORY)
829 M_DLD(d, REG_SP, 8 * var->regoff);
831 {M_FLTMOVE(var->regoff,d);}
832 store_reg_to_var_flt(iptr->dst, d);
836 case ICMD_ISTORE: /* ..., value ==> ... */
837 case ICMD_LSTORE: /* op1 = local variable */
840 if ((src->varkind == LOCALVAR) &&
841 (src->varnum == iptr->op1))
843 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
844 if (var->flags & INMEMORY) {
845 var_to_reg_int(s1, src, REG_ITMP1);
846 M_LST(s1, REG_SP, 8 * var->regoff);
849 var_to_reg_int(s1, src, var->regoff);
850 M_INTMOVE(s1, var->regoff);
854 case ICMD_FSTORE: /* ..., value ==> ... */
855 case ICMD_DSTORE: /* op1 = local variable */
857 if ((src->varkind == LOCALVAR) &&
858 (src->varnum == iptr->op1))
860 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
861 if (var->flags & INMEMORY) {
862 var_to_reg_flt(s1, src, REG_FTMP1);
863 M_DST(s1, REG_SP, 8 * var->regoff);
866 var_to_reg_flt(s1, src, var->regoff);
867 M_FLTMOVE(s1, var->regoff);
872 /* pop/dup/swap operations ********************************************/
874 /* attention: double and longs are only one entry in CACAO ICMDs */
876 case ICMD_POP: /* ..., value ==> ... */
877 case ICMD_POP2: /* ..., value, value ==> ... */
880 #define M_COPY(from,to) \
881 d = reg_of_var(to, REG_IFTMP); \
882 if ((from->regoff != to->regoff) || \
883 ((from->flags ^ to->flags) & INMEMORY)) { \
884 if (IS_FLT_DBL_TYPE(from->type)) { \
885 var_to_reg_flt(s1, from, d); \
887 store_reg_to_var_flt(to, d); \
890 var_to_reg_int(s1, from, d); \
892 store_reg_to_var_int(to, d); \
896 case ICMD_DUP: /* ..., a ==> ..., a, a */
897 M_COPY(src, iptr->dst);
900 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
902 M_COPY(src, iptr->dst->prev->prev);
904 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
906 M_COPY(src, iptr->dst);
907 M_COPY(src->prev, iptr->dst->prev);
910 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
912 M_COPY(src->prev, iptr->dst->prev->prev->prev);
914 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
916 M_COPY(src, iptr->dst);
917 M_COPY(src->prev, iptr->dst->prev);
918 M_COPY(src->prev->prev, iptr->dst->prev->prev);
919 M_COPY(src, iptr->dst->prev->prev->prev);
922 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
924 M_COPY(src, iptr->dst);
925 M_COPY(src->prev, iptr->dst->prev);
926 M_COPY(src->prev->prev, iptr->dst->prev->prev);
927 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
928 M_COPY(src, iptr->dst->prev->prev->prev->prev);
929 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
932 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
934 M_COPY(src, iptr->dst->prev);
935 M_COPY(src->prev, iptr->dst);
939 /* integer operations *************************************************/
941 case ICMD_INEG: /* ..., value ==> ..., - value */
943 var_to_reg_int(s1, src, REG_ITMP1);
944 d = reg_of_var(iptr->dst, REG_ITMP3);
945 M_ISUB(REG_ZERO, s1, d);
946 store_reg_to_var_int(iptr->dst, d);
949 case ICMD_LNEG: /* ..., value ==> ..., - value */
951 var_to_reg_int(s1, src, REG_ITMP1);
952 d = reg_of_var(iptr->dst, REG_ITMP3);
953 M_LSUB(REG_ZERO, s1, d);
954 store_reg_to_var_int(iptr->dst, d);
957 case ICMD_I2L: /* ..., value ==> ..., value */
959 var_to_reg_int(s1, src, REG_ITMP1);
960 d = reg_of_var(iptr->dst, REG_ITMP3);
962 store_reg_to_var_int(iptr->dst, d);
965 case ICMD_L2I: /* ..., value ==> ..., value */
967 var_to_reg_int(s1, src, REG_ITMP1);
968 d = reg_of_var(iptr->dst, REG_ITMP3);
969 M_IADD(s1, REG_ZERO, d );
970 store_reg_to_var_int(iptr->dst, d);
973 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
975 var_to_reg_int(s1, src, REG_ITMP1);
976 d = reg_of_var(iptr->dst, REG_ITMP3);
977 if (has_ext_instr_set) {
981 M_SLL_IMM(s1, 56, d);
982 M_SRA_IMM( d, 56, d);
984 store_reg_to_var_int(iptr->dst, d);
987 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
989 var_to_reg_int(s1, src, REG_ITMP1);
990 d = reg_of_var(iptr->dst, REG_ITMP3);
992 store_reg_to_var_int(iptr->dst, d);
995 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
997 var_to_reg_int(s1, src, REG_ITMP1);
998 d = reg_of_var(iptr->dst, REG_ITMP3);
999 if (has_ext_instr_set) {
1003 M_SLL_IMM(s1, 48, d);
1004 M_SRA_IMM( d, 48, d);
1006 store_reg_to_var_int(iptr->dst, d);
1010 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1012 var_to_reg_int(s1, src->prev, REG_ITMP1);
1013 var_to_reg_int(s2, src, REG_ITMP2);
1014 d = reg_of_var(iptr->dst, REG_ITMP3);
1016 store_reg_to_var_int(iptr->dst, d);
1019 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1020 /* val.i = constant */
1022 var_to_reg_int(s1, src, REG_ITMP1);
1023 d = reg_of_var(iptr->dst, REG_ITMP3);
1024 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1025 M_IADD_IMM(s1, iptr->val.i, d);
1028 ICONST(REG_ITMP2, iptr->val.i);
1029 M_IADD(s1, REG_ITMP2, d);
1031 store_reg_to_var_int(iptr->dst, d);
1034 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1036 var_to_reg_int(s1, src->prev, REG_ITMP1);
1037 var_to_reg_int(s2, src, REG_ITMP2);
1038 d = reg_of_var(iptr->dst, REG_ITMP3);
1040 store_reg_to_var_int(iptr->dst, d);
1043 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1044 /* val.l = constant */
1046 var_to_reg_int(s1, src, REG_ITMP1);
1047 d = reg_of_var(iptr->dst, REG_ITMP3);
1048 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1049 M_LADD_IMM(s1, iptr->val.l, d);
1052 LCONST(REG_ITMP2, iptr->val.l);
1053 M_LADD(s1, REG_ITMP2, d);
1055 store_reg_to_var_int(iptr->dst, d);
1058 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1060 var_to_reg_int(s1, src->prev, REG_ITMP1);
1061 var_to_reg_int(s2, src, REG_ITMP2);
1062 d = reg_of_var(iptr->dst, REG_ITMP3);
1064 store_reg_to_var_int(iptr->dst, d);
1067 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1068 /* val.i = constant */
1070 var_to_reg_int(s1, src, REG_ITMP1);
1071 d = reg_of_var(iptr->dst, REG_ITMP3);
1072 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1073 M_ISUB_IMM(s1, iptr->val.i, d);
1076 ICONST(REG_ITMP2, iptr->val.i);
1077 M_ISUB(s1, REG_ITMP2, d);
1079 store_reg_to_var_int(iptr->dst, d);
1082 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1084 var_to_reg_int(s1, src->prev, REG_ITMP1);
1085 var_to_reg_int(s2, src, REG_ITMP2);
1086 d = reg_of_var(iptr->dst, REG_ITMP3);
1088 store_reg_to_var_int(iptr->dst, d);
1091 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1092 /* val.l = constant */
1094 var_to_reg_int(s1, src, REG_ITMP1);
1095 d = reg_of_var(iptr->dst, REG_ITMP3);
1096 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1097 M_LSUB_IMM(s1, iptr->val.l, d);
1100 LCONST(REG_ITMP2, iptr->val.l);
1101 M_LSUB(s1, REG_ITMP2, d);
1103 store_reg_to_var_int(iptr->dst, d);
1106 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1108 var_to_reg_int(s1, src->prev, REG_ITMP1);
1109 var_to_reg_int(s2, src, REG_ITMP2);
1110 d = reg_of_var(iptr->dst, REG_ITMP3);
1112 store_reg_to_var_int(iptr->dst, d);
1115 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1116 /* val.i = constant */
1118 var_to_reg_int(s1, src, REG_ITMP1);
1119 d = reg_of_var(iptr->dst, REG_ITMP3);
1120 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1121 M_IMUL_IMM(s1, iptr->val.i, d);
1124 ICONST(REG_ITMP2, iptr->val.i);
1125 M_IMUL(s1, REG_ITMP2, d);
1127 store_reg_to_var_int(iptr->dst, d);
1130 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1132 var_to_reg_int(s1, src->prev, REG_ITMP1);
1133 var_to_reg_int(s2, src, REG_ITMP2);
1134 d = reg_of_var(iptr->dst, REG_ITMP3);
1136 store_reg_to_var_int(iptr->dst, d);
1139 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1140 /* val.l = constant */
1142 var_to_reg_int(s1, src, REG_ITMP1);
1143 d = reg_of_var(iptr->dst, REG_ITMP3);
1144 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1145 M_LMUL_IMM(s1, iptr->val.l, d);
1148 LCONST(REG_ITMP2, iptr->val.l);
1149 M_LMUL(s1, REG_ITMP2, d);
1151 store_reg_to_var_int(iptr->dst, d);
1154 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1155 case ICMD_LDIVPOW2: /* val.i = constant */
1157 var_to_reg_int(s1, src, REG_ITMP1);
1158 d = reg_of_var(iptr->dst, REG_ITMP3);
1159 if (iptr->val.i <= 15) {
1160 M_LDA(REG_ITMP2, s1, (1 << iptr->val.i) -1);
1161 M_CMOVGE(s1, s1, REG_ITMP2);
1164 M_SRA_IMM(s1, 63, REG_ITMP2);
1165 M_SRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1166 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1168 M_SRA_IMM(REG_ITMP2, iptr->val.i, d);
1169 store_reg_to_var_int(iptr->dst, d);
1172 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1174 var_to_reg_int(s1, src->prev, REG_ITMP1);
1175 var_to_reg_int(s2, src, REG_ITMP2);
1176 d = reg_of_var(iptr->dst, REG_ITMP3);
1177 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1178 M_SLL(s1, REG_ITMP3, d);
1179 M_IADD(d, REG_ZERO, d);
1180 store_reg_to_var_int(iptr->dst, d);
1183 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1184 /* val.i = constant */
1186 var_to_reg_int(s1, src, REG_ITMP1);
1187 d = reg_of_var(iptr->dst, REG_ITMP3);
1188 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1189 M_IADD(d, REG_ZERO, d);
1190 store_reg_to_var_int(iptr->dst, d);
1193 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1195 var_to_reg_int(s1, src->prev, REG_ITMP1);
1196 var_to_reg_int(s2, src, REG_ITMP2);
1197 d = reg_of_var(iptr->dst, REG_ITMP3);
1198 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1199 M_SRA(s1, REG_ITMP3, d);
1200 store_reg_to_var_int(iptr->dst, d);
1203 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1204 /* val.i = constant */
1206 var_to_reg_int(s1, src, REG_ITMP1);
1207 d = reg_of_var(iptr->dst, REG_ITMP3);
1208 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1209 store_reg_to_var_int(iptr->dst, d);
1212 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1214 var_to_reg_int(s1, src->prev, REG_ITMP1);
1215 var_to_reg_int(s2, src, REG_ITMP2);
1216 d = reg_of_var(iptr->dst, REG_ITMP3);
1217 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1219 M_SRL(d, REG_ITMP2, d);
1220 M_IADD(d, REG_ZERO, d);
1221 store_reg_to_var_int(iptr->dst, d);
1224 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1225 /* val.i = constant */
1227 var_to_reg_int(s1, src, REG_ITMP1);
1228 d = reg_of_var(iptr->dst, REG_ITMP3);
1230 M_SRL_IMM(d, iptr->val.i & 0x1f, d);
1231 M_IADD(d, REG_ZERO, d);
1232 store_reg_to_var_int(iptr->dst, d);
1235 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1237 var_to_reg_int(s1, src->prev, REG_ITMP1);
1238 var_to_reg_int(s2, src, REG_ITMP2);
1239 d = reg_of_var(iptr->dst, REG_ITMP3);
1241 store_reg_to_var_int(iptr->dst, d);
1244 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1245 /* val.i = constant */
1247 var_to_reg_int(s1, src, REG_ITMP1);
1248 d = reg_of_var(iptr->dst, REG_ITMP3);
1249 M_SLL_IMM(s1, iptr->val.i & 0x3f, d);
1250 store_reg_to_var_int(iptr->dst, d);
1253 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1255 var_to_reg_int(s1, src->prev, REG_ITMP1);
1256 var_to_reg_int(s2, src, REG_ITMP2);
1257 d = reg_of_var(iptr->dst, REG_ITMP3);
1259 store_reg_to_var_int(iptr->dst, d);
1262 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1263 /* val.i = constant */
1265 var_to_reg_int(s1, src, REG_ITMP1);
1266 d = reg_of_var(iptr->dst, REG_ITMP3);
1267 M_SRA_IMM(s1, iptr->val.i & 0x3f, d);
1268 store_reg_to_var_int(iptr->dst, d);
1271 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1273 var_to_reg_int(s1, src->prev, REG_ITMP1);
1274 var_to_reg_int(s2, src, REG_ITMP2);
1275 d = reg_of_var(iptr->dst, REG_ITMP3);
1277 store_reg_to_var_int(iptr->dst, d);
1280 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1281 /* val.i = constant */
1283 var_to_reg_int(s1, src, REG_ITMP1);
1284 d = reg_of_var(iptr->dst, REG_ITMP3);
1285 M_SRL_IMM(s1, iptr->val.i & 0x3f, d);
1286 store_reg_to_var_int(iptr->dst, d);
1289 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1292 var_to_reg_int(s1, src->prev, REG_ITMP1);
1293 var_to_reg_int(s2, src, REG_ITMP2);
1294 d = reg_of_var(iptr->dst, REG_ITMP3);
1296 store_reg_to_var_int(iptr->dst, d);
1299 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1300 /* val.i = constant */
1302 var_to_reg_int(s1, src, REG_ITMP1);
1303 d = reg_of_var(iptr->dst, REG_ITMP3);
1304 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1305 M_AND_IMM(s1, iptr->val.i, d);
1307 else if (iptr->val.i == 0xffff) {
1310 else if (iptr->val.i == 0xffffff) {
1311 M_ZAPNOT_IMM(s1, 0x07, d);
1314 ICONST(REG_ITMP2, iptr->val.i);
1315 M_AND(s1, REG_ITMP2, d);
1317 store_reg_to_var_int(iptr->dst, d);
1320 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1321 /* val.i = constant */
1323 var_to_reg_int(s1, src, REG_ITMP1);
1324 d = reg_of_var(iptr->dst, REG_ITMP3);
1326 M_MOV(s1, REG_ITMP1);
1329 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1330 M_AND_IMM(s1, iptr->val.i, d);
1332 M_ISUB(REG_ZERO, s1, d);
1333 M_AND_IMM(d, iptr->val.i, d);
1335 else if (iptr->val.i == 0xffff) {
1338 M_ISUB(REG_ZERO, s1, d);
1341 else if (iptr->val.i == 0xffffff) {
1342 M_ZAPNOT_IMM(s1, 0x07, d);
1344 M_ISUB(REG_ZERO, s1, d);
1345 M_ZAPNOT_IMM(d, 0x07, d);
1348 ICONST(REG_ITMP2, iptr->val.i);
1349 M_AND(s1, REG_ITMP2, d);
1351 M_ISUB(REG_ZERO, s1, d);
1352 M_AND(d, REG_ITMP2, d);
1354 M_ISUB(REG_ZERO, d, d);
1355 store_reg_to_var_int(iptr->dst, d);
1358 case ICMD_IREM0X10001: /* ..., value ==> ..., value % 0x100001 */
1360 /* b = value & 0xffff;
1362 a = ((b - a) & 0xffff) + (b < a);
1364 var_to_reg_int(s1, src, REG_ITMP1);
1365 d = reg_of_var(iptr->dst, REG_ITMP3);
1367 M_MOV(s1, REG_ITMP3);
1371 M_CZEXT(s1, REG_ITMP2);
1372 M_SRA_IMM(s1, 16, d);
1373 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1374 M_ISUB(REG_ITMP2, d, d);
1376 M_IADD(d, REG_ITMP1, d);
1377 M_BR(11 + (s1 == REG_ITMP1));
1378 M_ISUB(REG_ZERO, s1, REG_ITMP1);
1379 M_CZEXT(REG_ITMP1, REG_ITMP2);
1380 M_SRA_IMM(REG_ITMP1, 16, d);
1381 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1382 M_ISUB(REG_ITMP2, d, d);
1384 M_IADD(d, REG_ITMP1, d);
1385 M_ISUB(REG_ZERO, d, d);
1386 if (s1 == REG_ITMP1) {
1387 var_to_reg_int(s1, src, REG_ITMP1);
1389 M_SLL_IMM(s1, 33, REG_ITMP2);
1390 M_CMPEQ(REG_ITMP2, REG_ZERO, REG_ITMP2);
1391 M_ISUB(d, REG_ITMP2, d);
1392 store_reg_to_var_int(iptr->dst, d);
1395 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1396 /* val.l = constant */
1398 var_to_reg_int(s1, src, REG_ITMP1);
1399 d = reg_of_var(iptr->dst, REG_ITMP3);
1400 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1401 M_AND_IMM(s1, iptr->val.l, d);
1403 else if (iptr->val.l == 0xffffL) {
1406 else if (iptr->val.l == 0xffffffL) {
1407 M_ZAPNOT_IMM(s1, 0x07, d);
1409 else if (iptr->val.l == 0xffffffffL) {
1412 else if (iptr->val.l == 0xffffffffffL) {
1413 M_ZAPNOT_IMM(s1, 0x1f, d);
1415 else if (iptr->val.l == 0xffffffffffffL) {
1416 M_ZAPNOT_IMM(s1, 0x3f, d);
1418 else if (iptr->val.l == 0xffffffffffffffL) {
1419 M_ZAPNOT_IMM(s1, 0x7f, d);
1422 LCONST(REG_ITMP2, iptr->val.l);
1423 M_AND(s1, REG_ITMP2, d);
1425 store_reg_to_var_int(iptr->dst, d);
1428 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1429 /* val.l = constant */
1431 var_to_reg_int(s1, src, REG_ITMP1);
1432 d = reg_of_var(iptr->dst, REG_ITMP3);
1434 M_MOV(s1, REG_ITMP1);
1437 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1438 M_AND_IMM(s1, iptr->val.l, d);
1440 M_LSUB(REG_ZERO, s1, d);
1441 M_AND_IMM(d, iptr->val.l, d);
1443 else if (iptr->val.l == 0xffffL) {
1446 M_LSUB(REG_ZERO, s1, d);
1449 else if (iptr->val.l == 0xffffffL) {
1450 M_ZAPNOT_IMM(s1, 0x07, d);
1452 M_LSUB(REG_ZERO, s1, d);
1453 M_ZAPNOT_IMM(d, 0x07, d);
1455 else if (iptr->val.l == 0xffffffffL) {
1458 M_LSUB(REG_ZERO, s1, d);
1461 else if (iptr->val.l == 0xffffffffffL) {
1462 M_ZAPNOT_IMM(s1, 0x1f, d);
1464 M_LSUB(REG_ZERO, s1, d);
1465 M_ZAPNOT_IMM(d, 0x1f, d);
1467 else if (iptr->val.l == 0xffffffffffffL) {
1468 M_ZAPNOT_IMM(s1, 0x3f, d);
1470 M_LSUB(REG_ZERO, s1, d);
1471 M_ZAPNOT_IMM(d, 0x3f, d);
1473 else if (iptr->val.l == 0xffffffffffffffL) {
1474 M_ZAPNOT_IMM(s1, 0x7f, d);
1476 M_LSUB(REG_ZERO, s1, d);
1477 M_ZAPNOT_IMM(d, 0x7f, d);
1480 LCONST(REG_ITMP2, iptr->val.l);
1481 M_AND(s1, REG_ITMP2, d);
1483 M_LSUB(REG_ZERO, s1, d);
1484 M_AND(d, REG_ITMP2, d);
1486 M_LSUB(REG_ZERO, d, d);
1487 store_reg_to_var_int(iptr->dst, d);
1490 case ICMD_LREM0X10001:/* ..., value ==> ..., value % 0x10001 */
1492 var_to_reg_int(s1, src, REG_ITMP1);
1493 d = reg_of_var(iptr->dst, REG_ITMP3);
1495 M_MOV(s1, REG_ITMP3);
1498 M_CZEXT(s1, REG_ITMP2);
1499 M_SRA_IMM(s1, 16, d);
1500 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1501 M_LSUB(REG_ITMP2, d, d);
1503 M_LADD(d, REG_ITMP1, d);
1504 M_LDA(REG_ITMP2, REG_ZERO, -1);
1505 M_SRL_IMM(REG_ITMP2, 33, REG_ITMP2);
1506 if (s1 == REG_ITMP1) {
1507 var_to_reg_int(s1, src, REG_ITMP1);
1509 M_CMPULT(s1, REG_ITMP2, REG_ITMP2);
1510 M_BNEZ(REG_ITMP2, 11);
1511 M_LDA(d, REG_ZERO, -257);
1512 M_ZAPNOT_IMM(d, 0xcd, d);
1513 M_LSUB(REG_ZERO, s1, REG_ITMP2);
1514 M_CMOVGE(s1, s1, REG_ITMP2);
1515 M_UMULH(REG_ITMP2, d, REG_ITMP2);
1516 M_SRL_IMM(REG_ITMP2, 16, REG_ITMP2);
1517 M_LSUB(REG_ZERO, REG_ITMP2, d);
1518 M_CMOVGE(s1, REG_ITMP2, d);
1519 M_SLL_IMM(d, 16, REG_ITMP2);
1520 M_LADD(d, REG_ITMP2, d);
1522 store_reg_to_var_int(iptr->dst, d);
1525 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1528 var_to_reg_int(s1, src->prev, REG_ITMP1);
1529 var_to_reg_int(s2, src, REG_ITMP2);
1530 d = reg_of_var(iptr->dst, REG_ITMP3);
1532 store_reg_to_var_int(iptr->dst, d);
1535 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1536 /* val.i = constant */
1538 var_to_reg_int(s1, src, REG_ITMP1);
1539 d = reg_of_var(iptr->dst, REG_ITMP3);
1540 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1541 M_OR_IMM(s1, iptr->val.i, d);
1544 ICONST(REG_ITMP2, iptr->val.i);
1545 M_OR(s1, REG_ITMP2, d);
1547 store_reg_to_var_int(iptr->dst, d);
1550 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1551 /* val.l = constant */
1553 var_to_reg_int(s1, src, REG_ITMP1);
1554 d = reg_of_var(iptr->dst, REG_ITMP3);
1555 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1556 M_OR_IMM(s1, iptr->val.l, d);
1559 LCONST(REG_ITMP2, iptr->val.l);
1560 M_OR(s1, REG_ITMP2, d);
1562 store_reg_to_var_int(iptr->dst, d);
1565 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1568 var_to_reg_int(s1, src->prev, REG_ITMP1);
1569 var_to_reg_int(s2, src, REG_ITMP2);
1570 d = reg_of_var(iptr->dst, REG_ITMP3);
1572 store_reg_to_var_int(iptr->dst, d);
1575 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1576 /* val.i = constant */
1578 var_to_reg_int(s1, src, REG_ITMP1);
1579 d = reg_of_var(iptr->dst, REG_ITMP3);
1580 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1581 M_XOR_IMM(s1, iptr->val.i, d);
1584 ICONST(REG_ITMP2, iptr->val.i);
1585 M_XOR(s1, REG_ITMP2, d);
1587 store_reg_to_var_int(iptr->dst, d);
1590 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1591 /* val.l = constant */
1593 var_to_reg_int(s1, src, REG_ITMP1);
1594 d = reg_of_var(iptr->dst, REG_ITMP3);
1595 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1596 M_XOR_IMM(s1, iptr->val.l, d);
1599 LCONST(REG_ITMP2, iptr->val.l);
1600 M_XOR(s1, REG_ITMP2, d);
1602 store_reg_to_var_int(iptr->dst, d);
1606 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1608 var_to_reg_int(s1, src->prev, REG_ITMP1);
1609 var_to_reg_int(s2, src, REG_ITMP2);
1610 d = reg_of_var(iptr->dst, REG_ITMP3);
1611 M_CMPLT(s1, s2, REG_ITMP3);
1612 M_CMPLT(s2, s1, REG_ITMP1);
1613 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1614 store_reg_to_var_int(iptr->dst, d);
1618 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1619 /* op1 = variable, val.i = constant */
1621 var = &(locals[iptr->op1][TYPE_INT]);
1622 if (var->flags & INMEMORY) {
1624 M_LLD(s1, REG_SP, 8 * var->regoff);
1628 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1629 M_IADD_IMM(s1, iptr->val.i, s1);
1631 else if ((iptr->val.i > -256) && (iptr->val.i < 0)) {
1632 M_ISUB_IMM(s1, (-iptr->val.i), s1);
1635 M_LDA (s1, s1, iptr->val.i);
1636 M_IADD(s1, REG_ZERO, s1);
1638 if (var->flags & INMEMORY)
1639 M_LST(s1, REG_SP, 8 * var->regoff);
1643 /* floating operations ************************************************/
1645 case ICMD_FNEG: /* ..., value ==> ..., - value */
1647 var_to_reg_flt(s1, src, REG_FTMP1);
1648 d = reg_of_var(iptr->dst, REG_FTMP3);
1650 store_reg_to_var_flt(iptr->dst, d);
1653 case ICMD_DNEG: /* ..., value ==> ..., - value */
1655 var_to_reg_flt(s1, src, REG_FTMP1);
1656 d = reg_of_var(iptr->dst, REG_FTMP3);
1658 store_reg_to_var_flt(iptr->dst, d);
1661 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1663 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1664 var_to_reg_flt(s2, src, REG_FTMP2);
1665 d = reg_of_var(iptr->dst, REG_FTMP3);
1670 if (d == s1 || d == s2) {
1671 M_FADDS(s1, s2, REG_FTMP3);
1673 M_FMOV(REG_FTMP3, d);
1680 store_reg_to_var_flt(iptr->dst, d);
1683 case ICMD_DADD: /* ..., 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);
1692 if (d == s1 || d == s2) {
1693 M_DADDS(s1, s2, REG_FTMP3);
1695 M_FMOV(REG_FTMP3, d);
1702 store_reg_to_var_flt(iptr->dst, d);
1705 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1707 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1708 var_to_reg_flt(s2, src, REG_FTMP2);
1709 d = reg_of_var(iptr->dst, REG_FTMP3);
1714 if (d == s1 || d == s2) {
1715 M_FSUBS(s1, s2, REG_FTMP3);
1717 M_FMOV(REG_FTMP3, d);
1724 store_reg_to_var_flt(iptr->dst, d);
1727 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1729 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1730 var_to_reg_flt(s2, src, REG_FTMP2);
1731 d = reg_of_var(iptr->dst, REG_FTMP3);
1736 if (d == s1 || d == s2) {
1737 M_DSUBS(s1, s2, REG_FTMP3);
1739 M_FMOV(REG_FTMP3, d);
1746 store_reg_to_var_flt(iptr->dst, d);
1749 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1751 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1752 var_to_reg_flt(s2, src, REG_FTMP2);
1753 d = reg_of_var(iptr->dst, REG_FTMP3);
1758 if (d == s1 || d == s2) {
1759 M_FMULS(s1, s2, REG_FTMP3);
1761 M_FMOV(REG_FTMP3, d);
1768 store_reg_to_var_flt(iptr->dst, d);
1771 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1773 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1774 var_to_reg_flt(s2, src, REG_FTMP2);
1775 d = reg_of_var(iptr->dst, REG_FTMP3);
1780 if (d == s1 || d == s2) {
1781 M_DMULS(s1, s2, REG_FTMP3);
1783 M_FMOV(REG_FTMP3, d);
1790 store_reg_to_var_flt(iptr->dst, d);
1793 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1795 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1796 var_to_reg_flt(s2, src, REG_FTMP2);
1797 d = reg_of_var(iptr->dst, REG_FTMP3);
1802 if (d == s1 || d == s2) {
1803 M_FDIVS(s1, s2, REG_FTMP3);
1805 M_FMOV(REG_FTMP3, d);
1812 store_reg_to_var_flt(iptr->dst, d);
1815 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1817 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1818 var_to_reg_flt(s2, src, REG_FTMP2);
1819 d = reg_of_var(iptr->dst, REG_FTMP3);
1824 if (d == s1 || d == s2) {
1825 M_DDIVS(s1, s2, REG_FTMP3);
1827 M_FMOV(REG_FTMP3, d);
1834 store_reg_to_var_flt(iptr->dst, d);
1837 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1839 var_to_reg_int(s1, src, REG_ITMP1);
1840 d = reg_of_var(iptr->dst, REG_FTMP3);
1841 a = dseg_adddouble(0.0);
1842 M_LST (s1, REG_PV, a);
1843 M_DLD (d, REG_PV, a);
1845 store_reg_to_var_flt(iptr->dst, d);
1848 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1850 var_to_reg_int(s1, src, REG_ITMP1);
1851 d = reg_of_var(iptr->dst, REG_FTMP3);
1852 a = dseg_adddouble(0.0);
1853 M_LST (s1, REG_PV, a);
1854 M_DLD (d, REG_PV, a);
1856 store_reg_to_var_flt(iptr->dst, d);
1859 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1861 var_to_reg_flt(s1, src, REG_FTMP1);
1862 d = reg_of_var(iptr->dst, REG_ITMP3);
1863 a = dseg_adddouble(0.0);
1864 M_CVTDL_C(s1, REG_FTMP2);
1865 M_CVTLI(REG_FTMP2, REG_FTMP3);
1866 M_DST (REG_FTMP3, REG_PV, a);
1867 M_ILD (d, REG_PV, a);
1868 store_reg_to_var_int(iptr->dst, d);
1871 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1873 var_to_reg_flt(s1, src, REG_FTMP1);
1874 d = reg_of_var(iptr->dst, REG_ITMP3);
1875 a = dseg_adddouble(0.0);
1876 M_CVTDL_C(s1, REG_FTMP2);
1877 M_DST (REG_FTMP2, REG_PV, a);
1878 M_LLD (d, REG_PV, a);
1879 store_reg_to_var_int(iptr->dst, d);
1882 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1884 var_to_reg_flt(s1, src, REG_FTMP1);
1885 d = reg_of_var(iptr->dst, REG_FTMP3);
1887 store_reg_to_var_flt(iptr->dst, d);
1890 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1892 var_to_reg_flt(s1, src, REG_FTMP1);
1893 d = reg_of_var(iptr->dst, REG_FTMP3);
1901 store_reg_to_var_flt(iptr->dst, d);
1904 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1906 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1907 var_to_reg_flt(s2, src, REG_FTMP2);
1908 d = reg_of_var(iptr->dst, REG_ITMP3);
1910 M_LSUB_IMM(REG_ZERO, 1, d);
1911 M_FCMPEQ(s1, s2, REG_FTMP3);
1912 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1914 M_FCMPLT(s2, s1, REG_FTMP3);
1915 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1916 M_LADD_IMM(REG_ZERO, 1, d);
1919 M_LSUB_IMM(REG_ZERO, 1, d);
1920 M_FCMPEQS(s1, s2, REG_FTMP3);
1922 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1924 M_FCMPLTS(s2, s1, REG_FTMP3);
1926 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1927 M_LADD_IMM(REG_ZERO, 1, d);
1929 store_reg_to_var_int(iptr->dst, d);
1932 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1934 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1935 var_to_reg_flt(s2, src, REG_FTMP2);
1936 d = reg_of_var(iptr->dst, REG_ITMP3);
1938 M_LADD_IMM(REG_ZERO, 1, d);
1939 M_FCMPEQ(s1, s2, REG_FTMP3);
1940 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1942 M_FCMPLT(s1, s2, REG_FTMP3);
1943 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1944 M_LSUB_IMM(REG_ZERO, 1, d);
1947 M_LADD_IMM(REG_ZERO, 1, d);
1948 M_FCMPEQS(s1, s2, REG_FTMP3);
1950 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1952 M_FCMPLTS(s1, s2, REG_FTMP3);
1954 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1955 M_LSUB_IMM(REG_ZERO, 1, d);
1957 store_reg_to_var_int(iptr->dst, d);
1961 /* memory operations **************************************************/
1963 /* #define gen_bound_check \
1965 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1966 M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
1967 M_BEQZ(REG_ITMP3, 0);\
1968 codegen_addxboundrefs(mcodeptr);\
1972 #define gen_bound_check \
1973 if (checkbounds) { \
1974 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1975 M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
1976 M_BEQZ(REG_ITMP3, 0);\
1977 codegen_addxboundrefs(mcodeptr); \
1980 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1982 var_to_reg_int(s1, src, REG_ITMP1);
1983 d = reg_of_var(iptr->dst, REG_ITMP3);
1984 gen_nullptr_check(s1);
1985 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1986 store_reg_to_var_int(iptr->dst, d);
1989 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1991 var_to_reg_int(s1, src->prev, REG_ITMP1);
1992 var_to_reg_int(s2, src, REG_ITMP2);
1993 d = reg_of_var(iptr->dst, REG_ITMP3);
1994 if (iptr->op1 == 0) {
1995 gen_nullptr_check(s1);
1998 M_SAADDQ(s2, s1, REG_ITMP1);
1999 M_ALD( d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2000 store_reg_to_var_int(iptr->dst, d);
2003 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2005 var_to_reg_int(s1, src->prev, REG_ITMP1);
2006 var_to_reg_int(s2, src, REG_ITMP2);
2007 d = reg_of_var(iptr->dst, REG_ITMP3);
2008 if (iptr->op1 == 0) {
2009 gen_nullptr_check(s1);
2012 M_S8ADDQ(s2, s1, REG_ITMP1);
2013 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
2014 store_reg_to_var_int(iptr->dst, d);
2017 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2019 var_to_reg_int(s1, src->prev, REG_ITMP1);
2020 var_to_reg_int(s2, src, REG_ITMP2);
2021 d = reg_of_var(iptr->dst, REG_ITMP3);
2022 if (iptr->op1 == 0) {
2023 gen_nullptr_check(s1);
2027 M_S4ADDQ(s2, s1, REG_ITMP1);
2028 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
2029 store_reg_to_var_int(iptr->dst, d);
2032 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2034 var_to_reg_int(s1, src->prev, REG_ITMP1);
2035 var_to_reg_int(s2, src, REG_ITMP2);
2036 d = reg_of_var(iptr->dst, REG_FTMP3);
2037 if (iptr->op1 == 0) {
2038 gen_nullptr_check(s1);
2041 M_S4ADDQ(s2, s1, REG_ITMP1);
2042 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2043 store_reg_to_var_flt(iptr->dst, d);
2046 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2048 var_to_reg_int(s1, src->prev, REG_ITMP1);
2049 var_to_reg_int(s2, src, REG_ITMP2);
2050 d = reg_of_var(iptr->dst, REG_FTMP3);
2051 if (iptr->op1 == 0) {
2052 gen_nullptr_check(s1);
2055 M_S8ADDQ(s2, s1, REG_ITMP1);
2056 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2057 store_reg_to_var_flt(iptr->dst, d);
2060 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2062 var_to_reg_int(s1, src->prev, REG_ITMP1);
2063 var_to_reg_int(s2, src, REG_ITMP2);
2064 d = reg_of_var(iptr->dst, REG_ITMP3);
2065 if (iptr->op1 == 0) {
2066 gen_nullptr_check(s1);
2069 if (has_ext_instr_set) {
2070 M_LADD(s2, s1, REG_ITMP1);
2071 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2072 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2075 M_LADD (s2, s1, REG_ITMP1);
2076 M_LADD (s2, REG_ITMP1, REG_ITMP1);
2077 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
2078 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
2079 M_EXTWL(REG_ITMP2, REG_ITMP1, d);
2081 store_reg_to_var_int(iptr->dst, d);
2084 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2086 var_to_reg_int(s1, src->prev, REG_ITMP1);
2087 var_to_reg_int(s2, src, REG_ITMP2);
2088 d = reg_of_var(iptr->dst, REG_ITMP3);
2089 if (iptr->op1 == 0) {
2090 gen_nullptr_check(s1);
2093 if (has_ext_instr_set) {
2094 M_LADD(s2, s1, REG_ITMP1);
2095 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2096 M_SLDU( d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
2100 M_LADD(s2, s1, REG_ITMP1);
2101 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2102 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2103 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0])+2);
2104 M_EXTQH(REG_ITMP2, REG_ITMP1, d);
2105 M_SRA_IMM(d, 48, d);
2107 store_reg_to_var_int(iptr->dst, d);
2110 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2112 var_to_reg_int(s1, src->prev, REG_ITMP1);
2113 var_to_reg_int(s2, src, REG_ITMP2);
2114 d = reg_of_var(iptr->dst, REG_ITMP3);
2115 if (iptr->op1 == 0) {
2116 gen_nullptr_check(s1);
2119 if (has_ext_instr_set) {
2120 M_LADD (s2, s1, REG_ITMP1);
2121 M_BLDU (d, REG_ITMP1, OFFSET (java_bytearray, data[0]));
2125 M_LADD(s2, s1, REG_ITMP1);
2126 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2127 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0])+1);
2128 M_EXTQH(REG_ITMP2, REG_ITMP1, d);
2129 M_SRA_IMM(d, 56, d);
2131 store_reg_to_var_int(iptr->dst, d);
2135 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2137 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2138 var_to_reg_int(s2, src->prev, REG_ITMP2);
2139 if (iptr->op1 == 0) {
2140 gen_nullptr_check(s1);
2143 var_to_reg_int(s3, src, REG_ITMP3);
2144 M_SAADDQ(s2, s1, REG_ITMP1);
2145 M_AST (s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2148 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2150 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2151 var_to_reg_int(s2, src->prev, REG_ITMP2);
2152 if (iptr->op1 == 0) {
2153 gen_nullptr_check(s1);
2156 var_to_reg_int(s3, src, REG_ITMP3);
2157 M_S8ADDQ(s2, s1, REG_ITMP1);
2158 M_LST (s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
2161 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2163 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2164 var_to_reg_int(s2, src->prev, REG_ITMP2);
2165 if (iptr->op1 == 0) {
2166 gen_nullptr_check(s1);
2170 var_to_reg_int(s3, src, REG_ITMP3);
2171 M_S4ADDQ(s2, s1, REG_ITMP1);
2172 M_IST (s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
2175 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2177 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2178 var_to_reg_int(s2, src->prev, REG_ITMP2);
2179 if (iptr->op1 == 0) {
2180 gen_nullptr_check(s1);
2183 var_to_reg_flt(s3, src, REG_FTMP3);
2184 M_S4ADDQ(s2, s1, REG_ITMP1);
2185 M_FST (s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2188 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2190 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2191 var_to_reg_int(s2, src->prev, REG_ITMP2);
2192 if (iptr->op1 == 0) {
2193 gen_nullptr_check(s1);
2196 var_to_reg_flt(s3, src, REG_FTMP3);
2197 M_S8ADDQ(s2, s1, REG_ITMP1);
2198 M_DST (s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2201 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2203 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2204 var_to_reg_int(s2, src->prev, REG_ITMP2);
2205 if (iptr->op1 == 0) {
2206 gen_nullptr_check(s1);
2209 var_to_reg_int(s3, src, REG_ITMP3);
2210 if (has_ext_instr_set) {
2211 M_LADD(s2, s1, REG_ITMP1);
2212 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2213 M_SST (s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
2216 M_LADD (s2, s1, REG_ITMP1);
2217 M_LADD (s2, REG_ITMP1, REG_ITMP1);
2218 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
2219 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
2220 M_INSWL(s3, REG_ITMP1, REG_ITMP3);
2221 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2222 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2223 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2227 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2229 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2230 var_to_reg_int(s2, src->prev, REG_ITMP2);
2231 if (iptr->op1 == 0) {
2232 gen_nullptr_check(s1);
2235 var_to_reg_int(s3, src, REG_ITMP3);
2236 if (has_ext_instr_set) {
2237 M_LADD(s2, s1, REG_ITMP1);
2238 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2239 M_SST (s3, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2242 M_LADD (s2, s1, REG_ITMP1);
2243 M_LADD (s2, REG_ITMP1, REG_ITMP1);
2244 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2245 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2246 M_INSWL(s3, REG_ITMP1, REG_ITMP3);
2247 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2248 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2249 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2253 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2255 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2256 var_to_reg_int(s2, src->prev, REG_ITMP2);
2257 if (iptr->op1 == 0) {
2258 gen_nullptr_check(s1);
2261 var_to_reg_int(s3, src, REG_ITMP3);
2262 if (has_ext_instr_set) {
2263 M_LADD(s2, s1, REG_ITMP1);
2264 M_BST (s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2267 M_LADD (s2, s1, REG_ITMP1);
2268 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2269 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2270 M_INSBL(s3, REG_ITMP1, REG_ITMP3);
2271 M_MSKBL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2272 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2273 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2278 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2279 /* op1 = type, val.a = field address */
2281 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2282 M_ALD(REG_ITMP1, REG_PV, a);
2283 switch (iptr->op1) {
2285 var_to_reg_int(s2, src, REG_ITMP2);
2286 M_IST(s2, REG_ITMP1, 0);
2289 var_to_reg_int(s2, src, REG_ITMP2);
2290 M_LST(s2, REG_ITMP1, 0);
2293 var_to_reg_int(s2, src, REG_ITMP2);
2294 M_AST(s2, REG_ITMP1, 0);
2297 var_to_reg_flt(s2, src, REG_FTMP2);
2298 M_FST(s2, REG_ITMP1, 0);
2301 var_to_reg_flt(s2, src, REG_FTMP2);
2302 M_DST(s2, REG_ITMP1, 0);
2304 default: panic ("internal error");
2308 case ICMD_GETSTATIC: /* ... ==> ..., value */
2309 /* op1 = type, val.a = field address */
2311 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2312 M_ALD(REG_ITMP1, REG_PV, a);
2313 switch (iptr->op1) {
2315 d = reg_of_var(iptr->dst, REG_ITMP3);
2316 M_ILD(d, REG_ITMP1, 0);
2317 store_reg_to_var_int(iptr->dst, d);
2320 d = reg_of_var(iptr->dst, REG_ITMP3);
2321 M_LLD(d, REG_ITMP1, 0);
2322 store_reg_to_var_int(iptr->dst, d);
2325 d = reg_of_var(iptr->dst, REG_ITMP3);
2326 M_ALD(d, REG_ITMP1, 0);
2327 store_reg_to_var_int(iptr->dst, d);
2330 d = reg_of_var(iptr->dst, REG_FTMP1);
2331 M_FLD(d, REG_ITMP1, 0);
2332 store_reg_to_var_flt(iptr->dst, d);
2335 d = reg_of_var(iptr->dst, REG_FTMP1);
2336 M_DLD(d, REG_ITMP1, 0);
2337 store_reg_to_var_flt(iptr->dst, d);
2339 default: panic ("internal error");
2344 case ICMD_PUTFIELD: /* ..., value ==> ... */
2345 /* op1 = type, val.i = field offset */
2347 a = ((fieldinfo *)(iptr->val.a))->offset;
2348 switch (iptr->op1) {
2350 var_to_reg_int(s1, src->prev, REG_ITMP1);
2351 var_to_reg_int(s2, src, REG_ITMP2);
2352 gen_nullptr_check(s1);
2356 var_to_reg_int(s1, src->prev, REG_ITMP1);
2357 var_to_reg_int(s2, src, REG_ITMP2);
2358 gen_nullptr_check(s1);
2362 var_to_reg_int(s1, src->prev, REG_ITMP1);
2363 var_to_reg_int(s2, src, REG_ITMP2);
2364 gen_nullptr_check(s1);
2368 var_to_reg_int(s1, src->prev, REG_ITMP1);
2369 var_to_reg_flt(s2, src, REG_FTMP2);
2370 gen_nullptr_check(s1);
2374 var_to_reg_int(s1, src->prev, REG_ITMP1);
2375 var_to_reg_flt(s2, src, REG_FTMP2);
2376 gen_nullptr_check(s1);
2379 default: panic ("internal error");
2383 case ICMD_GETFIELD: /* ... ==> ..., value */
2384 /* op1 = type, val.i = field offset */
2386 a = ((fieldinfo *)(iptr->val.a))->offset;
2387 switch (iptr->op1) {
2389 var_to_reg_int(s1, src, REG_ITMP1);
2390 d = reg_of_var(iptr->dst, REG_ITMP3);
2391 gen_nullptr_check(s1);
2393 store_reg_to_var_int(iptr->dst, d);
2396 var_to_reg_int(s1, src, REG_ITMP1);
2397 d = reg_of_var(iptr->dst, REG_ITMP3);
2398 gen_nullptr_check(s1);
2400 store_reg_to_var_int(iptr->dst, d);
2403 var_to_reg_int(s1, src, REG_ITMP1);
2404 d = reg_of_var(iptr->dst, REG_ITMP3);
2405 gen_nullptr_check(s1);
2407 store_reg_to_var_int(iptr->dst, d);
2410 var_to_reg_int(s1, src, REG_ITMP1);
2411 d = reg_of_var(iptr->dst, REG_FTMP1);
2412 gen_nullptr_check(s1);
2414 store_reg_to_var_flt(iptr->dst, d);
2417 var_to_reg_int(s1, src, REG_ITMP1);
2418 d = reg_of_var(iptr->dst, REG_FTMP1);
2419 gen_nullptr_check(s1);
2421 store_reg_to_var_flt(iptr->dst, d);
2423 default: panic ("internal error");
2428 /* branch operations **************************************************/
2430 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2432 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2434 var_to_reg_int(s1, src, REG_ITMP1);
2435 M_INTMOVE(s1, REG_ITMP1_XPTR);
2436 a = dseg_addaddress(asm_handle_exception);
2437 M_ALD(REG_ITMP2, REG_PV, a);
2438 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2439 M_NOP; /* nop ensures that XPC is less than the end */
2440 /* of basic block */
2444 case ICMD_GOTO: /* ... ==> ... */
2445 /* op1 = target JavaVM pc */
2447 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2451 case ICMD_JSR: /* ... ==> ... */
2452 /* op1 = target JavaVM pc */
2454 M_BSR(REG_ITMP1, 0);
2455 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2458 case ICMD_RET: /* ... ==> ... */
2459 /* op1 = local variable */
2461 var = &(locals[iptr->op1][TYPE_ADR]);
2462 if (var->flags & INMEMORY) {
2463 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2464 M_RET(REG_ZERO, REG_ITMP1);
2467 M_RET(REG_ZERO, var->regoff);
2471 case ICMD_IFNULL: /* ..., value ==> ... */
2472 /* op1 = target JavaVM pc */
2474 var_to_reg_int(s1, src, REG_ITMP1);
2476 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2479 case ICMD_IFNONNULL: /* ..., value ==> ... */
2480 /* op1 = target JavaVM pc */
2482 var_to_reg_int(s1, src, REG_ITMP1);
2484 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2487 case ICMD_IFEQ: /* ..., value ==> ... */
2488 /* op1 = target JavaVM pc, val.i = constant */
2490 var_to_reg_int(s1, src, REG_ITMP1);
2491 if (iptr->val.i == 0) {
2495 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2496 M_CMPEQ_IMM(s1, iptr->val.i, REG_ITMP1);
2499 ICONST(REG_ITMP2, iptr->val.i);
2500 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2502 M_BNEZ(REG_ITMP1, 0);
2504 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2507 case ICMD_IFLT: /* ..., value ==> ... */
2508 /* op1 = target JavaVM pc, val.i = constant */
2510 var_to_reg_int(s1, src, REG_ITMP1);
2511 if (iptr->val.i == 0) {
2515 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2516 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2519 ICONST(REG_ITMP2, iptr->val.i);
2520 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2522 M_BNEZ(REG_ITMP1, 0);
2524 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2527 case ICMD_IFLE: /* ..., value ==> ... */
2528 /* op1 = target JavaVM pc, val.i = constant */
2530 var_to_reg_int(s1, src, REG_ITMP1);
2531 if (iptr->val.i == 0) {
2535 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2536 M_CMPLE_IMM(s1, iptr->val.i, REG_ITMP1);
2539 ICONST(REG_ITMP2, iptr->val.i);
2540 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2542 M_BNEZ(REG_ITMP1, 0);
2544 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2547 case ICMD_IFNE: /* ..., value ==> ... */
2548 /* op1 = target JavaVM pc, val.i = constant */
2550 var_to_reg_int(s1, src, REG_ITMP1);
2551 if (iptr->val.i == 0) {
2555 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2556 M_CMPEQ_IMM(s1, iptr->val.i, REG_ITMP1);
2559 ICONST(REG_ITMP2, iptr->val.i);
2560 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2562 M_BEQZ(REG_ITMP1, 0);
2564 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2567 case ICMD_IFGT: /* ..., value ==> ... */
2568 /* op1 = target JavaVM pc, val.i = constant */
2570 var_to_reg_int(s1, src, REG_ITMP1);
2571 if (iptr->val.i == 0) {
2575 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2576 M_CMPLE_IMM(s1, iptr->val.i, REG_ITMP1);
2579 ICONST(REG_ITMP2, iptr->val.i);
2580 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2582 M_BEQZ(REG_ITMP1, 0);
2584 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2587 case ICMD_IFGE: /* ..., value ==> ... */
2588 /* op1 = target JavaVM pc, val.i = constant */
2590 var_to_reg_int(s1, src, REG_ITMP1);
2591 if (iptr->val.i == 0) {
2595 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2596 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2599 ICONST(REG_ITMP2, iptr->val.i);
2600 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2602 M_BEQZ(REG_ITMP1, 0);
2604 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2607 case ICMD_IF_LEQ: /* ..., value ==> ... */
2608 /* op1 = target JavaVM pc, val.l = constant */
2610 var_to_reg_int(s1, src, REG_ITMP1);
2611 if (iptr->val.l == 0) {
2615 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2616 M_CMPEQ_IMM(s1, iptr->val.l, REG_ITMP1);
2619 LCONST(REG_ITMP2, iptr->val.l);
2620 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2622 M_BNEZ(REG_ITMP1, 0);
2624 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2627 case ICMD_IF_LLT: /* ..., value ==> ... */
2628 /* op1 = target JavaVM pc, val.l = constant */
2630 var_to_reg_int(s1, src, REG_ITMP1);
2631 if (iptr->val.l == 0) {
2635 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2636 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2639 LCONST(REG_ITMP2, iptr->val.l);
2640 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2642 M_BNEZ(REG_ITMP1, 0);
2644 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2647 case ICMD_IF_LLE: /* ..., value ==> ... */
2648 /* op1 = target JavaVM pc, val.l = constant */
2650 var_to_reg_int(s1, src, REG_ITMP1);
2651 if (iptr->val.l == 0) {
2655 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2656 M_CMPLE_IMM(s1, iptr->val.l, REG_ITMP1);
2659 LCONST(REG_ITMP2, iptr->val.l);
2660 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2662 M_BNEZ(REG_ITMP1, 0);
2664 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2667 case ICMD_IF_LNE: /* ..., value ==> ... */
2668 /* op1 = target JavaVM pc, val.l = constant */
2670 var_to_reg_int(s1, src, REG_ITMP1);
2671 if (iptr->val.l == 0) {
2675 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2676 M_CMPEQ_IMM(s1, iptr->val.l, REG_ITMP1);
2679 LCONST(REG_ITMP2, iptr->val.l);
2680 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2682 M_BEQZ(REG_ITMP1, 0);
2684 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2687 case ICMD_IF_LGT: /* ..., value ==> ... */
2688 /* op1 = target JavaVM pc, val.l = constant */
2690 var_to_reg_int(s1, src, REG_ITMP1);
2691 if (iptr->val.l == 0) {
2695 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2696 M_CMPLE_IMM(s1, iptr->val.l, REG_ITMP1);
2699 LCONST(REG_ITMP2, iptr->val.l);
2700 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2702 M_BEQZ(REG_ITMP1, 0);
2704 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2707 case ICMD_IF_LGE: /* ..., value ==> ... */
2708 /* op1 = target JavaVM pc, val.l = constant */
2710 var_to_reg_int(s1, src, REG_ITMP1);
2711 if (iptr->val.l == 0) {
2715 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2716 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2719 LCONST(REG_ITMP2, iptr->val.l);
2720 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2722 M_BEQZ(REG_ITMP1, 0);
2724 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2727 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2728 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2729 case ICMD_IF_ACMPEQ:
2731 var_to_reg_int(s1, src->prev, REG_ITMP1);
2732 var_to_reg_int(s2, src, REG_ITMP2);
2733 M_CMPEQ(s1, s2, REG_ITMP1);
2734 M_BNEZ(REG_ITMP1, 0);
2735 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2738 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2739 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2740 case ICMD_IF_ACMPNE:
2742 var_to_reg_int(s1, src->prev, REG_ITMP1);
2743 var_to_reg_int(s2, src, REG_ITMP2);
2744 M_CMPEQ(s1, s2, REG_ITMP1);
2745 M_BEQZ(REG_ITMP1, 0);
2746 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2749 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2750 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2752 var_to_reg_int(s1, src->prev, REG_ITMP1);
2753 var_to_reg_int(s2, src, REG_ITMP2);
2754 M_CMPLT(s1, s2, REG_ITMP1);
2755 M_BNEZ(REG_ITMP1, 0);
2756 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2759 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2760 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2762 var_to_reg_int(s1, src->prev, REG_ITMP1);
2763 var_to_reg_int(s2, src, REG_ITMP2);
2764 M_CMPLE(s1, s2, REG_ITMP1);
2765 M_BEQZ(REG_ITMP1, 0);
2766 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2769 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2770 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2772 var_to_reg_int(s1, src->prev, REG_ITMP1);
2773 var_to_reg_int(s2, src, REG_ITMP2);
2774 M_CMPLE(s1, s2, REG_ITMP1);
2775 M_BNEZ(REG_ITMP1, 0);
2776 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2779 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2780 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2782 var_to_reg_int(s1, src->prev, REG_ITMP1);
2783 var_to_reg_int(s2, src, REG_ITMP2);
2784 M_CMPLT(s1, s2, REG_ITMP1);
2785 M_BEQZ(REG_ITMP1, 0);
2786 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2789 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2791 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2794 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2795 /* val.i = constant */
2797 var_to_reg_int(s1, src, REG_ITMP1);
2798 d = reg_of_var(iptr->dst, REG_ITMP3);
2800 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2801 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2802 M_CMPEQ(s1, REG_ZERO, d);
2803 store_reg_to_var_int(iptr->dst, d);
2806 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2807 M_CMPEQ(s1, REG_ZERO, d);
2809 store_reg_to_var_int(iptr->dst, d);
2813 M_MOV(s1, REG_ITMP1);
2816 ICONST(d, iptr[1].val.i);
2818 if ((s3 >= 0) && (s3 <= 255)) {
2819 M_CMOVEQ_IMM(s1, s3, d);
2822 ICONST(REG_ITMP2, s3);
2823 M_CMOVEQ(s1, REG_ITMP2, d);
2825 store_reg_to_var_int(iptr->dst, d);
2828 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2829 /* val.i = constant */
2831 var_to_reg_int(s1, src, REG_ITMP1);
2832 d = reg_of_var(iptr->dst, REG_ITMP3);
2834 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2835 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2836 M_CMPEQ(s1, REG_ZERO, d);
2837 store_reg_to_var_int(iptr->dst, d);
2840 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2841 M_CMPEQ(s1, REG_ZERO, d);
2843 store_reg_to_var_int(iptr->dst, d);
2847 M_MOV(s1, REG_ITMP1);
2850 ICONST(d, iptr[1].val.i);
2852 if ((s3 >= 0) && (s3 <= 255)) {
2853 M_CMOVNE_IMM(s1, s3, d);
2856 ICONST(REG_ITMP2, s3);
2857 M_CMOVNE(s1, REG_ITMP2, d);
2859 store_reg_to_var_int(iptr->dst, d);
2862 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2863 /* val.i = constant */
2865 var_to_reg_int(s1, src, REG_ITMP1);
2866 d = reg_of_var(iptr->dst, REG_ITMP3);
2868 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2869 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2870 M_CMPLT(s1, REG_ZERO, d);
2871 store_reg_to_var_int(iptr->dst, d);
2874 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2875 M_CMPLE(REG_ZERO, s1, d);
2876 store_reg_to_var_int(iptr->dst, d);
2880 M_MOV(s1, REG_ITMP1);
2883 ICONST(d, iptr[1].val.i);
2885 if ((s3 >= 0) && (s3 <= 255)) {
2886 M_CMOVLT_IMM(s1, s3, d);
2889 ICONST(REG_ITMP2, s3);
2890 M_CMOVLT(s1, REG_ITMP2, d);
2892 store_reg_to_var_int(iptr->dst, d);
2895 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2896 /* val.i = constant */
2898 var_to_reg_int(s1, src, REG_ITMP1);
2899 d = reg_of_var(iptr->dst, REG_ITMP3);
2901 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2902 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2903 M_CMPLE(REG_ZERO, s1, d);
2904 store_reg_to_var_int(iptr->dst, d);
2907 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2908 M_CMPLT(s1, REG_ZERO, d);
2909 store_reg_to_var_int(iptr->dst, d);
2913 M_MOV(s1, REG_ITMP1);
2916 ICONST(d, iptr[1].val.i);
2918 if ((s3 >= 0) && (s3 <= 255)) {
2919 M_CMOVGE_IMM(s1, s3, d);
2922 ICONST(REG_ITMP2, s3);
2923 M_CMOVGE(s1, REG_ITMP2, d);
2925 store_reg_to_var_int(iptr->dst, d);
2928 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2929 /* val.i = constant */
2931 var_to_reg_int(s1, src, REG_ITMP1);
2932 d = reg_of_var(iptr->dst, REG_ITMP3);
2934 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2935 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2936 M_CMPLT(REG_ZERO, s1, d);
2937 store_reg_to_var_int(iptr->dst, d);
2940 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2941 M_CMPLE(s1, REG_ZERO, d);
2942 store_reg_to_var_int(iptr->dst, d);
2946 M_MOV(s1, REG_ITMP1);
2949 ICONST(d, iptr[1].val.i);
2951 if ((s3 >= 0) && (s3 <= 255)) {
2952 M_CMOVGT_IMM(s1, s3, d);
2955 ICONST(REG_ITMP2, s3);
2956 M_CMOVGT(s1, REG_ITMP2, d);
2958 store_reg_to_var_int(iptr->dst, d);
2961 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2962 /* val.i = constant */
2964 var_to_reg_int(s1, src, REG_ITMP1);
2965 d = reg_of_var(iptr->dst, REG_ITMP3);
2967 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2968 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2969 M_CMPLE(s1, REG_ZERO, d);
2970 store_reg_to_var_int(iptr->dst, d);
2973 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2974 M_CMPLT(REG_ZERO, s1, d);
2975 store_reg_to_var_int(iptr->dst, d);
2979 M_MOV(s1, REG_ITMP1);
2982 ICONST(d, iptr[1].val.i);
2984 if ((s3 >= 0) && (s3 <= 255)) {
2985 M_CMOVLE_IMM(s1, s3, d);
2988 ICONST(REG_ITMP2, s3);
2989 M_CMOVLE(s1, REG_ITMP2, d);
2991 store_reg_to_var_int(iptr->dst, d);
2995 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3000 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3002 a = dseg_addaddress ((void*) (builtin_monitorexit));
3003 M_ALD(REG_PV, REG_PV, a);
3004 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
3005 M_JSR(REG_RA, REG_PV);
3006 disp = -(int)((u1*) mcodeptr - mcodebase);
3007 M_LDA(REG_PV, REG_RA, disp);
3010 var_to_reg_int(s1, src, REG_RESULT);
3011 M_INTMOVE(s1, REG_RESULT);
3012 goto nowperformreturn;
3014 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3018 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3020 a = dseg_addaddress ((void*) (builtin_monitorexit));
3021 M_ALD(REG_PV, REG_PV, a);
3022 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
3023 M_JSR(REG_RA, REG_PV);
3024 disp = -(int)((u1*) mcodeptr - mcodebase);
3025 M_LDA(REG_PV, REG_RA, disp);
3028 var_to_reg_flt(s1, src, REG_FRESULT);
3029 M_FLTMOVE(s1, REG_FRESULT);
3030 goto nowperformreturn;
3032 case ICMD_RETURN: /* ... ==> ... */
3035 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3037 a = dseg_addaddress ((void*) (builtin_monitorexit));
3038 M_ALD(REG_PV, REG_PV, a);
3039 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
3040 M_JSR(REG_RA, REG_PV);
3041 disp = -(int)((u1*) mcodeptr - mcodebase);
3042 M_LDA(REG_PV, REG_RA, disp);
3050 p = parentargs_base;
3052 /* restore return address */
3055 {p--; M_LLD (REG_RA, REG_SP, 8 * p);}
3057 /* restore saved registers */
3059 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
3060 {p--; M_LLD(savintregs[r], REG_SP, 8 * p);}
3061 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
3062 {p--; M_DLD(savfltregs[r], REG_SP, 8 * p);}
3064 /* deallocate stack */
3066 if (parentargs_base)
3067 {M_LDA(REG_SP, REG_SP, parentargs_base*8);}
3069 /* call trace function */
3072 M_LDA (REG_SP, REG_SP, -24);
3073 M_AST(REG_RA, REG_SP, 0);
3074 M_LST(REG_RESULT, REG_SP, 8);
3075 M_DST(REG_FRESULT, REG_SP,16);
3076 a = dseg_addaddress (method);
3077 M_ALD(argintregs[0], REG_PV, a);
3078 M_MOV(REG_RESULT, argintregs[1]);
3079 M_FLTMOVE(REG_FRESULT, argfltregs[2]);
3080 M_FLTMOVE(REG_FRESULT, argfltregs[3]);
3081 a = dseg_addaddress ((void*) (builtin_displaymethodstop));
3082 M_ALD(REG_PV, REG_PV, a);
3083 M_JSR (REG_RA, REG_PV);
3084 s1 = (int)((u1*) mcodeptr - mcodebase);
3085 if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
3088 while (ml<-32768) { ml+=65536; mh--; }
3089 M_LDA (REG_PV, REG_RA, ml );
3090 M_LDAH (REG_PV, REG_PV, mh );
3092 M_DLD(REG_FRESULT, REG_SP,16);
3093 M_LLD(REG_RESULT, REG_SP, 8);
3094 M_ALD(REG_RA, REG_SP, 0);
3095 M_LDA (REG_SP, REG_SP, 24);
3098 M_RET(REG_ZERO, REG_RA);
3104 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3109 tptr = (void **) iptr->target;
3111 s4ptr = iptr->val.a;
3112 l = s4ptr[1]; /* low */
3113 i = s4ptr[2]; /* high */
3115 var_to_reg_int(s1, src, REG_ITMP1);
3117 {M_INTMOVE(s1, REG_ITMP1);}
3118 else if (l <= 32768) {
3119 M_LDA(REG_ITMP1, s1, -l);
3122 ICONST(REG_ITMP2, l);
3123 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3130 M_CMPULE_IMM(REG_ITMP1, i - 1, REG_ITMP2);
3132 M_LDA(REG_ITMP2, REG_ZERO, i - 1);
3133 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3135 M_BEQZ(REG_ITMP2, 0);
3138 /* codegen_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr); */
3139 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3141 /* build jump table top down and use address of lowest entry */
3143 /* s4ptr += 3 + i; */
3147 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3148 dseg_addtarget((basicblock *) tptr[0]);
3153 /* length of dataseg after last dseg_addtarget is used by load */
3155 M_SAADDQ(REG_ITMP1, REG_PV, REG_ITMP2);
3156 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
3157 M_JMP(REG_ZERO, REG_ITMP2);
3162 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3164 s4 i, l, val, *s4ptr;
3167 tptr = (void **) iptr->target;
3169 s4ptr = iptr->val.a;
3170 l = s4ptr[0]; /* default */
3171 i = s4ptr[1]; /* count */
3173 MCODECHECK((i<<2)+8);
3174 var_to_reg_int(s1, src, REG_ITMP1);
3180 if ((val >= 0) && (val <= 255)) {
3181 M_CMPEQ_IMM(s1, val, REG_ITMP2);
3184 if ((val >= -32768) && (val <= 32767)) {
3185 M_LDA(REG_ITMP2, REG_ZERO, val);
3188 a = dseg_adds4 (val);
3189 M_ILD(REG_ITMP2, REG_PV, a);
3191 M_CMPEQ(s1, REG_ITMP2, REG_ITMP2);
3193 M_BNEZ(REG_ITMP2, 0);
3194 /* codegen_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr); */
3195 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3199 /* codegen_addreference(BlockPtrOfPC(l), mcodeptr); */
3201 tptr = (void **) iptr->target;
3202 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3209 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3210 /* op1 = return type, val.a = function pointer*/
3214 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3215 /* op1 = return type, val.a = function pointer*/
3219 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3220 /* op1 = return type, val.a = function pointer*/
3224 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3225 /* op1 = arg count, val.a = method pointer */
3227 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3228 /* op1 = arg count, val.a = method pointer */
3230 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3231 /* op1 = arg count, val.a = method pointer */
3233 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3234 /* op1 = arg count, val.a = method pointer */
3242 MCODECHECK((s3 << 1) + 64);
3244 /* copy arguments to registers or stack location */
3246 for (; --s3 >= 0; src = src->prev) {
3247 if (src->varkind == ARGVAR)
3249 if (IS_INT_LNG_TYPE(src->type)) {
3250 if (s3 < INT_ARG_CNT) {
3251 s1 = argintregs[s3];
3252 var_to_reg_int(d, src, s1);
3256 var_to_reg_int(d, src, REG_ITMP1);
3257 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3261 if (s3 < FLT_ARG_CNT) {
3262 s1 = argfltregs[s3];
3263 var_to_reg_flt(d, src, s1);
3267 var_to_reg_flt(d, src, REG_FTMP1);
3268 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3273 switch (iptr->opc) {
3277 a = dseg_addaddress ((void*) (m));
3279 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
3281 goto makeactualcall;
3283 case ICMD_INVOKESTATIC:
3284 case ICMD_INVOKESPECIAL:
3285 a = dseg_addaddress (m->stubroutine);
3287 M_ALD(REG_PV, REG_PV, a ); /* method pointer in r27 */
3290 goto makeactualcall;
3292 case ICMD_INVOKEVIRTUAL:
3294 gen_nullptr_check(argintregs[0]);
3295 M_ALD(REG_METHODPTR, argintregs[0],
3296 OFFSET(java_objectheader, vftbl));
3297 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
3298 sizeof(methodptr) * m->vftblindex);
3301 goto makeactualcall;
3303 case ICMD_INVOKEINTERFACE:
3306 gen_nullptr_check(argintregs[0]);
3307 M_ALD(REG_METHODPTR, argintregs[0],
3308 OFFSET(java_objectheader, vftbl));
3309 M_ALD(REG_METHODPTR, REG_METHODPTR,
3310 OFFSET(vftbl, interfacetable[0]) -
3311 sizeof(methodptr*) * ci->index);
3312 M_ALD(REG_PV, REG_METHODPTR,
3313 sizeof(methodptr) * (m - ci->methods));
3316 goto makeactualcall;
3320 error ("Unkown ICMD-Command: %d", iptr->opc);
3325 M_JSR (REG_RA, REG_PV);
3329 s1 = (int)((u1*) mcodeptr - mcodebase);
3330 if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
3333 while (ml<-32768) { ml+=65536; mh--; }
3334 M_LDA (REG_PV, REG_RA, ml );
3335 M_LDAH (REG_PV, REG_PV, mh );
3338 /* d contains return type */
3340 if (d != TYPE_VOID) {
3341 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3342 s1 = reg_of_var(iptr->dst, REG_RESULT);
3343 M_INTMOVE(REG_RESULT, s1);
3344 store_reg_to_var_int(iptr->dst, s1);
3347 s1 = reg_of_var(iptr->dst, REG_FRESULT);
3348 M_FLTMOVE(REG_FRESULT, s1);
3349 store_reg_to_var_flt(iptr->dst, s1);
3356 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3358 /* op1: 0 == array, 1 == class */
3359 /* val.a: (classinfo*) superclass */
3361 /* superclass is an interface:
3363 * return (sub != NULL) &&
3364 * (sub->vftbl->interfacetablelength > super->index) &&
3365 * (sub->vftbl->interfacetable[-super->index] != NULL);
3367 * superclass is a class:
3369 * return ((sub != NULL) && (0
3370 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3371 * super->vftbl->diffvall));
3375 classinfo *super = (classinfo*) iptr->val.a;
3377 var_to_reg_int(s1, src, REG_ITMP1);
3378 d = reg_of_var(iptr->dst, REG_ITMP3);
3380 M_MOV(s1, REG_ITMP1);
3384 if (iptr->op1) { /* class/interface */
3385 if (super->flags & ACC_INTERFACE) { /* interface */
3387 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3388 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3389 M_LDA(REG_ITMP2, REG_ITMP2, - super->index);
3390 M_BLEZ(REG_ITMP2, 2);
3391 M_ALD(REG_ITMP1, REG_ITMP1,
3392 OFFSET(vftbl, interfacetable[0]) -
3393 super->index * sizeof(methodptr*));
3394 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3398 s2 = super->vftbl->diffval;
3399 M_BEQZ(s1, 4 + (s2 > 255));
3400 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3401 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3402 M_LDA(REG_ITMP1, REG_ITMP1, - super->vftbl->baseval);
3404 M_CMPULE_IMM(REG_ITMP1, s2, d);
3406 M_LDA(REG_ITMP2, REG_ZERO, s2);
3407 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3411 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3412 a = dseg_addaddress ((void*) super->vftbl);
3413 M_ALD(REG_ITMP2, REG_PV, a);
3414 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3415 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3416 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3417 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3418 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3422 panic ("internal error: no inlined array instanceof");
3424 store_reg_to_var_int(iptr->dst, d);
3427 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3429 /* op1: 0 == array, 1 == class */
3430 /* val.a: (classinfo*) superclass */
3432 /* superclass is an interface:
3434 * OK if ((sub == NULL) ||
3435 * (sub->vftbl->interfacetablelength > super->index) &&
3436 * (sub->vftbl->interfacetable[-super->index] != NULL));
3438 * superclass is a class:
3440 * OK if ((sub == NULL) || (0
3441 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3442 * super->vftbl->diffvall));
3446 classinfo *super = (classinfo*) iptr->val.a;
3448 d = reg_of_var(iptr->dst, REG_ITMP3);
3449 var_to_reg_int(s1, src, d);
3450 if (iptr->op1) { /* class/interface */
3451 if (super->flags & ACC_INTERFACE) { /* interface */
3453 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3454 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3455 M_LDA(REG_ITMP2, REG_ITMP2, - super->index);
3456 M_BLEZ(REG_ITMP2, 0);
3457 codegen_addxcastrefs(mcodeptr);
3458 M_ALD(REG_ITMP2, REG_ITMP1,
3459 OFFSET(vftbl, interfacetable[0]) -
3460 super->index * sizeof(methodptr*));
3461 M_BEQZ(REG_ITMP2, 0);
3462 codegen_addxcastrefs(mcodeptr);
3466 s2 = super->vftbl->diffval;
3467 M_BEQZ(s1, 4 + (s2 != 0) + (s2 > 255));
3468 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3469 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3470 M_LDA(REG_ITMP1, REG_ITMP1, - super->vftbl->baseval);
3472 M_BNEZ(REG_ITMP1, 0);
3474 else if (s2 <= 255) {
3475 M_CMPULE_IMM(REG_ITMP1, s2, REG_ITMP2);
3476 M_BEQZ(REG_ITMP2, 0);
3479 M_LDA(REG_ITMP2, REG_ZERO, s2);
3480 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3481 M_BEQZ(REG_ITMP2, 0);
3484 M_BEQZ(s1, 8 + (d == REG_ITMP3));
3485 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3486 a = dseg_addaddress ((void*) super->vftbl);
3487 M_ALD(REG_ITMP2, REG_PV, a);
3488 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3489 if (d != REG_ITMP3) {
3490 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3491 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3492 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3495 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, baseval));
3496 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3497 M_ALD(REG_ITMP2, REG_PV, a);
3498 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3500 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3501 M_BEQZ(REG_ITMP2, 0);
3502 codegen_addxcastrefs(mcodeptr);
3506 panic ("internal error: no inlined array checkcast");
3509 store_reg_to_var_int(iptr->dst, d);
3512 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3514 var_to_reg_int(s1, src, REG_ITMP1);
3516 codegen_addxcheckarefs(mcodeptr);
3519 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3520 /* op1 = dimension, val.a = array descriptor */
3522 /* check for negative sizes and copy sizes to stack if necessary */
3524 MCODECHECK((iptr->op1 << 1) + 64);
3526 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3527 var_to_reg_int(s2, src, REG_ITMP1);
3529 codegen_addxcheckarefs(mcodeptr);
3531 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3533 if (src->varkind != ARGVAR) {
3534 M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
3538 /* a0 = dimension count */
3540 ICONST(argintregs[0], iptr->op1);
3542 /* a1 = arraydescriptor */
3544 a = dseg_addaddress(iptr->val.a);
3545 M_ALD(argintregs[1], REG_PV, a);
3547 /* a2 = pointer to dimensions = stack pointer */
3549 M_INTMOVE(REG_SP, argintregs[2]);
3551 a = dseg_addaddress((void*) (builtin_nmultianewarray));
3552 M_ALD(REG_PV, REG_PV, a);
3553 M_JSR(REG_RA, REG_PV);
3554 s1 = (int)((u1*) mcodeptr - mcodebase);
3556 M_LDA (REG_PV, REG_RA, -s1);
3558 s4 ml = -s1, mh = 0;
3559 while (ml < -32768) {ml += 65536; mh--;}
3560 M_LDA(REG_PV, REG_RA, ml);
3561 M_LDAH(REG_PV, REG_PV, mh);
3563 s1 = reg_of_var(iptr->dst, REG_RESULT);
3564 M_INTMOVE(REG_RESULT, s1);
3565 store_reg_to_var_int(iptr->dst, s1);
3569 default: error ("Unknown pseudo command: %d", iptr->opc);
3575 } /* for instruction */
3577 /* copy values to interface registers */
3579 src = bptr->outstack;
3580 len = bptr->outdepth;
3584 if ((src->varkind != STACKVAR)) {
3586 if (IS_FLT_DBL_TYPE(s2)) {
3587 var_to_reg_flt(s1, src, REG_FTMP1);
3588 if (!(interfaces[len][s2].flags & INMEMORY)) {
3589 M_FLTMOVE(s1,interfaces[len][s2].regoff);
3592 M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3596 var_to_reg_int(s1, src, REG_ITMP1);
3597 if (!(interfaces[len][s2].flags & INMEMORY)) {
3598 M_INTMOVE(s1,interfaces[len][s2].regoff);
3601 M_LST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3607 } /* if (bptr -> flags >= BBREACHED) */
3608 } /* for basic block */
3610 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3613 /* generate bound check stubs */
3615 s4 *xcodeptr = NULL;
3617 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3618 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3619 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3620 xboundrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3625 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3626 xboundrefs->branchpos, (u1*) mcodeptr - mcodebase);
3630 M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos - 4);
3632 if (xcodeptr != NULL) {
3633 int disp = (xcodeptr-mcodeptr)-1;
3637 xcodeptr = mcodeptr;
3639 a = dseg_addaddress(proto_java_lang_ArrayIndexOutOfBoundsException);
3640 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3642 a = dseg_addaddress(asm_handle_exception);
3643 M_ALD(REG_ITMP3, REG_PV, a);
3645 M_JMP(REG_ZERO, REG_ITMP3);
3649 /* generate negative array size check stubs */
3653 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3654 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3655 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3656 xcheckarefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3660 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3661 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
3665 M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos - 4);
3667 if (xcodeptr != NULL) {
3668 int disp = (xcodeptr-mcodeptr)-1;
3672 xcodeptr = mcodeptr;
3674 a = dseg_addaddress(proto_java_lang_NegativeArraySizeException);
3675 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3677 a = dseg_addaddress(asm_handle_exception);
3678 M_ALD(REG_ITMP3, REG_PV, a);
3680 M_JMP(REG_ZERO, REG_ITMP3);
3684 /* generate cast check stubs */
3688 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3689 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3690 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3691 xcastrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3695 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3696 xcastrefs->branchpos, (u1*) mcodeptr - mcodebase);
3700 M_LDA(REG_ITMP2_XPC, REG_PV, xcastrefs->branchpos - 4);
3702 if (xcodeptr != NULL) {
3703 int disp = (xcodeptr-mcodeptr)-1;
3707 xcodeptr = mcodeptr;
3709 a = dseg_addaddress(proto_java_lang_ClassCastException);
3710 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3712 a = dseg_addaddress(asm_handle_exception);
3713 M_ALD(REG_ITMP3, REG_PV, a);
3715 M_JMP(REG_ZERO, REG_ITMP3);
3720 #ifdef SOFTNULLPTRCHECK
3722 /* generate null pointer check stubs */
3726 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3727 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3728 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3729 xnullrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3733 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3734 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
3738 M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
3740 if (xcodeptr != NULL) {
3741 int disp = (xcodeptr-mcodeptr)-1;
3745 xcodeptr = mcodeptr;
3747 a = dseg_addaddress(proto_java_lang_NullPointerException);
3748 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3750 a = dseg_addaddress(asm_handle_exception);
3751 M_ALD(REG_ITMP3, REG_PV, a);
3753 M_JMP(REG_ZERO, REG_ITMP3);
3760 codegen_finish((int)((u1*) mcodeptr - mcodebase));
3764 /* redefinition of code generation macros (compiling into array) **************/
3767 These macros are newly defined to allow code generation into an array.
3768 This is necessary, because the original M_.. macros generate code by
3769 calling 'codegen_adds4' that uses an additional data structure to
3772 For a faster (but less flexible) version to generate code, these
3773 macros directly use the (s4* p) - pointer to put the code directly
3774 in a locally defined array.
3775 This makes sense only for the stub-generation-routines below.
3779 #define M_OP3(op,fu,a,b,c,const) \
3780 *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \
3781 ((const)<<12)|((fu)<<5)|((c)) )
3783 #define M_FOP3(op,fu,a,b,c) \
3784 *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) )
3786 #define M_BRA(op,a,disp) \
3787 *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) )
3789 #define M_MEM(op,a,b,disp) \
3790 *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) )
3793 /* function createcompilerstub *************************************************
3795 creates a stub routine which calls the compiler
3797 *******************************************************************************/
3799 #define COMPSTUBSIZE 3
3801 u1 *createcompilerstub (methodinfo *m)
3803 u8 *s = CNEW (u8, COMPSTUBSIZE); /* memory to hold the stub */
3804 s4 *p = (s4*) s; /* code generation pointer */
3806 /* code for the stub */
3807 M_ALD (REG_PV, REG_PV, 16); /* load pointer to the compiler */
3808 M_JMP (0, REG_PV); /* jump to the compiler, return address
3809 in reg 0 is used as method pointer */
3810 s[1] = (u8) m; /* literals to be adressed */
3811 s[2] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3814 count_cstub_len += COMPSTUBSIZE * 8;
3821 /* function removecompilerstub *************************************************
3823 deletes a compilerstub from memory (simply by freeing it)
3825 *******************************************************************************/
3827 void removecompilerstub (u1 *stub)
3829 CFREE (stub, COMPSTUBSIZE * 8);
3833 bool isFloat(char **utf_ptr,char *desc_end)
3837 if (*utf_ptr>=desc_end)
3838 panic("illegal methoddescriptor (isFloat)");
3839 switch (c=utf_nextu2(utf_ptr)) {
3841 while (utf_nextu2(utf_ptr)!=';');
3860 while ((ch = utf_nextu2(utf_ptr))=='[')
3864 while (utf_nextu2(utf_ptr)!=';')
3871 printf("CHAR: %c\n",c);
3872 panic ("illegal methoddescriptor(isFloat)");
3879 u4 ngen_get_parametercount(methodinfo *m)
3881 utf *descr = m->descriptor; /* method-descriptor */
3882 char *utf_ptr = descr->text; /* current position in utf-text */
3883 char *desc_end = utf_end(descr); /* points behind utf string */
3884 java_objectarray* result;
3885 int parametercount = 0;
3889 utf_nextu2(&utf_ptr);
3891 /* determine number of parameters */
3892 while ( *utf_ptr != ')' ) {
3893 isFloat(&utf_ptr,desc_end);
3897 return parametercount;
3901 /* function: createnativestub **************************************************
3903 creates a stub routine which calls a native method
3905 *******************************************************************************/
3907 #define NATIVESTUBSIZE 35
3908 #define NATIVESTUBOFFSET 9
3910 int runverbosenat = 1;
3912 u1 *createnativestub (functionptr f, methodinfo *m)
3916 int paramsOnStack=0;
3918 int paramsStillToMove=0;
3919 int paramTargetOffset=0;
3920 int paramSourceOffset=0;
3922 u8 *s = CNEW (u8, (NATIVESTUBSIZE)); /* memory to hold the stub */
3923 u8 *cs = s + NATIVESTUBOFFSET;
3924 s4 *p = (s4*) (cs); /* code generation pointer */
3926 utf *descr = m->descriptor; /* method-descriptor */
3927 char *utf_ptr = descr->text; /* current position in utf-text */
3928 char *desc_end = utf_end(descr); /* points behind utf string */
3932 *(cs-1) = (u8) f; /* address of native method */
3933 *(cs-2) = (u8) (&exceptionptr); /* address of exceptionptr */
3934 *(cs-3) = (u8) asm_handle_nat_exception; /* addr of asm exception handler */
3935 *(cs-4) = (u8) (&env); /* addr of jni_environement */
3936 *(cs-5) = (u8) asm_builtin_trace;
3938 *(cs-7) = (u8) asm_builtin_exittrace;
3939 *(cs-8) = (u8) builtin_trace_exception;
3940 *(cs-9) = (u8) m->class;
3948 utf_display(m->class->name);
3950 utf_display(m->name);
3951 printf(" 0x%p\n", cs);
3954 M_LDA (REG_SP, REG_SP, -8); /* build up stackframe */
3955 M_AST (REG_RA, REG_SP, 0); /* store return address */
3958 if (runverbosenat) {
3959 M_ALD(REG_ITMP1, REG_PV, -6*8);
3960 M_ALD(REG_PV, REG_PV, -5*8);
3962 M_JSR(REG_RA, REG_PV);
3963 disp = -(int) (p - (s4*) cs)*4;
3964 M_LDA(REG_PV, REG_RA, disp);
3970 utf_display(m->descriptor);
3972 paramCount=ngen_get_parametercount(m);
3975 paramsOnStack=paramCount-(6/*paramregs*/ -1/*env*/ - ((m->flags & ACC_STATIC)?1:0));
3976 paramsStillToMove=paramsOnStack;
3977 if (paramsOnStack>0)
3978 M_LDA(REG_SP,REG_SP,-8*paramsOnStack);
3980 if (m->flags & ACC_STATIC) {
3982 if (paramsOnStack>0) {
3983 utf_nextu2(&utf_ptr);
3985 isFloat(&utf_ptr,desc_end);
3987 if (isFloat(&utf_ptr,desc_end))
3988 M_DST (argfltregs[4], REG_SP, 0);
3990 M_LST (argintregs[4], REG_SP, 0);
3992 if (paramsOnStack>1)
3993 if (isFloat(&utf_ptr,desc_end))
3994 M_DST (argfltregs[5], REG_SP, 8);
3996 M_LST (argintregs[5], REG_SP, 8);
3998 paramsStillToMove -=2;
3999 paramTargetOffset=16;
4004 if (paramsOnStack>0) {
4005 utf_nextu2(&utf_ptr);
4007 isFloat(&utf_ptr,desc_end);
4009 if (isFloat(&utf_ptr,desc_end))
4010 M_DST (argfltregs[5], REG_SP, 0);
4012 M_LST (argintregs[5], REG_SP, 0);
4013 paramsStillToMove -=1;
4014 paramTargetOffset = 8;
4016 M_MOV (argintregs[4],argintregs[5]);
4017 M_FMOV (argfltregs[4],argfltregs[5]);
4019 M_MOV (argintregs[3],argintregs[4+regoffset]);
4020 M_FMOV (argfltregs[3],argfltregs[4+regoffset]);
4022 M_MOV (argintregs[2],argintregs[3+regoffset]);
4023 M_FMOV (argfltregs[2],argfltregs[3+regoffset]);
4025 M_MOV (argintregs[1],argintregs[2+regoffset]);
4026 M_FMOV (argfltregs[1],argfltregs[2+regoffset]);
4028 M_MOV (argintregs[0],argintregs[1+regoffset]);
4029 M_FMOV (argfltregs[0],argfltregs[1+regoffset]);
4031 if (m->flags & ACC_STATIC) {
4032 M_ALD (argintregs[1],REG_PV, -9*8);/* class adress */
4035 paramSourceOffset=8*paramsOnStack+9;
4036 for (i=0;i<paramsStillToMove;i++) {
4037 if (isFloat(&utf_ptr,desc_end)) {
4038 M_DLD(REG_ITMP1,REG_SP,paramSourceOffset);
4039 M_DST (REG_ITMP1, REG_SP, paramTargetOffset);
4041 M_ALD(REG_ITMP1,REG_SP,paramSourceOffset);
4042 M_LST (REG_ITMP1, REG_SP, paramTargetOffset);
4044 paramSourceOffset+=8;
4045 paramTargetOffset+=8;
4048 M_ALD (argintregs[0], REG_PV, -4*8);/* load adress of jni_environement */
4050 M_ALD (REG_PV, REG_PV, -1*8); /* load adress of native method */
4053 M_JSR (REG_RA, REG_PV); /* call native method */
4055 disp = -(int) (p - (s4*) cs)*4;
4056 M_LDA (REG_PV, REG_RA, disp); /* recompute pv from ra */
4057 M_ALD (REG_ITMP3, REG_PV, -2*8); /* get address of exceptionptr */
4059 M_ALD (REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4061 if (paramsOnStack>0)
4062 M_LDA(REG_SP,REG_SP,8*paramsOnStack);
4066 3 + (runverbosenat ? 6 : 0)); /* if no exception then return */
4069 if (runverbosenat) {
4070 M_ALD(argintregs[0], REG_PV, -6*8);
4071 M_MOV(REG_RESULT, argintregs[1]);
4072 M_FMOV(REG_FRESULT, argfltregs[2]);
4073 M_FMOV(REG_FRESULT, argfltregs[3]);
4074 M_ALD(REG_PV, REG_PV, -7*8);
4075 M_JSR(REG_RA, REG_PV);
4079 M_ALD (REG_RA, REG_SP, 0); /* load return address */
4080 M_LDA (REG_SP, REG_SP, 8); /* remove stackframe */
4082 M_RET (REG_ZERO, REG_RA); /* return to caller */
4084 M_AST (REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4087 if (runverbosenat) {
4088 M_LDA(REG_SP, REG_SP, -9);
4089 M_AST(REG_ITMP1, REG_SP, 0);
4090 M_MOV(REG_ITMP1, argintregs[0]);
4091 M_ALD(argintregs[1], REG_PV, -6*8);
4092 M_ALD(argintregs[2], REG_SP, 0);
4093 M_CLR(argintregs[3]);
4094 M_ALD(REG_PV, REG_PV, -8*8);
4095 M_JSR(REG_RA, REG_PV);
4096 disp = -(int) (p - (s4*) cs)*4;
4097 M_LDA (REG_PV, REG_RA, disp);
4098 M_ALD(REG_ITMP1, REG_SP, 0);
4099 M_LDA(REG_SP, REG_SP, 9);
4103 M_ALD (REG_RA, REG_SP, 0); /* load return address */
4104 M_LDA (REG_SP, REG_SP, 8); /* remove stackframe */
4106 M_LDA (REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4108 M_ALD (REG_ITMP3, REG_PV, -3*8); /* load asm exception handler address */
4109 M_JMP (REG_ZERO, REG_ITMP3); /* jump to asm exception handler */
4113 static int stubprinted;
4115 printf("stubsize: %d/2\n", (int) (p - (s4*) s));
4121 count_nstub_len += NATIVESTUBSIZE * 8;
4124 return (u1*) (s + NATIVESTUBOFFSET);
4127 /* function: removenativestub **************************************************
4129 removes a previously created native-stub from memory
4131 *******************************************************************************/
4133 void removenativestub (u1 *stub)
4135 CFREE ((u8*) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 8);
4140 * These are local overrides for various environment variables in Emacs.
4141 * Please do not remove this and leave it at the end of the file, where
4142 * Emacs will automagically detect them.
4143 * ---------------------------------------------------------------------
4146 * indent-tabs-mode: t