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 1298 2004-07-10 17:06:21Z stefan $
41 #include "jit/alpha/codegen.h"
43 #include "jit/parse.h"
53 /* include independent code generation stuff */
54 #include "jit/codegen.inc"
55 #include "jit/reg.inc"
58 /* *****************************************************************************
60 Datatypes and Register Allocations:
61 -----------------------------------
63 On 64-bit-machines (like the Alpha) all operands are stored in the
64 registers in a 64-bit form, even when the correspondig JavaVM operands
65 only need 32 bits. This is done by a canonical representation:
67 32-bit integers are allways stored as sign-extended 64-bit values (this
68 approach is directly supported by the Alpha architecture and is very easy
71 32-bit-floats are stored in a 64-bit doubleprecision register by simply
72 expanding the exponent and mantissa with zeroes. (also supported by the
78 The calling conventions and the layout of the stack is explained in detail
79 in the documention file: calling.doc
81 *******************************************************************************/
84 /* register descripton - array ************************************************/
86 /* #define REG_RES 0 reserved register for OS or code generator */
87 /* #define REG_RET 1 return value register */
88 /* #define REG_EXC 2 exception value register (only old jit) */
89 /* #define REG_SAV 3 (callee) saved register */
90 /* #define REG_TMP 4 scratch temporary register (caller saved) */
91 /* #define REG_ARG 5 argument register (caller saved) */
93 /* #define REG_END -1 last entry in tables */
96 REG_RET, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
97 REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
98 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
99 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
102 /* for use of reserved registers, see comment above */
104 int nregdescfloat[] = {
105 REG_RET, REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
106 REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
107 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
108 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES,
111 /* for use of reserved registers, see comment above */
114 /* parameter allocation mode */
116 int nreg_parammode = PARAMMODE_NUMBERED;
118 /* parameter-registers will be allocated by assigning the
119 1. parameter: int/float-reg 16
120 2. parameter: int/float-reg 17
121 3. parameter: int/float-reg 18 ....
125 /* stackframe-infos ***********************************************************/
127 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
129 /* -> see file 'calling.doc' */
132 /* additional functions and macros to generate code ***************************/
134 /* #define BlockPtrOfPC(pc) block+block_index[pc] */
135 #define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
139 #define COUNT_SPILLS count_spills++
145 /* gen_nullptr_check(objreg) */
147 #define gen_nullptr_check(objreg) \
149 M_BEQZ((objreg), 0); \
150 codegen_addxnullrefs(mcodeptr); \
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; \
204 /* store_reg_to_var_xxx:
205 This function generates the code to store the result of an operation
206 back into a spilled pseudo-variable.
207 If the pseudo-variable has not been spilled in the first place, this
208 function will generate nothing.
210 v ............ Pseudovariable
211 tempregnum ... Number of the temporary registers as returned by
215 #define store_reg_to_var_int(sptr, tempregnum) { \
216 if ((sptr)->flags & INMEMORY) { \
218 M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
222 #define store_reg_to_var_flt(sptr, tempregnum) { \
223 if ((sptr)->flags & INMEMORY) { \
225 M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
230 /* NullPointerException handlers and exception handling initialisation */
232 typedef struct sigctx_struct {
234 long sc_onstack; /* sigstack state to restore */
235 long sc_mask; /* signal mask to restore */
236 long sc_pc; /* pc at time of signal */
237 long sc_ps; /* psl to retore */
238 long sc_regs[32]; /* processor regs 0 to 31 */
239 long sc_ownedfp; /* fp has been used */
240 long sc_fpregs[32]; /* fp regs 0 to 31 */
241 unsigned long sc_fpcr; /* floating point control register */
242 unsigned long sc_fp_control; /* software fpcr */
244 unsigned long sc_reserved1, sc_reserved2;
245 unsigned long sc_ssize;
247 unsigned long sc_traparg_a0;
248 unsigned long sc_traparg_a1;
249 unsigned long sc_traparg_a2;
250 unsigned long sc_fp_trap_pc;
251 unsigned long sc_fp_trigger_sum;
252 unsigned long sc_fp_trigger_inst;
253 unsigned long sc_retcode[2];
257 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
258 void thread_restartcriticalsection(ucontext_t *uc)
261 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.sc_pc)) != NULL)
262 uc->uc_mcontext.sc_pc = (u8) critical;
266 /* NullPointerException signal handler for hardware null pointer check */
268 void catch_NullPointerException(int sig, int code, sigctx_struct *sigctx)
273 java_objectheader *xptr;
275 /* Reset signal handler - necessary for SysV, does no harm for BSD */
277 instr = *((int*)(sigctx->sc_pc));
278 faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f];
280 if (faultaddr == 0) {
281 signal(sig, (void*) catch_NullPointerException); /* reinstall handler */
283 sigaddset(&nsig, sig);
284 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
286 xptr = new_exception(string_java_lang_NullPointerException);
288 sigctx->sc_regs[REG_ITMP1_XPTR] = (u8) xptr;
289 sigctx->sc_regs[REG_ITMP2_XPC] = sigctx->sc_pc;
290 sigctx->sc_pc = (u8) asm_handle_exception;
294 faultaddr += (long) ((instr << 16) >> 16);
295 fprintf(stderr, "faulting address: 0x%016lx\n", faultaddr);
296 panic("Stack overflow");
303 void init_exceptions(void)
308 /* Linux on Digital Alpha needs an initialisation of the ieee floating point
309 control for IEEE compliant arithmetic (option -mieee of GCC). Under
310 Digital Unix this is done automatically.
315 extern unsigned long ieee_get_fp_control();
316 extern void ieee_set_fp_control(unsigned long fp_control);
318 void init_exceptions(void)
320 /* initialize floating point control */
322 ieee_set_fp_control(ieee_get_fp_control()
323 & ~IEEE_TRAP_ENABLE_INV
324 & ~IEEE_TRAP_ENABLE_DZE
325 /* & ~IEEE_TRAP_ENABLE_UNF we dont want underflow */
326 & ~IEEE_TRAP_ENABLE_OVF);
329 /* install signal handlers we need to convert to exceptions */
333 signal(SIGSEGV, (void*) catch_NullPointerException);
337 signal(SIGBUS, (void*) catch_NullPointerException);
343 /* function gen_mcode **********************************************************
345 generates machine code
347 *******************************************************************************/
349 void codegen(methodinfo *m)
351 s4 len, s1, s2, s3, d;
365 /* keep code size smaller */
368 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
370 /* space to save used callee saved registers */
372 savedregs_num += (r->savintregcnt - r->maxsavintreguse);
373 savedregs_num += (r->savfltregcnt - r->maxsavfltreguse);
375 parentargs_base = r->maxmemuse + savedregs_num;
377 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
379 if (checksync && (m->flags & ACC_SYNCHRONIZED))
384 /* create method header */
386 (void) dseg_addaddress(m); /* MethodPointer */
387 (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
389 #if defined(USE_THREADS)
391 /* IsSync contains the offset relative to the stack pointer for the
392 argument of monitor_exit used in the exception handler. Since the
393 offset could be zero and give a wrong meaning of the flag it is
397 if (checksync && (m->flags & ACC_SYNCHRONIZED))
398 (void) dseg_adds4((r->maxmemuse + 1) * 8); /* IsSync */
403 (void) dseg_adds4(0); /* IsSync */
405 (void) dseg_adds4(m->isleafmethod); /* IsLeaf */
406 (void) dseg_adds4(r->savintregcnt - r->maxsavintreguse);/* IntSave */
407 (void) dseg_adds4(r->savfltregcnt - r->maxsavfltreguse);/* FltSave */
409 dseg_addlinenumbertablesize();
411 (void) dseg_adds4(m->exceptiontablelength); /* ExTableSize */
413 /* create exception table */
415 for (ex = m->exceptiontable; ex != NULL; ex = ex->down) {
416 dseg_addtarget(ex->start);
417 dseg_addtarget(ex->end);
418 dseg_addtarget(ex->handler);
419 (void) dseg_addaddress(ex->catchtype);
422 /* initialize mcode variables */
424 mcodeptr = (s4*) mcodebase;
425 mcodeend = (s4*) (mcodebase + mcodesize);
426 MCODECHECK(128 + m->paramcount);
428 /* create stack frame (if necessary) */
430 if (parentargs_base) {
431 M_LDA (REG_SP, REG_SP, -parentargs_base * 8);
434 /* save return address and used callee saved registers */
437 if (!m->isleafmethod) {
438 p--; M_AST(REG_RA, REG_SP, p * 8);
440 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
441 p--; M_LST(r->savintregs[i], REG_SP, p * 8);
443 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
444 p--; M_DST(r->savfltregs[i], REG_SP, p * 8);
447 /* save monitorenter argument */
449 #if defined(USE_THREADS)
450 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
451 if (m->flags & ACC_STATIC) {
452 p = dseg_addaddress(m->class);
453 M_ALD(REG_ITMP1, REG_PV, p);
454 M_AST(REG_ITMP1, REG_SP, r->maxmemuse * 8);
457 M_AST(r->argintregs[0], REG_SP, r->maxmemuse * 8);
462 /* copy argument registers to stack and call trace function with pointer
463 to arguments on stack.
468 M_LDA(REG_SP, REG_SP, -((INT_ARG_CNT + FLT_ARG_CNT + 2) * 8));
469 M_AST(REG_RA, REG_SP, 1 * 8);
471 /* save integer argument registers */
472 for (p = 0; /* p < m->paramcount && */ p < INT_ARG_CNT; p++) {
473 M_LST(r->argintregs[p], REG_SP, (2 + p) * 8);
476 /* save and copy float arguments into integer registers */
477 for (p = 0; /* p < m->paramcount && */ p < FLT_ARG_CNT; p++) {
478 t = m->paramtypes[p];
480 if (IS_FLT_DBL_TYPE(t)) {
481 if (IS_2_WORD_TYPE(t)) {
482 M_DST(r->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
485 M_FST(r->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
488 M_LLD(r->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
491 M_DST(r->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
495 p = dseg_addaddress(m);
496 M_ALD(REG_ITMP1, REG_PV, p);
497 M_AST(REG_ITMP1, REG_SP, 0 * 8);
498 p = dseg_addaddress((void *) builtin_trace_args);
499 M_ALD(REG_PV, REG_PV, p);
500 M_JSR(REG_RA, REG_PV);
501 disp = -(s4) ((u1 *) mcodeptr - mcodebase);
502 M_LDA(REG_PV, REG_RA, disp);
503 M_ALD(REG_RA, REG_SP, 1 * 8);
505 for (p = 0; /* p < mparamcount && */ p < INT_ARG_CNT; p++) {
506 M_LLD(r->argintregs[p], REG_SP, (2 + p) * 8);
509 for (p = 0; /* p < mparamcount && */ p < FLT_ARG_CNT; p++) {
510 t = m->paramtypes[p];
512 if (IS_FLT_DBL_TYPE(t)) {
513 if (IS_2_WORD_TYPE(t)) {
514 M_DLD(r->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
517 M_FLD(r->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
521 M_DLD(r->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
525 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT + 2) * 8);
528 /* take arguments out of register or stack frame */
530 for (p = 0, l = 0; p < m->paramcount; p++) {
531 t = m->paramtypes[p];
532 var = &(r->locals[l][t]);
534 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
538 if (IS_INT_LNG_TYPE(t)) { /* integer args */
539 if (p < INT_ARG_CNT) { /* register arguments */
540 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
541 M_INTMOVE(r->argintregs[p], var->regoff);
542 } else { /* reg arg -> spilled */
543 M_LST(r->argintregs[p], REG_SP, 8 * var->regoff);
546 } else { /* stack arguments */
547 pa = p - INT_ARG_CNT;
548 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
549 M_LLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
551 } else { /* stack arg -> spilled */
552 M_LLD(REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
553 M_LST(REG_ITMP1, REG_SP, 8 * var->regoff);
557 } else { /* floating args */
558 if (p < FLT_ARG_CNT) { /* register arguments */
559 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
560 M_FLTMOVE(r->argfltregs[p], var->regoff);
562 } else { /* reg arg -> spilled */
563 M_DST(r->argfltregs[p], REG_SP, 8 * var->regoff);
566 } else { /* stack arguments */
567 pa = p - FLT_ARG_CNT;
568 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
569 M_DLD(var->regoff, REG_SP, 8 * (parentargs_base + pa) );
571 } else { /* stack-arg -> spilled */
572 M_DLD(REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
573 M_DST(REG_FTMP1, REG_SP, 8 * var->regoff);
579 /* call monitorenter function */
581 #if defined(USE_THREADS)
582 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
584 s8 func_enter = (m->flags & ACC_STATIC) ?
585 (s8) builtin_staticmonitorenter : (s8) builtin_monitorenter;
586 p = dseg_addaddress((void*) func_enter);
587 M_ALD(REG_PV, REG_PV, p);
588 M_ALD(r->argintregs[0], REG_SP, r->maxmemuse * 8);
589 M_JSR(REG_RA, REG_PV);
590 disp = -(s4) ((u1 *) mcodeptr - mcodebase);
591 M_LDA(REG_PV, REG_RA, disp);
596 /* end of header generation */
598 /* walk through all basic blocks */
599 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
601 bptr->mpc = (s4) ((u1 *) mcodeptr - mcodebase);
603 if (bptr->flags >= BBREACHED) {
605 /* branch resolving */
609 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
610 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
611 brefs->branchpos, bptr->mpc);
615 /* copy interface registers to their destination */
620 while (src != NULL) {
622 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
623 d = reg_of_var(m, src, REG_ITMP1);
624 M_INTMOVE(REG_ITMP1, d);
625 store_reg_to_var_int(src, d);
628 d = reg_of_var(m, src, REG_IFTMP);
629 if ((src->varkind != STACKVAR)) {
631 if (IS_FLT_DBL_TYPE(s2)) {
632 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
633 s1 = r->interfaces[len][s2].regoff;
637 M_DLD(d, REG_SP, 8 * r->interfaces[len][s2].regoff);
639 store_reg_to_var_flt(src, d);
642 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
643 s1 = r->interfaces[len][s2].regoff;
647 M_LLD(d, REG_SP, 8 * r->interfaces[len][s2].regoff);
649 store_reg_to_var_int(src, d);
656 /* walk through all instructions */
660 for (iptr = bptr->iinstr;
662 src = iptr->dst, len--, iptr++) {
664 MCODECHECK(64); /* an instruction usually needs < 64 words */
667 case ICMD_NOP: /* ... ==> ... */
670 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
672 var_to_reg_int(s1, src, REG_ITMP1);
674 codegen_addxnullrefs(mcodeptr);
677 /* constant operations ************************************************/
679 #define ICONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LDA(r,REG_ZERO,c);} \
680 else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
682 #define LCONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LDA(r,REG_ZERO,c);} \
683 else{a=dseg_adds8(c);M_LLD(r,REG_PV,a);}
685 case ICMD_ICONST: /* ... ==> ..., constant */
686 /* op1 = 0, val.i = constant */
688 d = reg_of_var(m, iptr->dst, REG_ITMP1);
689 ICONST(d, iptr->val.i);
690 store_reg_to_var_int(iptr->dst, d);
693 case ICMD_LCONST: /* ... ==> ..., constant */
694 /* op1 = 0, val.l = constant */
696 d = reg_of_var(m, iptr->dst, REG_ITMP1);
697 LCONST(d, iptr->val.l);
698 store_reg_to_var_int(iptr->dst, d);
701 case ICMD_FCONST: /* ... ==> ..., constant */
702 /* op1 = 0, val.f = constant */
704 d = reg_of_var(m, iptr->dst, REG_FTMP1);
705 a = dseg_addfloat(iptr->val.f);
707 store_reg_to_var_flt(iptr->dst, d);
710 case ICMD_DCONST: /* ... ==> ..., constant */
711 /* op1 = 0, val.d = constant */
713 d = reg_of_var(m, iptr->dst, REG_FTMP1);
714 a = dseg_adddouble(iptr->val.d);
716 store_reg_to_var_flt(iptr->dst, d);
719 case ICMD_ACONST: /* ... ==> ..., constant */
720 /* op1 = 0, val.a = constant */
722 d = reg_of_var(m, iptr->dst, REG_ITMP1);
724 a = dseg_addaddress (iptr->val.a);
728 M_INTMOVE(REG_ZERO, d);
730 store_reg_to_var_int(iptr->dst, d);
734 /* load/store operations **********************************************/
736 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
737 case ICMD_LLOAD: /* op1 = local variable */
740 d = reg_of_var(m, iptr->dst, REG_ITMP1);
741 if ((iptr->dst->varkind == LOCALVAR) &&
742 (iptr->dst->varnum == iptr->op1))
744 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
745 if (var->flags & INMEMORY)
746 M_LLD(d, REG_SP, 8 * var->regoff);
748 {M_INTMOVE(var->regoff,d);}
749 store_reg_to_var_int(iptr->dst, d);
752 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
753 case ICMD_DLOAD: /* op1 = local variable */
755 d = reg_of_var(m, iptr->dst, REG_FTMP1);
756 if ((iptr->dst->varkind == LOCALVAR) &&
757 (iptr->dst->varnum == iptr->op1))
759 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
760 if (var->flags & INMEMORY)
761 M_DLD(d, REG_SP, 8 * var->regoff);
763 {M_FLTMOVE(var->regoff,d);}
764 store_reg_to_var_flt(iptr->dst, d);
768 case ICMD_ISTORE: /* ..., value ==> ... */
769 case ICMD_LSTORE: /* op1 = local variable */
772 if ((src->varkind == LOCALVAR) &&
773 (src->varnum == iptr->op1))
775 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
776 if (var->flags & INMEMORY) {
777 var_to_reg_int(s1, src, REG_ITMP1);
778 M_LST(s1, REG_SP, 8 * var->regoff);
781 var_to_reg_int(s1, src, var->regoff);
782 M_INTMOVE(s1, var->regoff);
786 case ICMD_FSTORE: /* ..., value ==> ... */
787 case ICMD_DSTORE: /* op1 = local variable */
789 if ((src->varkind == LOCALVAR) &&
790 (src->varnum == iptr->op1))
792 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
793 if (var->flags & INMEMORY) {
794 var_to_reg_flt(s1, src, REG_FTMP1);
795 M_DST(s1, REG_SP, 8 * var->regoff);
798 var_to_reg_flt(s1, src, var->regoff);
799 M_FLTMOVE(s1, var->regoff);
804 /* pop/dup/swap operations ********************************************/
806 /* attention: double and longs are only one entry in CACAO ICMDs */
808 case ICMD_POP: /* ..., value ==> ... */
809 case ICMD_POP2: /* ..., value, value ==> ... */
812 #define M_COPY(from,to) \
813 d = reg_of_var(m, to, REG_IFTMP); \
814 if ((from->regoff != to->regoff) || \
815 ((from->flags ^ to->flags) & INMEMORY)) { \
816 if (IS_FLT_DBL_TYPE(from->type)) { \
817 var_to_reg_flt(s1, from, d); \
819 store_reg_to_var_flt(to, d); \
822 var_to_reg_int(s1, from, d); \
824 store_reg_to_var_int(to, d); \
828 case ICMD_DUP: /* ..., a ==> ..., a, a */
829 M_COPY(src, iptr->dst);
832 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
834 M_COPY(src, iptr->dst->prev->prev);
836 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
838 M_COPY(src, iptr->dst);
839 M_COPY(src->prev, iptr->dst->prev);
842 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
844 M_COPY(src->prev, iptr->dst->prev->prev->prev);
846 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
848 M_COPY(src, iptr->dst);
849 M_COPY(src->prev, iptr->dst->prev);
850 M_COPY(src->prev->prev, iptr->dst->prev->prev);
851 M_COPY(src, iptr->dst->prev->prev->prev);
854 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
856 M_COPY(src, iptr->dst);
857 M_COPY(src->prev, iptr->dst->prev);
858 M_COPY(src->prev->prev, iptr->dst->prev->prev);
859 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
860 M_COPY(src, iptr->dst->prev->prev->prev->prev);
861 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
864 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
866 M_COPY(src, iptr->dst->prev);
867 M_COPY(src->prev, iptr->dst);
871 /* integer operations *************************************************/
873 case ICMD_INEG: /* ..., value ==> ..., - value */
875 var_to_reg_int(s1, src, REG_ITMP1);
876 d = reg_of_var(m, iptr->dst, REG_ITMP3);
877 M_ISUB(REG_ZERO, s1, d);
878 store_reg_to_var_int(iptr->dst, d);
881 case ICMD_LNEG: /* ..., value ==> ..., - value */
883 var_to_reg_int(s1, src, REG_ITMP1);
884 d = reg_of_var(m, iptr->dst, REG_ITMP3);
885 M_LSUB(REG_ZERO, s1, d);
886 store_reg_to_var_int(iptr->dst, d);
889 case ICMD_I2L: /* ..., value ==> ..., value */
891 var_to_reg_int(s1, src, REG_ITMP1);
892 d = reg_of_var(m, iptr->dst, REG_ITMP3);
894 store_reg_to_var_int(iptr->dst, d);
897 case ICMD_L2I: /* ..., value ==> ..., value */
899 var_to_reg_int(s1, src, REG_ITMP1);
900 d = reg_of_var(m, iptr->dst, REG_ITMP3);
901 M_IADD(s1, REG_ZERO, d );
902 store_reg_to_var_int(iptr->dst, d);
905 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
907 var_to_reg_int(s1, src, REG_ITMP1);
908 d = reg_of_var(m, iptr->dst, REG_ITMP3);
909 if (has_ext_instr_set) {
913 M_SLL_IMM(s1, 56, d);
914 M_SRA_IMM( d, 56, d);
916 store_reg_to_var_int(iptr->dst, d);
919 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
921 var_to_reg_int(s1, src, REG_ITMP1);
922 d = reg_of_var(m, iptr->dst, REG_ITMP3);
924 store_reg_to_var_int(iptr->dst, d);
927 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
929 var_to_reg_int(s1, src, REG_ITMP1);
930 d = reg_of_var(m, iptr->dst, REG_ITMP3);
931 if (has_ext_instr_set) {
935 M_SLL_IMM(s1, 48, d);
936 M_SRA_IMM( d, 48, d);
938 store_reg_to_var_int(iptr->dst, d);
942 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
944 var_to_reg_int(s1, src->prev, REG_ITMP1);
945 var_to_reg_int(s2, src, REG_ITMP2);
946 d = reg_of_var(m, iptr->dst, REG_ITMP3);
948 store_reg_to_var_int(iptr->dst, d);
951 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
952 /* val.i = constant */
954 var_to_reg_int(s1, src, REG_ITMP1);
955 d = reg_of_var(m, iptr->dst, REG_ITMP3);
956 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
957 M_IADD_IMM(s1, iptr->val.i, d);
960 ICONST(REG_ITMP2, iptr->val.i);
961 M_IADD(s1, REG_ITMP2, d);
963 store_reg_to_var_int(iptr->dst, d);
966 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
968 var_to_reg_int(s1, src->prev, REG_ITMP1);
969 var_to_reg_int(s2, src, REG_ITMP2);
970 d = reg_of_var(m, iptr->dst, REG_ITMP3);
972 store_reg_to_var_int(iptr->dst, d);
975 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
976 /* val.l = constant */
978 var_to_reg_int(s1, src, REG_ITMP1);
979 d = reg_of_var(m, iptr->dst, REG_ITMP3);
980 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
981 M_LADD_IMM(s1, iptr->val.l, d);
984 LCONST(REG_ITMP2, iptr->val.l);
985 M_LADD(s1, REG_ITMP2, d);
987 store_reg_to_var_int(iptr->dst, d);
990 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
992 var_to_reg_int(s1, src->prev, REG_ITMP1);
993 var_to_reg_int(s2, src, REG_ITMP2);
994 d = reg_of_var(m, iptr->dst, REG_ITMP3);
996 store_reg_to_var_int(iptr->dst, d);
999 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1000 /* val.i = constant */
1002 var_to_reg_int(s1, src, REG_ITMP1);
1003 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1004 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1005 M_ISUB_IMM(s1, iptr->val.i, d);
1008 ICONST(REG_ITMP2, iptr->val.i);
1009 M_ISUB(s1, REG_ITMP2, d);
1011 store_reg_to_var_int(iptr->dst, d);
1014 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1016 var_to_reg_int(s1, src->prev, REG_ITMP1);
1017 var_to_reg_int(s2, src, REG_ITMP2);
1018 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1020 store_reg_to_var_int(iptr->dst, d);
1023 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1024 /* val.l = constant */
1026 var_to_reg_int(s1, src, REG_ITMP1);
1027 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1028 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1029 M_LSUB_IMM(s1, iptr->val.l, d);
1032 LCONST(REG_ITMP2, iptr->val.l);
1033 M_LSUB(s1, REG_ITMP2, d);
1035 store_reg_to_var_int(iptr->dst, d);
1038 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1040 var_to_reg_int(s1, src->prev, REG_ITMP1);
1041 var_to_reg_int(s2, src, REG_ITMP2);
1042 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1044 store_reg_to_var_int(iptr->dst, d);
1047 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1048 /* val.i = constant */
1050 var_to_reg_int(s1, src, REG_ITMP1);
1051 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1052 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1053 M_IMUL_IMM(s1, iptr->val.i, d);
1056 ICONST(REG_ITMP2, iptr->val.i);
1057 M_IMUL(s1, REG_ITMP2, d);
1059 store_reg_to_var_int(iptr->dst, d);
1062 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1064 var_to_reg_int(s1, src->prev, REG_ITMP1);
1065 var_to_reg_int(s2, src, REG_ITMP2);
1066 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1068 store_reg_to_var_int(iptr->dst, d);
1071 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1072 /* val.l = constant */
1074 var_to_reg_int(s1, src, REG_ITMP1);
1075 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1076 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1077 M_LMUL_IMM(s1, iptr->val.l, d);
1080 LCONST(REG_ITMP2, iptr->val.l);
1081 M_LMUL(s1, REG_ITMP2, d);
1083 store_reg_to_var_int(iptr->dst, d);
1086 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1087 case ICMD_LDIVPOW2: /* val.i = constant */
1089 var_to_reg_int(s1, src, REG_ITMP1);
1090 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1091 if (iptr->val.i <= 15) {
1092 M_LDA(REG_ITMP2, s1, (1 << iptr->val.i) -1);
1093 M_CMOVGE(s1, s1, REG_ITMP2);
1096 M_SRA_IMM(s1, 63, REG_ITMP2);
1097 M_SRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1098 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1100 M_SRA_IMM(REG_ITMP2, iptr->val.i, d);
1101 store_reg_to_var_int(iptr->dst, d);
1104 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1106 var_to_reg_int(s1, src->prev, REG_ITMP1);
1107 var_to_reg_int(s2, src, REG_ITMP2);
1108 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1109 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1110 M_SLL(s1, REG_ITMP3, d);
1111 M_IADD(d, REG_ZERO, d);
1112 store_reg_to_var_int(iptr->dst, d);
1115 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1116 /* val.i = constant */
1118 var_to_reg_int(s1, src, REG_ITMP1);
1119 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1120 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1121 M_IADD(d, REG_ZERO, d);
1122 store_reg_to_var_int(iptr->dst, d);
1125 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1127 var_to_reg_int(s1, src->prev, REG_ITMP1);
1128 var_to_reg_int(s2, src, REG_ITMP2);
1129 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1130 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1131 M_SRA(s1, REG_ITMP3, d);
1132 store_reg_to_var_int(iptr->dst, d);
1135 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1136 /* val.i = constant */
1138 var_to_reg_int(s1, src, REG_ITMP1);
1139 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1140 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1141 store_reg_to_var_int(iptr->dst, d);
1144 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1146 var_to_reg_int(s1, src->prev, REG_ITMP1);
1147 var_to_reg_int(s2, src, REG_ITMP2);
1148 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1149 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1151 M_SRL(d, REG_ITMP2, d);
1152 M_IADD(d, REG_ZERO, d);
1153 store_reg_to_var_int(iptr->dst, d);
1156 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1157 /* val.i = constant */
1159 var_to_reg_int(s1, src, REG_ITMP1);
1160 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1162 M_SRL_IMM(d, iptr->val.i & 0x1f, d);
1163 M_IADD(d, REG_ZERO, d);
1164 store_reg_to_var_int(iptr->dst, d);
1167 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1169 var_to_reg_int(s1, src->prev, REG_ITMP1);
1170 var_to_reg_int(s2, src, REG_ITMP2);
1171 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1173 store_reg_to_var_int(iptr->dst, d);
1176 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1177 /* val.i = constant */
1179 var_to_reg_int(s1, src, REG_ITMP1);
1180 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1181 M_SLL_IMM(s1, iptr->val.i & 0x3f, d);
1182 store_reg_to_var_int(iptr->dst, d);
1185 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1187 var_to_reg_int(s1, src->prev, REG_ITMP1);
1188 var_to_reg_int(s2, src, REG_ITMP2);
1189 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1191 store_reg_to_var_int(iptr->dst, d);
1194 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1195 /* val.i = constant */
1197 var_to_reg_int(s1, src, REG_ITMP1);
1198 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1199 M_SRA_IMM(s1, iptr->val.i & 0x3f, d);
1200 store_reg_to_var_int(iptr->dst, d);
1203 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1205 var_to_reg_int(s1, src->prev, REG_ITMP1);
1206 var_to_reg_int(s2, src, REG_ITMP2);
1207 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1209 store_reg_to_var_int(iptr->dst, d);
1212 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1213 /* val.i = constant */
1215 var_to_reg_int(s1, src, REG_ITMP1);
1216 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1217 M_SRL_IMM(s1, iptr->val.i & 0x3f, d);
1218 store_reg_to_var_int(iptr->dst, d);
1221 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1224 var_to_reg_int(s1, src->prev, REG_ITMP1);
1225 var_to_reg_int(s2, src, REG_ITMP2);
1226 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1228 store_reg_to_var_int(iptr->dst, d);
1231 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1232 /* val.i = constant */
1234 var_to_reg_int(s1, src, REG_ITMP1);
1235 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1236 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1237 M_AND_IMM(s1, iptr->val.i, d);
1239 else if (iptr->val.i == 0xffff) {
1242 else if (iptr->val.i == 0xffffff) {
1243 M_ZAPNOT_IMM(s1, 0x07, d);
1246 ICONST(REG_ITMP2, iptr->val.i);
1247 M_AND(s1, REG_ITMP2, d);
1249 store_reg_to_var_int(iptr->dst, d);
1252 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1253 /* val.i = constant */
1255 var_to_reg_int(s1, src, REG_ITMP1);
1256 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1258 M_MOV(s1, REG_ITMP1);
1261 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1262 M_AND_IMM(s1, iptr->val.i, d);
1264 M_ISUB(REG_ZERO, s1, d);
1265 M_AND_IMM(d, iptr->val.i, d);
1267 else if (iptr->val.i == 0xffff) {
1270 M_ISUB(REG_ZERO, s1, d);
1273 else if (iptr->val.i == 0xffffff) {
1274 M_ZAPNOT_IMM(s1, 0x07, d);
1276 M_ISUB(REG_ZERO, s1, d);
1277 M_ZAPNOT_IMM(d, 0x07, d);
1280 ICONST(REG_ITMP2, iptr->val.i);
1281 M_AND(s1, REG_ITMP2, d);
1283 M_ISUB(REG_ZERO, s1, d);
1284 M_AND(d, REG_ITMP2, d);
1286 M_ISUB(REG_ZERO, d, d);
1287 store_reg_to_var_int(iptr->dst, d);
1290 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1291 /* val.l = constant */
1293 var_to_reg_int(s1, src, REG_ITMP1);
1294 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1295 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1296 M_AND_IMM(s1, iptr->val.l, d);
1298 else if (iptr->val.l == 0xffffL) {
1301 else if (iptr->val.l == 0xffffffL) {
1302 M_ZAPNOT_IMM(s1, 0x07, d);
1304 else if (iptr->val.l == 0xffffffffL) {
1307 else if (iptr->val.l == 0xffffffffffL) {
1308 M_ZAPNOT_IMM(s1, 0x1f, d);
1310 else if (iptr->val.l == 0xffffffffffffL) {
1311 M_ZAPNOT_IMM(s1, 0x3f, d);
1313 else if (iptr->val.l == 0xffffffffffffffL) {
1314 M_ZAPNOT_IMM(s1, 0x7f, d);
1317 LCONST(REG_ITMP2, iptr->val.l);
1318 M_AND(s1, REG_ITMP2, d);
1320 store_reg_to_var_int(iptr->dst, d);
1323 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1324 /* val.l = constant */
1326 var_to_reg_int(s1, src, REG_ITMP1);
1327 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1329 M_MOV(s1, REG_ITMP1);
1332 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1333 M_AND_IMM(s1, iptr->val.l, d);
1335 M_LSUB(REG_ZERO, s1, d);
1336 M_AND_IMM(d, iptr->val.l, d);
1338 else if (iptr->val.l == 0xffffL) {
1341 M_LSUB(REG_ZERO, s1, d);
1344 else if (iptr->val.l == 0xffffffL) {
1345 M_ZAPNOT_IMM(s1, 0x07, d);
1347 M_LSUB(REG_ZERO, s1, d);
1348 M_ZAPNOT_IMM(d, 0x07, d);
1350 else if (iptr->val.l == 0xffffffffL) {
1353 M_LSUB(REG_ZERO, s1, d);
1356 else if (iptr->val.l == 0xffffffffffL) {
1357 M_ZAPNOT_IMM(s1, 0x1f, d);
1359 M_LSUB(REG_ZERO, s1, d);
1360 M_ZAPNOT_IMM(d, 0x1f, d);
1362 else if (iptr->val.l == 0xffffffffffffL) {
1363 M_ZAPNOT_IMM(s1, 0x3f, d);
1365 M_LSUB(REG_ZERO, s1, d);
1366 M_ZAPNOT_IMM(d, 0x3f, d);
1368 else if (iptr->val.l == 0xffffffffffffffL) {
1369 M_ZAPNOT_IMM(s1, 0x7f, d);
1371 M_LSUB(REG_ZERO, s1, d);
1372 M_ZAPNOT_IMM(d, 0x7f, d);
1375 LCONST(REG_ITMP2, iptr->val.l);
1376 M_AND(s1, REG_ITMP2, d);
1378 M_LSUB(REG_ZERO, s1, d);
1379 M_AND(d, REG_ITMP2, d);
1381 M_LSUB(REG_ZERO, d, d);
1382 store_reg_to_var_int(iptr->dst, d);
1385 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1388 var_to_reg_int(s1, src->prev, REG_ITMP1);
1389 var_to_reg_int(s2, src, REG_ITMP2);
1390 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1392 store_reg_to_var_int(iptr->dst, d);
1395 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1396 /* val.i = constant */
1398 var_to_reg_int(s1, src, REG_ITMP1);
1399 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1400 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1401 M_OR_IMM(s1, iptr->val.i, d);
1404 ICONST(REG_ITMP2, iptr->val.i);
1405 M_OR(s1, REG_ITMP2, d);
1407 store_reg_to_var_int(iptr->dst, d);
1410 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1411 /* val.l = constant */
1413 var_to_reg_int(s1, src, REG_ITMP1);
1414 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1415 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1416 M_OR_IMM(s1, iptr->val.l, d);
1419 LCONST(REG_ITMP2, iptr->val.l);
1420 M_OR(s1, REG_ITMP2, d);
1422 store_reg_to_var_int(iptr->dst, d);
1425 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1428 var_to_reg_int(s1, src->prev, REG_ITMP1);
1429 var_to_reg_int(s2, src, REG_ITMP2);
1430 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1432 store_reg_to_var_int(iptr->dst, d);
1435 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1436 /* val.i = constant */
1438 var_to_reg_int(s1, src, REG_ITMP1);
1439 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1440 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1441 M_XOR_IMM(s1, iptr->val.i, d);
1444 ICONST(REG_ITMP2, iptr->val.i);
1445 M_XOR(s1, REG_ITMP2, d);
1447 store_reg_to_var_int(iptr->dst, d);
1450 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1451 /* val.l = constant */
1453 var_to_reg_int(s1, src, REG_ITMP1);
1454 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1455 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1456 M_XOR_IMM(s1, iptr->val.l, d);
1459 LCONST(REG_ITMP2, iptr->val.l);
1460 M_XOR(s1, REG_ITMP2, d);
1462 store_reg_to_var_int(iptr->dst, d);
1466 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1468 var_to_reg_int(s1, src->prev, REG_ITMP1);
1469 var_to_reg_int(s2, src, REG_ITMP2);
1470 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1471 M_CMPLT(s1, s2, REG_ITMP3);
1472 M_CMPLT(s2, s1, REG_ITMP1);
1473 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1474 store_reg_to_var_int(iptr->dst, d);
1478 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1479 /* op1 = variable, val.i = constant */
1481 var = &(r->locals[iptr->op1][TYPE_INT]);
1482 if (var->flags & INMEMORY) {
1484 M_LLD(s1, REG_SP, 8 * var->regoff);
1488 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1489 M_IADD_IMM(s1, iptr->val.i, s1);
1491 else if ((iptr->val.i > -256) && (iptr->val.i < 0)) {
1492 M_ISUB_IMM(s1, (-iptr->val.i), s1);
1495 M_LDA (s1, s1, iptr->val.i);
1496 M_IADD(s1, REG_ZERO, s1);
1498 if (var->flags & INMEMORY)
1499 M_LST(s1, REG_SP, 8 * var->regoff);
1503 /* floating operations ************************************************/
1505 case ICMD_FNEG: /* ..., value ==> ..., - value */
1507 var_to_reg_flt(s1, src, REG_FTMP1);
1508 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1510 store_reg_to_var_flt(iptr->dst, d);
1513 case ICMD_DNEG: /* ..., value ==> ..., - value */
1515 var_to_reg_flt(s1, src, REG_FTMP1);
1516 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1518 store_reg_to_var_flt(iptr->dst, d);
1521 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1523 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1524 var_to_reg_flt(s2, src, REG_FTMP2);
1525 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1530 if (d == s1 || d == s2) {
1531 M_FADDS(s1, s2, REG_FTMP3);
1533 M_FMOV(REG_FTMP3, d);
1540 store_reg_to_var_flt(iptr->dst, d);
1543 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1545 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1546 var_to_reg_flt(s2, src, REG_FTMP2);
1547 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1552 if (d == s1 || d == s2) {
1553 M_DADDS(s1, s2, REG_FTMP3);
1555 M_FMOV(REG_FTMP3, d);
1562 store_reg_to_var_flt(iptr->dst, d);
1565 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1567 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1568 var_to_reg_flt(s2, src, REG_FTMP2);
1569 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1574 if (d == s1 || d == s2) {
1575 M_FSUBS(s1, s2, REG_FTMP3);
1577 M_FMOV(REG_FTMP3, d);
1584 store_reg_to_var_flt(iptr->dst, d);
1587 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1589 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1590 var_to_reg_flt(s2, src, REG_FTMP2);
1591 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1596 if (d == s1 || d == s2) {
1597 M_DSUBS(s1, s2, REG_FTMP3);
1599 M_FMOV(REG_FTMP3, d);
1606 store_reg_to_var_flt(iptr->dst, d);
1609 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1611 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1612 var_to_reg_flt(s2, src, REG_FTMP2);
1613 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1618 if (d == s1 || d == s2) {
1619 M_FMULS(s1, s2, REG_FTMP3);
1621 M_FMOV(REG_FTMP3, d);
1628 store_reg_to_var_flt(iptr->dst, d);
1631 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1633 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1634 var_to_reg_flt(s2, src, REG_FTMP2);
1635 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1640 if (d == s1 || d == s2) {
1641 M_DMULS(s1, s2, REG_FTMP3);
1643 M_FMOV(REG_FTMP3, d);
1650 store_reg_to_var_flt(iptr->dst, d);
1653 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1655 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1656 var_to_reg_flt(s2, src, REG_FTMP2);
1657 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1662 if (d == s1 || d == s2) {
1663 M_FDIVS(s1, s2, REG_FTMP3);
1665 M_FMOV(REG_FTMP3, d);
1672 store_reg_to_var_flt(iptr->dst, d);
1675 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1677 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1678 var_to_reg_flt(s2, src, REG_FTMP2);
1679 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1684 if (d == s1 || d == s2) {
1685 M_DDIVS(s1, s2, REG_FTMP3);
1687 M_FMOV(REG_FTMP3, d);
1694 store_reg_to_var_flt(iptr->dst, d);
1697 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1699 var_to_reg_int(s1, src, REG_ITMP1);
1700 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1701 a = dseg_adddouble(0.0);
1702 M_LST (s1, REG_PV, a);
1703 M_DLD (d, REG_PV, a);
1705 store_reg_to_var_flt(iptr->dst, d);
1708 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1710 var_to_reg_int(s1, src, REG_ITMP1);
1711 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1712 a = dseg_adddouble(0.0);
1713 M_LST (s1, REG_PV, a);
1714 M_DLD (d, REG_PV, a);
1716 store_reg_to_var_flt(iptr->dst, d);
1719 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1721 var_to_reg_flt(s1, src, REG_FTMP1);
1722 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1723 a = dseg_adddouble(0.0);
1724 M_CVTDL_C(s1, REG_FTMP2);
1725 M_CVTLI(REG_FTMP2, REG_FTMP3);
1726 M_DST (REG_FTMP3, REG_PV, a);
1727 M_ILD (d, REG_PV, a);
1728 store_reg_to_var_int(iptr->dst, d);
1731 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1733 var_to_reg_flt(s1, src, REG_FTMP1);
1734 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1735 a = dseg_adddouble(0.0);
1736 M_CVTDL_C(s1, REG_FTMP2);
1737 M_DST (REG_FTMP2, REG_PV, a);
1738 M_LLD (d, REG_PV, a);
1739 store_reg_to_var_int(iptr->dst, d);
1742 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1744 var_to_reg_flt(s1, src, REG_FTMP1);
1745 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1748 store_reg_to_var_flt(iptr->dst, d);
1751 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1753 var_to_reg_flt(s1, src, REG_FTMP1);
1754 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1762 store_reg_to_var_flt(iptr->dst, d);
1765 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1767 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1768 var_to_reg_flt(s2, src, REG_FTMP2);
1769 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1771 M_LSUB_IMM(REG_ZERO, 1, d);
1772 M_FCMPEQ(s1, s2, REG_FTMP3);
1773 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1775 M_FCMPLT(s2, s1, REG_FTMP3);
1776 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1777 M_LADD_IMM(REG_ZERO, 1, d);
1780 M_LSUB_IMM(REG_ZERO, 1, d);
1781 M_FCMPEQS(s1, s2, REG_FTMP3);
1783 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1785 M_FCMPLTS(s2, s1, REG_FTMP3);
1787 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1788 M_LADD_IMM(REG_ZERO, 1, d);
1790 store_reg_to_var_int(iptr->dst, d);
1793 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg 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(m, iptr->dst, REG_ITMP3);
1799 M_LADD_IMM(REG_ZERO, 1, d);
1800 M_FCMPEQ(s1, s2, REG_FTMP3);
1801 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1803 M_FCMPLT(s1, s2, REG_FTMP3);
1804 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1805 M_LSUB_IMM(REG_ZERO, 1, d);
1808 M_LADD_IMM(REG_ZERO, 1, d);
1809 M_FCMPEQS(s1, s2, REG_FTMP3);
1811 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1813 M_FCMPLTS(s1, s2, REG_FTMP3);
1815 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1816 M_LSUB_IMM(REG_ZERO, 1, d);
1818 store_reg_to_var_int(iptr->dst, d);
1822 /* memory operations **************************************************/
1824 #define gen_bound_check \
1825 if (checkbounds) { \
1826 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1827 M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
1828 M_BEQZ(REG_ITMP3, 0);\
1829 codegen_addxboundrefs(mcodeptr, s2); \
1832 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1834 var_to_reg_int(s1, src, REG_ITMP1);
1835 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1836 gen_nullptr_check(s1);
1837 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1838 store_reg_to_var_int(iptr->dst, d);
1841 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1843 var_to_reg_int(s1, src->prev, REG_ITMP1);
1844 var_to_reg_int(s2, src, REG_ITMP2);
1845 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1846 if (iptr->op1 == 0) {
1847 gen_nullptr_check(s1);
1850 M_SAADDQ(s2, s1, REG_ITMP1);
1851 M_ALD( d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1852 store_reg_to_var_int(iptr->dst, d);
1855 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1857 var_to_reg_int(s1, src->prev, REG_ITMP1);
1858 var_to_reg_int(s2, src, REG_ITMP2);
1859 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1860 if (iptr->op1 == 0) {
1861 gen_nullptr_check(s1);
1864 M_S8ADDQ(s2, s1, REG_ITMP1);
1865 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1866 store_reg_to_var_int(iptr->dst, d);
1869 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1871 var_to_reg_int(s1, src->prev, REG_ITMP1);
1872 var_to_reg_int(s2, src, REG_ITMP2);
1873 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1874 if (iptr->op1 == 0) {
1875 gen_nullptr_check(s1);
1879 M_S4ADDQ(s2, s1, REG_ITMP1);
1880 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1881 store_reg_to_var_int(iptr->dst, d);
1884 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1886 var_to_reg_int(s1, src->prev, REG_ITMP1);
1887 var_to_reg_int(s2, src, REG_ITMP2);
1888 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1889 if (iptr->op1 == 0) {
1890 gen_nullptr_check(s1);
1893 M_S4ADDQ(s2, s1, REG_ITMP1);
1894 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1895 store_reg_to_var_flt(iptr->dst, d);
1898 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1900 var_to_reg_int(s1, src->prev, REG_ITMP1);
1901 var_to_reg_int(s2, src, REG_ITMP2);
1902 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1903 if (iptr->op1 == 0) {
1904 gen_nullptr_check(s1);
1907 M_S8ADDQ(s2, s1, REG_ITMP1);
1908 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1909 store_reg_to_var_flt(iptr->dst, d);
1912 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1914 var_to_reg_int(s1, src->prev, REG_ITMP1);
1915 var_to_reg_int(s2, src, REG_ITMP2);
1916 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1917 if (iptr->op1 == 0) {
1918 gen_nullptr_check(s1);
1921 if (has_ext_instr_set) {
1922 M_LADD(s2, s1, REG_ITMP1);
1923 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1924 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1927 M_LADD (s2, s1, REG_ITMP1);
1928 M_LADD (s2, REG_ITMP1, REG_ITMP1);
1929 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
1930 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
1931 M_EXTWL(REG_ITMP2, REG_ITMP1, d);
1933 store_reg_to_var_int(iptr->dst, d);
1936 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1938 var_to_reg_int(s1, src->prev, REG_ITMP1);
1939 var_to_reg_int(s2, src, REG_ITMP2);
1940 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1941 if (iptr->op1 == 0) {
1942 gen_nullptr_check(s1);
1945 if (has_ext_instr_set) {
1946 M_LADD(s2, s1, REG_ITMP1);
1947 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1948 M_SLDU( d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
1952 M_LADD(s2, s1, REG_ITMP1);
1953 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1954 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
1955 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0])+2);
1956 M_EXTQH(REG_ITMP2, REG_ITMP1, d);
1957 M_SRA_IMM(d, 48, d);
1959 store_reg_to_var_int(iptr->dst, d);
1962 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1964 var_to_reg_int(s1, src->prev, REG_ITMP1);
1965 var_to_reg_int(s2, src, REG_ITMP2);
1966 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1967 if (iptr->op1 == 0) {
1968 gen_nullptr_check(s1);
1971 if (has_ext_instr_set) {
1972 M_LADD (s2, s1, REG_ITMP1);
1973 M_BLDU (d, REG_ITMP1, OFFSET (java_bytearray, data[0]));
1977 M_LADD(s2, s1, REG_ITMP1);
1978 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1979 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0])+1);
1980 M_EXTQH(REG_ITMP2, REG_ITMP1, d);
1981 M_SRA_IMM(d, 56, d);
1983 store_reg_to_var_int(iptr->dst, d);
1987 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1989 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1990 var_to_reg_int(s2, src->prev, REG_ITMP2);
1991 if (iptr->op1 == 0) {
1992 gen_nullptr_check(s1);
1995 var_to_reg_int(s3, src, REG_ITMP3);
1996 M_SAADDQ(s2, s1, REG_ITMP1);
1997 M_AST (s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2000 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2002 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2003 var_to_reg_int(s2, src->prev, REG_ITMP2);
2004 if (iptr->op1 == 0) {
2005 gen_nullptr_check(s1);
2008 var_to_reg_int(s3, src, REG_ITMP3);
2009 M_S8ADDQ(s2, s1, REG_ITMP1);
2010 M_LST (s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
2013 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2015 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2016 var_to_reg_int(s2, src->prev, REG_ITMP2);
2017 if (iptr->op1 == 0) {
2018 gen_nullptr_check(s1);
2022 var_to_reg_int(s3, src, REG_ITMP3);
2023 M_S4ADDQ(s2, s1, REG_ITMP1);
2024 M_IST (s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
2027 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2029 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2030 var_to_reg_int(s2, src->prev, REG_ITMP2);
2031 if (iptr->op1 == 0) {
2032 gen_nullptr_check(s1);
2035 var_to_reg_flt(s3, src, REG_FTMP3);
2036 M_S4ADDQ(s2, s1, REG_ITMP1);
2037 M_FST (s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2040 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2042 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2043 var_to_reg_int(s2, src->prev, REG_ITMP2);
2044 if (iptr->op1 == 0) {
2045 gen_nullptr_check(s1);
2048 var_to_reg_flt(s3, src, REG_FTMP3);
2049 M_S8ADDQ(s2, s1, REG_ITMP1);
2050 M_DST (s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2053 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2055 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2056 var_to_reg_int(s2, src->prev, REG_ITMP2);
2057 if (iptr->op1 == 0) {
2058 gen_nullptr_check(s1);
2061 var_to_reg_int(s3, src, REG_ITMP3);
2062 if (has_ext_instr_set) {
2063 M_LADD(s2, s1, REG_ITMP1);
2064 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2065 M_SST (s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
2068 M_LADD (s2, s1, REG_ITMP1);
2069 M_LADD (s2, REG_ITMP1, REG_ITMP1);
2070 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
2071 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
2072 M_INSWL(s3, REG_ITMP1, REG_ITMP3);
2073 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2074 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2075 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2079 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2081 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2082 var_to_reg_int(s2, src->prev, REG_ITMP2);
2083 if (iptr->op1 == 0) {
2084 gen_nullptr_check(s1);
2087 var_to_reg_int(s3, src, REG_ITMP3);
2088 if (has_ext_instr_set) {
2089 M_LADD(s2, s1, REG_ITMP1);
2090 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2091 M_SST (s3, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2094 M_LADD (s2, s1, REG_ITMP1);
2095 M_LADD (s2, REG_ITMP1, REG_ITMP1);
2096 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2097 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2098 M_INSWL(s3, REG_ITMP1, REG_ITMP3);
2099 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2100 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2101 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2105 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2107 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2108 var_to_reg_int(s2, src->prev, REG_ITMP2);
2109 if (iptr->op1 == 0) {
2110 gen_nullptr_check(s1);
2113 var_to_reg_int(s3, src, REG_ITMP3);
2114 if (has_ext_instr_set) {
2115 M_LADD(s2, s1, REG_ITMP1);
2116 M_BST (s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2119 M_LADD (s2, s1, REG_ITMP1);
2120 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2121 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2122 M_INSBL(s3, REG_ITMP1, REG_ITMP3);
2123 M_MSKBL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2124 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2125 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2130 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2132 var_to_reg_int(s1, src->prev, REG_ITMP1);
2133 var_to_reg_int(s2, src, REG_ITMP2);
2134 if (iptr->op1 == 0) {
2135 gen_nullptr_check(s1);
2138 M_S4ADDQ(s2, s1, REG_ITMP1);
2139 M_IST(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
2142 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2144 var_to_reg_int(s1, src->prev, REG_ITMP1);
2145 var_to_reg_int(s2, src, REG_ITMP2);
2146 if (iptr->op1 == 0) {
2147 gen_nullptr_check(s1);
2150 M_S8ADDQ(s2, s1, REG_ITMP1);
2151 M_LST(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
2154 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2156 var_to_reg_int(s1, src->prev, REG_ITMP1);
2157 var_to_reg_int(s2, src, REG_ITMP2);
2158 if (iptr->op1 == 0) {
2159 gen_nullptr_check(s1);
2162 M_SAADDQ(s2, s1, REG_ITMP1);
2163 M_AST(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2166 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2168 var_to_reg_int(s1, src->prev, REG_ITMP1);
2169 var_to_reg_int(s2, src, REG_ITMP2);
2170 if (iptr->op1 == 0) {
2171 gen_nullptr_check(s1);
2174 if (has_ext_instr_set) {
2175 M_LADD(s2, s1, REG_ITMP1);
2176 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2179 M_LADD(s2, s1, REG_ITMP1);
2180 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2181 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2182 M_INSBL(REG_ZERO, REG_ITMP1, REG_ITMP3);
2183 M_MSKBL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2184 M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2185 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2189 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2191 var_to_reg_int(s1, src->prev, REG_ITMP1);
2192 var_to_reg_int(s2, src, REG_ITMP2);
2193 if (iptr->op1 == 0) {
2194 gen_nullptr_check(s1);
2197 if (has_ext_instr_set) {
2198 M_LADD(s2, s1, REG_ITMP1);
2199 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2200 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
2203 M_LADD(s2, s1, REG_ITMP1);
2204 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2205 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
2206 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
2207 M_INSWL(REG_ZERO, REG_ITMP1, REG_ITMP3);
2208 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2209 M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2210 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2214 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2216 var_to_reg_int(s1, src->prev, REG_ITMP1);
2217 var_to_reg_int(s2, src, REG_ITMP2);
2218 if (iptr->op1 == 0) {
2219 gen_nullptr_check(s1);
2222 if (has_ext_instr_set) {
2223 M_LADD(s2, s1, REG_ITMP1);
2224 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2225 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2228 M_LADD(s2, s1, REG_ITMP1);
2229 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2230 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2231 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2232 M_INSWL(REG_ZERO, REG_ITMP1, REG_ITMP3);
2233 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2234 M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2235 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2240 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2241 /* op1 = type, val.a = field address */
2243 /* if class isn't yet initialized, do it */
2244 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2245 /* call helper function which patches this code */
2246 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
2247 M_ALD(REG_ITMP1, REG_PV, a);
2248 a = dseg_addaddress(asm_check_clinit);
2249 M_ALD(REG_PV, REG_PV, a);
2250 M_JSR(REG_RA, REG_PV);
2253 s1 = (int) ((u1*) mcodeptr - mcodebase);
2255 M_LDA(REG_PV, REG_RA, -s1);
2259 s4 ml = -s1, mh = 0;
2260 while (ml < -32768) { ml += 65536; mh--; }
2261 M_LDA(REG_PV, REG_RA, ml);
2262 M_LDAH(REG_PV, REG_PV, mh);
2266 a = dseg_addaddress(&(((fieldinfo *)(iptr->val.a))->value));
2267 M_ALD(REG_ITMP1, REG_PV, a);
2268 switch (iptr->op1) {
2270 var_to_reg_int(s2, src, REG_ITMP2);
2271 M_IST(s2, REG_ITMP1, 0);
2274 var_to_reg_int(s2, src, REG_ITMP2);
2275 M_LST(s2, REG_ITMP1, 0);
2278 var_to_reg_int(s2, src, REG_ITMP2);
2279 M_AST(s2, REG_ITMP1, 0);
2282 var_to_reg_flt(s2, src, REG_FTMP2);
2283 M_FST(s2, REG_ITMP1, 0);
2286 var_to_reg_flt(s2, src, REG_FTMP2);
2287 M_DST(s2, REG_ITMP1, 0);
2289 default: panic ("internal error");
2293 case ICMD_GETSTATIC: /* ... ==> ..., value */
2294 /* op1 = type, val.a = field address */
2296 /* if class isn't yet initialized, do it */
2297 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2298 /* call helper function which patches this code */
2299 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
2300 M_ALD(REG_ITMP1, REG_PV, a);
2301 a = dseg_addaddress(asm_check_clinit);
2302 M_ALD(REG_PV, REG_PV, a);
2303 M_JSR(REG_RA, REG_PV);
2306 s1 = (int) ((u1*) mcodeptr - mcodebase);
2308 M_LDA(REG_PV, REG_RA, -s1);
2312 s4 ml = -s1, mh = 0;
2313 while (ml < -32768) { ml += 65536; mh--; }
2314 M_LDA(REG_PV, REG_RA, ml);
2315 M_LDAH(REG_PV, REG_PV, mh);
2319 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2320 M_ALD(REG_ITMP1, REG_PV, a);
2321 switch (iptr->op1) {
2323 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2324 M_ILD(d, REG_ITMP1, 0);
2325 store_reg_to_var_int(iptr->dst, d);
2328 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2329 M_LLD(d, REG_ITMP1, 0);
2330 store_reg_to_var_int(iptr->dst, d);
2333 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2334 M_ALD(d, REG_ITMP1, 0);
2335 store_reg_to_var_int(iptr->dst, d);
2338 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2339 M_FLD(d, REG_ITMP1, 0);
2340 store_reg_to_var_flt(iptr->dst, d);
2343 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2344 M_DLD(d, REG_ITMP1, 0);
2345 store_reg_to_var_flt(iptr->dst, d);
2347 default: panic ("internal error");
2352 case ICMD_PUTFIELD: /* ..., value ==> ... */
2353 /* op1 = type, val.i = field offset */
2355 a = ((fieldinfo *)(iptr->val.a))->offset;
2356 switch (iptr->op1) {
2358 var_to_reg_int(s1, src->prev, REG_ITMP1);
2359 var_to_reg_int(s2, src, REG_ITMP2);
2360 gen_nullptr_check(s1);
2364 var_to_reg_int(s1, src->prev, REG_ITMP1);
2365 var_to_reg_int(s2, src, REG_ITMP2);
2366 gen_nullptr_check(s1);
2370 var_to_reg_int(s1, src->prev, REG_ITMP1);
2371 var_to_reg_int(s2, src, REG_ITMP2);
2372 gen_nullptr_check(s1);
2376 var_to_reg_int(s1, src->prev, REG_ITMP1);
2377 var_to_reg_flt(s2, src, REG_FTMP2);
2378 gen_nullptr_check(s1);
2382 var_to_reg_int(s1, src->prev, REG_ITMP1);
2383 var_to_reg_flt(s2, src, REG_FTMP2);
2384 gen_nullptr_check(s1);
2387 default: panic ("internal error");
2391 case ICMD_GETFIELD: /* ... ==> ..., value */
2392 /* op1 = type, val.i = field offset */
2394 a = ((fieldinfo *)(iptr->val.a))->offset;
2395 switch (iptr->op1) {
2397 var_to_reg_int(s1, src, REG_ITMP1);
2398 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2399 gen_nullptr_check(s1);
2401 store_reg_to_var_int(iptr->dst, d);
2404 var_to_reg_int(s1, src, REG_ITMP1);
2405 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2406 gen_nullptr_check(s1);
2408 store_reg_to_var_int(iptr->dst, d);
2411 var_to_reg_int(s1, src, REG_ITMP1);
2412 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2413 gen_nullptr_check(s1);
2415 store_reg_to_var_int(iptr->dst, d);
2418 var_to_reg_int(s1, src, REG_ITMP1);
2419 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2420 gen_nullptr_check(s1);
2422 store_reg_to_var_flt(iptr->dst, d);
2425 var_to_reg_int(s1, src, REG_ITMP1);
2426 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2427 gen_nullptr_check(s1);
2429 store_reg_to_var_flt(iptr->dst, d);
2431 default: panic ("internal error");
2436 /* branch operations **************************************************/
2438 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2440 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2442 var_to_reg_int(s1, src, REG_ITMP1);
2443 M_INTMOVE(s1, REG_ITMP1_XPTR);
2444 a = dseg_addaddress(asm_handle_exception);
2445 M_ALD(REG_ITMP2, REG_PV, a);
2446 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2447 M_NOP; /* nop ensures that XPC is less than the end */
2448 /* of basic block */
2452 case ICMD_GOTO: /* ... ==> ... */
2453 /* op1 = target JavaVM pc */
2455 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2459 case ICMD_JSR: /* ... ==> ... */
2460 /* op1 = target JavaVM pc */
2462 M_BSR(REG_ITMP1, 0);
2463 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2466 case ICMD_RET: /* ... ==> ... */
2467 /* op1 = local variable */
2469 var = &(r->locals[iptr->op1][TYPE_ADR]);
2470 if (var->flags & INMEMORY) {
2471 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2472 M_RET(REG_ZERO, REG_ITMP1);
2475 M_RET(REG_ZERO, var->regoff);
2479 case ICMD_IFNULL: /* ..., 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_IFNONNULL: /* ..., value ==> ... */
2488 /* op1 = target JavaVM pc */
2490 var_to_reg_int(s1, src, REG_ITMP1);
2492 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2495 case ICMD_IFEQ: /* ..., value ==> ... */
2496 /* op1 = target JavaVM pc, val.i = constant */
2498 var_to_reg_int(s1, src, REG_ITMP1);
2499 if (iptr->val.i == 0) {
2503 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2504 M_CMPEQ_IMM(s1, iptr->val.i, REG_ITMP1);
2507 ICONST(REG_ITMP2, iptr->val.i);
2508 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2510 M_BNEZ(REG_ITMP1, 0);
2512 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2515 case ICMD_IFLT: /* ..., value ==> ... */
2516 /* op1 = target JavaVM pc, val.i = constant */
2518 var_to_reg_int(s1, src, REG_ITMP1);
2519 if (iptr->val.i == 0) {
2523 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2524 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2527 ICONST(REG_ITMP2, iptr->val.i);
2528 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2530 M_BNEZ(REG_ITMP1, 0);
2532 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2535 case ICMD_IFLE: /* ..., value ==> ... */
2536 /* op1 = target JavaVM pc, val.i = constant */
2538 var_to_reg_int(s1, src, REG_ITMP1);
2539 if (iptr->val.i == 0) {
2543 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2544 M_CMPLE_IMM(s1, iptr->val.i, REG_ITMP1);
2547 ICONST(REG_ITMP2, iptr->val.i);
2548 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2550 M_BNEZ(REG_ITMP1, 0);
2552 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2555 case ICMD_IFNE: /* ..., value ==> ... */
2556 /* op1 = target JavaVM pc, val.i = constant */
2558 var_to_reg_int(s1, src, REG_ITMP1);
2559 if (iptr->val.i == 0) {
2563 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2564 M_CMPEQ_IMM(s1, iptr->val.i, REG_ITMP1);
2567 ICONST(REG_ITMP2, iptr->val.i);
2568 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2570 M_BEQZ(REG_ITMP1, 0);
2572 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2575 case ICMD_IFGT: /* ..., value ==> ... */
2576 /* op1 = target JavaVM pc, val.i = constant */
2578 var_to_reg_int(s1, src, REG_ITMP1);
2579 if (iptr->val.i == 0) {
2583 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2584 M_CMPLE_IMM(s1, iptr->val.i, REG_ITMP1);
2587 ICONST(REG_ITMP2, iptr->val.i);
2588 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2590 M_BEQZ(REG_ITMP1, 0);
2592 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2595 case ICMD_IFGE: /* ..., value ==> ... */
2596 /* op1 = target JavaVM pc, val.i = constant */
2598 var_to_reg_int(s1, src, REG_ITMP1);
2599 if (iptr->val.i == 0) {
2603 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2604 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2607 ICONST(REG_ITMP2, iptr->val.i);
2608 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2610 M_BEQZ(REG_ITMP1, 0);
2612 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2615 case ICMD_IF_LEQ: /* ..., value ==> ... */
2616 /* op1 = target JavaVM pc, val.l = constant */
2618 var_to_reg_int(s1, src, REG_ITMP1);
2619 if (iptr->val.l == 0) {
2623 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2624 M_CMPEQ_IMM(s1, iptr->val.l, REG_ITMP1);
2627 LCONST(REG_ITMP2, iptr->val.l);
2628 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2630 M_BNEZ(REG_ITMP1, 0);
2632 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2635 case ICMD_IF_LLT: /* ..., value ==> ... */
2636 /* op1 = target JavaVM pc, val.l = constant */
2638 var_to_reg_int(s1, src, REG_ITMP1);
2639 if (iptr->val.l == 0) {
2643 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2644 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2647 LCONST(REG_ITMP2, iptr->val.l);
2648 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2650 M_BNEZ(REG_ITMP1, 0);
2652 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2655 case ICMD_IF_LLE: /* ..., value ==> ... */
2656 /* op1 = target JavaVM pc, val.l = constant */
2658 var_to_reg_int(s1, src, REG_ITMP1);
2659 if (iptr->val.l == 0) {
2663 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2664 M_CMPLE_IMM(s1, iptr->val.l, REG_ITMP1);
2667 LCONST(REG_ITMP2, iptr->val.l);
2668 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2670 M_BNEZ(REG_ITMP1, 0);
2672 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2675 case ICMD_IF_LNE: /* ..., value ==> ... */
2676 /* op1 = target JavaVM pc, val.l = constant */
2678 var_to_reg_int(s1, src, REG_ITMP1);
2679 if (iptr->val.l == 0) {
2683 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2684 M_CMPEQ_IMM(s1, iptr->val.l, REG_ITMP1);
2687 LCONST(REG_ITMP2, iptr->val.l);
2688 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2690 M_BEQZ(REG_ITMP1, 0);
2692 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2695 case ICMD_IF_LGT: /* ..., value ==> ... */
2696 /* op1 = target JavaVM pc, val.l = constant */
2698 var_to_reg_int(s1, src, REG_ITMP1);
2699 if (iptr->val.l == 0) {
2703 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2704 M_CMPLE_IMM(s1, iptr->val.l, REG_ITMP1);
2707 LCONST(REG_ITMP2, iptr->val.l);
2708 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2710 M_BEQZ(REG_ITMP1, 0);
2712 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2715 case ICMD_IF_LGE: /* ..., value ==> ... */
2716 /* op1 = target JavaVM pc, val.l = constant */
2718 var_to_reg_int(s1, src, REG_ITMP1);
2719 if (iptr->val.l == 0) {
2723 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2724 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2727 LCONST(REG_ITMP2, iptr->val.l);
2728 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2730 M_BEQZ(REG_ITMP1, 0);
2732 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2735 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2736 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2737 case ICMD_IF_ACMPEQ:
2739 var_to_reg_int(s1, src->prev, REG_ITMP1);
2740 var_to_reg_int(s2, src, REG_ITMP2);
2741 M_CMPEQ(s1, s2, REG_ITMP1);
2742 M_BNEZ(REG_ITMP1, 0);
2743 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2746 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2747 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2748 case ICMD_IF_ACMPNE:
2750 var_to_reg_int(s1, src->prev, REG_ITMP1);
2751 var_to_reg_int(s2, src, REG_ITMP2);
2752 M_CMPEQ(s1, s2, REG_ITMP1);
2753 M_BEQZ(REG_ITMP1, 0);
2754 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2757 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2758 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2760 var_to_reg_int(s1, src->prev, REG_ITMP1);
2761 var_to_reg_int(s2, src, REG_ITMP2);
2762 M_CMPLT(s1, s2, REG_ITMP1);
2763 M_BNEZ(REG_ITMP1, 0);
2764 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2767 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2768 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2770 var_to_reg_int(s1, src->prev, REG_ITMP1);
2771 var_to_reg_int(s2, src, REG_ITMP2);
2772 M_CMPLE(s1, s2, REG_ITMP1);
2773 M_BEQZ(REG_ITMP1, 0);
2774 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2777 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2778 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2780 var_to_reg_int(s1, src->prev, REG_ITMP1);
2781 var_to_reg_int(s2, src, REG_ITMP2);
2782 M_CMPLE(s1, s2, REG_ITMP1);
2783 M_BNEZ(REG_ITMP1, 0);
2784 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2787 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2788 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2790 var_to_reg_int(s1, src->prev, REG_ITMP1);
2791 var_to_reg_int(s2, src, REG_ITMP2);
2792 M_CMPLT(s1, s2, REG_ITMP1);
2793 M_BEQZ(REG_ITMP1, 0);
2794 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2797 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2799 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2802 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2803 /* val.i = constant */
2805 var_to_reg_int(s1, src, REG_ITMP1);
2806 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2808 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2809 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2810 M_CMPEQ(s1, REG_ZERO, d);
2811 store_reg_to_var_int(iptr->dst, d);
2814 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2815 M_CMPEQ(s1, REG_ZERO, d);
2817 store_reg_to_var_int(iptr->dst, d);
2821 M_MOV(s1, REG_ITMP1);
2824 ICONST(d, iptr[1].val.i);
2826 if ((s3 >= 0) && (s3 <= 255)) {
2827 M_CMOVEQ_IMM(s1, s3, d);
2830 ICONST(REG_ITMP2, s3);
2831 M_CMOVEQ(s1, REG_ITMP2, d);
2833 store_reg_to_var_int(iptr->dst, d);
2836 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2837 /* val.i = constant */
2839 var_to_reg_int(s1, src, REG_ITMP1);
2840 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2842 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2843 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2844 M_CMPEQ(s1, REG_ZERO, d);
2845 store_reg_to_var_int(iptr->dst, d);
2848 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2849 M_CMPEQ(s1, REG_ZERO, d);
2851 store_reg_to_var_int(iptr->dst, d);
2855 M_MOV(s1, REG_ITMP1);
2858 ICONST(d, iptr[1].val.i);
2860 if ((s3 >= 0) && (s3 <= 255)) {
2861 M_CMOVNE_IMM(s1, s3, d);
2864 ICONST(REG_ITMP2, s3);
2865 M_CMOVNE(s1, REG_ITMP2, d);
2867 store_reg_to_var_int(iptr->dst, d);
2870 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2871 /* val.i = constant */
2873 var_to_reg_int(s1, src, REG_ITMP1);
2874 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2876 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2877 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2878 M_CMPLT(s1, REG_ZERO, d);
2879 store_reg_to_var_int(iptr->dst, d);
2882 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2883 M_CMPLE(REG_ZERO, s1, d);
2884 store_reg_to_var_int(iptr->dst, d);
2888 M_MOV(s1, REG_ITMP1);
2891 ICONST(d, iptr[1].val.i);
2893 if ((s3 >= 0) && (s3 <= 255)) {
2894 M_CMOVLT_IMM(s1, s3, d);
2897 ICONST(REG_ITMP2, s3);
2898 M_CMOVLT(s1, REG_ITMP2, d);
2900 store_reg_to_var_int(iptr->dst, d);
2903 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2904 /* val.i = constant */
2906 var_to_reg_int(s1, src, REG_ITMP1);
2907 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2909 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2910 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2911 M_CMPLE(REG_ZERO, s1, d);
2912 store_reg_to_var_int(iptr->dst, d);
2915 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2916 M_CMPLT(s1, REG_ZERO, d);
2917 store_reg_to_var_int(iptr->dst, d);
2921 M_MOV(s1, REG_ITMP1);
2924 ICONST(d, iptr[1].val.i);
2926 if ((s3 >= 0) && (s3 <= 255)) {
2927 M_CMOVGE_IMM(s1, s3, d);
2930 ICONST(REG_ITMP2, s3);
2931 M_CMOVGE(s1, REG_ITMP2, d);
2933 store_reg_to_var_int(iptr->dst, d);
2936 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2937 /* val.i = constant */
2939 var_to_reg_int(s1, src, REG_ITMP1);
2940 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2942 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2943 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2944 M_CMPLT(REG_ZERO, s1, d);
2945 store_reg_to_var_int(iptr->dst, d);
2948 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2949 M_CMPLE(s1, REG_ZERO, d);
2950 store_reg_to_var_int(iptr->dst, d);
2954 M_MOV(s1, REG_ITMP1);
2957 ICONST(d, iptr[1].val.i);
2959 if ((s3 >= 0) && (s3 <= 255)) {
2960 M_CMOVGT_IMM(s1, s3, d);
2963 ICONST(REG_ITMP2, s3);
2964 M_CMOVGT(s1, REG_ITMP2, d);
2966 store_reg_to_var_int(iptr->dst, d);
2969 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2970 /* val.i = constant */
2972 var_to_reg_int(s1, src, REG_ITMP1);
2973 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2975 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2976 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2977 M_CMPLE(s1, REG_ZERO, d);
2978 store_reg_to_var_int(iptr->dst, d);
2981 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2982 M_CMPLT(REG_ZERO, s1, d);
2983 store_reg_to_var_int(iptr->dst, d);
2987 M_MOV(s1, REG_ITMP1);
2990 ICONST(d, iptr[1].val.i);
2992 if ((s3 >= 0) && (s3 <= 255)) {
2993 M_CMOVLE_IMM(s1, s3, d);
2996 ICONST(REG_ITMP2, s3);
2997 M_CMOVLE(s1, REG_ITMP2, d);
2999 store_reg_to_var_int(iptr->dst, d);
3003 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3007 var_to_reg_int(s1, src, REG_RESULT);
3008 M_INTMOVE(s1, REG_RESULT);
3010 #if defined(USE_THREADS)
3011 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3013 a = dseg_addaddress((void *) (builtin_monitorexit));
3014 M_ALD(REG_PV, REG_PV, a);
3015 M_ALD(r->argintregs[0], REG_SP, r->maxmemuse * 8);
3016 M_LST(REG_RESULT, REG_SP, r->maxmemuse * 8);
3017 M_JSR(REG_RA, REG_PV);
3018 disp = -(s4) ((u1 *) mcodeptr - mcodebase);
3019 M_LDA(REG_PV, REG_RA, disp);
3020 M_LLD(REG_RESULT, REG_SP, r->maxmemuse * 8);
3024 goto nowperformreturn;
3026 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3029 var_to_reg_flt(s1, src, REG_FRESULT);
3030 M_FLTMOVE(s1, REG_FRESULT);
3032 #if defined(USE_THREADS)
3033 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3035 a = dseg_addaddress((void *) (builtin_monitorexit));
3036 M_ALD(REG_PV, REG_PV, a);
3037 M_ALD(r->argintregs[0], REG_SP, r->maxmemuse * 8);
3038 M_DST(REG_FRESULT, REG_SP, r->maxmemuse * 8);
3039 M_JSR(REG_RA, REG_PV);
3040 disp = -(s4) ((u1 *) mcodeptr - mcodebase);
3041 M_LDA(REG_PV, REG_RA, disp);
3042 M_DLD(REG_FRESULT, REG_SP, r->maxmemuse * 8);
3046 goto nowperformreturn;
3048 case ICMD_RETURN: /* ... ==> ... */
3050 #if defined(USE_THREADS)
3051 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3053 a = dseg_addaddress((void *) (builtin_monitorexit));
3054 M_ALD(REG_PV, REG_PV, a);
3055 M_ALD(r->argintregs[0], REG_SP, r->maxmemuse * 8);
3056 M_JSR(REG_RA, REG_PV);
3057 disp = -(s4) ((u1 *) mcodeptr - mcodebase);
3058 M_LDA(REG_PV, REG_RA, disp);
3066 p = parentargs_base;
3068 /* restore return address */
3070 if (!m->isleafmethod) {
3071 p--; M_LLD(REG_RA, REG_SP, p * 8);
3074 /* restore saved registers */
3076 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
3077 p--; M_LLD(r->savintregs[i], REG_SP, p * 8);
3079 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
3080 p--; M_DLD(r->savfltregs[i], REG_SP, p * 8);
3083 /* deallocate stack */
3085 if (parentargs_base) {
3086 M_LDA(REG_SP, REG_SP, parentargs_base * 8);
3089 /* call trace function */
3092 M_LDA(REG_SP, REG_SP, -3 * 8);
3093 M_AST(REG_RA, REG_SP, 0 * 8);
3094 M_LST(REG_RESULT, REG_SP, 1 * 8);
3095 M_DST(REG_FRESULT, REG_SP, 2 * 8);
3096 a = dseg_addaddress(m);
3097 M_ALD(r->argintregs[0], REG_PV, a);
3098 M_MOV(REG_RESULT, r->argintregs[1]);
3099 M_FLTMOVE(REG_FRESULT, r->argfltregs[2]);
3100 M_FLTMOVE(REG_FRESULT, r->argfltregs[3]);
3101 a = dseg_addaddress((void *) builtin_displaymethodstop);
3102 M_ALD(REG_PV, REG_PV, a);
3103 M_JSR(REG_RA, REG_PV);
3104 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3105 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3107 s4 ml = -s1, mh = 0;
3108 while (ml < -32768) { ml += 65536; mh--; }
3109 M_LDA(REG_PV, REG_RA, ml);
3110 M_LDAH(REG_PV, REG_PV, mh);
3112 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
3113 M_LLD(REG_RESULT, REG_SP, 1 * 8);
3114 M_ALD(REG_RA, REG_SP, 0 * 8);
3115 M_LDA(REG_SP, REG_SP, 3 * 8);
3118 M_RET(REG_ZERO, REG_RA);
3124 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3129 tptr = (void **) iptr->target;
3131 s4ptr = iptr->val.a;
3132 l = s4ptr[1]; /* low */
3133 i = s4ptr[2]; /* high */
3135 var_to_reg_int(s1, src, REG_ITMP1);
3137 {M_INTMOVE(s1, REG_ITMP1);}
3138 else if (l <= 32768) {
3139 M_LDA(REG_ITMP1, s1, -l);
3142 ICONST(REG_ITMP2, l);
3143 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3150 M_CMPULE_IMM(REG_ITMP1, i - 1, REG_ITMP2);
3152 M_LDA(REG_ITMP2, REG_ZERO, i - 1);
3153 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3155 M_BEQZ(REG_ITMP2, 0);
3158 /* codegen_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr); */
3159 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3161 /* build jump table top down and use address of lowest entry */
3163 /* s4ptr += 3 + i; */
3167 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3168 dseg_addtarget((basicblock *) tptr[0]);
3173 /* length of dataseg after last dseg_addtarget is used by load */
3175 M_SAADDQ(REG_ITMP1, REG_PV, REG_ITMP2);
3176 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
3177 M_JMP(REG_ZERO, REG_ITMP2);
3182 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3184 s4 i, l, val, *s4ptr;
3187 tptr = (void **) iptr->target;
3189 s4ptr = iptr->val.a;
3190 l = s4ptr[0]; /* default */
3191 i = s4ptr[1]; /* count */
3193 MCODECHECK((i<<2)+8);
3194 var_to_reg_int(s1, src, REG_ITMP1);
3200 if ((val >= 0) && (val <= 255)) {
3201 M_CMPEQ_IMM(s1, val, REG_ITMP2);
3204 if ((val >= -32768) && (val <= 32767)) {
3205 M_LDA(REG_ITMP2, REG_ZERO, val);
3208 a = dseg_adds4 (val);
3209 M_ILD(REG_ITMP2, REG_PV, a);
3211 M_CMPEQ(s1, REG_ITMP2, REG_ITMP2);
3213 M_BNEZ(REG_ITMP2, 0);
3214 /* codegen_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr); */
3215 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3219 /* codegen_addreference(BlockPtrOfPC(l), mcodeptr); */
3221 tptr = (void **) iptr->target;
3222 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3229 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3230 /* op1 = return type, val.a = function pointer*/
3234 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3235 /* op1 = return type, val.a = function pointer*/
3239 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3240 /* op1 = return type, val.a = function pointer*/
3244 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3245 /* op1 = arg count, val.a = method pointer */
3247 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3248 /* op1 = arg count, val.a = method pointer */
3250 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3251 /* op1 = arg count, val.a = method pointer */
3253 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3254 /* op1 = arg count, val.a = method pointer */
3262 MCODECHECK((s3 << 1) + 64);
3264 /* copy arguments to registers or stack location */
3266 for (; --s3 >= 0; src = src->prev) {
3267 if (src->varkind == ARGVAR)
3269 if (IS_INT_LNG_TYPE(src->type)) {
3270 if (s3 < INT_ARG_CNT) {
3271 s1 = r->argintregs[s3];
3272 var_to_reg_int(d, src, s1);
3276 var_to_reg_int(d, src, REG_ITMP1);
3277 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3281 if (s3 < FLT_ARG_CNT) {
3282 s1 = r->argfltregs[s3];
3283 var_to_reg_flt(d, src, s1);
3287 var_to_reg_flt(d, src, REG_FTMP1);
3288 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3294 switch (iptr->opc) {
3298 a = dseg_addaddress((void *) lm);
3300 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
3302 goto makeactualcall;
3304 case ICMD_INVOKESTATIC:
3305 case ICMD_INVOKESPECIAL:
3306 a = dseg_addaddress(lm->stubroutine);
3308 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
3311 goto makeactualcall;
3313 case ICMD_INVOKEVIRTUAL:
3315 gen_nullptr_check(r->argintregs[0]);
3316 M_ALD(REG_METHODPTR, r->argintregs[0],
3317 OFFSET(java_objectheader, vftbl));
3318 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) +
3319 sizeof(methodptr) * lm->vftblindex);
3322 goto makeactualcall;
3324 case ICMD_INVOKEINTERFACE:
3327 gen_nullptr_check(r->argintregs[0]);
3328 M_ALD(REG_METHODPTR, r->argintregs[0],
3329 OFFSET(java_objectheader, vftbl));
3330 M_ALD(REG_METHODPTR, REG_METHODPTR,
3331 OFFSET(vftbl_t, interfacetable[0]) -
3332 sizeof(methodptr*) * ci->index);
3333 M_ALD(REG_PV, REG_METHODPTR,
3334 sizeof(methodptr) * (lm - ci->methods));
3337 goto makeactualcall;
3341 error ("Unkown ICMD-Command: %d", iptr->opc);
3346 M_JSR(REG_RA, REG_PV);
3350 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3351 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3353 s4 ml = -s1, mh = 0;
3354 while (ml < -32768) { ml += 65536; mh--; }
3355 M_LDA(REG_PV, REG_RA, ml);
3356 M_LDAH(REG_PV, REG_PV, mh);
3359 /* d contains return type */
3361 if (d != TYPE_VOID) {
3362 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3363 s1 = reg_of_var(m, iptr->dst, REG_RESULT);
3364 M_INTMOVE(REG_RESULT, s1);
3365 store_reg_to_var_int(iptr->dst, s1);
3368 s1 = reg_of_var(m, iptr->dst, REG_FRESULT);
3369 M_FLTMOVE(REG_FRESULT, s1);
3370 store_reg_to_var_flt(iptr->dst, s1);
3377 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3379 /* op1: 0 == array, 1 == class */
3380 /* val.a: (classinfo*) superclass */
3382 /* superclass is an interface:
3384 * return (sub != NULL) &&
3385 * (sub->vftbl->interfacetablelength > super->index) &&
3386 * (sub->vftbl->interfacetable[-super->index] != NULL);
3388 * superclass is a class:
3390 * return ((sub != NULL) && (0
3391 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3392 * super->vftbl->diffvall));
3396 classinfo *super = (classinfo*) iptr->val.a;
3398 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3399 codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
3401 var_to_reg_int(s1, src, REG_ITMP1);
3402 d = reg_of_var(m, iptr->dst, REG_ITMP3);
3404 M_MOV(s1, REG_ITMP1);
3408 if (iptr->op1) { /* class/interface */
3409 if (super->flags & ACC_INTERFACE) { /* interface */
3411 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3412 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3413 M_LDA(REG_ITMP2, REG_ITMP2, - super->index);
3414 M_BLEZ(REG_ITMP2, 2);
3415 M_ALD(REG_ITMP1, REG_ITMP1,
3416 OFFSET(vftbl_t, interfacetable[0]) -
3417 super->index * sizeof(methodptr*));
3418 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3422 s2 = super->vftbl->diffval;
3423 M_BEQZ(s1, 4 + (s2 > 255));
3424 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3425 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3426 M_LDA(REG_ITMP1, REG_ITMP1, - super->vftbl->baseval);
3428 M_CMPULE_IMM(REG_ITMP1, s2, d);
3430 M_LDA(REG_ITMP2, REG_ZERO, s2);
3431 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3435 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3436 a = dseg_addaddress ((void*) super->vftbl);
3437 M_ALD(REG_ITMP2, REG_PV, a);
3438 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3439 codegen_threadcritstart((u1*) mcodeptr - mcodebase);
3441 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3442 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3443 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3444 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3445 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
3447 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3448 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3452 panic ("internal error: no inlined array instanceof");
3454 store_reg_to_var_int(iptr->dst, d);
3457 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3459 /* op1: 0 == array, 1 == class */
3460 /* val.a: (classinfo*) superclass */
3462 /* superclass is an interface:
3464 * OK if ((sub == NULL) ||
3465 * (sub->vftbl->interfacetablelength > super->index) &&
3466 * (sub->vftbl->interfacetable[-super->index] != NULL));
3468 * superclass is a class:
3470 * OK if ((sub == NULL) || (0
3471 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3472 * super->vftbl->diffvall));
3476 classinfo *super = (classinfo*) iptr->val.a;
3478 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3479 codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
3481 d = reg_of_var(m, iptr->dst, REG_ITMP3);
3482 var_to_reg_int(s1, src, d);
3483 if (iptr->op1) { /* class/interface */
3484 if (super->flags & ACC_INTERFACE) { /* interface */
3486 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3487 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3488 M_LDA(REG_ITMP2, REG_ITMP2, - super->index);
3489 M_BLEZ(REG_ITMP2, 0);
3490 codegen_addxcastrefs(mcodeptr);
3491 M_ALD(REG_ITMP2, REG_ITMP1,
3492 OFFSET(vftbl_t, interfacetable[0]) -
3493 super->index * sizeof(methodptr*));
3494 M_BEQZ(REG_ITMP2, 0);
3495 codegen_addxcastrefs(mcodeptr);
3499 s2 = super->vftbl->diffval;
3500 M_BEQZ(s1, 4 + (s2 != 0) + (s2 > 255));
3501 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3502 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3503 M_LDA(REG_ITMP1, REG_ITMP1, - super->vftbl->baseval);
3505 M_BNEZ(REG_ITMP1, 0);
3507 else if (s2 <= 255) {
3508 M_CMPULE_IMM(REG_ITMP1, s2, REG_ITMP2);
3509 M_BEQZ(REG_ITMP2, 0);
3512 M_LDA(REG_ITMP2, REG_ZERO, s2);
3513 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3514 M_BEQZ(REG_ITMP2, 0);
3517 M_BEQZ(s1, 8 + (d == REG_ITMP3));
3518 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3519 a = dseg_addaddress ((void*) super->vftbl);
3520 M_ALD(REG_ITMP2, REG_PV, a);
3521 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3522 codegen_threadcritstart((u1*) mcodeptr - mcodebase);
3524 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3525 if (d != REG_ITMP3) {
3526 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3527 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3528 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3529 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
3531 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3534 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3535 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3536 M_ALD(REG_ITMP2, REG_PV, a);
3537 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3538 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3539 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
3542 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3543 M_BEQZ(REG_ITMP2, 0);
3544 codegen_addxcastrefs(mcodeptr);
3548 panic ("internal error: no inlined array checkcast");
3551 store_reg_to_var_int(iptr->dst, d);
3554 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3556 var_to_reg_int(s1, src, REG_ITMP1);
3558 codegen_addxcheckarefs(mcodeptr);
3561 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3563 M_BEQZ(REG_RESULT, 0);
3564 codegen_addxexceptionrefs(mcodeptr);
3567 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3568 /* op1 = dimension, val.a = array descriptor */
3570 /* check for negative sizes and copy sizes to stack if necessary */
3572 MCODECHECK((iptr->op1 << 1) + 64);
3574 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3575 var_to_reg_int(s2, src, REG_ITMP1);
3577 codegen_addxcheckarefs(mcodeptr);
3579 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3581 if (src->varkind != ARGVAR) {
3582 M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
3586 /* a0 = dimension count */
3588 ICONST(r->argintregs[0], iptr->op1);
3590 /* a1 = arraydescriptor */
3592 a = dseg_addaddress(iptr->val.a);
3593 M_ALD(r->argintregs[1], REG_PV, a);
3595 /* a2 = pointer to dimensions = stack pointer */
3597 M_INTMOVE(REG_SP, r->argintregs[2]);
3599 a = dseg_addaddress((void *) builtin_nmultianewarray);
3600 M_ALD(REG_PV, REG_PV, a);
3601 M_JSR(REG_RA, REG_PV);
3602 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3604 M_LDA(REG_PV, REG_RA, -s1);
3606 s4 ml = -s1, mh = 0;
3607 while (ml < -32768) { ml += 65536; mh--; }
3608 M_LDA(REG_PV, REG_RA, ml);
3609 M_LDAH(REG_PV, REG_PV, mh);
3611 s1 = reg_of_var(m, iptr->dst, REG_RESULT);
3612 M_INTMOVE(REG_RESULT, s1);
3613 store_reg_to_var_int(iptr->dst, s1);
3617 default: error ("Unknown pseudo command: %d", iptr->opc);
3623 } /* for instruction */
3625 /* copy values to interface registers */
3627 src = bptr->outstack;
3628 len = bptr->outdepth;
3632 if ((src->varkind != STACKVAR)) {
3634 if (IS_FLT_DBL_TYPE(s2)) {
3635 var_to_reg_flt(s1, src, REG_FTMP1);
3636 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
3637 M_FLTMOVE(s1,r->interfaces[len][s2].regoff);
3640 M_DST(s1, REG_SP, 8 * r->interfaces[len][s2].regoff);
3644 var_to_reg_int(s1, src, REG_ITMP1);
3645 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
3646 M_INTMOVE(s1,r->interfaces[len][s2].regoff);
3649 M_LST(s1, REG_SP, 8 * r->interfaces[len][s2].regoff);
3655 } /* if (bptr -> flags >= BBREACHED) */
3656 } /* for basic block */
3658 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3661 /* generate bound check stubs */
3663 s4 *xcodeptr = NULL;
3665 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3666 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3667 xboundrefs->branchpos,
3668 (u1*) mcodeptr - mcodebase);
3672 /* move index register into REG_ITMP1 */
3673 M_MOV(xboundrefs->reg, REG_ITMP1);
3674 M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos - 4);
3676 if (xcodeptr != NULL) {
3677 M_BR(xcodeptr - mcodeptr - 1);
3680 xcodeptr = mcodeptr;
3682 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3683 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3685 a = dseg_addaddress(string_java_lang_ArrayIndexOutOfBoundsException);
3686 M_ALD(r->argintregs[0], REG_PV, a);
3687 M_MOV(REG_ITMP1, r->argintregs[1]);
3689 a = dseg_addaddress(new_exception_int);
3690 M_ALD(REG_PV, REG_PV, a);
3691 M_JSR(REG_RA, REG_PV);
3694 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3695 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3697 s4 ml = -s1, mh = 0;
3698 while (ml < -32768) { ml += 65536; mh--; }
3699 M_LDA(REG_PV, REG_RA, ml);
3700 M_LDAH(REG_PV, REG_PV, mh);
3703 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3705 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3706 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3708 a = dseg_addaddress(asm_handle_exception);
3709 M_ALD(REG_ITMP3, REG_PV, a);
3711 M_JMP(REG_ZERO, REG_ITMP3);
3715 /* generate negative array size check stubs */
3719 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3720 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3721 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3722 xcheckarefs->branchpos,
3723 (u1*) xcodeptr - (u1*) mcodebase - 4);
3727 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3728 xcheckarefs->branchpos,
3729 (u1*) mcodeptr - mcodebase);
3733 M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos - 4);
3735 if (xcodeptr != NULL) {
3736 M_BR(xcodeptr - mcodeptr - 1);
3739 xcodeptr = mcodeptr;
3741 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3742 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3744 a = dseg_addaddress(string_java_lang_NegativeArraySizeException);
3745 M_ALD(r->argintregs[0], REG_PV, a);
3747 a = dseg_addaddress(new_exception);
3748 M_ALD(REG_PV, REG_PV, a);
3749 M_JSR(REG_RA, REG_PV);
3752 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3753 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3755 s4 ml = -s1, mh = 0;
3756 while (ml < -32768) { ml += 65536; mh--; }
3757 M_LDA(REG_PV, REG_RA, ml);
3758 M_LDAH(REG_PV, REG_PV, mh);
3761 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3763 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3764 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3766 a = dseg_addaddress(asm_handle_exception);
3767 M_ALD(REG_ITMP3, REG_PV, a);
3769 M_JMP(REG_ZERO, REG_ITMP3);
3773 /* generate cast check stubs */
3777 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3778 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3779 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3780 xcastrefs->branchpos,
3781 (u1*) xcodeptr - (u1*) mcodebase - 4);
3785 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3786 xcastrefs->branchpos,
3787 (u1*) mcodeptr - mcodebase);
3791 M_LDA(REG_ITMP2_XPC, REG_PV, xcastrefs->branchpos - 4);
3793 if (xcodeptr != NULL) {
3794 M_BR(xcodeptr - mcodeptr - 1);
3797 xcodeptr = mcodeptr;
3799 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3800 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3802 a = dseg_addaddress(string_java_lang_ClassCastException);
3803 M_ALD(r->argintregs[0], REG_PV, a);
3805 a = dseg_addaddress(new_exception);
3806 M_ALD(REG_PV, REG_PV, a);
3807 M_JSR(REG_RA, REG_PV);
3810 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3811 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3813 s4 ml = -s1, mh = 0;
3814 while (ml < -32768) { ml += 65536; mh--; }
3815 M_LDA(REG_PV, REG_RA, ml);
3816 M_LDAH(REG_PV, REG_PV, mh);
3819 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3821 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3822 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3824 a = dseg_addaddress(asm_handle_exception);
3825 M_ALD(REG_ITMP3, REG_PV, a);
3827 M_JMP(REG_ZERO, REG_ITMP3);
3831 /* generate exception check stubs */
3835 for (; xexceptionrefs != NULL; xexceptionrefs = xexceptionrefs->next) {
3836 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3837 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
3838 xexceptionrefs->branchpos,
3839 (u1*) xcodeptr - (u1*) mcodebase - 4);
3843 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
3844 xexceptionrefs->branchpos,
3845 (u1*) mcodeptr - mcodebase);
3849 M_LDA(REG_ITMP2_XPC, REG_PV, xexceptionrefs->branchpos - 4);
3851 if (xcodeptr != NULL) {
3852 M_BR(xcodeptr - mcodeptr - 1);
3855 xcodeptr = mcodeptr;
3857 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3858 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3859 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3861 a = dseg_addaddress(&builtin_get_exceptionptrptr);
3862 M_ALD(REG_PV, REG_PV, a);
3863 M_JSR(REG_RA, REG_PV);
3866 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3867 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3869 s4 ml = -s1, mh = 0;
3870 while (ml < -32768) { ml += 65536; mh--; }
3871 M_LDA(REG_PV, REG_RA, ml);
3872 M_LDAH(REG_PV, REG_PV, mh);
3875 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3876 M_AST(REG_ZERO, REG_RESULT, 0);
3878 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3879 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3881 a = dseg_addaddress(&_exceptionptr);
3882 M_ALD(REG_ITMP3, REG_PV, a);
3883 M_ALD(REG_ITMP1_XPTR, REG_ITMP3, 0);
3884 M_AST(REG_ZERO, REG_ITMP3, 0);
3887 a = dseg_addaddress(asm_handle_exception);
3888 M_ALD(REG_ITMP3, REG_PV, a);
3890 M_JMP(REG_ZERO, REG_ITMP3);
3894 /* generate null pointer check stubs */
3898 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3899 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3900 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3901 xnullrefs->branchpos,
3902 (u1*) xcodeptr - (u1*) mcodebase - 4);
3906 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3907 xnullrefs->branchpos,
3908 (u1*) mcodeptr - mcodebase);
3912 M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
3914 if (xcodeptr != NULL) {
3915 M_BR(xcodeptr - mcodeptr - 1);
3918 xcodeptr = mcodeptr;
3920 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3921 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3923 a = dseg_addaddress(string_java_lang_NullPointerException);
3924 M_ALD(r->argintregs[0], REG_PV, a);
3926 a = dseg_addaddress(new_exception);
3927 M_ALD(REG_PV, REG_PV, a);
3928 M_JSR(REG_RA, REG_PV);
3931 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3932 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3934 s4 ml = -s1, mh = 0;
3935 while (ml < -32768) { ml += 65536; mh--; }
3936 M_LDA(REG_PV, REG_RA, ml);
3937 M_LDAH(REG_PV, REG_PV, mh);
3940 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3942 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3943 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3945 a = dseg_addaddress(asm_handle_exception);
3946 M_ALD(REG_ITMP3, REG_PV, a);
3948 M_JMP(REG_ZERO, REG_ITMP3);
3953 codegen_finish(m, (s4) ((u1 *) mcodeptr - mcodebase));
3957 /* function createcompilerstub *************************************************
3959 creates a stub routine which calls the compiler
3961 *******************************************************************************/
3963 #define COMPSTUBSIZE 3
3965 u1 *createcompilerstub(methodinfo *m)
3967 u8 *s = CNEW(u8, COMPSTUBSIZE); /* memory to hold the stub */
3968 s4 *mcodeptr = (s4 *) s; /* code generation pointer */
3970 /* code for the stub */
3971 M_ALD(REG_PV, REG_PV, 16); /* load pointer to the compiler */
3972 M_JMP(0, REG_PV); /* jump to the compiler, return address
3973 in reg 0 is used as method pointer */
3974 s[1] = (u8) m; /* literals to be adressed */
3975 s[2] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3977 #if defined(STATISTICS)
3979 count_cstub_len += COMPSTUBSIZE * 8;
3986 /* function removecompilerstub *************************************************
3988 deletes a compilerstub from memory (simply by freeing it)
3990 *******************************************************************************/
3992 void removecompilerstub(u1 *stub)
3994 CFREE(stub, COMPSTUBSIZE * 8);
3998 /* function: createnativestub **************************************************
4000 creates a stub routine which calls a native method
4002 *******************************************************************************/
4004 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4005 #define NATIVESTUBSTACK 2
4006 #define NATIVESTUBTHREADEXTRA 6
4008 #define NATIVESTUBSTACK 1
4009 #define NATIVESTUBTHREADEXTRA 1
4012 #define NATIVESTUBSIZE (44 + NATIVESTUBTHREADEXTRA - 1)
4013 #define NATIVESTATICSIZE 5
4014 #define NATIVEVERBOSESIZE (39 + 13)
4015 #define NATIVESTUBOFFSET 9
4017 u1 *createnativestub(functionptr f, methodinfo *m)
4019 u8 *s; /* memory pointer to hold the stub */
4021 s4 *mcodeptr; /* code generation pointer */
4022 s4 stackframesize = 0; /* size of stackframe if needed */
4027 /* keep code size smaller */
4029 r = m->registerdata;
4031 descriptor2types(m); /* set paramcount and paramtypes */
4033 stubsize = NATIVESTUBSIZE; /* calculate nativestub size */
4034 if ((m->flags & ACC_STATIC) && !m->class->initialized)
4035 stubsize += NATIVESTATICSIZE;
4038 stubsize += NATIVEVERBOSESIZE;
4040 s = CNEW(u8, stubsize); /* memory to hold the stub */
4041 cs = s + NATIVESTUBOFFSET;
4042 mcodeptr = (s4 *) (cs); /* code generation pointer */
4044 *(cs-1) = (u8) f; /* address of native method */
4045 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4046 *(cs-2) = (u8) &builtin_get_exceptionptrptr;
4048 *(cs-2) = (u8) (&_exceptionptr); /* address of exceptionptr */
4050 *(cs-3) = (u8) asm_handle_nat_exception; /* addr of asm exception handler */
4051 *(cs-4) = (u8) (&env); /* addr of jni_environement */
4052 *(cs-5) = (u8) builtin_trace_args;
4054 *(cs-7) = (u8) builtin_displaymethodstop;
4055 *(cs-8) = (u8) m->class;
4056 *(cs-9) = (u8) asm_check_clinit;
4058 M_LDA(REG_SP, REG_SP, -NATIVESTUBSTACK * 8); /* build up stackframe */
4059 M_AST(REG_RA, REG_SP, 0 * 8); /* store return address */
4061 /* if function is static, check for initialized */
4063 if (m->flags & ACC_STATIC) {
4064 /* if class isn't yet initialized, do it */
4065 if (!m->class->initialized) {
4066 /* call helper function which patches this code */
4067 M_ALD(REG_ITMP1, REG_PV, -8 * 8); /* class */
4068 M_ALD(REG_PV, REG_PV, -9 * 8); /* asm_check_clinit */
4069 M_JSR(REG_RA, REG_PV);
4070 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4071 M_LDA(REG_PV, REG_RA, disp);
4072 M_NOP; /* this is essential for code patching */
4076 /* max. 39 instructions */
4080 M_LDA(REG_SP, REG_SP, -((INT_ARG_CNT + FLT_ARG_CNT + 2) * 8));
4081 M_AST(REG_RA, REG_SP, 1 * 8);
4083 /* save integer argument registers */
4084 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
4085 M_LST(r->argintregs[p], REG_SP, (2 + p) * 8);
4088 /* save and copy float arguments into integer registers */
4089 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
4090 t = m->paramtypes[p];
4092 if (IS_FLT_DBL_TYPE(t)) {
4093 if (IS_2_WORD_TYPE(t)) {
4094 M_DST(r->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4095 M_LLD(r->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4098 M_FST(r->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4099 M_ILD(r->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4103 M_DST(r->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4107 M_ALD(REG_ITMP1, REG_PV, -6 * 8);
4108 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4109 M_ALD(REG_PV, REG_PV, -5 * 8);
4110 M_JSR(REG_RA, REG_PV);
4111 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4112 M_LDA(REG_PV, REG_RA, disp);
4114 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
4115 M_LLD(r->argintregs[p], REG_SP, (2 + p) * 8);
4118 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
4119 t = m->paramtypes[p];
4121 if (IS_FLT_DBL_TYPE(t)) {
4122 if (IS_2_WORD_TYPE(t)) {
4123 M_DLD(r->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4126 M_FLD(r->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4130 M_DLD(r->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
4134 M_ALD(REG_RA, REG_SP, 1 * 8);
4135 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT + 2) * 8);
4138 /* save argument registers on stack -- if we have to */
4139 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
4141 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
4142 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
4144 stackframesize = stackparamcnt + paramshiftcnt;
4146 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
4148 /* copy stack arguments into new stack frame -- if any */
4149 for (i = 0; i < stackparamcnt; i++) {
4150 M_LLD(REG_ITMP1, REG_SP, (stackparamcnt + 1 + i) * 8);
4151 M_LST(REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
4154 if (m->flags & ACC_STATIC) {
4155 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4156 M_DST(r->argfltregs[5], REG_SP, 1 * 8);
4158 M_LST(r->argintregs[5], REG_SP, 1 * 8);
4161 if (IS_FLT_DBL_TYPE(m->paramtypes[4])) {
4162 M_DST(r->argfltregs[4], REG_SP, 0 * 8);
4164 M_LST(r->argintregs[4], REG_SP, 0 * 8);
4168 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4169 M_DST(r->argfltregs[5], REG_SP, 0 * 8);
4171 M_LST(r->argintregs[5], REG_SP, 0 * 8);
4176 if (m->flags & ACC_STATIC) {
4177 M_MOV(r->argintregs[3], r->argintregs[5]);
4178 M_MOV(r->argintregs[2], r->argintregs[4]);
4179 M_MOV(r->argintregs[1], r->argintregs[3]);
4180 M_MOV(r->argintregs[0], r->argintregs[2]);
4181 M_FMOV(r->argfltregs[3], r->argfltregs[5]);
4182 M_FMOV(r->argfltregs[2], r->argfltregs[4]);
4183 M_FMOV(r->argfltregs[1], r->argfltregs[3]);
4184 M_FMOV(r->argfltregs[0], r->argfltregs[2]);
4186 /* put class into second argument register */
4187 M_ALD(r->argintregs[1], REG_PV, -8 * 8);
4190 M_MOV(r->argintregs[4], r->argintregs[5]);
4191 M_MOV(r->argintregs[3], r->argintregs[4]);
4192 M_MOV(r->argintregs[2], r->argintregs[3]);
4193 M_MOV(r->argintregs[1], r->argintregs[2]);
4194 M_MOV(r->argintregs[0], r->argintregs[1]);
4195 M_FMOV(r->argfltregs[4], r->argfltregs[5]);
4196 M_FMOV(r->argfltregs[3], r->argfltregs[4]);
4197 M_FMOV(r->argfltregs[2], r->argfltregs[3]);
4198 M_FMOV(r->argfltregs[1], r->argfltregs[2]);
4199 M_FMOV(r->argfltregs[0], r->argfltregs[1]);
4202 /* put env into first argument register */
4203 M_ALD(r->argintregs[0], REG_PV, -4 * 8);
4205 M_ALD(REG_PV, REG_PV, -1 * 8); /* load adress of native method */
4206 M_JSR(REG_RA, REG_PV); /* call native method */
4207 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4208 M_LDA(REG_PV, REG_RA, disp); /* recompute pv from ra */
4210 /* remove stackframe if there is one */
4211 if (stackframesize) {
4212 M_LDA(REG_SP, REG_SP, stackframesize * 8);
4215 /* 13 instructions */
4217 M_LDA(REG_SP, REG_SP, -2 * 8);
4218 M_ALD(r->argintregs[0], REG_PV, -6 * 8); /* load method adress */
4219 M_LST(REG_RESULT, REG_SP, 0 * 8);
4220 M_DST(REG_FRESULT, REG_SP, 1 * 8);
4221 M_MOV(REG_RESULT, r->argintregs[1]);
4222 M_FMOV(REG_FRESULT, r->argfltregs[2]);
4223 M_FMOV(REG_FRESULT, r->argfltregs[3]);
4224 M_ALD(REG_PV, REG_PV, -7 * 8); /* builtin_displaymethodstop */
4225 M_JSR(REG_RA, REG_PV);
4226 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4227 M_LDA(REG_PV, REG_RA, disp);
4228 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4229 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
4230 M_LDA(REG_SP, REG_SP, 2 * 8);
4233 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4234 if (IS_FLT_DBL_TYPE(m->returntype))
4235 M_DST(REG_FRESULT, REG_SP, 1 * 8);
4237 M_AST(REG_RESULT, REG_SP, 1 * 8);
4238 M_ALD(REG_PV, REG_PV, -2 * 8); /* builtin_get_exceptionptrptr */
4239 M_JSR(REG_RA, REG_PV);
4240 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4241 M_LDA(REG_PV, REG_RA, disp);
4242 M_MOV(REG_RESULT, REG_ITMP3);
4243 if (IS_FLT_DBL_TYPE(m->returntype))
4244 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
4246 M_ALD(REG_RESULT, REG_SP, 1 * 8);
4248 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* get address of exceptionptr */
4250 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4251 M_BNEZ(REG_ITMP1, 3); /* if no exception then return */
4253 M_ALD(REG_RA, REG_SP, 0 * 8); /* load return address */
4254 M_LDA(REG_SP, REG_SP, NATIVESTUBSTACK * 8); /* remove stackframe */
4255 M_RET(REG_ZERO, REG_RA); /* return to caller */
4257 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4259 M_ALD(REG_RA, REG_SP, 0 * 8); /* load return address */
4260 M_LDA(REG_SP, REG_SP, NATIVESTUBSTACK * 8); /* remove stackframe */
4261 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4262 M_ALD(REG_ITMP3, REG_PV, -3 * 8); /* load asm exception handler address */
4263 M_JMP(REG_ZERO, REG_ITMP3); /* jump to asm exception handler */
4266 dolog_plain("stubsize: %d (for %d params)\n", (int) (mcodeptr - (s4*) s), m->paramcount);
4269 #if defined(STATISTICS)
4271 count_nstub_len += NATIVESTUBSIZE * 8;
4274 return (u1 *) (s + NATIVESTUBOFFSET);
4278 /* function: removenativestub **************************************************
4280 removes a previously created native-stub from memory
4282 *******************************************************************************/
4284 void removenativestub(u1 *stub)
4286 CFREE((u8 *) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 8);
4291 * These are local overrides for various environment variables in Emacs.
4292 * Please do not remove this and leave it at the end of the file, where
4293 * Emacs will automagically detect them.
4294 * ---------------------------------------------------------------------
4297 * indent-tabs-mode: t