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 963 2004-03-15 07:37:49Z jowenn $
52 /* include independent code generation stuff */
53 #include "codegen.inc"
57 /* *****************************************************************************
59 Datatypes and Register Allocations:
60 -----------------------------------
62 On 64-bit-machines (like the Alpha) all operands are stored in the
63 registers in a 64-bit form, even when the correspondig JavaVM operands
64 only need 32 bits. This is done by a canonical representation:
66 32-bit integers are allways stored as sign-extended 64-bit values (this
67 approach is directly supported by the Alpha architecture and is very easy
70 32-bit-floats are stored in a 64-bit doubleprecision register by simply
71 expanding the exponent and mantissa with zeroes. (also supported by the
77 The calling conventions and the layout of the stack is explained in detail
78 in the documention file: calling.doc
80 *******************************************************************************/
83 /* register descripton - array ************************************************/
85 /* #define REG_RES 0 reserved register for OS or code generator */
86 /* #define REG_RET 1 return value register */
87 /* #define REG_EXC 2 exception value register (only old jit) */
88 /* #define REG_SAV 3 (callee) saved register */
89 /* #define REG_TMP 4 scratch temporary register (caller saved) */
90 /* #define REG_ARG 5 argument register (caller saved) */
92 /* #define REG_END -1 last entry in tables */
95 REG_RET, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
96 REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
97 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
98 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
101 /* for use of reserved registers, see comment above */
103 int nregdescfloat[] = {
104 REG_RET, REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
105 REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
106 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
107 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES,
110 /* for use of reserved registers, see comment above */
113 /* parameter allocation mode */
115 int nreg_parammode = PARAMMODE_NUMBERED;
117 /* parameter-registers will be allocated by assigning the
118 1. parameter: int/float-reg 16
119 2. parameter: int/float-reg 17
120 3. parameter: int/float-reg 18 ....
124 /* stackframe-infos ***********************************************************/
126 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
128 /* -> see file 'calling.doc' */
131 /* additional functions and macros to generate code ***************************/
133 /* #define BlockPtrOfPC(pc) block+block_index[pc] */
134 #define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
138 #define COUNT_SPILLS count_spills++
144 /* gen_nullptr_check(objreg) */
146 #define gen_nullptr_check(objreg) \
148 M_BEQZ((objreg), 0); \
149 codegen_addxnullrefs(mcodeptr); \
153 /* MCODECHECK(icnt) */
155 #define MCODECHECK(icnt) \
156 if((mcodeptr + (icnt)) > mcodeend) mcodeptr = codegen_increase((u1*) mcodeptr)
159 generates an integer-move from register a to b.
160 if a and b are the same int-register, no code will be generated.
163 #define M_INTMOVE(a,b) if (a != b) { M_MOV(a, b); }
167 generates a floating-point-move from register a to b.
168 if a and b are the same float-register, no code will be generated
171 #define M_FLTMOVE(a,b) if (a != b) { M_FMOV(a, b); }
175 this function generates code to fetch data from a pseudo-register
176 into a real register.
177 If the pseudo-register has actually been assigned to a real
178 register, no code will be emitted, since following operations
179 can use this register directly.
181 v: pseudoregister to be fetched from
182 tempregnum: temporary register to be used if v is actually spilled to ram
184 return: the register number, where the operand can be found after
185 fetching (this wil be either tempregnum or the register
186 number allready given to v)
189 #define var_to_reg_int(regnr,v,tempnr) { \
190 if ((v)->flags & INMEMORY) \
191 {COUNT_SPILLS;M_LLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
192 else regnr=(v)->regoff; \
196 #define var_to_reg_flt(regnr,v,tempnr) { \
197 if ((v)->flags & INMEMORY) \
198 {COUNT_SPILLS;M_DLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
199 else regnr=(v)->regoff; \
204 This function determines a register, to which the result of an operation
205 should go, when it is ultimatively intended to store the result in
207 If v is assigned to an actual register, this register will be returned.
208 Otherwise (when v is spilled) this function returns tempregnum.
209 If not already done, regoff and flags are set in the stack location.
212 static int reg_of_var(stackptr v, int tempregnum)
216 switch (v->varkind) {
218 if (!(v->flags & INMEMORY))
222 var = &(interfaces[v->varnum][v->type]);
223 v->regoff = var->regoff;
224 if (!(var->flags & INMEMORY))
228 var = &(locals[v->varnum][v->type]);
229 v->regoff = var->regoff;
230 if (!(var->flags & INMEMORY))
234 v->regoff = v->varnum;
235 if (IS_FLT_DBL_TYPE(v->type)) {
236 if (v->varnum < fltreg_argnum) {
237 v->regoff = argfltregs[v->varnum];
238 return(argfltregs[v->varnum]);
242 if (v->varnum < intreg_argnum) {
243 v->regoff = argintregs[v->varnum];
244 return(argintregs[v->varnum]);
246 v->regoff -= intreg_argnum;
249 v->flags |= INMEMORY;
254 /* store_reg_to_var_xxx:
255 This function generates the code to store the result of an operation
256 back into a spilled pseudo-variable.
257 If the pseudo-variable has not been spilled in the first place, this
258 function will generate nothing.
260 v ............ Pseudovariable
261 tempregnum ... Number of the temporary registers as returned by
265 #define store_reg_to_var_int(sptr, tempregnum) { \
266 if ((sptr)->flags & INMEMORY) { \
268 M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
272 #define store_reg_to_var_flt(sptr, tempregnum) { \
273 if ((sptr)->flags & INMEMORY) { \
275 M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
280 /* NullPointerException handlers and exception handling initialisation */
282 typedef struct sigctx_struct {
284 long sc_onstack; /* sigstack state to restore */
285 long sc_mask; /* signal mask to restore */
286 long sc_pc; /* pc at time of signal */
287 long sc_ps; /* psl to retore */
288 long sc_regs[32]; /* processor regs 0 to 31 */
289 long sc_ownedfp; /* fp has been used */
290 long sc_fpregs[32]; /* fp regs 0 to 31 */
291 unsigned long sc_fpcr; /* floating point control register */
292 unsigned long sc_fp_control; /* software fpcr */
294 unsigned long sc_reserved1, sc_reserved2;
295 unsigned long sc_ssize;
297 unsigned long sc_traparg_a0;
298 unsigned long sc_traparg_a1;
299 unsigned long sc_traparg_a2;
300 unsigned long sc_fp_trap_pc;
301 unsigned long sc_fp_trigger_sum;
302 unsigned long sc_fp_trigger_inst;
303 unsigned long sc_retcode[2];
307 /* NullPointerException signal handler for hardware null pointer check */
309 void catch_NullPointerException(int sig, int code, sigctx_struct *sigctx)
315 /* Reset signal handler - necessary for SysV, does no harm for BSD */
317 instr = *((int*)(sigctx->sc_pc));
318 faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f];
320 if (faultaddr == 0) {
321 signal(sig, (void*) catch_NullPointerException); /* reinstall handler */
323 sigaddset(&nsig, sig);
324 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
326 if (!proto_java_lang_NullPointerException) {
327 proto_java_lang_NullPointerException =
328 new_exception(string_java_lang_NullPointerException);
331 sigctx->sc_regs[REG_ITMP1_XPTR] =
332 (long) proto_java_lang_NullPointerException;
333 sigctx->sc_regs[REG_ITMP2_XPC] = sigctx->sc_pc;
334 sigctx->sc_pc = (long) asm_handle_exception;
338 faultaddr += (long) ((instr << 16) >> 16);
339 fprintf(stderr, "faulting address: 0x%16lx\n", faultaddr);
340 panic("Stack overflow");
347 void init_exceptions(void)
352 /* Linux on Digital Alpha needs an initialisation of the ieee floating point
353 control for IEEE compliant arithmetic (option -mieee of GCC). Under
354 Digital Unix this is done automatically.
359 extern unsigned long ieee_get_fp_control();
360 extern void ieee_set_fp_control(unsigned long fp_control);
362 void init_exceptions(void)
364 /* initialize floating point control */
366 ieee_set_fp_control(ieee_get_fp_control()
367 & ~IEEE_TRAP_ENABLE_INV
368 & ~IEEE_TRAP_ENABLE_DZE
369 /* & ~IEEE_TRAP_ENABLE_UNF we dont want underflow */
370 & ~IEEE_TRAP_ENABLE_OVF);
373 /* install signal handlers we need to convert to exceptions */
377 signal(SIGSEGV, (void*) catch_NullPointerException);
381 signal(SIGBUS, (void*) catch_NullPointerException);
387 /* function gen_mcode **********************************************************
389 generates machine code
391 *******************************************************************************/
395 int len, s1, s2, s3, d;
408 savedregs_num = (isleafmethod) ? 0 : 1; /* space to save the RA */
410 /* space to save used callee saved registers */
412 savedregs_num += (savintregcnt - maxsavintreguse);
413 savedregs_num += (savfltregcnt - maxsavfltreguse);
415 parentargs_base = maxmemuse + savedregs_num;
417 #ifdef USE_THREADS /* space to save argument of monitor_enter */
419 if (checksync && (method->flags & ACC_SYNCHRONIZED))
424 /* create method header */
426 (void) dseg_addaddress(method); /* MethodPointer */
427 (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
431 /* IsSync contains the offset relative to the stack pointer for the
432 argument of monitor_exit used in the exception handler. Since the
433 offset could be zero and give a wrong meaning of the flag it is
437 if (checksync && (method->flags & ACC_SYNCHRONIZED))
438 (void) dseg_adds4((maxmemuse + 1) * 8); /* IsSync */
443 (void) dseg_adds4(0); /* IsSync */
445 (void) dseg_adds4(isleafmethod); /* IsLeaf */
446 (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
447 (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
449 (void) dseg_addlinenumbertablesize() /* line number table size + start*/
451 (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
453 /* create exception table */
455 for (ex = extable; ex != NULL; ex = ex->down) {
458 if (ex->start != NULL)
459 printf("adding start - %d - ", ex->start->debug_nr);
461 printf("PANIC - start is NULL");
466 dseg_addtarget(ex->start);
470 printf("adding end - %d - ", ex->end->debug_nr);
472 printf("PANIC - end is NULL");
477 dseg_addtarget(ex->end);
480 if (ex->handler != NULL)
481 printf("adding handler - %d\n", ex->handler->debug_nr);
483 printf("PANIC - handler is NULL");
488 dseg_addtarget(ex->handler);
490 (void) dseg_addaddress(ex->catchtype);
493 /* initialize mcode variables */
495 mcodeptr = (s4*) mcodebase;
496 mcodeend = (s4*) (mcodebase + mcodesize);
497 MCODECHECK(128 + mparamcount);
499 /* create stack frame (if necessary) */
502 {M_LDA (REG_SP, REG_SP, -parentargs_base * 8);}
504 /* save return address and used callee saved registers */
508 {p--; M_AST (REG_RA, REG_SP, 8*p);}
509 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
510 {p--; M_LST (savintregs[r], REG_SP, 8 * p);}
511 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
512 {p--; M_DST (savfltregs[r], REG_SP, 8 * p);}
514 /* save monitorenter argument */
517 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
518 if (method->flags & ACC_STATIC) {
519 p = dseg_addaddress (class);
520 M_ALD(REG_ITMP1, REG_PV, p);
521 M_AST(REG_ITMP1, REG_SP, 8 * maxmemuse);
524 M_AST (argintregs[0], REG_SP, 8 * maxmemuse);
529 /* copy argument registers to stack and call trace function with pointer
530 to arguments on stack.
535 M_LDA(REG_SP, REG_SP, -(14 * 8));
536 M_AST(REG_RA, REG_SP, 1 * 8);
538 /* save integer argument registers */
539 for (p = 0; p < mparamcount && p < INT_ARG_CNT; p++) {
540 M_LST(argintregs[p], REG_SP, (2 + p) * 8);
543 /* save and copy float arguments into integer registers */
544 for (p = 0; p < mparamcount && p < FLT_ARG_CNT; p++) {
547 if (IS_FLT_DBL_TYPE(t)) {
548 if (IS_2_WORD_TYPE(t)) {
549 M_DST(argfltregs[p], REG_SP, (8 + p) * 8);
551 M_FST(argfltregs[p], REG_SP, (8 + p) * 8);
554 M_LLD(argintregs[p], REG_SP, (8 + p) * 8);
557 M_DST(argfltregs[p], REG_SP, (8 + p) * 8);
561 p = dseg_addaddress(method);
562 M_ALD(REG_ITMP1, REG_PV, p);
563 M_AST(REG_ITMP1, REG_SP, 0);
564 p = dseg_addaddress((void *) builtin_trace_args);
565 M_ALD(REG_PV, REG_PV, p);
566 M_JSR(REG_RA, REG_PV);
567 disp = -(int)((u1 *) mcodeptr - mcodebase);
568 M_LDA(REG_PV, REG_RA, disp);
569 M_ALD(REG_RA, REG_SP, 1 * 8);
571 for (p = 0; p < mparamcount && p < INT_ARG_CNT; p++) {
572 M_LLD(argintregs[p], REG_SP, (2 + p) * 8);
575 for (p = 0; p < mparamcount && p < FLT_ARG_CNT; p++) {
578 if (IS_FLT_DBL_TYPE(t)) {
579 if (IS_2_WORD_TYPE(t)) {
580 M_DLD(argfltregs[p], REG_SP, (8 + p) * 8);
582 M_FLD(argfltregs[p], REG_SP, (8 + p) * 8);
585 M_DLD(argfltregs[p], REG_SP, (8 + p) * 8);
589 M_LDA (REG_SP, REG_SP, 14 * 8);
592 /* take arguments out of register or stack frame */
594 for (p = 0, l = 0; p < mparamcount; p++) {
596 var = &(locals[l][t]);
598 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
603 if (IS_INT_LNG_TYPE(t)) { /* integer args */
604 if (p < INT_ARG_CNT) { /* register arguments */
605 if (!(var->flags & INMEMORY)) /* reg arg -> register */
606 {M_INTMOVE (argintregs[p], r);}
607 else /* reg arg -> spilled */
608 M_LST (argintregs[p], REG_SP, 8 * r);
610 else { /* stack arguments */
611 pa = p - INT_ARG_CNT;
612 if (!(var->flags & INMEMORY)) /* stack arg -> register */
613 M_LLD (r, REG_SP, 8 * (parentargs_base + pa));
614 else { /* stack arg -> spilled */
615 M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
616 M_LST (REG_ITMP1, REG_SP, 8 * r);
620 else { /* floating args */
621 if (p < FLT_ARG_CNT) { /* register arguments */
622 if (!(var->flags & INMEMORY)) /* reg arg -> register */
623 {M_FLTMOVE (argfltregs[p], r);}
624 else /* reg arg -> spilled */
625 M_DST (argfltregs[p], REG_SP, 8 * r);
627 else { /* stack arguments */
628 pa = p - FLT_ARG_CNT;
629 if (!(var->flags & INMEMORY)) /* stack-arg -> register */
630 M_DLD (r, REG_SP, 8 * (parentargs_base + pa) );
631 else { /* stack-arg -> spilled */
632 M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
633 M_DST (REG_FTMP1, REG_SP, 8 * r);
639 /* call trace function */
642 if (runverbose && !isleafmethod) {
643 M_LDA (REG_SP, REG_SP, -8);
644 p = dseg_addaddress (method);
645 M_ALD(REG_ITMP1, REG_PV, p);
646 M_AST(REG_ITMP1, REG_SP, 0);
647 p = dseg_addaddress ((void*) (builtin_trace_args));
648 M_ALD(REG_PV, REG_PV, p);
649 M_JSR(REG_RA, REG_PV);
650 M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
651 M_LDA(REG_SP, REG_SP, 8);
655 /* call monitorenter function */
658 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
660 p = dseg_addaddress ((void*) (builtin_monitorenter));
661 M_ALD(REG_PV, REG_PV, p);
662 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
663 M_JSR(REG_RA, REG_PV);
664 disp = -(int)((u1*) mcodeptr - mcodebase);
665 M_LDA(REG_PV, REG_RA, disp);
670 /* end of header generation */
672 /* walk through all basic blocks */
673 for (bptr = block; bptr != NULL; bptr = bptr->next) {
675 bptr->mpc = (int)((u1*) mcodeptr - mcodebase);
677 if (bptr->flags >= BBREACHED) {
679 /* branch resolving */
683 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
684 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
685 brefs->branchpos, bptr->mpc);
689 /* copy interface registers to their destination */
694 while (src != NULL) {
696 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
697 d = reg_of_var(src, REG_ITMP1);
698 M_INTMOVE(REG_ITMP1, d);
699 store_reg_to_var_int(src, d);
702 d = reg_of_var(src, REG_IFTMP);
703 if ((src->varkind != STACKVAR)) {
705 if (IS_FLT_DBL_TYPE(s2)) {
706 if (!(interfaces[len][s2].flags & INMEMORY)) {
707 s1 = interfaces[len][s2].regoff;
711 M_DLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
713 store_reg_to_var_flt(src, d);
716 if (!(interfaces[len][s2].flags & INMEMORY)) {
717 s1 = interfaces[len][s2].regoff;
721 M_LLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
723 store_reg_to_var_int(src, d);
730 /* walk through all instructions */
734 for (iptr = bptr->iinstr;
736 src = iptr->dst, len--, iptr++) {
738 MCODECHECK(64); /* an instruction usually needs < 64 words */
740 if (iptr->line!=currentline) {
741 dseg_addlinenumber(iptr->line,mcodeptr);
742 currentline=iptr->line;
747 case ICMD_NOP: /* ... ==> ... */
750 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
752 var_to_reg_int(s1, src, REG_ITMP1);
754 codegen_addxnullrefs(mcodeptr);
757 /* constant operations ************************************************/
759 #define ICONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LDA(r,REG_ZERO,c);} \
760 else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
762 #define LCONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LDA(r,REG_ZERO,c);} \
763 else{a=dseg_adds8(c);M_LLD(r,REG_PV,a);}
765 case ICMD_ICONST: /* ... ==> ..., constant */
766 /* op1 = 0, val.i = constant */
768 d = reg_of_var(iptr->dst, REG_ITMP1);
769 ICONST(d, iptr->val.i);
770 store_reg_to_var_int(iptr->dst, d);
773 case ICMD_LCONST: /* ... ==> ..., constant */
774 /* op1 = 0, val.l = constant */
776 d = reg_of_var(iptr->dst, REG_ITMP1);
777 LCONST(d, iptr->val.l);
778 store_reg_to_var_int(iptr->dst, d);
781 case ICMD_FCONST: /* ... ==> ..., constant */
782 /* op1 = 0, val.f = constant */
784 d = reg_of_var(iptr->dst, REG_FTMP1);
785 a = dseg_addfloat(iptr->val.f);
787 store_reg_to_var_flt(iptr->dst, d);
790 case ICMD_DCONST: /* ... ==> ..., constant */
791 /* op1 = 0, val.d = constant */
793 d = reg_of_var(iptr->dst, REG_FTMP1);
794 a = dseg_adddouble(iptr->val.d);
796 store_reg_to_var_flt(iptr->dst, d);
799 case ICMD_ACONST: /* ... ==> ..., constant */
800 /* op1 = 0, val.a = constant */
802 d = reg_of_var(iptr->dst, REG_ITMP1);
804 a = dseg_addaddress (iptr->val.a);
808 M_INTMOVE(REG_ZERO, d);
810 store_reg_to_var_int(iptr->dst, d);
814 /* load/store operations **********************************************/
816 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
817 case ICMD_LLOAD: /* op1 = local variable */
820 d = reg_of_var(iptr->dst, REG_ITMP1);
821 if ((iptr->dst->varkind == LOCALVAR) &&
822 (iptr->dst->varnum == iptr->op1))
824 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
825 if (var->flags & INMEMORY)
826 M_LLD(d, REG_SP, 8 * var->regoff);
828 {M_INTMOVE(var->regoff,d);}
829 store_reg_to_var_int(iptr->dst, d);
832 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
833 case ICMD_DLOAD: /* op1 = local variable */
835 d = reg_of_var(iptr->dst, REG_FTMP1);
836 if ((iptr->dst->varkind == LOCALVAR) &&
837 (iptr->dst->varnum == iptr->op1))
839 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
840 if (var->flags & INMEMORY)
841 M_DLD(d, REG_SP, 8 * var->regoff);
843 {M_FLTMOVE(var->regoff,d);}
844 store_reg_to_var_flt(iptr->dst, d);
848 case ICMD_ISTORE: /* ..., value ==> ... */
849 case ICMD_LSTORE: /* op1 = local variable */
852 if ((src->varkind == LOCALVAR) &&
853 (src->varnum == iptr->op1))
855 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
856 if (var->flags & INMEMORY) {
857 var_to_reg_int(s1, src, REG_ITMP1);
858 M_LST(s1, REG_SP, 8 * var->regoff);
861 var_to_reg_int(s1, src, var->regoff);
862 M_INTMOVE(s1, var->regoff);
866 case ICMD_FSTORE: /* ..., value ==> ... */
867 case ICMD_DSTORE: /* op1 = local variable */
869 if ((src->varkind == LOCALVAR) &&
870 (src->varnum == iptr->op1))
872 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
873 if (var->flags & INMEMORY) {
874 var_to_reg_flt(s1, src, REG_FTMP1);
875 M_DST(s1, REG_SP, 8 * var->regoff);
878 var_to_reg_flt(s1, src, var->regoff);
879 M_FLTMOVE(s1, var->regoff);
884 /* pop/dup/swap operations ********************************************/
886 /* attention: double and longs are only one entry in CACAO ICMDs */
888 case ICMD_POP: /* ..., value ==> ... */
889 case ICMD_POP2: /* ..., value, value ==> ... */
892 #define M_COPY(from,to) \
893 d = reg_of_var(to, REG_IFTMP); \
894 if ((from->regoff != to->regoff) || \
895 ((from->flags ^ to->flags) & INMEMORY)) { \
896 if (IS_FLT_DBL_TYPE(from->type)) { \
897 var_to_reg_flt(s1, from, d); \
899 store_reg_to_var_flt(to, d); \
902 var_to_reg_int(s1, from, d); \
904 store_reg_to_var_int(to, d); \
908 case ICMD_DUP: /* ..., a ==> ..., a, a */
909 M_COPY(src, iptr->dst);
912 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
914 M_COPY(src, iptr->dst->prev->prev);
916 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
918 M_COPY(src, iptr->dst);
919 M_COPY(src->prev, iptr->dst->prev);
922 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
924 M_COPY(src->prev, iptr->dst->prev->prev->prev);
926 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
928 M_COPY(src, iptr->dst);
929 M_COPY(src->prev, iptr->dst->prev);
930 M_COPY(src->prev->prev, iptr->dst->prev->prev);
931 M_COPY(src, iptr->dst->prev->prev->prev);
934 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
936 M_COPY(src, iptr->dst);
937 M_COPY(src->prev, iptr->dst->prev);
938 M_COPY(src->prev->prev, iptr->dst->prev->prev);
939 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
940 M_COPY(src, iptr->dst->prev->prev->prev->prev);
941 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
944 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
946 M_COPY(src, iptr->dst->prev);
947 M_COPY(src->prev, iptr->dst);
951 /* integer operations *************************************************/
953 case ICMD_INEG: /* ..., value ==> ..., - value */
955 var_to_reg_int(s1, src, REG_ITMP1);
956 d = reg_of_var(iptr->dst, REG_ITMP3);
957 M_ISUB(REG_ZERO, s1, d);
958 store_reg_to_var_int(iptr->dst, d);
961 case ICMD_LNEG: /* ..., value ==> ..., - value */
963 var_to_reg_int(s1, src, REG_ITMP1);
964 d = reg_of_var(iptr->dst, REG_ITMP3);
965 M_LSUB(REG_ZERO, s1, d);
966 store_reg_to_var_int(iptr->dst, d);
969 case ICMD_I2L: /* ..., value ==> ..., value */
971 var_to_reg_int(s1, src, REG_ITMP1);
972 d = reg_of_var(iptr->dst, REG_ITMP3);
974 store_reg_to_var_int(iptr->dst, d);
977 case ICMD_L2I: /* ..., value ==> ..., value */
979 var_to_reg_int(s1, src, REG_ITMP1);
980 d = reg_of_var(iptr->dst, REG_ITMP3);
981 M_IADD(s1, REG_ZERO, d );
982 store_reg_to_var_int(iptr->dst, d);
985 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
987 var_to_reg_int(s1, src, REG_ITMP1);
988 d = reg_of_var(iptr->dst, REG_ITMP3);
989 if (has_ext_instr_set) {
993 M_SLL_IMM(s1, 56, d);
994 M_SRA_IMM( d, 56, d);
996 store_reg_to_var_int(iptr->dst, d);
999 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1001 var_to_reg_int(s1, src, REG_ITMP1);
1002 d = reg_of_var(iptr->dst, REG_ITMP3);
1004 store_reg_to_var_int(iptr->dst, d);
1007 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1009 var_to_reg_int(s1, src, REG_ITMP1);
1010 d = reg_of_var(iptr->dst, REG_ITMP3);
1011 if (has_ext_instr_set) {
1015 M_SLL_IMM(s1, 48, d);
1016 M_SRA_IMM( d, 48, d);
1018 store_reg_to_var_int(iptr->dst, d);
1022 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1024 var_to_reg_int(s1, src->prev, REG_ITMP1);
1025 var_to_reg_int(s2, src, REG_ITMP2);
1026 d = reg_of_var(iptr->dst, REG_ITMP3);
1028 store_reg_to_var_int(iptr->dst, d);
1031 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1032 /* val.i = constant */
1034 var_to_reg_int(s1, src, REG_ITMP1);
1035 d = reg_of_var(iptr->dst, REG_ITMP3);
1036 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1037 M_IADD_IMM(s1, iptr->val.i, d);
1040 ICONST(REG_ITMP2, iptr->val.i);
1041 M_IADD(s1, REG_ITMP2, d);
1043 store_reg_to_var_int(iptr->dst, d);
1046 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1048 var_to_reg_int(s1, src->prev, REG_ITMP1);
1049 var_to_reg_int(s2, src, REG_ITMP2);
1050 d = reg_of_var(iptr->dst, REG_ITMP3);
1052 store_reg_to_var_int(iptr->dst, d);
1055 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1056 /* val.l = constant */
1058 var_to_reg_int(s1, src, REG_ITMP1);
1059 d = reg_of_var(iptr->dst, REG_ITMP3);
1060 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1061 M_LADD_IMM(s1, iptr->val.l, d);
1064 LCONST(REG_ITMP2, iptr->val.l);
1065 M_LADD(s1, REG_ITMP2, d);
1067 store_reg_to_var_int(iptr->dst, d);
1070 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1072 var_to_reg_int(s1, src->prev, REG_ITMP1);
1073 var_to_reg_int(s2, src, REG_ITMP2);
1074 d = reg_of_var(iptr->dst, REG_ITMP3);
1076 store_reg_to_var_int(iptr->dst, d);
1079 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1080 /* val.i = constant */
1082 var_to_reg_int(s1, src, REG_ITMP1);
1083 d = reg_of_var(iptr->dst, REG_ITMP3);
1084 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1085 M_ISUB_IMM(s1, iptr->val.i, d);
1088 ICONST(REG_ITMP2, iptr->val.i);
1089 M_ISUB(s1, REG_ITMP2, d);
1091 store_reg_to_var_int(iptr->dst, d);
1094 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1096 var_to_reg_int(s1, src->prev, REG_ITMP1);
1097 var_to_reg_int(s2, src, REG_ITMP2);
1098 d = reg_of_var(iptr->dst, REG_ITMP3);
1100 store_reg_to_var_int(iptr->dst, d);
1103 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1104 /* val.l = constant */
1106 var_to_reg_int(s1, src, REG_ITMP1);
1107 d = reg_of_var(iptr->dst, REG_ITMP3);
1108 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1109 M_LSUB_IMM(s1, iptr->val.l, d);
1112 LCONST(REG_ITMP2, iptr->val.l);
1113 M_LSUB(s1, REG_ITMP2, d);
1115 store_reg_to_var_int(iptr->dst, d);
1118 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1120 var_to_reg_int(s1, src->prev, REG_ITMP1);
1121 var_to_reg_int(s2, src, REG_ITMP2);
1122 d = reg_of_var(iptr->dst, REG_ITMP3);
1124 store_reg_to_var_int(iptr->dst, d);
1127 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1128 /* val.i = constant */
1130 var_to_reg_int(s1, src, REG_ITMP1);
1131 d = reg_of_var(iptr->dst, REG_ITMP3);
1132 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1133 M_IMUL_IMM(s1, iptr->val.i, d);
1136 ICONST(REG_ITMP2, iptr->val.i);
1137 M_IMUL(s1, REG_ITMP2, d);
1139 store_reg_to_var_int(iptr->dst, d);
1142 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1144 var_to_reg_int(s1, src->prev, REG_ITMP1);
1145 var_to_reg_int(s2, src, REG_ITMP2);
1146 d = reg_of_var(iptr->dst, REG_ITMP3);
1148 store_reg_to_var_int(iptr->dst, d);
1151 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1152 /* val.l = constant */
1154 var_to_reg_int(s1, src, REG_ITMP1);
1155 d = reg_of_var(iptr->dst, REG_ITMP3);
1156 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1157 M_LMUL_IMM(s1, iptr->val.l, d);
1160 LCONST(REG_ITMP2, iptr->val.l);
1161 M_LMUL(s1, REG_ITMP2, d);
1163 store_reg_to_var_int(iptr->dst, d);
1166 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1167 case ICMD_LDIVPOW2: /* val.i = constant */
1169 var_to_reg_int(s1, src, REG_ITMP1);
1170 d = reg_of_var(iptr->dst, REG_ITMP3);
1171 if (iptr->val.i <= 15) {
1172 M_LDA(REG_ITMP2, s1, (1 << iptr->val.i) -1);
1173 M_CMOVGE(s1, s1, REG_ITMP2);
1176 M_SRA_IMM(s1, 63, REG_ITMP2);
1177 M_SRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1178 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1180 M_SRA_IMM(REG_ITMP2, iptr->val.i, d);
1181 store_reg_to_var_int(iptr->dst, d);
1184 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1186 var_to_reg_int(s1, src->prev, REG_ITMP1);
1187 var_to_reg_int(s2, src, REG_ITMP2);
1188 d = reg_of_var(iptr->dst, REG_ITMP3);
1189 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1190 M_SLL(s1, REG_ITMP3, d);
1191 M_IADD(d, REG_ZERO, d);
1192 store_reg_to_var_int(iptr->dst, d);
1195 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1196 /* val.i = constant */
1198 var_to_reg_int(s1, src, REG_ITMP1);
1199 d = reg_of_var(iptr->dst, REG_ITMP3);
1200 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1201 M_IADD(d, REG_ZERO, d);
1202 store_reg_to_var_int(iptr->dst, d);
1205 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1207 var_to_reg_int(s1, src->prev, REG_ITMP1);
1208 var_to_reg_int(s2, src, REG_ITMP2);
1209 d = reg_of_var(iptr->dst, REG_ITMP3);
1210 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1211 M_SRA(s1, REG_ITMP3, d);
1212 store_reg_to_var_int(iptr->dst, d);
1215 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1216 /* val.i = constant */
1218 var_to_reg_int(s1, src, REG_ITMP1);
1219 d = reg_of_var(iptr->dst, REG_ITMP3);
1220 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1221 store_reg_to_var_int(iptr->dst, d);
1224 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1226 var_to_reg_int(s1, src->prev, REG_ITMP1);
1227 var_to_reg_int(s2, src, REG_ITMP2);
1228 d = reg_of_var(iptr->dst, REG_ITMP3);
1229 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1231 M_SRL(d, REG_ITMP2, d);
1232 M_IADD(d, REG_ZERO, d);
1233 store_reg_to_var_int(iptr->dst, d);
1236 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1237 /* val.i = constant */
1239 var_to_reg_int(s1, src, REG_ITMP1);
1240 d = reg_of_var(iptr->dst, REG_ITMP3);
1242 M_SRL_IMM(d, iptr->val.i & 0x1f, d);
1243 M_IADD(d, REG_ZERO, d);
1244 store_reg_to_var_int(iptr->dst, d);
1247 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1249 var_to_reg_int(s1, src->prev, REG_ITMP1);
1250 var_to_reg_int(s2, src, REG_ITMP2);
1251 d = reg_of_var(iptr->dst, REG_ITMP3);
1253 store_reg_to_var_int(iptr->dst, d);
1256 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1257 /* val.i = constant */
1259 var_to_reg_int(s1, src, REG_ITMP1);
1260 d = reg_of_var(iptr->dst, REG_ITMP3);
1261 M_SLL_IMM(s1, iptr->val.i & 0x3f, d);
1262 store_reg_to_var_int(iptr->dst, d);
1265 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1267 var_to_reg_int(s1, src->prev, REG_ITMP1);
1268 var_to_reg_int(s2, src, REG_ITMP2);
1269 d = reg_of_var(iptr->dst, REG_ITMP3);
1271 store_reg_to_var_int(iptr->dst, d);
1274 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1275 /* val.i = constant */
1277 var_to_reg_int(s1, src, REG_ITMP1);
1278 d = reg_of_var(iptr->dst, REG_ITMP3);
1279 M_SRA_IMM(s1, iptr->val.i & 0x3f, d);
1280 store_reg_to_var_int(iptr->dst, d);
1283 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1285 var_to_reg_int(s1, src->prev, REG_ITMP1);
1286 var_to_reg_int(s2, src, REG_ITMP2);
1287 d = reg_of_var(iptr->dst, REG_ITMP3);
1289 store_reg_to_var_int(iptr->dst, d);
1292 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1293 /* val.i = constant */
1295 var_to_reg_int(s1, src, REG_ITMP1);
1296 d = reg_of_var(iptr->dst, REG_ITMP3);
1297 M_SRL_IMM(s1, iptr->val.i & 0x3f, d);
1298 store_reg_to_var_int(iptr->dst, d);
1301 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1304 var_to_reg_int(s1, src->prev, REG_ITMP1);
1305 var_to_reg_int(s2, src, REG_ITMP2);
1306 d = reg_of_var(iptr->dst, REG_ITMP3);
1308 store_reg_to_var_int(iptr->dst, d);
1311 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1312 /* val.i = constant */
1314 var_to_reg_int(s1, src, REG_ITMP1);
1315 d = reg_of_var(iptr->dst, REG_ITMP3);
1316 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1317 M_AND_IMM(s1, iptr->val.i, d);
1319 else if (iptr->val.i == 0xffff) {
1322 else if (iptr->val.i == 0xffffff) {
1323 M_ZAPNOT_IMM(s1, 0x07, d);
1326 ICONST(REG_ITMP2, iptr->val.i);
1327 M_AND(s1, REG_ITMP2, d);
1329 store_reg_to_var_int(iptr->dst, d);
1332 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1333 /* val.i = constant */
1335 var_to_reg_int(s1, src, REG_ITMP1);
1336 d = reg_of_var(iptr->dst, REG_ITMP3);
1338 M_MOV(s1, REG_ITMP1);
1341 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1342 M_AND_IMM(s1, iptr->val.i, d);
1344 M_ISUB(REG_ZERO, s1, d);
1345 M_AND_IMM(d, iptr->val.i, d);
1347 else if (iptr->val.i == 0xffff) {
1350 M_ISUB(REG_ZERO, s1, d);
1353 else if (iptr->val.i == 0xffffff) {
1354 M_ZAPNOT_IMM(s1, 0x07, d);
1356 M_ISUB(REG_ZERO, s1, d);
1357 M_ZAPNOT_IMM(d, 0x07, d);
1360 ICONST(REG_ITMP2, iptr->val.i);
1361 M_AND(s1, REG_ITMP2, d);
1363 M_ISUB(REG_ZERO, s1, d);
1364 M_AND(d, REG_ITMP2, d);
1366 M_ISUB(REG_ZERO, d, d);
1367 store_reg_to_var_int(iptr->dst, d);
1370 case ICMD_IREM0X10001: /* ..., value ==> ..., value % 0x100001 */
1372 /* b = value & 0xffff;
1374 a = ((b - a) & 0xffff) + (b < a);
1376 var_to_reg_int(s1, src, REG_ITMP1);
1377 d = reg_of_var(iptr->dst, REG_ITMP3);
1379 M_MOV(s1, REG_ITMP3);
1383 M_CZEXT(s1, REG_ITMP2);
1384 M_SRA_IMM(s1, 16, d);
1385 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1386 M_ISUB(REG_ITMP2, d, d);
1388 M_IADD(d, REG_ITMP1, d);
1389 M_BR(11 + (s1 == REG_ITMP1));
1390 M_ISUB(REG_ZERO, s1, REG_ITMP1);
1391 M_CZEXT(REG_ITMP1, REG_ITMP2);
1392 M_SRA_IMM(REG_ITMP1, 16, d);
1393 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1394 M_ISUB(REG_ITMP2, d, d);
1396 M_IADD(d, REG_ITMP1, d);
1397 M_ISUB(REG_ZERO, d, d);
1398 if (s1 == REG_ITMP1) {
1399 var_to_reg_int(s1, src, REG_ITMP1);
1401 M_SLL_IMM(s1, 33, REG_ITMP2);
1402 M_CMPEQ(REG_ITMP2, REG_ZERO, REG_ITMP2);
1403 M_ISUB(d, REG_ITMP2, d);
1404 store_reg_to_var_int(iptr->dst, d);
1407 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1408 /* val.l = constant */
1410 var_to_reg_int(s1, src, REG_ITMP1);
1411 d = reg_of_var(iptr->dst, REG_ITMP3);
1412 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1413 M_AND_IMM(s1, iptr->val.l, d);
1415 else if (iptr->val.l == 0xffffL) {
1418 else if (iptr->val.l == 0xffffffL) {
1419 M_ZAPNOT_IMM(s1, 0x07, d);
1421 else if (iptr->val.l == 0xffffffffL) {
1424 else if (iptr->val.l == 0xffffffffffL) {
1425 M_ZAPNOT_IMM(s1, 0x1f, d);
1427 else if (iptr->val.l == 0xffffffffffffL) {
1428 M_ZAPNOT_IMM(s1, 0x3f, d);
1430 else if (iptr->val.l == 0xffffffffffffffL) {
1431 M_ZAPNOT_IMM(s1, 0x7f, d);
1434 LCONST(REG_ITMP2, iptr->val.l);
1435 M_AND(s1, REG_ITMP2, d);
1437 store_reg_to_var_int(iptr->dst, d);
1440 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1441 /* val.l = constant */
1443 var_to_reg_int(s1, src, REG_ITMP1);
1444 d = reg_of_var(iptr->dst, REG_ITMP3);
1446 M_MOV(s1, REG_ITMP1);
1449 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1450 M_AND_IMM(s1, iptr->val.l, d);
1452 M_LSUB(REG_ZERO, s1, d);
1453 M_AND_IMM(d, iptr->val.l, d);
1455 else if (iptr->val.l == 0xffffL) {
1458 M_LSUB(REG_ZERO, s1, d);
1461 else if (iptr->val.l == 0xffffffL) {
1462 M_ZAPNOT_IMM(s1, 0x07, d);
1464 M_LSUB(REG_ZERO, s1, d);
1465 M_ZAPNOT_IMM(d, 0x07, d);
1467 else if (iptr->val.l == 0xffffffffL) {
1470 M_LSUB(REG_ZERO, s1, d);
1473 else if (iptr->val.l == 0xffffffffffL) {
1474 M_ZAPNOT_IMM(s1, 0x1f, d);
1476 M_LSUB(REG_ZERO, s1, d);
1477 M_ZAPNOT_IMM(d, 0x1f, d);
1479 else if (iptr->val.l == 0xffffffffffffL) {
1480 M_ZAPNOT_IMM(s1, 0x3f, d);
1482 M_LSUB(REG_ZERO, s1, d);
1483 M_ZAPNOT_IMM(d, 0x3f, d);
1485 else if (iptr->val.l == 0xffffffffffffffL) {
1486 M_ZAPNOT_IMM(s1, 0x7f, d);
1488 M_LSUB(REG_ZERO, s1, d);
1489 M_ZAPNOT_IMM(d, 0x7f, d);
1492 LCONST(REG_ITMP2, iptr->val.l);
1493 M_AND(s1, REG_ITMP2, d);
1495 M_LSUB(REG_ZERO, s1, d);
1496 M_AND(d, REG_ITMP2, d);
1498 M_LSUB(REG_ZERO, d, d);
1499 store_reg_to_var_int(iptr->dst, d);
1502 case ICMD_LREM0X10001:/* ..., value ==> ..., value % 0x10001 */
1504 var_to_reg_int(s1, src, REG_ITMP1);
1505 d = reg_of_var(iptr->dst, REG_ITMP3);
1507 M_MOV(s1, REG_ITMP3);
1510 M_CZEXT(s1, REG_ITMP2);
1511 M_SRA_IMM(s1, 16, d);
1512 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1513 M_LSUB(REG_ITMP2, d, d);
1515 M_LADD(d, REG_ITMP1, d);
1516 M_LDA(REG_ITMP2, REG_ZERO, -1);
1517 M_SRL_IMM(REG_ITMP2, 33, REG_ITMP2);
1518 if (s1 == REG_ITMP1) {
1519 var_to_reg_int(s1, src, REG_ITMP1);
1521 M_CMPULT(s1, REG_ITMP2, REG_ITMP2);
1522 M_BNEZ(REG_ITMP2, 11);
1523 M_LDA(d, REG_ZERO, -257);
1524 M_ZAPNOT_IMM(d, 0xcd, d);
1525 M_LSUB(REG_ZERO, s1, REG_ITMP2);
1526 M_CMOVGE(s1, s1, REG_ITMP2);
1527 M_UMULH(REG_ITMP2, d, REG_ITMP2);
1528 M_SRL_IMM(REG_ITMP2, 16, REG_ITMP2);
1529 M_LSUB(REG_ZERO, REG_ITMP2, d);
1530 M_CMOVGE(s1, REG_ITMP2, d);
1531 M_SLL_IMM(d, 16, REG_ITMP2);
1532 M_LADD(d, REG_ITMP2, d);
1534 store_reg_to_var_int(iptr->dst, d);
1537 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1540 var_to_reg_int(s1, src->prev, REG_ITMP1);
1541 var_to_reg_int(s2, src, REG_ITMP2);
1542 d = reg_of_var(iptr->dst, REG_ITMP3);
1544 store_reg_to_var_int(iptr->dst, d);
1547 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1548 /* val.i = constant */
1550 var_to_reg_int(s1, src, REG_ITMP1);
1551 d = reg_of_var(iptr->dst, REG_ITMP3);
1552 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1553 M_OR_IMM(s1, iptr->val.i, d);
1556 ICONST(REG_ITMP2, iptr->val.i);
1557 M_OR(s1, REG_ITMP2, d);
1559 store_reg_to_var_int(iptr->dst, d);
1562 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1563 /* val.l = constant */
1565 var_to_reg_int(s1, src, REG_ITMP1);
1566 d = reg_of_var(iptr->dst, REG_ITMP3);
1567 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1568 M_OR_IMM(s1, iptr->val.l, d);
1571 LCONST(REG_ITMP2, iptr->val.l);
1572 M_OR(s1, REG_ITMP2, d);
1574 store_reg_to_var_int(iptr->dst, d);
1577 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1580 var_to_reg_int(s1, src->prev, REG_ITMP1);
1581 var_to_reg_int(s2, src, REG_ITMP2);
1582 d = reg_of_var(iptr->dst, REG_ITMP3);
1584 store_reg_to_var_int(iptr->dst, d);
1587 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1588 /* val.i = constant */
1590 var_to_reg_int(s1, src, REG_ITMP1);
1591 d = reg_of_var(iptr->dst, REG_ITMP3);
1592 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1593 M_XOR_IMM(s1, iptr->val.i, d);
1596 ICONST(REG_ITMP2, iptr->val.i);
1597 M_XOR(s1, REG_ITMP2, d);
1599 store_reg_to_var_int(iptr->dst, d);
1602 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1603 /* val.l = constant */
1605 var_to_reg_int(s1, src, REG_ITMP1);
1606 d = reg_of_var(iptr->dst, REG_ITMP3);
1607 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1608 M_XOR_IMM(s1, iptr->val.l, d);
1611 LCONST(REG_ITMP2, iptr->val.l);
1612 M_XOR(s1, REG_ITMP2, d);
1614 store_reg_to_var_int(iptr->dst, d);
1618 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1620 var_to_reg_int(s1, src->prev, REG_ITMP1);
1621 var_to_reg_int(s2, src, REG_ITMP2);
1622 d = reg_of_var(iptr->dst, REG_ITMP3);
1623 M_CMPLT(s1, s2, REG_ITMP3);
1624 M_CMPLT(s2, s1, REG_ITMP1);
1625 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1626 store_reg_to_var_int(iptr->dst, d);
1630 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1631 /* op1 = variable, val.i = constant */
1633 var = &(locals[iptr->op1][TYPE_INT]);
1634 if (var->flags & INMEMORY) {
1636 M_LLD(s1, REG_SP, 8 * var->regoff);
1640 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1641 M_IADD_IMM(s1, iptr->val.i, s1);
1643 else if ((iptr->val.i > -256) && (iptr->val.i < 0)) {
1644 M_ISUB_IMM(s1, (-iptr->val.i), s1);
1647 M_LDA (s1, s1, iptr->val.i);
1648 M_IADD(s1, REG_ZERO, s1);
1650 if (var->flags & INMEMORY)
1651 M_LST(s1, REG_SP, 8 * var->regoff);
1655 /* floating operations ************************************************/
1657 case ICMD_FNEG: /* ..., value ==> ..., - value */
1659 var_to_reg_flt(s1, src, REG_FTMP1);
1660 d = reg_of_var(iptr->dst, REG_FTMP3);
1662 store_reg_to_var_flt(iptr->dst, d);
1665 case ICMD_DNEG: /* ..., value ==> ..., - value */
1667 var_to_reg_flt(s1, src, REG_FTMP1);
1668 d = reg_of_var(iptr->dst, REG_FTMP3);
1670 store_reg_to_var_flt(iptr->dst, d);
1673 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1675 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1676 var_to_reg_flt(s2, src, REG_FTMP2);
1677 d = reg_of_var(iptr->dst, REG_FTMP3);
1682 if (d == s1 || d == s2) {
1683 M_FADDS(s1, s2, REG_FTMP3);
1685 M_FMOV(REG_FTMP3, d);
1692 store_reg_to_var_flt(iptr->dst, d);
1695 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1697 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1698 var_to_reg_flt(s2, src, REG_FTMP2);
1699 d = reg_of_var(iptr->dst, REG_FTMP3);
1704 if (d == s1 || d == s2) {
1705 M_DADDS(s1, s2, REG_FTMP3);
1707 M_FMOV(REG_FTMP3, d);
1714 store_reg_to_var_flt(iptr->dst, d);
1717 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1719 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1720 var_to_reg_flt(s2, src, REG_FTMP2);
1721 d = reg_of_var(iptr->dst, REG_FTMP3);
1726 if (d == s1 || d == s2) {
1727 M_FSUBS(s1, s2, REG_FTMP3);
1729 M_FMOV(REG_FTMP3, d);
1736 store_reg_to_var_flt(iptr->dst, d);
1739 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1741 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1742 var_to_reg_flt(s2, src, REG_FTMP2);
1743 d = reg_of_var(iptr->dst, REG_FTMP3);
1748 if (d == s1 || d == s2) {
1749 M_DSUBS(s1, s2, REG_FTMP3);
1751 M_FMOV(REG_FTMP3, d);
1758 store_reg_to_var_flt(iptr->dst, d);
1761 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1763 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1764 var_to_reg_flt(s2, src, REG_FTMP2);
1765 d = reg_of_var(iptr->dst, REG_FTMP3);
1770 if (d == s1 || d == s2) {
1771 M_FMULS(s1, s2, REG_FTMP3);
1773 M_FMOV(REG_FTMP3, d);
1780 store_reg_to_var_flt(iptr->dst, d);
1783 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1785 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1786 var_to_reg_flt(s2, src, REG_FTMP2);
1787 d = reg_of_var(iptr->dst, REG_FTMP3);
1792 if (d == s1 || d == s2) {
1793 M_DMULS(s1, s2, REG_FTMP3);
1795 M_FMOV(REG_FTMP3, d);
1802 store_reg_to_var_flt(iptr->dst, d);
1805 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1807 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1808 var_to_reg_flt(s2, src, REG_FTMP2);
1809 d = reg_of_var(iptr->dst, REG_FTMP3);
1814 if (d == s1 || d == s2) {
1815 M_FDIVS(s1, s2, REG_FTMP3);
1817 M_FMOV(REG_FTMP3, d);
1824 store_reg_to_var_flt(iptr->dst, d);
1827 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1829 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1830 var_to_reg_flt(s2, src, REG_FTMP2);
1831 d = reg_of_var(iptr->dst, REG_FTMP3);
1836 if (d == s1 || d == s2) {
1837 M_DDIVS(s1, s2, REG_FTMP3);
1839 M_FMOV(REG_FTMP3, d);
1846 store_reg_to_var_flt(iptr->dst, d);
1849 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1851 var_to_reg_int(s1, src, REG_ITMP1);
1852 d = reg_of_var(iptr->dst, REG_FTMP3);
1853 a = dseg_adddouble(0.0);
1854 M_LST (s1, REG_PV, a);
1855 M_DLD (d, REG_PV, a);
1857 store_reg_to_var_flt(iptr->dst, d);
1860 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1862 var_to_reg_int(s1, src, REG_ITMP1);
1863 d = reg_of_var(iptr->dst, REG_FTMP3);
1864 a = dseg_adddouble(0.0);
1865 M_LST (s1, REG_PV, a);
1866 M_DLD (d, REG_PV, a);
1868 store_reg_to_var_flt(iptr->dst, d);
1871 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1873 var_to_reg_flt(s1, src, REG_FTMP1);
1874 d = reg_of_var(iptr->dst, REG_ITMP3);
1875 a = dseg_adddouble(0.0);
1876 M_CVTDL_C(s1, REG_FTMP2);
1877 M_CVTLI(REG_FTMP2, REG_FTMP3);
1878 M_DST (REG_FTMP3, REG_PV, a);
1879 M_ILD (d, REG_PV, a);
1880 store_reg_to_var_int(iptr->dst, d);
1883 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1885 var_to_reg_flt(s1, src, REG_FTMP1);
1886 d = reg_of_var(iptr->dst, REG_ITMP3);
1887 a = dseg_adddouble(0.0);
1888 M_CVTDL_C(s1, REG_FTMP2);
1889 M_DST (REG_FTMP2, REG_PV, a);
1890 M_LLD (d, REG_PV, a);
1891 store_reg_to_var_int(iptr->dst, d);
1894 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1896 var_to_reg_flt(s1, src, REG_FTMP1);
1897 d = reg_of_var(iptr->dst, REG_FTMP3);
1900 store_reg_to_var_flt(iptr->dst, d);
1903 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1905 var_to_reg_flt(s1, src, REG_FTMP1);
1906 d = reg_of_var(iptr->dst, REG_FTMP3);
1914 store_reg_to_var_flt(iptr->dst, d);
1917 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1919 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1920 var_to_reg_flt(s2, src, REG_FTMP2);
1921 d = reg_of_var(iptr->dst, REG_ITMP3);
1923 M_LSUB_IMM(REG_ZERO, 1, d);
1924 M_FCMPEQ(s1, s2, REG_FTMP3);
1925 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1927 M_FCMPLT(s2, s1, REG_FTMP3);
1928 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1929 M_LADD_IMM(REG_ZERO, 1, d);
1932 M_LSUB_IMM(REG_ZERO, 1, d);
1933 M_FCMPEQS(s1, s2, REG_FTMP3);
1935 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1937 M_FCMPLTS(s2, s1, REG_FTMP3);
1939 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1940 M_LADD_IMM(REG_ZERO, 1, d);
1942 store_reg_to_var_int(iptr->dst, d);
1945 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1947 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1948 var_to_reg_flt(s2, src, REG_FTMP2);
1949 d = reg_of_var(iptr->dst, REG_ITMP3);
1951 M_LADD_IMM(REG_ZERO, 1, d);
1952 M_FCMPEQ(s1, s2, REG_FTMP3);
1953 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1955 M_FCMPLT(s1, s2, REG_FTMP3);
1956 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1957 M_LSUB_IMM(REG_ZERO, 1, d);
1960 M_LADD_IMM(REG_ZERO, 1, d);
1961 M_FCMPEQS(s1, s2, REG_FTMP3);
1963 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1965 M_FCMPLTS(s1, s2, REG_FTMP3);
1967 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1968 M_LSUB_IMM(REG_ZERO, 1, d);
1970 store_reg_to_var_int(iptr->dst, d);
1974 /* memory operations **************************************************/
1976 /* #define gen_bound_check \
1978 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1979 M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
1980 M_BEQZ(REG_ITMP3, 0);\
1981 codegen_addxboundrefs(mcodeptr);\
1985 #define gen_bound_check \
1986 if (checkbounds) { \
1987 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1988 M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
1989 M_BEQZ(REG_ITMP3, 0);\
1990 codegen_addxboundrefs(mcodeptr, s2); \
1993 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1995 var_to_reg_int(s1, src, REG_ITMP1);
1996 d = reg_of_var(iptr->dst, REG_ITMP3);
1997 gen_nullptr_check(s1);
1998 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1999 store_reg_to_var_int(iptr->dst, d);
2002 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2004 var_to_reg_int(s1, src->prev, REG_ITMP1);
2005 var_to_reg_int(s2, src, REG_ITMP2);
2006 d = reg_of_var(iptr->dst, REG_ITMP3);
2007 if (iptr->op1 == 0) {
2008 gen_nullptr_check(s1);
2011 M_SAADDQ(s2, s1, REG_ITMP1);
2012 M_ALD( d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2013 store_reg_to_var_int(iptr->dst, d);
2016 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2018 var_to_reg_int(s1, src->prev, REG_ITMP1);
2019 var_to_reg_int(s2, src, REG_ITMP2);
2020 d = reg_of_var(iptr->dst, REG_ITMP3);
2021 if (iptr->op1 == 0) {
2022 gen_nullptr_check(s1);
2025 M_S8ADDQ(s2, s1, REG_ITMP1);
2026 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
2027 store_reg_to_var_int(iptr->dst, d);
2030 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2032 var_to_reg_int(s1, src->prev, REG_ITMP1);
2033 var_to_reg_int(s2, src, REG_ITMP2);
2034 d = reg_of_var(iptr->dst, REG_ITMP3);
2035 if (iptr->op1 == 0) {
2036 gen_nullptr_check(s1);
2040 M_S4ADDQ(s2, s1, REG_ITMP1);
2041 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
2042 store_reg_to_var_int(iptr->dst, d);
2045 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2047 var_to_reg_int(s1, src->prev, REG_ITMP1);
2048 var_to_reg_int(s2, src, REG_ITMP2);
2049 d = reg_of_var(iptr->dst, REG_FTMP3);
2050 if (iptr->op1 == 0) {
2051 gen_nullptr_check(s1);
2054 M_S4ADDQ(s2, s1, REG_ITMP1);
2055 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2056 store_reg_to_var_flt(iptr->dst, d);
2059 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2061 var_to_reg_int(s1, src->prev, REG_ITMP1);
2062 var_to_reg_int(s2, src, REG_ITMP2);
2063 d = reg_of_var(iptr->dst, REG_FTMP3);
2064 if (iptr->op1 == 0) {
2065 gen_nullptr_check(s1);
2068 M_S8ADDQ(s2, s1, REG_ITMP1);
2069 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2070 store_reg_to_var_flt(iptr->dst, d);
2073 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2075 var_to_reg_int(s1, src->prev, REG_ITMP1);
2076 var_to_reg_int(s2, src, REG_ITMP2);
2077 d = reg_of_var(iptr->dst, REG_ITMP3);
2078 if (iptr->op1 == 0) {
2079 gen_nullptr_check(s1);
2082 if (has_ext_instr_set) {
2083 M_LADD(s2, s1, REG_ITMP1);
2084 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2085 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2088 M_LADD (s2, s1, REG_ITMP1);
2089 M_LADD (s2, REG_ITMP1, REG_ITMP1);
2090 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
2091 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
2092 M_EXTWL(REG_ITMP2, REG_ITMP1, d);
2094 store_reg_to_var_int(iptr->dst, d);
2097 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2099 var_to_reg_int(s1, src->prev, REG_ITMP1);
2100 var_to_reg_int(s2, src, REG_ITMP2);
2101 d = reg_of_var(iptr->dst, REG_ITMP3);
2102 if (iptr->op1 == 0) {
2103 gen_nullptr_check(s1);
2106 if (has_ext_instr_set) {
2107 M_LADD(s2, s1, REG_ITMP1);
2108 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2109 M_SLDU( d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
2113 M_LADD(s2, s1, REG_ITMP1);
2114 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2115 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2116 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0])+2);
2117 M_EXTQH(REG_ITMP2, REG_ITMP1, d);
2118 M_SRA_IMM(d, 48, d);
2120 store_reg_to_var_int(iptr->dst, d);
2123 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2125 var_to_reg_int(s1, src->prev, REG_ITMP1);
2126 var_to_reg_int(s2, src, REG_ITMP2);
2127 d = reg_of_var(iptr->dst, REG_ITMP3);
2128 if (iptr->op1 == 0) {
2129 gen_nullptr_check(s1);
2132 if (has_ext_instr_set) {
2133 M_LADD (s2, s1, REG_ITMP1);
2134 M_BLDU (d, REG_ITMP1, OFFSET (java_bytearray, data[0]));
2138 M_LADD(s2, s1, REG_ITMP1);
2139 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2140 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0])+1);
2141 M_EXTQH(REG_ITMP2, REG_ITMP1, d);
2142 M_SRA_IMM(d, 56, d);
2144 store_reg_to_var_int(iptr->dst, d);
2148 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2150 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2151 var_to_reg_int(s2, src->prev, REG_ITMP2);
2152 if (iptr->op1 == 0) {
2153 gen_nullptr_check(s1);
2156 var_to_reg_int(s3, src, REG_ITMP3);
2157 M_SAADDQ(s2, s1, REG_ITMP1);
2158 M_AST (s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2161 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2163 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2164 var_to_reg_int(s2, src->prev, REG_ITMP2);
2165 if (iptr->op1 == 0) {
2166 gen_nullptr_check(s1);
2169 var_to_reg_int(s3, src, REG_ITMP3);
2170 M_S8ADDQ(s2, s1, REG_ITMP1);
2171 M_LST (s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
2174 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2176 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2177 var_to_reg_int(s2, src->prev, REG_ITMP2);
2178 if (iptr->op1 == 0) {
2179 gen_nullptr_check(s1);
2183 var_to_reg_int(s3, src, REG_ITMP3);
2184 M_S4ADDQ(s2, s1, REG_ITMP1);
2185 M_IST (s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
2188 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2190 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2191 var_to_reg_int(s2, src->prev, REG_ITMP2);
2192 if (iptr->op1 == 0) {
2193 gen_nullptr_check(s1);
2196 var_to_reg_flt(s3, src, REG_FTMP3);
2197 M_S4ADDQ(s2, s1, REG_ITMP1);
2198 M_FST (s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2201 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2203 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2204 var_to_reg_int(s2, src->prev, REG_ITMP2);
2205 if (iptr->op1 == 0) {
2206 gen_nullptr_check(s1);
2209 var_to_reg_flt(s3, src, REG_FTMP3);
2210 M_S8ADDQ(s2, s1, REG_ITMP1);
2211 M_DST (s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2214 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2216 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2217 var_to_reg_int(s2, src->prev, REG_ITMP2);
2218 if (iptr->op1 == 0) {
2219 gen_nullptr_check(s1);
2222 var_to_reg_int(s3, src, REG_ITMP3);
2223 if (has_ext_instr_set) {
2224 M_LADD(s2, s1, REG_ITMP1);
2225 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2226 M_SST (s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
2229 M_LADD (s2, s1, REG_ITMP1);
2230 M_LADD (s2, REG_ITMP1, REG_ITMP1);
2231 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
2232 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
2233 M_INSWL(s3, REG_ITMP1, REG_ITMP3);
2234 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2235 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2236 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2240 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2242 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2243 var_to_reg_int(s2, src->prev, REG_ITMP2);
2244 if (iptr->op1 == 0) {
2245 gen_nullptr_check(s1);
2248 var_to_reg_int(s3, src, REG_ITMP3);
2249 if (has_ext_instr_set) {
2250 M_LADD(s2, s1, REG_ITMP1);
2251 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2252 M_SST (s3, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2255 M_LADD (s2, s1, REG_ITMP1);
2256 M_LADD (s2, REG_ITMP1, REG_ITMP1);
2257 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2258 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2259 M_INSWL(s3, REG_ITMP1, REG_ITMP3);
2260 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2261 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2262 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2266 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2268 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2269 var_to_reg_int(s2, src->prev, REG_ITMP2);
2270 if (iptr->op1 == 0) {
2271 gen_nullptr_check(s1);
2274 var_to_reg_int(s3, src, REG_ITMP3);
2275 if (has_ext_instr_set) {
2276 M_LADD(s2, s1, REG_ITMP1);
2277 M_BST (s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2280 M_LADD (s2, s1, REG_ITMP1);
2281 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2282 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2283 M_INSBL(s3, REG_ITMP1, REG_ITMP3);
2284 M_MSKBL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2285 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2286 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2291 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2292 /* op1 = type, val.a = field address */
2294 /* if class isn't yet initialized, do it */
2295 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2296 /* call helper function which patches this code */
2297 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
2298 M_ALD(REG_ITMP1, REG_PV, a);
2299 a = dseg_addaddress(asm_check_clinit);
2300 M_ALD(REG_PV, REG_PV, a);
2301 M_JSR(REG_RA, REG_PV);
2304 s1 = (int) ((u1*) mcodeptr - mcodebase);
2306 M_LDA(REG_PV, REG_RA, -s1);
2310 s4 ml = -s1, mh = 0;
2311 while (ml < -32768) { ml += 65536; mh--; }
2312 M_LDA(REG_PV, REG_RA, ml);
2313 M_LDAH(REG_PV, REG_PV, mh);
2317 a = dseg_addaddress(&(((fieldinfo *)(iptr->val.a))->value));
2318 M_ALD(REG_ITMP1, REG_PV, a);
2319 switch (iptr->op1) {
2321 var_to_reg_int(s2, src, REG_ITMP2);
2322 M_IST(s2, REG_ITMP1, 0);
2325 var_to_reg_int(s2, src, REG_ITMP2);
2326 M_LST(s2, REG_ITMP1, 0);
2329 var_to_reg_int(s2, src, REG_ITMP2);
2330 M_AST(s2, REG_ITMP1, 0);
2333 var_to_reg_flt(s2, src, REG_FTMP2);
2334 M_FST(s2, REG_ITMP1, 0);
2337 var_to_reg_flt(s2, src, REG_FTMP2);
2338 M_DST(s2, REG_ITMP1, 0);
2340 default: panic ("internal error");
2344 case ICMD_GETSTATIC: /* ... ==> ..., value */
2345 /* op1 = type, val.a = field address */
2347 /* if class isn't yet initialized, do it */
2348 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2349 /* call helper function which patches this code */
2350 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
2351 M_ALD(REG_ITMP1, REG_PV, a);
2352 a = dseg_addaddress(asm_check_clinit);
2353 M_ALD(REG_PV, REG_PV, a);
2354 M_JSR(REG_RA, REG_PV);
2357 s1 = (int) ((u1*) mcodeptr - mcodebase);
2359 M_LDA(REG_PV, REG_RA, -s1);
2363 s4 ml = -s1, mh = 0;
2364 while (ml < -32768) { ml += 65536; mh--; }
2365 M_LDA(REG_PV, REG_RA, ml);
2366 M_LDAH(REG_PV, REG_PV, mh);
2370 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2371 M_ALD(REG_ITMP1, REG_PV, a);
2372 switch (iptr->op1) {
2374 d = reg_of_var(iptr->dst, REG_ITMP3);
2375 M_ILD(d, REG_ITMP1, 0);
2376 store_reg_to_var_int(iptr->dst, d);
2379 d = reg_of_var(iptr->dst, REG_ITMP3);
2380 M_LLD(d, REG_ITMP1, 0);
2381 store_reg_to_var_int(iptr->dst, d);
2384 d = reg_of_var(iptr->dst, REG_ITMP3);
2385 M_ALD(d, REG_ITMP1, 0);
2386 store_reg_to_var_int(iptr->dst, d);
2389 d = reg_of_var(iptr->dst, REG_FTMP1);
2390 M_FLD(d, REG_ITMP1, 0);
2391 store_reg_to_var_flt(iptr->dst, d);
2394 d = reg_of_var(iptr->dst, REG_FTMP1);
2395 M_DLD(d, REG_ITMP1, 0);
2396 store_reg_to_var_flt(iptr->dst, d);
2398 default: panic ("internal error");
2403 case ICMD_PUTFIELD: /* ..., value ==> ... */
2404 /* op1 = type, val.i = field offset */
2406 a = ((fieldinfo *)(iptr->val.a))->offset;
2407 switch (iptr->op1) {
2409 var_to_reg_int(s1, src->prev, REG_ITMP1);
2410 var_to_reg_int(s2, src, REG_ITMP2);
2411 gen_nullptr_check(s1);
2415 var_to_reg_int(s1, src->prev, REG_ITMP1);
2416 var_to_reg_int(s2, src, REG_ITMP2);
2417 gen_nullptr_check(s1);
2421 var_to_reg_int(s1, src->prev, REG_ITMP1);
2422 var_to_reg_int(s2, src, REG_ITMP2);
2423 gen_nullptr_check(s1);
2427 var_to_reg_int(s1, src->prev, REG_ITMP1);
2428 var_to_reg_flt(s2, src, REG_FTMP2);
2429 gen_nullptr_check(s1);
2433 var_to_reg_int(s1, src->prev, REG_ITMP1);
2434 var_to_reg_flt(s2, src, REG_FTMP2);
2435 gen_nullptr_check(s1);
2438 default: panic ("internal error");
2442 case ICMD_GETFIELD: /* ... ==> ..., value */
2443 /* op1 = type, val.i = field offset */
2445 a = ((fieldinfo *)(iptr->val.a))->offset;
2446 switch (iptr->op1) {
2448 var_to_reg_int(s1, src, REG_ITMP1);
2449 d = reg_of_var(iptr->dst, REG_ITMP3);
2450 gen_nullptr_check(s1);
2452 store_reg_to_var_int(iptr->dst, d);
2455 var_to_reg_int(s1, src, REG_ITMP1);
2456 d = reg_of_var(iptr->dst, REG_ITMP3);
2457 gen_nullptr_check(s1);
2459 store_reg_to_var_int(iptr->dst, d);
2462 var_to_reg_int(s1, src, REG_ITMP1);
2463 d = reg_of_var(iptr->dst, REG_ITMP3);
2464 gen_nullptr_check(s1);
2466 store_reg_to_var_int(iptr->dst, d);
2469 var_to_reg_int(s1, src, REG_ITMP1);
2470 d = reg_of_var(iptr->dst, REG_FTMP1);
2471 gen_nullptr_check(s1);
2473 store_reg_to_var_flt(iptr->dst, d);
2476 var_to_reg_int(s1, src, REG_ITMP1);
2477 d = reg_of_var(iptr->dst, REG_FTMP1);
2478 gen_nullptr_check(s1);
2480 store_reg_to_var_flt(iptr->dst, d);
2482 default: panic ("internal error");
2487 /* branch operations **************************************************/
2489 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2491 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2493 var_to_reg_int(s1, src, REG_ITMP1);
2494 M_INTMOVE(s1, REG_ITMP1_XPTR);
2495 a = dseg_addaddress(asm_handle_exception);
2496 M_ALD(REG_ITMP2, REG_PV, a);
2497 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2498 M_NOP; /* nop ensures that XPC is less than the end */
2499 /* of basic block */
2503 case ICMD_GOTO: /* ... ==> ... */
2504 /* op1 = target JavaVM pc */
2506 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2510 case ICMD_JSR: /* ... ==> ... */
2511 /* op1 = target JavaVM pc */
2513 M_BSR(REG_ITMP1, 0);
2514 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2517 case ICMD_RET: /* ... ==> ... */
2518 /* op1 = local variable */
2520 var = &(locals[iptr->op1][TYPE_ADR]);
2521 if (var->flags & INMEMORY) {
2522 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2523 M_RET(REG_ZERO, REG_ITMP1);
2526 M_RET(REG_ZERO, var->regoff);
2530 case ICMD_IFNULL: /* ..., value ==> ... */
2531 /* op1 = target JavaVM pc */
2533 var_to_reg_int(s1, src, REG_ITMP1);
2535 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2538 case ICMD_IFNONNULL: /* ..., value ==> ... */
2539 /* op1 = target JavaVM pc */
2541 var_to_reg_int(s1, src, REG_ITMP1);
2543 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2546 case ICMD_IFEQ: /* ..., value ==> ... */
2547 /* op1 = target JavaVM pc, val.i = constant */
2549 var_to_reg_int(s1, src, REG_ITMP1);
2550 if (iptr->val.i == 0) {
2554 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2555 M_CMPEQ_IMM(s1, iptr->val.i, REG_ITMP1);
2558 ICONST(REG_ITMP2, iptr->val.i);
2559 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2561 M_BNEZ(REG_ITMP1, 0);
2563 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2566 case ICMD_IFLT: /* ..., value ==> ... */
2567 /* op1 = target JavaVM pc, val.i = constant */
2569 var_to_reg_int(s1, src, REG_ITMP1);
2570 if (iptr->val.i == 0) {
2574 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2575 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2578 ICONST(REG_ITMP2, iptr->val.i);
2579 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2581 M_BNEZ(REG_ITMP1, 0);
2583 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2586 case ICMD_IFLE: /* ..., value ==> ... */
2587 /* op1 = target JavaVM pc, val.i = constant */
2589 var_to_reg_int(s1, src, REG_ITMP1);
2590 if (iptr->val.i == 0) {
2594 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2595 M_CMPLE_IMM(s1, iptr->val.i, REG_ITMP1);
2598 ICONST(REG_ITMP2, iptr->val.i);
2599 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2601 M_BNEZ(REG_ITMP1, 0);
2603 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2606 case ICMD_IFNE: /* ..., value ==> ... */
2607 /* op1 = target JavaVM pc, val.i = constant */
2609 var_to_reg_int(s1, src, REG_ITMP1);
2610 if (iptr->val.i == 0) {
2614 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2615 M_CMPEQ_IMM(s1, iptr->val.i, REG_ITMP1);
2618 ICONST(REG_ITMP2, iptr->val.i);
2619 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2621 M_BEQZ(REG_ITMP1, 0);
2623 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2626 case ICMD_IFGT: /* ..., value ==> ... */
2627 /* op1 = target JavaVM pc, val.i = constant */
2629 var_to_reg_int(s1, src, REG_ITMP1);
2630 if (iptr->val.i == 0) {
2634 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2635 M_CMPLE_IMM(s1, iptr->val.i, REG_ITMP1);
2638 ICONST(REG_ITMP2, iptr->val.i);
2639 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2641 M_BEQZ(REG_ITMP1, 0);
2643 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2646 case ICMD_IFGE: /* ..., value ==> ... */
2647 /* op1 = target JavaVM pc, val.i = constant */
2649 var_to_reg_int(s1, src, REG_ITMP1);
2650 if (iptr->val.i == 0) {
2654 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2655 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2658 ICONST(REG_ITMP2, iptr->val.i);
2659 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2661 M_BEQZ(REG_ITMP1, 0);
2663 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2666 case ICMD_IF_LEQ: /* ..., value ==> ... */
2667 /* op1 = target JavaVM pc, val.l = constant */
2669 var_to_reg_int(s1, src, REG_ITMP1);
2670 if (iptr->val.l == 0) {
2674 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2675 M_CMPEQ_IMM(s1, iptr->val.l, REG_ITMP1);
2678 LCONST(REG_ITMP2, iptr->val.l);
2679 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2681 M_BNEZ(REG_ITMP1, 0);
2683 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2686 case ICMD_IF_LLT: /* ..., value ==> ... */
2687 /* op1 = target JavaVM pc, val.l = constant */
2689 var_to_reg_int(s1, src, REG_ITMP1);
2690 if (iptr->val.l == 0) {
2694 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2695 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2698 LCONST(REG_ITMP2, iptr->val.l);
2699 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2701 M_BNEZ(REG_ITMP1, 0);
2703 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2706 case ICMD_IF_LLE: /* ..., value ==> ... */
2707 /* op1 = target JavaVM pc, val.l = constant */
2709 var_to_reg_int(s1, src, REG_ITMP1);
2710 if (iptr->val.l == 0) {
2714 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2715 M_CMPLE_IMM(s1, iptr->val.l, REG_ITMP1);
2718 LCONST(REG_ITMP2, iptr->val.l);
2719 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2721 M_BNEZ(REG_ITMP1, 0);
2723 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2726 case ICMD_IF_LNE: /* ..., value ==> ... */
2727 /* op1 = target JavaVM pc, val.l = constant */
2729 var_to_reg_int(s1, src, REG_ITMP1);
2730 if (iptr->val.l == 0) {
2734 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2735 M_CMPEQ_IMM(s1, iptr->val.l, REG_ITMP1);
2738 LCONST(REG_ITMP2, iptr->val.l);
2739 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2741 M_BEQZ(REG_ITMP1, 0);
2743 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2746 case ICMD_IF_LGT: /* ..., value ==> ... */
2747 /* op1 = target JavaVM pc, val.l = constant */
2749 var_to_reg_int(s1, src, REG_ITMP1);
2750 if (iptr->val.l == 0) {
2754 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2755 M_CMPLE_IMM(s1, iptr->val.l, REG_ITMP1);
2758 LCONST(REG_ITMP2, iptr->val.l);
2759 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2761 M_BEQZ(REG_ITMP1, 0);
2763 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2766 case ICMD_IF_LGE: /* ..., value ==> ... */
2767 /* op1 = target JavaVM pc, val.l = constant */
2769 var_to_reg_int(s1, src, REG_ITMP1);
2770 if (iptr->val.l == 0) {
2774 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2775 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2778 LCONST(REG_ITMP2, iptr->val.l);
2779 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2781 M_BEQZ(REG_ITMP1, 0);
2783 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2786 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2787 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2788 case ICMD_IF_ACMPEQ:
2790 var_to_reg_int(s1, src->prev, REG_ITMP1);
2791 var_to_reg_int(s2, src, REG_ITMP2);
2792 M_CMPEQ(s1, s2, REG_ITMP1);
2793 M_BNEZ(REG_ITMP1, 0);
2794 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2797 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2798 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2799 case ICMD_IF_ACMPNE:
2801 var_to_reg_int(s1, src->prev, REG_ITMP1);
2802 var_to_reg_int(s2, src, REG_ITMP2);
2803 M_CMPEQ(s1, s2, REG_ITMP1);
2804 M_BEQZ(REG_ITMP1, 0);
2805 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2808 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2809 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2811 var_to_reg_int(s1, src->prev, REG_ITMP1);
2812 var_to_reg_int(s2, src, REG_ITMP2);
2813 M_CMPLT(s1, s2, REG_ITMP1);
2814 M_BNEZ(REG_ITMP1, 0);
2815 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2818 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2819 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2821 var_to_reg_int(s1, src->prev, REG_ITMP1);
2822 var_to_reg_int(s2, src, REG_ITMP2);
2823 M_CMPLE(s1, s2, REG_ITMP1);
2824 M_BEQZ(REG_ITMP1, 0);
2825 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2828 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2829 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2831 var_to_reg_int(s1, src->prev, REG_ITMP1);
2832 var_to_reg_int(s2, src, REG_ITMP2);
2833 M_CMPLE(s1, s2, REG_ITMP1);
2834 M_BNEZ(REG_ITMP1, 0);
2835 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2838 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2839 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2841 var_to_reg_int(s1, src->prev, REG_ITMP1);
2842 var_to_reg_int(s2, src, REG_ITMP2);
2843 M_CMPLT(s1, s2, REG_ITMP1);
2844 M_BEQZ(REG_ITMP1, 0);
2845 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2848 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2850 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2853 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2854 /* val.i = constant */
2856 var_to_reg_int(s1, src, REG_ITMP1);
2857 d = reg_of_var(iptr->dst, REG_ITMP3);
2859 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2860 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2861 M_CMPEQ(s1, REG_ZERO, d);
2862 store_reg_to_var_int(iptr->dst, d);
2865 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2866 M_CMPEQ(s1, REG_ZERO, d);
2868 store_reg_to_var_int(iptr->dst, d);
2872 M_MOV(s1, REG_ITMP1);
2875 ICONST(d, iptr[1].val.i);
2877 if ((s3 >= 0) && (s3 <= 255)) {
2878 M_CMOVEQ_IMM(s1, s3, d);
2881 ICONST(REG_ITMP2, s3);
2882 M_CMOVEQ(s1, REG_ITMP2, d);
2884 store_reg_to_var_int(iptr->dst, d);
2887 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2888 /* val.i = constant */
2890 var_to_reg_int(s1, src, REG_ITMP1);
2891 d = reg_of_var(iptr->dst, REG_ITMP3);
2893 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2894 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2895 M_CMPEQ(s1, REG_ZERO, d);
2896 store_reg_to_var_int(iptr->dst, d);
2899 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2900 M_CMPEQ(s1, REG_ZERO, d);
2902 store_reg_to_var_int(iptr->dst, d);
2906 M_MOV(s1, REG_ITMP1);
2909 ICONST(d, iptr[1].val.i);
2911 if ((s3 >= 0) && (s3 <= 255)) {
2912 M_CMOVNE_IMM(s1, s3, d);
2915 ICONST(REG_ITMP2, s3);
2916 M_CMOVNE(s1, REG_ITMP2, d);
2918 store_reg_to_var_int(iptr->dst, d);
2921 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2922 /* val.i = constant */
2924 var_to_reg_int(s1, src, REG_ITMP1);
2925 d = reg_of_var(iptr->dst, REG_ITMP3);
2927 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2928 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2929 M_CMPLT(s1, REG_ZERO, d);
2930 store_reg_to_var_int(iptr->dst, d);
2933 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2934 M_CMPLE(REG_ZERO, s1, d);
2935 store_reg_to_var_int(iptr->dst, d);
2939 M_MOV(s1, REG_ITMP1);
2942 ICONST(d, iptr[1].val.i);
2944 if ((s3 >= 0) && (s3 <= 255)) {
2945 M_CMOVLT_IMM(s1, s3, d);
2948 ICONST(REG_ITMP2, s3);
2949 M_CMOVLT(s1, REG_ITMP2, d);
2951 store_reg_to_var_int(iptr->dst, d);
2954 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2955 /* val.i = constant */
2957 var_to_reg_int(s1, src, REG_ITMP1);
2958 d = reg_of_var(iptr->dst, REG_ITMP3);
2960 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2961 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2962 M_CMPLE(REG_ZERO, s1, d);
2963 store_reg_to_var_int(iptr->dst, d);
2966 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2967 M_CMPLT(s1, REG_ZERO, d);
2968 store_reg_to_var_int(iptr->dst, d);
2972 M_MOV(s1, REG_ITMP1);
2975 ICONST(d, iptr[1].val.i);
2977 if ((s3 >= 0) && (s3 <= 255)) {
2978 M_CMOVGE_IMM(s1, s3, d);
2981 ICONST(REG_ITMP2, s3);
2982 M_CMOVGE(s1, REG_ITMP2, d);
2984 store_reg_to_var_int(iptr->dst, d);
2987 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2988 /* val.i = constant */
2990 var_to_reg_int(s1, src, REG_ITMP1);
2991 d = reg_of_var(iptr->dst, REG_ITMP3);
2993 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2994 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2995 M_CMPLT(REG_ZERO, s1, d);
2996 store_reg_to_var_int(iptr->dst, d);
2999 if ((s3 == 0) && (iptr[1].val.i == 1)) {
3000 M_CMPLE(s1, REG_ZERO, d);
3001 store_reg_to_var_int(iptr->dst, d);
3005 M_MOV(s1, REG_ITMP1);
3008 ICONST(d, iptr[1].val.i);
3010 if ((s3 >= 0) && (s3 <= 255)) {
3011 M_CMOVGT_IMM(s1, s3, d);
3014 ICONST(REG_ITMP2, s3);
3015 M_CMOVGT(s1, REG_ITMP2, d);
3017 store_reg_to_var_int(iptr->dst, d);
3020 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3021 /* val.i = constant */
3023 var_to_reg_int(s1, src, REG_ITMP1);
3024 d = reg_of_var(iptr->dst, REG_ITMP3);
3026 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
3027 if ((s3 == 1) && (iptr[1].val.i == 0)) {
3028 M_CMPLE(s1, REG_ZERO, d);
3029 store_reg_to_var_int(iptr->dst, d);
3032 if ((s3 == 0) && (iptr[1].val.i == 1)) {
3033 M_CMPLT(REG_ZERO, s1, d);
3034 store_reg_to_var_int(iptr->dst, d);
3038 M_MOV(s1, REG_ITMP1);
3041 ICONST(d, iptr[1].val.i);
3043 if ((s3 >= 0) && (s3 <= 255)) {
3044 M_CMOVLE_IMM(s1, s3, d);
3047 ICONST(REG_ITMP2, s3);
3048 M_CMOVLE(s1, REG_ITMP2, d);
3050 store_reg_to_var_int(iptr->dst, d);
3054 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3059 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3061 a = dseg_addaddress ((void*) (builtin_monitorexit));
3062 M_ALD(REG_PV, REG_PV, a);
3063 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
3064 M_JSR(REG_RA, REG_PV);
3065 disp = -(int)((u1*) mcodeptr - mcodebase);
3066 M_LDA(REG_PV, REG_RA, disp);
3069 var_to_reg_int(s1, src, REG_RESULT);
3070 M_INTMOVE(s1, REG_RESULT);
3071 goto nowperformreturn;
3073 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3077 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3079 a = dseg_addaddress ((void*) (builtin_monitorexit));
3080 M_ALD(REG_PV, REG_PV, a);
3081 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
3082 M_JSR(REG_RA, REG_PV);
3083 disp = -(int)((u1*) mcodeptr - mcodebase);
3084 M_LDA(REG_PV, REG_RA, disp);
3087 var_to_reg_flt(s1, src, REG_FRESULT);
3088 M_FLTMOVE(s1, REG_FRESULT);
3089 goto nowperformreturn;
3091 case ICMD_RETURN: /* ... ==> ... */
3094 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3096 a = dseg_addaddress ((void*) (builtin_monitorexit));
3097 M_ALD(REG_PV, REG_PV, a);
3098 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
3099 M_JSR(REG_RA, REG_PV);
3100 disp = -(int)((u1*) mcodeptr - mcodebase);
3101 M_LDA(REG_PV, REG_RA, disp);
3109 p = parentargs_base;
3111 /* restore return address */
3114 {p--; M_LLD (REG_RA, REG_SP, 8 * p);}
3116 /* restore saved registers */
3118 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
3119 {p--; M_LLD(savintregs[r], REG_SP, 8 * p);}
3120 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
3121 {p--; M_DLD(savfltregs[r], REG_SP, 8 * p);}
3123 /* deallocate stack */
3125 if (parentargs_base)
3126 {M_LDA(REG_SP, REG_SP, parentargs_base*8);}
3128 /* call trace function */
3131 M_LDA (REG_SP, REG_SP, -24);
3132 M_AST(REG_RA, REG_SP, 0);
3133 M_LST(REG_RESULT, REG_SP, 8);
3134 M_DST(REG_FRESULT, REG_SP,16);
3135 a = dseg_addaddress(method);
3136 M_ALD(argintregs[0], REG_PV, a);
3137 M_MOV(REG_RESULT, argintregs[1]);
3138 M_FLTMOVE(REG_FRESULT, argfltregs[2]);
3139 M_FLTMOVE(REG_FRESULT, argfltregs[3]);
3140 a = dseg_addaddress((void *) builtin_displaymethodstop);
3141 M_ALD(REG_PV, REG_PV, a);
3142 M_JSR (REG_RA, REG_PV);
3143 s1 = (int)((u1*) mcodeptr - mcodebase);
3144 if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
3147 while (ml<-32768) { ml+=65536; mh--; }
3148 M_LDA (REG_PV, REG_RA, ml );
3149 M_LDAH (REG_PV, REG_PV, mh );
3151 M_DLD(REG_FRESULT, REG_SP,16);
3152 M_LLD(REG_RESULT, REG_SP, 8);
3153 M_ALD(REG_RA, REG_SP, 0);
3154 M_LDA (REG_SP, REG_SP, 24);
3157 M_RET(REG_ZERO, REG_RA);
3163 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3168 tptr = (void **) iptr->target;
3170 s4ptr = iptr->val.a;
3171 l = s4ptr[1]; /* low */
3172 i = s4ptr[2]; /* high */
3174 var_to_reg_int(s1, src, REG_ITMP1);
3176 {M_INTMOVE(s1, REG_ITMP1);}
3177 else if (l <= 32768) {
3178 M_LDA(REG_ITMP1, s1, -l);
3181 ICONST(REG_ITMP2, l);
3182 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3189 M_CMPULE_IMM(REG_ITMP1, i - 1, REG_ITMP2);
3191 M_LDA(REG_ITMP2, REG_ZERO, i - 1);
3192 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3194 M_BEQZ(REG_ITMP2, 0);
3197 /* codegen_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr); */
3198 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3200 /* build jump table top down and use address of lowest entry */
3202 /* s4ptr += 3 + i; */
3206 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3207 dseg_addtarget((basicblock *) tptr[0]);
3212 /* length of dataseg after last dseg_addtarget is used by load */
3214 M_SAADDQ(REG_ITMP1, REG_PV, REG_ITMP2);
3215 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
3216 M_JMP(REG_ZERO, REG_ITMP2);
3221 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3223 s4 i, l, val, *s4ptr;
3226 tptr = (void **) iptr->target;
3228 s4ptr = iptr->val.a;
3229 l = s4ptr[0]; /* default */
3230 i = s4ptr[1]; /* count */
3232 MCODECHECK((i<<2)+8);
3233 var_to_reg_int(s1, src, REG_ITMP1);
3239 if ((val >= 0) && (val <= 255)) {
3240 M_CMPEQ_IMM(s1, val, REG_ITMP2);
3243 if ((val >= -32768) && (val <= 32767)) {
3244 M_LDA(REG_ITMP2, REG_ZERO, val);
3247 a = dseg_adds4 (val);
3248 M_ILD(REG_ITMP2, REG_PV, a);
3250 M_CMPEQ(s1, REG_ITMP2, REG_ITMP2);
3252 M_BNEZ(REG_ITMP2, 0);
3253 /* codegen_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr); */
3254 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3258 /* codegen_addreference(BlockPtrOfPC(l), mcodeptr); */
3260 tptr = (void **) iptr->target;
3261 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3268 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3269 /* op1 = return type, val.a = function pointer*/
3273 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3274 /* op1 = return type, val.a = function pointer*/
3278 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3279 /* op1 = return type, val.a = function pointer*/
3283 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3284 /* op1 = arg count, val.a = method pointer */
3286 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3287 /* op1 = arg count, val.a = method pointer */
3289 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3290 /* op1 = arg count, val.a = method pointer */
3292 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3293 /* op1 = arg count, val.a = method pointer */
3301 MCODECHECK((s3 << 1) + 64);
3303 /* copy arguments to registers or stack location */
3305 for (; --s3 >= 0; src = src->prev) {
3306 if (src->varkind == ARGVAR)
3308 if (IS_INT_LNG_TYPE(src->type)) {
3309 if (s3 < INT_ARG_CNT) {
3310 s1 = argintregs[s3];
3311 var_to_reg_int(d, src, s1);
3315 var_to_reg_int(d, src, REG_ITMP1);
3316 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3320 if (s3 < FLT_ARG_CNT) {
3321 s1 = argfltregs[s3];
3322 var_to_reg_flt(d, src, s1);
3326 var_to_reg_flt(d, src, REG_FTMP1);
3327 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3332 switch (iptr->opc) {
3336 a = dseg_addaddress ((void*) (m));
3338 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
3340 goto makeactualcall;
3342 case ICMD_INVOKESTATIC:
3343 case ICMD_INVOKESPECIAL:
3344 a = dseg_addaddress (m->stubroutine);
3346 M_ALD(REG_PV, REG_PV, a ); /* method pointer in r27 */
3349 goto makeactualcall;
3351 case ICMD_INVOKEVIRTUAL:
3353 gen_nullptr_check(argintregs[0]);
3354 M_ALD(REG_METHODPTR, argintregs[0],
3355 OFFSET(java_objectheader, vftbl));
3356 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
3357 sizeof(methodptr) * m->vftblindex);
3360 goto makeactualcall;
3362 case ICMD_INVOKEINTERFACE:
3365 gen_nullptr_check(argintregs[0]);
3366 M_ALD(REG_METHODPTR, argintregs[0],
3367 OFFSET(java_objectheader, vftbl));
3368 M_ALD(REG_METHODPTR, REG_METHODPTR,
3369 OFFSET(vftbl, interfacetable[0]) -
3370 sizeof(methodptr*) * ci->index);
3371 M_ALD(REG_PV, REG_METHODPTR,
3372 sizeof(methodptr) * (m - ci->methods));
3375 goto makeactualcall;
3379 error ("Unkown ICMD-Command: %d", iptr->opc);
3384 M_JSR (REG_RA, REG_PV);
3388 s1 = (int)((u1*) mcodeptr - mcodebase);
3389 if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
3392 while (ml<-32768) { ml+=65536; mh--; }
3393 M_LDA (REG_PV, REG_RA, ml );
3394 M_LDAH (REG_PV, REG_PV, mh );
3397 /* d contains return type */
3399 if (d != TYPE_VOID) {
3400 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3401 s1 = reg_of_var(iptr->dst, REG_RESULT);
3402 M_INTMOVE(REG_RESULT, s1);
3403 store_reg_to_var_int(iptr->dst, s1);
3406 s1 = reg_of_var(iptr->dst, REG_FRESULT);
3407 M_FLTMOVE(REG_FRESULT, s1);
3408 store_reg_to_var_flt(iptr->dst, s1);
3415 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3417 /* op1: 0 == array, 1 == class */
3418 /* val.a: (classinfo*) superclass */
3420 /* superclass is an interface:
3422 * return (sub != NULL) &&
3423 * (sub->vftbl->interfacetablelength > super->index) &&
3424 * (sub->vftbl->interfacetable[-super->index] != NULL);
3426 * superclass is a class:
3428 * return ((sub != NULL) && (0
3429 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3430 * super->vftbl->diffvall));
3434 classinfo *super = (classinfo*) iptr->val.a;
3436 var_to_reg_int(s1, src, REG_ITMP1);
3437 d = reg_of_var(iptr->dst, REG_ITMP3);
3439 M_MOV(s1, REG_ITMP1);
3443 if (iptr->op1) { /* class/interface */
3444 if (super->flags & ACC_INTERFACE) { /* interface */
3446 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3447 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3448 M_LDA(REG_ITMP2, REG_ITMP2, - super->index);
3449 M_BLEZ(REG_ITMP2, 2);
3450 M_ALD(REG_ITMP1, REG_ITMP1,
3451 OFFSET(vftbl, interfacetable[0]) -
3452 super->index * sizeof(methodptr*));
3453 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3457 s2 = super->vftbl->diffval;
3458 M_BEQZ(s1, 4 + (s2 > 255));
3459 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3460 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3461 M_LDA(REG_ITMP1, REG_ITMP1, - super->vftbl->baseval);
3463 M_CMPULE_IMM(REG_ITMP1, s2, d);
3465 M_LDA(REG_ITMP2, REG_ZERO, s2);
3466 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3470 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3471 a = dseg_addaddress ((void*) super->vftbl);
3472 M_ALD(REG_ITMP2, REG_PV, a);
3473 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3474 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3475 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3476 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3477 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3481 panic ("internal error: no inlined array instanceof");
3483 store_reg_to_var_int(iptr->dst, d);
3486 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3488 /* op1: 0 == array, 1 == class */
3489 /* val.a: (classinfo*) superclass */
3491 /* superclass is an interface:
3493 * OK if ((sub == NULL) ||
3494 * (sub->vftbl->interfacetablelength > super->index) &&
3495 * (sub->vftbl->interfacetable[-super->index] != NULL));
3497 * superclass is a class:
3499 * OK if ((sub == NULL) || (0
3500 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3501 * super->vftbl->diffvall));
3505 classinfo *super = (classinfo*) iptr->val.a;
3507 d = reg_of_var(iptr->dst, REG_ITMP3);
3508 var_to_reg_int(s1, src, d);
3509 if (iptr->op1) { /* class/interface */
3510 if (super->flags & ACC_INTERFACE) { /* interface */
3512 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3513 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3514 M_LDA(REG_ITMP2, REG_ITMP2, - super->index);
3515 M_BLEZ(REG_ITMP2, 0);
3516 codegen_addxcastrefs(mcodeptr);
3517 M_ALD(REG_ITMP2, REG_ITMP1,
3518 OFFSET(vftbl, interfacetable[0]) -
3519 super->index * sizeof(methodptr*));
3520 M_BEQZ(REG_ITMP2, 0);
3521 codegen_addxcastrefs(mcodeptr);
3525 s2 = super->vftbl->diffval;
3526 M_BEQZ(s1, 4 + (s2 != 0) + (s2 > 255));
3527 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3528 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3529 M_LDA(REG_ITMP1, REG_ITMP1, - super->vftbl->baseval);
3531 M_BNEZ(REG_ITMP1, 0);
3533 else if (s2 <= 255) {
3534 M_CMPULE_IMM(REG_ITMP1, s2, REG_ITMP2);
3535 M_BEQZ(REG_ITMP2, 0);
3538 M_LDA(REG_ITMP2, REG_ZERO, s2);
3539 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3540 M_BEQZ(REG_ITMP2, 0);
3543 M_BEQZ(s1, 8 + (d == REG_ITMP3));
3544 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3545 a = dseg_addaddress ((void*) super->vftbl);
3546 M_ALD(REG_ITMP2, REG_PV, a);
3547 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3548 if (d != REG_ITMP3) {
3549 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3550 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3551 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3554 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, baseval));
3555 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3556 M_ALD(REG_ITMP2, REG_PV, a);
3557 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3559 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3560 M_BEQZ(REG_ITMP2, 0);
3561 codegen_addxcastrefs(mcodeptr);
3565 panic ("internal error: no inlined array checkcast");
3568 store_reg_to_var_int(iptr->dst, d);
3571 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3573 var_to_reg_int(s1, src, REG_ITMP1);
3575 codegen_addxcheckarefs(mcodeptr);
3578 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3579 /* op1 = dimension, val.a = array descriptor */
3581 /* check for negative sizes and copy sizes to stack if necessary */
3583 MCODECHECK((iptr->op1 << 1) + 64);
3585 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3586 var_to_reg_int(s2, src, REG_ITMP1);
3588 codegen_addxcheckarefs(mcodeptr);
3590 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3592 if (src->varkind != ARGVAR) {
3593 M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
3597 /* a0 = dimension count */
3599 ICONST(argintregs[0], iptr->op1);
3601 /* a1 = arraydescriptor */
3603 a = dseg_addaddress(iptr->val.a);
3604 M_ALD(argintregs[1], REG_PV, a);
3606 /* a2 = pointer to dimensions = stack pointer */
3608 M_INTMOVE(REG_SP, argintregs[2]);
3610 a = dseg_addaddress((void*) (builtin_nmultianewarray));
3611 M_ALD(REG_PV, REG_PV, a);
3612 M_JSR(REG_RA, REG_PV);
3613 s1 = (int)((u1*) mcodeptr - mcodebase);
3615 M_LDA (REG_PV, REG_RA, -s1);
3617 s4 ml = -s1, mh = 0;
3618 while (ml < -32768) {ml += 65536; mh--;}
3619 M_LDA(REG_PV, REG_RA, ml);
3620 M_LDAH(REG_PV, REG_PV, mh);
3622 s1 = reg_of_var(iptr->dst, REG_RESULT);
3623 M_INTMOVE(REG_RESULT, s1);
3624 store_reg_to_var_int(iptr->dst, s1);
3628 default: error ("Unknown pseudo command: %d", iptr->opc);
3634 } /* for instruction */
3636 /* copy values to interface registers */
3638 src = bptr->outstack;
3639 len = bptr->outdepth;
3643 if ((src->varkind != STACKVAR)) {
3645 if (IS_FLT_DBL_TYPE(s2)) {
3646 var_to_reg_flt(s1, src, REG_FTMP1);
3647 if (!(interfaces[len][s2].flags & INMEMORY)) {
3648 M_FLTMOVE(s1,interfaces[len][s2].regoff);
3651 M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3655 var_to_reg_int(s1, src, REG_ITMP1);
3656 if (!(interfaces[len][s2].flags & INMEMORY)) {
3657 M_INTMOVE(s1,interfaces[len][s2].regoff);
3660 M_LST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3666 } /* if (bptr -> flags >= BBREACHED) */
3667 } /* for basic block */
3669 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3671 codegen_createlinenumbertable();
3674 /* generate bound check stubs */
3676 s4 *xcodeptr = NULL;
3678 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3679 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3680 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3681 xboundrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - (4 + 4));
3686 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3687 xboundrefs->branchpos, (u1*) mcodeptr - mcodebase);
3691 M_MOV(xboundrefs->reg, REG_ITMP1);
3692 M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos - 4);
3694 if (xcodeptr != NULL) {
3695 M_BR(xcodeptr - mcodeptr - 1);
3698 xcodeptr = mcodeptr;
3700 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3701 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3703 a = dseg_addaddress(string_java_lang_ArrayIndexOutOfBoundsException);
3704 M_ALD(argintregs[0], REG_PV, a);
3705 M_MOV(REG_ITMP1, argintregs[1]);
3707 a = dseg_addaddress(new_exception_int);
3708 M_ALD(REG_PV, REG_PV, a);
3709 M_JSR(REG_RA, REG_PV);
3712 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3713 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3715 s4 ml = -s1, mh = 0;
3716 while (ml < -32768) { ml += 65536; mh--; }
3717 M_LDA(REG_PV, REG_RA, ml);
3718 M_LDAH(REG_PV, REG_PV, mh);
3721 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3723 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3724 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3726 a = dseg_addaddress(asm_handle_exception);
3727 M_ALD(REG_ITMP3, REG_PV, a);
3729 M_JMP(REG_ZERO, REG_ITMP3);
3733 /* generate negative array size check stubs */
3737 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3738 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3739 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3740 xcheckarefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3744 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3745 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
3749 M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos - 4);
3751 if (xcodeptr != NULL) {
3752 M_BR(xcodeptr - mcodeptr - 1);
3755 xcodeptr = mcodeptr;
3757 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3758 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3760 a = dseg_addaddress(string_java_lang_NegativeArraySizeException);
3761 M_ALD(argintregs[0], REG_PV, a);
3763 a = dseg_addaddress(new_exception);
3764 M_ALD(REG_PV, REG_PV, a);
3765 M_JSR(REG_RA, REG_PV);
3768 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3769 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3771 s4 ml = -s1, mh = 0;
3772 while (ml < -32768) { ml += 65536; mh--; }
3773 M_LDA(REG_PV, REG_RA, ml);
3774 M_LDAH(REG_PV, REG_PV, mh);
3777 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3779 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3780 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3782 a = dseg_addaddress(asm_handle_exception);
3783 M_ALD(REG_ITMP3, REG_PV, a);
3785 M_JMP(REG_ZERO, REG_ITMP3);
3789 /* generate cast check stubs */
3793 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3794 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3795 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3796 xcastrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3800 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3801 xcastrefs->branchpos, (u1*) mcodeptr - mcodebase);
3805 M_LDA(REG_ITMP2_XPC, REG_PV, xcastrefs->branchpos - 4);
3807 if (xcodeptr != NULL) {
3808 M_BR(xcodeptr - mcodeptr - 1);
3811 xcodeptr = mcodeptr;
3813 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3814 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3816 a = dseg_addaddress(string_java_lang_ClassCastException);
3817 M_ALD(argintregs[0], REG_PV, a);
3819 a = dseg_addaddress(new_exception);
3820 M_ALD(REG_PV, REG_PV, a);
3821 M_JSR(REG_RA, REG_PV);
3824 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3825 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3827 s4 ml = -s1, mh = 0;
3828 while (ml < -32768) { ml += 65536; mh--; }
3829 M_LDA(REG_PV, REG_RA, ml);
3830 M_LDAH(REG_PV, REG_PV, mh);
3833 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3835 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3836 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3838 a = dseg_addaddress(asm_handle_exception);
3839 M_ALD(REG_ITMP3, REG_PV, a);
3841 M_JMP(REG_ZERO, REG_ITMP3);
3845 /* generate null pointer check stubs */
3849 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3850 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3851 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3852 xnullrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3856 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3857 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
3861 M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
3863 if (xcodeptr != NULL) {
3864 M_BR(xcodeptr - mcodeptr - 1);
3867 xcodeptr = mcodeptr;
3869 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3870 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3872 a = dseg_addaddress(string_java_lang_NullPointerException);
3873 M_ALD(argintregs[0], REG_PV, a);
3875 a = dseg_addaddress(new_exception);
3876 M_ALD(REG_PV, REG_PV, a);
3877 M_JSR(REG_RA, REG_PV);
3880 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3881 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3883 s4 ml = -s1, mh = 0;
3884 while (ml < -32768) { ml += 65536; mh--; }
3885 M_LDA(REG_PV, REG_RA, ml);
3886 M_LDAH(REG_PV, REG_PV, mh);
3889 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3891 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3892 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3894 a = dseg_addaddress(asm_handle_exception);
3895 M_ALD(REG_ITMP3, REG_PV, a);
3897 M_JMP(REG_ZERO, REG_ITMP3);
3902 codegen_finish((int)((u1*) mcodeptr - mcodebase));
3906 /* function createcompilerstub *************************************************
3908 creates a stub routine which calls the compiler
3910 *******************************************************************************/
3912 #define COMPSTUBSIZE 3
3914 u1 *createcompilerstub(methodinfo *m)
3916 u8 *s = CNEW(u8, COMPSTUBSIZE); /* memory to hold the stub */
3917 s4 *mcodeptr = (s4 *) s; /* code generation pointer */
3919 /* code for the stub */
3920 M_ALD(REG_PV, REG_PV, 16); /* load pointer to the compiler */
3921 M_JMP(0, REG_PV); /* jump to the compiler, return address
3922 in reg 0 is used as method pointer */
3923 s[1] = (u8) m; /* literals to be adressed */
3924 s[2] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3927 count_cstub_len += COMPSTUBSIZE * 8;
3934 /* function removecompilerstub *************************************************
3936 deletes a compilerstub from memory (simply by freeing it)
3938 *******************************************************************************/
3940 void removecompilerstub(u1 *stub)
3942 CFREE(stub, COMPSTUBSIZE * 8);
3946 /* function: createnativestub **************************************************
3948 creates a stub routine which calls a native method
3950 *******************************************************************************/
3952 #define NATIVESTUBSIZE 44
3953 #define NATIVEVERBOSESIZE 39 + 13
3954 #define NATIVESTUBOFFSET 8
3956 u1 *createnativestub(functionptr f, methodinfo *m)
3958 u8 *s; /* memory pointer to hold the stub */
3960 s4 *mcodeptr; /* code generation pointer */
3961 int stackframesize = 0; /* size of stackframe if needed */
3966 descriptor2types(m); /* set paramcount and paramtypes */
3968 stubsize = runverbose ? NATIVESTUBSIZE + NATIVEVERBOSESIZE : NATIVESTUBSIZE;
3969 s = CNEW(u8, stubsize); /* memory to hold the stub */
3970 cs = s + NATIVESTUBOFFSET;
3971 mcodeptr = (s4 *) (cs); /* code generation pointer */
3973 *(cs-1) = (u8) f; /* address of native method */
3974 *(cs-2) = (u8) (&_exceptionptr); /* address of exceptionptr */
3975 *(cs-3) = (u8) asm_handle_nat_exception; /* addr of asm exception handler */
3976 *(cs-4) = (u8) (&env); /* addr of jni_environement */
3977 *(cs-5) = (u8) builtin_trace_args;
3979 *(cs-7) = (u8) builtin_displaymethodstop;
3980 *(cs-8) = (u8) m->class;
3982 M_LDA(REG_SP, REG_SP, -8); /* build up stackframe */
3983 M_AST(REG_RA, REG_SP, 0); /* store return address */
3985 /* max. 39 instructions */
3989 M_LDA(REG_SP, REG_SP, -(14 * 8));
3990 M_AST(REG_RA, REG_SP, 1 * 8);
3992 /* save integer argument registers */
3993 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3994 M_LST(argintregs[p], REG_SP, (2 + p) * 8);
3997 /* save and copy float arguments into integer registers */
3998 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3999 t = m->paramtypes[p];
4001 if (IS_FLT_DBL_TYPE(t)) {
4002 if (IS_2_WORD_TYPE(t)) {
4003 M_DST(argfltregs[p], REG_SP, (8 + p) * 8);
4004 M_LLD(argintregs[p], REG_SP, (8 + p) * 8);
4007 M_FST(argfltregs[p], REG_SP, (8 + p) * 8);
4008 M_ILD(argintregs[p], REG_SP, (8 + p) * 8);
4012 M_DST(argfltregs[p], REG_SP, (8 + p) * 8);
4016 M_ALD(REG_ITMP1, REG_PV, -6 * 8);
4017 M_AST(REG_ITMP1, REG_SP, 0);
4018 M_ALD(REG_PV, REG_PV, -5 * 8);
4019 M_JSR(REG_RA, REG_PV);
4020 disp = -(int) (mcodeptr - (s4*) cs) * 4;
4021 M_LDA(REG_PV, REG_RA, disp);
4023 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
4024 M_LLD(argintregs[p], REG_SP, (2 + p) * 8);
4027 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
4028 t = m->paramtypes[p];
4030 if (IS_FLT_DBL_TYPE(t)) {
4031 if (IS_2_WORD_TYPE(t)) {
4032 M_DLD(argfltregs[p], REG_SP, (8 + p) * 8);
4035 M_FLD(argfltregs[p], REG_SP, (8 + p) * 8);
4039 M_DLD(argfltregs[p], REG_SP, (8 + p) * 8);
4043 M_ALD(REG_RA, REG_SP, 1 * 8);
4044 M_LDA(REG_SP, REG_SP, 14 * 8);
4047 /* save argument registers on stack -- if we have to */
4048 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
4050 int paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
4051 int stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
4053 stackframesize = stackparamcnt + paramshiftcnt;
4055 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
4057 /* copy stack arguments into new stack frame -- if any */
4058 for (i = 0; i < stackparamcnt; i++) {
4059 M_LLD(REG_ITMP1, REG_SP, (stackparamcnt + 1 + i) * 8);
4060 M_LST(REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
4063 if (m->flags & ACC_STATIC) {
4064 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4065 M_DST(argfltregs[5], REG_SP, 1 * 8);
4067 M_LST(argintregs[5], REG_SP, 1 * 8);
4070 if (IS_FLT_DBL_TYPE(m->paramtypes[4])) {
4071 M_DST(argfltregs[4], REG_SP, 0 * 8);
4073 M_LST(argintregs[4], REG_SP, 0 * 8);
4077 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4078 M_DST(argfltregs[5], REG_SP, 0 * 8);
4080 M_LST(argintregs[5], REG_SP, 0 * 8);
4085 if (m->flags & ACC_STATIC) {
4086 M_MOV(argintregs[3], argintregs[5]);
4087 M_MOV(argintregs[2], argintregs[4]);
4088 M_MOV(argintregs[1], argintregs[3]);
4089 M_MOV(argintregs[0], argintregs[2]);
4090 M_FMOV(argfltregs[3], argfltregs[5]);
4091 M_FMOV(argfltregs[2], argfltregs[4]);
4092 M_FMOV(argfltregs[1], argfltregs[3]);
4093 M_FMOV(argfltregs[0], argfltregs[2]);
4095 /* put class into second argument register */
4096 M_ALD(argintregs[1], REG_PV, -8 * 8);
4099 M_MOV(argintregs[4], argintregs[5]);
4100 M_MOV(argintregs[3], argintregs[4]);
4101 M_MOV(argintregs[2], argintregs[3]);
4102 M_MOV(argintregs[1], argintregs[2]);
4103 M_MOV(argintregs[0], argintregs[1]);
4104 M_FMOV(argfltregs[4], argfltregs[5]);
4105 M_FMOV(argfltregs[3], argfltregs[4]);
4106 M_FMOV(argfltregs[2], argfltregs[3]);
4107 M_FMOV(argfltregs[1], argfltregs[2]);
4108 M_FMOV(argfltregs[0], argfltregs[1]);
4111 /* put env into first argument register */
4112 M_ALD(argintregs[0], REG_PV, -4 * 8);
4114 M_ALD(REG_PV, REG_PV, -1 * 8); /* load adress of native method */
4115 M_JSR(REG_RA, REG_PV); /* call native method */
4116 disp = -(int) (mcodeptr - (s4*) cs) * 4;
4117 M_LDA(REG_PV, REG_RA, disp); /* recompute pv from ra */
4119 /* remove stackframe if there is one */
4120 if (stackframesize) {
4121 M_LDA(REG_SP, REG_SP, stackframesize * 8);
4124 /* 13 instructions */
4126 M_LDA(REG_SP, REG_SP, -(2 * 8));
4127 M_ALD(argintregs[0], REG_PV, -6 * 8); /* load method adress */
4128 M_LST(REG_RESULT, REG_SP, 0 * 8);
4129 M_DST(REG_FRESULT, REG_SP, 1 * 8);
4130 M_MOV(REG_RESULT, argintregs[1]);
4131 M_FMOV(REG_FRESULT, argfltregs[2]);
4132 M_FMOV(REG_FRESULT, argfltregs[3]);
4133 M_ALD(REG_PV, REG_PV, -7 * 8); /* builtin_displaymethodstop */
4134 M_JSR(REG_RA, REG_PV);
4135 disp = -(int) (mcodeptr - (s4*) cs) * 4;
4136 M_LDA(REG_PV, REG_RA, disp);
4137 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4138 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
4139 M_LDA(REG_SP, REG_SP, 2 * 8);
4142 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* get address of exceptionptr */
4143 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4144 M_BNEZ(REG_ITMP1, 3); /* if no exception then return */
4146 M_ALD(REG_RA, REG_SP, 0); /* load return address */
4147 M_LDA(REG_SP, REG_SP, 8); /* remove stackframe */
4148 M_RET(REG_ZERO, REG_RA); /* return to caller */
4150 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4152 M_ALD(REG_RA, REG_SP, 0); /* load return address */
4153 M_LDA(REG_SP, REG_SP, 8); /* remove stackframe */
4154 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4155 M_ALD(REG_ITMP3, REG_PV, -3 * 8); /* load asm exception handler address */
4156 M_JMP(REG_ZERO, REG_ITMP3); /* jump to asm exception handler */
4159 dolog_plain("stubsize: %d (for %d params)\n", (int) (mcodeptr - (s4*) s), m->paramcount);
4163 count_nstub_len += NATIVESTUBSIZE * 8;
4166 return (u1*) (s + NATIVESTUBOFFSET);
4170 /* function: removenativestub **************************************************
4172 removes a previously created native-stub from memory
4174 *******************************************************************************/
4176 void removenativestub(u1 *stub)
4178 CFREE((u8*) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 8);
4183 * These are local overrides for various environment variables in Emacs.
4184 * Please do not remove this and leave it at the end of the file, where
4185 * Emacs will automagically detect them.
4186 * ---------------------------------------------------------------------
4189 * indent-tabs-mode: t