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 948 2004-03-07 22:12:28Z twisti $
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;
407 savedregs_num = (isleafmethod) ? 0 : 1; /* space to save the RA */
409 /* space to save used callee saved registers */
411 savedregs_num += (savintregcnt - maxsavintreguse);
412 savedregs_num += (savfltregcnt - maxsavfltreguse);
414 parentargs_base = maxmemuse + savedregs_num;
416 #ifdef USE_THREADS /* space to save argument of monitor_enter */
418 if (checksync && (method->flags & ACC_SYNCHRONIZED))
423 /* create method header */
425 (void) dseg_addaddress(method); /* MethodPointer */
426 (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
430 /* IsSync contains the offset relative to the stack pointer for the
431 argument of monitor_exit used in the exception handler. Since the
432 offset could be zero and give a wrong meaning of the flag it is
436 if (checksync && (method->flags & ACC_SYNCHRONIZED))
437 (void) dseg_adds4((maxmemuse + 1) * 8); /* IsSync */
442 (void) dseg_adds4(0); /* IsSync */
444 (void) dseg_adds4(isleafmethod); /* IsLeaf */
445 (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
446 (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
447 (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
449 /* create exception table */
451 for (ex = extable; ex != NULL; ex = ex->down) {
454 if (ex->start != NULL)
455 printf("adding start - %d - ", ex->start->debug_nr);
457 printf("PANIC - start is NULL");
462 dseg_addtarget(ex->start);
466 printf("adding end - %d - ", ex->end->debug_nr);
468 printf("PANIC - end is NULL");
473 dseg_addtarget(ex->end);
476 if (ex->handler != NULL)
477 printf("adding handler - %d\n", ex->handler->debug_nr);
479 printf("PANIC - handler is NULL");
484 dseg_addtarget(ex->handler);
486 (void) dseg_addaddress(ex->catchtype);
489 /* initialize mcode variables */
491 mcodeptr = (s4*) mcodebase;
492 mcodeend = (s4*) (mcodebase + mcodesize);
493 MCODECHECK(128 + mparamcount);
495 /* create stack frame (if necessary) */
498 {M_LDA (REG_SP, REG_SP, -parentargs_base * 8);}
500 /* save return address and used callee saved registers */
504 {p--; M_AST (REG_RA, REG_SP, 8*p);}
505 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
506 {p--; M_LST (savintregs[r], REG_SP, 8 * p);}
507 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
508 {p--; M_DST (savfltregs[r], REG_SP, 8 * p);}
510 /* save monitorenter argument */
513 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
514 if (method->flags & ACC_STATIC) {
515 p = dseg_addaddress (class);
516 M_ALD(REG_ITMP1, REG_PV, p);
517 M_AST(REG_ITMP1, REG_SP, 8 * maxmemuse);
520 M_AST (argintregs[0], REG_SP, 8 * maxmemuse);
525 /* copy argument registers to stack and call trace function with pointer
526 to arguments on stack.
531 M_LDA(REG_SP, REG_SP, -(14 * 8));
532 M_AST(REG_RA, REG_SP, 1 * 8);
534 /* save integer argument registers */
535 for (p = 0; p < mparamcount && p < INT_ARG_CNT; p++) {
536 M_LST(argintregs[p], REG_SP, (2 + p) * 8);
539 /* save and copy float arguments into integer registers */
540 for (p = 0; p < mparamcount && p < FLT_ARG_CNT; p++) {
543 if (IS_FLT_DBL_TYPE(t)) {
544 if (IS_2_WORD_TYPE(t)) {
545 M_DST(argfltregs[p], REG_SP, (8 + p) * 8);
547 M_FST(argfltregs[p], REG_SP, (8 + p) * 8);
550 M_LLD(argintregs[p], REG_SP, (8 + p) * 8);
553 M_DST(argfltregs[p], REG_SP, (8 + p) * 8);
557 p = dseg_addaddress(method);
558 M_ALD(REG_ITMP1, REG_PV, p);
559 M_AST(REG_ITMP1, REG_SP, 0);
560 p = dseg_addaddress((void *) builtin_trace_args);
561 M_ALD(REG_PV, REG_PV, p);
562 M_JSR(REG_RA, REG_PV);
563 disp = -(int)((u1 *) mcodeptr - mcodebase);
564 M_LDA(REG_PV, REG_RA, disp);
565 M_ALD(REG_RA, REG_SP, 1 * 8);
567 for (p = 0; p < mparamcount && p < INT_ARG_CNT; p++) {
568 M_LLD(argintregs[p], REG_SP, (2 + p) * 8);
571 for (p = 0; p < mparamcount && p < FLT_ARG_CNT; p++) {
574 if (IS_FLT_DBL_TYPE(t)) {
575 if (IS_2_WORD_TYPE(t)) {
576 M_DLD(argfltregs[p], REG_SP, (8 + p) * 8);
578 M_FLD(argfltregs[p], REG_SP, (8 + p) * 8);
581 M_DLD(argfltregs[p], REG_SP, (8 + p) * 8);
585 M_LDA (REG_SP, REG_SP, 14 * 8);
588 /* take arguments out of register or stack frame */
590 for (p = 0, l = 0; p < mparamcount; p++) {
592 var = &(locals[l][t]);
594 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
599 if (IS_INT_LNG_TYPE(t)) { /* integer args */
600 if (p < INT_ARG_CNT) { /* register arguments */
601 if (!(var->flags & INMEMORY)) /* reg arg -> register */
602 {M_INTMOVE (argintregs[p], r);}
603 else /* reg arg -> spilled */
604 M_LST (argintregs[p], REG_SP, 8 * r);
606 else { /* stack arguments */
607 pa = p - INT_ARG_CNT;
608 if (!(var->flags & INMEMORY)) /* stack arg -> register */
609 M_LLD (r, REG_SP, 8 * (parentargs_base + pa));
610 else { /* stack arg -> spilled */
611 M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
612 M_LST (REG_ITMP1, REG_SP, 8 * r);
616 else { /* floating args */
617 if (p < FLT_ARG_CNT) { /* register arguments */
618 if (!(var->flags & INMEMORY)) /* reg arg -> register */
619 {M_FLTMOVE (argfltregs[p], r);}
620 else /* reg arg -> spilled */
621 M_DST (argfltregs[p], REG_SP, 8 * r);
623 else { /* stack arguments */
624 pa = p - FLT_ARG_CNT;
625 if (!(var->flags & INMEMORY)) /* stack-arg -> register */
626 M_DLD (r, REG_SP, 8 * (parentargs_base + pa) );
627 else { /* stack-arg -> spilled */
628 M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
629 M_DST (REG_FTMP1, REG_SP, 8 * r);
635 /* call trace function */
638 if (runverbose && !isleafmethod) {
639 M_LDA (REG_SP, REG_SP, -8);
640 p = dseg_addaddress (method);
641 M_ALD(REG_ITMP1, REG_PV, p);
642 M_AST(REG_ITMP1, REG_SP, 0);
643 p = dseg_addaddress ((void*) (builtin_trace_args));
644 M_ALD(REG_PV, REG_PV, p);
645 M_JSR(REG_RA, REG_PV);
646 M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
647 M_LDA(REG_SP, REG_SP, 8);
651 /* call monitorenter function */
654 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
656 p = dseg_addaddress ((void*) (builtin_monitorenter));
657 M_ALD(REG_PV, REG_PV, p);
658 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
659 M_JSR(REG_RA, REG_PV);
660 disp = -(int)((u1*) mcodeptr - mcodebase);
661 M_LDA(REG_PV, REG_RA, disp);
666 /* end of header generation */
668 /* walk through all basic blocks */
669 for (bptr = block; bptr != NULL; bptr = bptr->next) {
671 bptr->mpc = (int)((u1*) mcodeptr - mcodebase);
673 if (bptr->flags >= BBREACHED) {
675 /* branch resolving */
679 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
680 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
681 brefs->branchpos, bptr->mpc);
685 /* copy interface registers to their destination */
690 while (src != NULL) {
692 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
693 d = reg_of_var(src, REG_ITMP1);
694 M_INTMOVE(REG_ITMP1, d);
695 store_reg_to_var_int(src, d);
698 d = reg_of_var(src, REG_IFTMP);
699 if ((src->varkind != STACKVAR)) {
701 if (IS_FLT_DBL_TYPE(s2)) {
702 if (!(interfaces[len][s2].flags & INMEMORY)) {
703 s1 = interfaces[len][s2].regoff;
707 M_DLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
709 store_reg_to_var_flt(src, d);
712 if (!(interfaces[len][s2].flags & INMEMORY)) {
713 s1 = interfaces[len][s2].regoff;
717 M_LLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
719 store_reg_to_var_int(src, d);
726 /* walk through all instructions */
730 for (iptr = bptr->iinstr;
732 src = iptr->dst, len--, iptr++) {
734 MCODECHECK(64); /* an instruction usually needs < 64 words */
737 case ICMD_NOP: /* ... ==> ... */
740 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
742 var_to_reg_int(s1, src, REG_ITMP1);
744 codegen_addxnullrefs(mcodeptr);
747 /* constant operations ************************************************/
749 #define ICONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LDA(r,REG_ZERO,c);} \
750 else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
752 #define LCONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LDA(r,REG_ZERO,c);} \
753 else{a=dseg_adds8(c);M_LLD(r,REG_PV,a);}
755 case ICMD_ICONST: /* ... ==> ..., constant */
756 /* op1 = 0, val.i = constant */
758 d = reg_of_var(iptr->dst, REG_ITMP1);
759 ICONST(d, iptr->val.i);
760 store_reg_to_var_int(iptr->dst, d);
763 case ICMD_LCONST: /* ... ==> ..., constant */
764 /* op1 = 0, val.l = constant */
766 d = reg_of_var(iptr->dst, REG_ITMP1);
767 LCONST(d, iptr->val.l);
768 store_reg_to_var_int(iptr->dst, d);
771 case ICMD_FCONST: /* ... ==> ..., constant */
772 /* op1 = 0, val.f = constant */
774 d = reg_of_var(iptr->dst, REG_FTMP1);
775 a = dseg_addfloat(iptr->val.f);
777 store_reg_to_var_flt(iptr->dst, d);
780 case ICMD_DCONST: /* ... ==> ..., constant */
781 /* op1 = 0, val.d = constant */
783 d = reg_of_var(iptr->dst, REG_FTMP1);
784 a = dseg_adddouble(iptr->val.d);
786 store_reg_to_var_flt(iptr->dst, d);
789 case ICMD_ACONST: /* ... ==> ..., constant */
790 /* op1 = 0, val.a = constant */
792 d = reg_of_var(iptr->dst, REG_ITMP1);
794 a = dseg_addaddress (iptr->val.a);
798 M_INTMOVE(REG_ZERO, d);
800 store_reg_to_var_int(iptr->dst, d);
804 /* load/store operations **********************************************/
806 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
807 case ICMD_LLOAD: /* op1 = local variable */
810 d = reg_of_var(iptr->dst, REG_ITMP1);
811 if ((iptr->dst->varkind == LOCALVAR) &&
812 (iptr->dst->varnum == iptr->op1))
814 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
815 if (var->flags & INMEMORY)
816 M_LLD(d, REG_SP, 8 * var->regoff);
818 {M_INTMOVE(var->regoff,d);}
819 store_reg_to_var_int(iptr->dst, d);
822 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
823 case ICMD_DLOAD: /* op1 = local variable */
825 d = reg_of_var(iptr->dst, REG_FTMP1);
826 if ((iptr->dst->varkind == LOCALVAR) &&
827 (iptr->dst->varnum == iptr->op1))
829 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
830 if (var->flags & INMEMORY)
831 M_DLD(d, REG_SP, 8 * var->regoff);
833 {M_FLTMOVE(var->regoff,d);}
834 store_reg_to_var_flt(iptr->dst, d);
838 case ICMD_ISTORE: /* ..., value ==> ... */
839 case ICMD_LSTORE: /* op1 = local variable */
842 if ((src->varkind == LOCALVAR) &&
843 (src->varnum == iptr->op1))
845 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
846 if (var->flags & INMEMORY) {
847 var_to_reg_int(s1, src, REG_ITMP1);
848 M_LST(s1, REG_SP, 8 * var->regoff);
851 var_to_reg_int(s1, src, var->regoff);
852 M_INTMOVE(s1, var->regoff);
856 case ICMD_FSTORE: /* ..., value ==> ... */
857 case ICMD_DSTORE: /* op1 = local variable */
859 if ((src->varkind == LOCALVAR) &&
860 (src->varnum == iptr->op1))
862 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
863 if (var->flags & INMEMORY) {
864 var_to_reg_flt(s1, src, REG_FTMP1);
865 M_DST(s1, REG_SP, 8 * var->regoff);
868 var_to_reg_flt(s1, src, var->regoff);
869 M_FLTMOVE(s1, var->regoff);
874 /* pop/dup/swap operations ********************************************/
876 /* attention: double and longs are only one entry in CACAO ICMDs */
878 case ICMD_POP: /* ..., value ==> ... */
879 case ICMD_POP2: /* ..., value, value ==> ... */
882 #define M_COPY(from,to) \
883 d = reg_of_var(to, REG_IFTMP); \
884 if ((from->regoff != to->regoff) || \
885 ((from->flags ^ to->flags) & INMEMORY)) { \
886 if (IS_FLT_DBL_TYPE(from->type)) { \
887 var_to_reg_flt(s1, from, d); \
889 store_reg_to_var_flt(to, d); \
892 var_to_reg_int(s1, from, d); \
894 store_reg_to_var_int(to, d); \
898 case ICMD_DUP: /* ..., a ==> ..., a, a */
899 M_COPY(src, iptr->dst);
902 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
904 M_COPY(src, iptr->dst->prev->prev);
906 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
908 M_COPY(src, iptr->dst);
909 M_COPY(src->prev, iptr->dst->prev);
912 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
914 M_COPY(src->prev, iptr->dst->prev->prev->prev);
916 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
918 M_COPY(src, iptr->dst);
919 M_COPY(src->prev, iptr->dst->prev);
920 M_COPY(src->prev->prev, iptr->dst->prev->prev);
921 M_COPY(src, iptr->dst->prev->prev->prev);
924 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
926 M_COPY(src, iptr->dst);
927 M_COPY(src->prev, iptr->dst->prev);
928 M_COPY(src->prev->prev, iptr->dst->prev->prev);
929 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
930 M_COPY(src, iptr->dst->prev->prev->prev->prev);
931 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
934 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
936 M_COPY(src, iptr->dst->prev);
937 M_COPY(src->prev, iptr->dst);
941 /* integer operations *************************************************/
943 case ICMD_INEG: /* ..., value ==> ..., - value */
945 var_to_reg_int(s1, src, REG_ITMP1);
946 d = reg_of_var(iptr->dst, REG_ITMP3);
947 M_ISUB(REG_ZERO, s1, d);
948 store_reg_to_var_int(iptr->dst, d);
951 case ICMD_LNEG: /* ..., value ==> ..., - value */
953 var_to_reg_int(s1, src, REG_ITMP1);
954 d = reg_of_var(iptr->dst, REG_ITMP3);
955 M_LSUB(REG_ZERO, s1, d);
956 store_reg_to_var_int(iptr->dst, d);
959 case ICMD_I2L: /* ..., value ==> ..., value */
961 var_to_reg_int(s1, src, REG_ITMP1);
962 d = reg_of_var(iptr->dst, REG_ITMP3);
964 store_reg_to_var_int(iptr->dst, d);
967 case ICMD_L2I: /* ..., value ==> ..., value */
969 var_to_reg_int(s1, src, REG_ITMP1);
970 d = reg_of_var(iptr->dst, REG_ITMP3);
971 M_IADD(s1, REG_ZERO, d );
972 store_reg_to_var_int(iptr->dst, d);
975 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
977 var_to_reg_int(s1, src, REG_ITMP1);
978 d = reg_of_var(iptr->dst, REG_ITMP3);
979 if (has_ext_instr_set) {
983 M_SLL_IMM(s1, 56, d);
984 M_SRA_IMM( d, 56, d);
986 store_reg_to_var_int(iptr->dst, d);
989 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
991 var_to_reg_int(s1, src, REG_ITMP1);
992 d = reg_of_var(iptr->dst, REG_ITMP3);
994 store_reg_to_var_int(iptr->dst, d);
997 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
999 var_to_reg_int(s1, src, REG_ITMP1);
1000 d = reg_of_var(iptr->dst, REG_ITMP3);
1001 if (has_ext_instr_set) {
1005 M_SLL_IMM(s1, 48, d);
1006 M_SRA_IMM( d, 48, d);
1008 store_reg_to_var_int(iptr->dst, d);
1012 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1014 var_to_reg_int(s1, src->prev, REG_ITMP1);
1015 var_to_reg_int(s2, src, REG_ITMP2);
1016 d = reg_of_var(iptr->dst, REG_ITMP3);
1018 store_reg_to_var_int(iptr->dst, d);
1021 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1022 /* val.i = constant */
1024 var_to_reg_int(s1, src, REG_ITMP1);
1025 d = reg_of_var(iptr->dst, REG_ITMP3);
1026 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1027 M_IADD_IMM(s1, iptr->val.i, d);
1030 ICONST(REG_ITMP2, iptr->val.i);
1031 M_IADD(s1, REG_ITMP2, d);
1033 store_reg_to_var_int(iptr->dst, d);
1036 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1038 var_to_reg_int(s1, src->prev, REG_ITMP1);
1039 var_to_reg_int(s2, src, REG_ITMP2);
1040 d = reg_of_var(iptr->dst, REG_ITMP3);
1042 store_reg_to_var_int(iptr->dst, d);
1045 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1046 /* val.l = constant */
1048 var_to_reg_int(s1, src, REG_ITMP1);
1049 d = reg_of_var(iptr->dst, REG_ITMP3);
1050 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1051 M_LADD_IMM(s1, iptr->val.l, d);
1054 LCONST(REG_ITMP2, iptr->val.l);
1055 M_LADD(s1, REG_ITMP2, d);
1057 store_reg_to_var_int(iptr->dst, d);
1060 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1062 var_to_reg_int(s1, src->prev, REG_ITMP1);
1063 var_to_reg_int(s2, src, REG_ITMP2);
1064 d = reg_of_var(iptr->dst, REG_ITMP3);
1066 store_reg_to_var_int(iptr->dst, d);
1069 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1070 /* val.i = constant */
1072 var_to_reg_int(s1, src, REG_ITMP1);
1073 d = reg_of_var(iptr->dst, REG_ITMP3);
1074 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1075 M_ISUB_IMM(s1, iptr->val.i, d);
1078 ICONST(REG_ITMP2, iptr->val.i);
1079 M_ISUB(s1, REG_ITMP2, d);
1081 store_reg_to_var_int(iptr->dst, d);
1084 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1086 var_to_reg_int(s1, src->prev, REG_ITMP1);
1087 var_to_reg_int(s2, src, REG_ITMP2);
1088 d = reg_of_var(iptr->dst, REG_ITMP3);
1090 store_reg_to_var_int(iptr->dst, d);
1093 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1094 /* val.l = constant */
1096 var_to_reg_int(s1, src, REG_ITMP1);
1097 d = reg_of_var(iptr->dst, REG_ITMP3);
1098 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1099 M_LSUB_IMM(s1, iptr->val.l, d);
1102 LCONST(REG_ITMP2, iptr->val.l);
1103 M_LSUB(s1, REG_ITMP2, d);
1105 store_reg_to_var_int(iptr->dst, d);
1108 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1110 var_to_reg_int(s1, src->prev, REG_ITMP1);
1111 var_to_reg_int(s2, src, REG_ITMP2);
1112 d = reg_of_var(iptr->dst, REG_ITMP3);
1114 store_reg_to_var_int(iptr->dst, d);
1117 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1118 /* val.i = constant */
1120 var_to_reg_int(s1, src, REG_ITMP1);
1121 d = reg_of_var(iptr->dst, REG_ITMP3);
1122 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1123 M_IMUL_IMM(s1, iptr->val.i, d);
1126 ICONST(REG_ITMP2, iptr->val.i);
1127 M_IMUL(s1, REG_ITMP2, d);
1129 store_reg_to_var_int(iptr->dst, d);
1132 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1134 var_to_reg_int(s1, src->prev, REG_ITMP1);
1135 var_to_reg_int(s2, src, REG_ITMP2);
1136 d = reg_of_var(iptr->dst, REG_ITMP3);
1138 store_reg_to_var_int(iptr->dst, d);
1141 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1142 /* val.l = constant */
1144 var_to_reg_int(s1, src, REG_ITMP1);
1145 d = reg_of_var(iptr->dst, REG_ITMP3);
1146 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1147 M_LMUL_IMM(s1, iptr->val.l, d);
1150 LCONST(REG_ITMP2, iptr->val.l);
1151 M_LMUL(s1, REG_ITMP2, d);
1153 store_reg_to_var_int(iptr->dst, d);
1156 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1157 case ICMD_LDIVPOW2: /* val.i = constant */
1159 var_to_reg_int(s1, src, REG_ITMP1);
1160 d = reg_of_var(iptr->dst, REG_ITMP3);
1161 if (iptr->val.i <= 15) {
1162 M_LDA(REG_ITMP2, s1, (1 << iptr->val.i) -1);
1163 M_CMOVGE(s1, s1, REG_ITMP2);
1166 M_SRA_IMM(s1, 63, REG_ITMP2);
1167 M_SRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1168 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1170 M_SRA_IMM(REG_ITMP2, iptr->val.i, d);
1171 store_reg_to_var_int(iptr->dst, d);
1174 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1176 var_to_reg_int(s1, src->prev, REG_ITMP1);
1177 var_to_reg_int(s2, src, REG_ITMP2);
1178 d = reg_of_var(iptr->dst, REG_ITMP3);
1179 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1180 M_SLL(s1, REG_ITMP3, d);
1181 M_IADD(d, REG_ZERO, d);
1182 store_reg_to_var_int(iptr->dst, d);
1185 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1186 /* val.i = constant */
1188 var_to_reg_int(s1, src, REG_ITMP1);
1189 d = reg_of_var(iptr->dst, REG_ITMP3);
1190 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1191 M_IADD(d, REG_ZERO, d);
1192 store_reg_to_var_int(iptr->dst, d);
1195 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1197 var_to_reg_int(s1, src->prev, REG_ITMP1);
1198 var_to_reg_int(s2, src, REG_ITMP2);
1199 d = reg_of_var(iptr->dst, REG_ITMP3);
1200 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1201 M_SRA(s1, REG_ITMP3, d);
1202 store_reg_to_var_int(iptr->dst, d);
1205 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1206 /* val.i = constant */
1208 var_to_reg_int(s1, src, REG_ITMP1);
1209 d = reg_of_var(iptr->dst, REG_ITMP3);
1210 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1211 store_reg_to_var_int(iptr->dst, d);
1214 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1216 var_to_reg_int(s1, src->prev, REG_ITMP1);
1217 var_to_reg_int(s2, src, REG_ITMP2);
1218 d = reg_of_var(iptr->dst, REG_ITMP3);
1219 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1221 M_SRL(d, REG_ITMP2, d);
1222 M_IADD(d, REG_ZERO, d);
1223 store_reg_to_var_int(iptr->dst, d);
1226 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1227 /* val.i = constant */
1229 var_to_reg_int(s1, src, REG_ITMP1);
1230 d = reg_of_var(iptr->dst, REG_ITMP3);
1232 M_SRL_IMM(d, iptr->val.i & 0x1f, d);
1233 M_IADD(d, REG_ZERO, d);
1234 store_reg_to_var_int(iptr->dst, d);
1237 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1239 var_to_reg_int(s1, src->prev, REG_ITMP1);
1240 var_to_reg_int(s2, src, REG_ITMP2);
1241 d = reg_of_var(iptr->dst, REG_ITMP3);
1243 store_reg_to_var_int(iptr->dst, d);
1246 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1247 /* val.i = constant */
1249 var_to_reg_int(s1, src, REG_ITMP1);
1250 d = reg_of_var(iptr->dst, REG_ITMP3);
1251 M_SLL_IMM(s1, iptr->val.i & 0x3f, d);
1252 store_reg_to_var_int(iptr->dst, d);
1255 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1257 var_to_reg_int(s1, src->prev, REG_ITMP1);
1258 var_to_reg_int(s2, src, REG_ITMP2);
1259 d = reg_of_var(iptr->dst, REG_ITMP3);
1261 store_reg_to_var_int(iptr->dst, d);
1264 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1265 /* val.i = constant */
1267 var_to_reg_int(s1, src, REG_ITMP1);
1268 d = reg_of_var(iptr->dst, REG_ITMP3);
1269 M_SRA_IMM(s1, iptr->val.i & 0x3f, d);
1270 store_reg_to_var_int(iptr->dst, d);
1273 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1275 var_to_reg_int(s1, src->prev, REG_ITMP1);
1276 var_to_reg_int(s2, src, REG_ITMP2);
1277 d = reg_of_var(iptr->dst, REG_ITMP3);
1279 store_reg_to_var_int(iptr->dst, d);
1282 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1283 /* val.i = constant */
1285 var_to_reg_int(s1, src, REG_ITMP1);
1286 d = reg_of_var(iptr->dst, REG_ITMP3);
1287 M_SRL_IMM(s1, iptr->val.i & 0x3f, d);
1288 store_reg_to_var_int(iptr->dst, d);
1291 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1294 var_to_reg_int(s1, src->prev, REG_ITMP1);
1295 var_to_reg_int(s2, src, REG_ITMP2);
1296 d = reg_of_var(iptr->dst, REG_ITMP3);
1298 store_reg_to_var_int(iptr->dst, d);
1301 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1302 /* val.i = constant */
1304 var_to_reg_int(s1, src, REG_ITMP1);
1305 d = reg_of_var(iptr->dst, REG_ITMP3);
1306 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1307 M_AND_IMM(s1, iptr->val.i, d);
1309 else if (iptr->val.i == 0xffff) {
1312 else if (iptr->val.i == 0xffffff) {
1313 M_ZAPNOT_IMM(s1, 0x07, d);
1316 ICONST(REG_ITMP2, iptr->val.i);
1317 M_AND(s1, REG_ITMP2, d);
1319 store_reg_to_var_int(iptr->dst, d);
1322 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1323 /* val.i = constant */
1325 var_to_reg_int(s1, src, REG_ITMP1);
1326 d = reg_of_var(iptr->dst, REG_ITMP3);
1328 M_MOV(s1, REG_ITMP1);
1331 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1332 M_AND_IMM(s1, iptr->val.i, d);
1334 M_ISUB(REG_ZERO, s1, d);
1335 M_AND_IMM(d, iptr->val.i, d);
1337 else if (iptr->val.i == 0xffff) {
1340 M_ISUB(REG_ZERO, s1, d);
1343 else if (iptr->val.i == 0xffffff) {
1344 M_ZAPNOT_IMM(s1, 0x07, d);
1346 M_ISUB(REG_ZERO, s1, d);
1347 M_ZAPNOT_IMM(d, 0x07, d);
1350 ICONST(REG_ITMP2, iptr->val.i);
1351 M_AND(s1, REG_ITMP2, d);
1353 M_ISUB(REG_ZERO, s1, d);
1354 M_AND(d, REG_ITMP2, d);
1356 M_ISUB(REG_ZERO, d, d);
1357 store_reg_to_var_int(iptr->dst, d);
1360 case ICMD_IREM0X10001: /* ..., value ==> ..., value % 0x100001 */
1362 /* b = value & 0xffff;
1364 a = ((b - a) & 0xffff) + (b < a);
1366 var_to_reg_int(s1, src, REG_ITMP1);
1367 d = reg_of_var(iptr->dst, REG_ITMP3);
1369 M_MOV(s1, REG_ITMP3);
1373 M_CZEXT(s1, REG_ITMP2);
1374 M_SRA_IMM(s1, 16, d);
1375 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1376 M_ISUB(REG_ITMP2, d, d);
1378 M_IADD(d, REG_ITMP1, d);
1379 M_BR(11 + (s1 == REG_ITMP1));
1380 M_ISUB(REG_ZERO, s1, REG_ITMP1);
1381 M_CZEXT(REG_ITMP1, REG_ITMP2);
1382 M_SRA_IMM(REG_ITMP1, 16, d);
1383 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1384 M_ISUB(REG_ITMP2, d, d);
1386 M_IADD(d, REG_ITMP1, d);
1387 M_ISUB(REG_ZERO, d, d);
1388 if (s1 == REG_ITMP1) {
1389 var_to_reg_int(s1, src, REG_ITMP1);
1391 M_SLL_IMM(s1, 33, REG_ITMP2);
1392 M_CMPEQ(REG_ITMP2, REG_ZERO, REG_ITMP2);
1393 M_ISUB(d, REG_ITMP2, d);
1394 store_reg_to_var_int(iptr->dst, d);
1397 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1398 /* val.l = constant */
1400 var_to_reg_int(s1, src, REG_ITMP1);
1401 d = reg_of_var(iptr->dst, REG_ITMP3);
1402 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1403 M_AND_IMM(s1, iptr->val.l, d);
1405 else if (iptr->val.l == 0xffffL) {
1408 else if (iptr->val.l == 0xffffffL) {
1409 M_ZAPNOT_IMM(s1, 0x07, d);
1411 else if (iptr->val.l == 0xffffffffL) {
1414 else if (iptr->val.l == 0xffffffffffL) {
1415 M_ZAPNOT_IMM(s1, 0x1f, d);
1417 else if (iptr->val.l == 0xffffffffffffL) {
1418 M_ZAPNOT_IMM(s1, 0x3f, d);
1420 else if (iptr->val.l == 0xffffffffffffffL) {
1421 M_ZAPNOT_IMM(s1, 0x7f, d);
1424 LCONST(REG_ITMP2, iptr->val.l);
1425 M_AND(s1, REG_ITMP2, d);
1427 store_reg_to_var_int(iptr->dst, d);
1430 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1431 /* val.l = constant */
1433 var_to_reg_int(s1, src, REG_ITMP1);
1434 d = reg_of_var(iptr->dst, REG_ITMP3);
1436 M_MOV(s1, REG_ITMP1);
1439 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1440 M_AND_IMM(s1, iptr->val.l, d);
1442 M_LSUB(REG_ZERO, s1, d);
1443 M_AND_IMM(d, iptr->val.l, d);
1445 else if (iptr->val.l == 0xffffL) {
1448 M_LSUB(REG_ZERO, s1, d);
1451 else if (iptr->val.l == 0xffffffL) {
1452 M_ZAPNOT_IMM(s1, 0x07, d);
1454 M_LSUB(REG_ZERO, s1, d);
1455 M_ZAPNOT_IMM(d, 0x07, d);
1457 else if (iptr->val.l == 0xffffffffL) {
1460 M_LSUB(REG_ZERO, s1, d);
1463 else if (iptr->val.l == 0xffffffffffL) {
1464 M_ZAPNOT_IMM(s1, 0x1f, d);
1466 M_LSUB(REG_ZERO, s1, d);
1467 M_ZAPNOT_IMM(d, 0x1f, d);
1469 else if (iptr->val.l == 0xffffffffffffL) {
1470 M_ZAPNOT_IMM(s1, 0x3f, d);
1472 M_LSUB(REG_ZERO, s1, d);
1473 M_ZAPNOT_IMM(d, 0x3f, d);
1475 else if (iptr->val.l == 0xffffffffffffffL) {
1476 M_ZAPNOT_IMM(s1, 0x7f, d);
1478 M_LSUB(REG_ZERO, s1, d);
1479 M_ZAPNOT_IMM(d, 0x7f, d);
1482 LCONST(REG_ITMP2, iptr->val.l);
1483 M_AND(s1, REG_ITMP2, d);
1485 M_LSUB(REG_ZERO, s1, d);
1486 M_AND(d, REG_ITMP2, d);
1488 M_LSUB(REG_ZERO, d, d);
1489 store_reg_to_var_int(iptr->dst, d);
1492 case ICMD_LREM0X10001:/* ..., value ==> ..., value % 0x10001 */
1494 var_to_reg_int(s1, src, REG_ITMP1);
1495 d = reg_of_var(iptr->dst, REG_ITMP3);
1497 M_MOV(s1, REG_ITMP3);
1500 M_CZEXT(s1, REG_ITMP2);
1501 M_SRA_IMM(s1, 16, d);
1502 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1503 M_LSUB(REG_ITMP2, d, d);
1505 M_LADD(d, REG_ITMP1, d);
1506 M_LDA(REG_ITMP2, REG_ZERO, -1);
1507 M_SRL_IMM(REG_ITMP2, 33, REG_ITMP2);
1508 if (s1 == REG_ITMP1) {
1509 var_to_reg_int(s1, src, REG_ITMP1);
1511 M_CMPULT(s1, REG_ITMP2, REG_ITMP2);
1512 M_BNEZ(REG_ITMP2, 11);
1513 M_LDA(d, REG_ZERO, -257);
1514 M_ZAPNOT_IMM(d, 0xcd, d);
1515 M_LSUB(REG_ZERO, s1, REG_ITMP2);
1516 M_CMOVGE(s1, s1, REG_ITMP2);
1517 M_UMULH(REG_ITMP2, d, REG_ITMP2);
1518 M_SRL_IMM(REG_ITMP2, 16, REG_ITMP2);
1519 M_LSUB(REG_ZERO, REG_ITMP2, d);
1520 M_CMOVGE(s1, REG_ITMP2, d);
1521 M_SLL_IMM(d, 16, REG_ITMP2);
1522 M_LADD(d, REG_ITMP2, d);
1524 store_reg_to_var_int(iptr->dst, d);
1527 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1530 var_to_reg_int(s1, src->prev, REG_ITMP1);
1531 var_to_reg_int(s2, src, REG_ITMP2);
1532 d = reg_of_var(iptr->dst, REG_ITMP3);
1534 store_reg_to_var_int(iptr->dst, d);
1537 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1538 /* val.i = constant */
1540 var_to_reg_int(s1, src, REG_ITMP1);
1541 d = reg_of_var(iptr->dst, REG_ITMP3);
1542 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1543 M_OR_IMM(s1, iptr->val.i, d);
1546 ICONST(REG_ITMP2, iptr->val.i);
1547 M_OR(s1, REG_ITMP2, d);
1549 store_reg_to_var_int(iptr->dst, d);
1552 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1553 /* val.l = constant */
1555 var_to_reg_int(s1, src, REG_ITMP1);
1556 d = reg_of_var(iptr->dst, REG_ITMP3);
1557 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1558 M_OR_IMM(s1, iptr->val.l, d);
1561 LCONST(REG_ITMP2, iptr->val.l);
1562 M_OR(s1, REG_ITMP2, d);
1564 store_reg_to_var_int(iptr->dst, d);
1567 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1570 var_to_reg_int(s1, src->prev, REG_ITMP1);
1571 var_to_reg_int(s2, src, REG_ITMP2);
1572 d = reg_of_var(iptr->dst, REG_ITMP3);
1574 store_reg_to_var_int(iptr->dst, d);
1577 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1578 /* val.i = constant */
1580 var_to_reg_int(s1, src, REG_ITMP1);
1581 d = reg_of_var(iptr->dst, REG_ITMP3);
1582 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1583 M_XOR_IMM(s1, iptr->val.i, d);
1586 ICONST(REG_ITMP2, iptr->val.i);
1587 M_XOR(s1, REG_ITMP2, d);
1589 store_reg_to_var_int(iptr->dst, d);
1592 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1593 /* val.l = constant */
1595 var_to_reg_int(s1, src, REG_ITMP1);
1596 d = reg_of_var(iptr->dst, REG_ITMP3);
1597 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1598 M_XOR_IMM(s1, iptr->val.l, d);
1601 LCONST(REG_ITMP2, iptr->val.l);
1602 M_XOR(s1, REG_ITMP2, d);
1604 store_reg_to_var_int(iptr->dst, d);
1608 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1610 var_to_reg_int(s1, src->prev, REG_ITMP1);
1611 var_to_reg_int(s2, src, REG_ITMP2);
1612 d = reg_of_var(iptr->dst, REG_ITMP3);
1613 M_CMPLT(s1, s2, REG_ITMP3);
1614 M_CMPLT(s2, s1, REG_ITMP1);
1615 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1616 store_reg_to_var_int(iptr->dst, d);
1620 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1621 /* op1 = variable, val.i = constant */
1623 var = &(locals[iptr->op1][TYPE_INT]);
1624 if (var->flags & INMEMORY) {
1626 M_LLD(s1, REG_SP, 8 * var->regoff);
1630 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1631 M_IADD_IMM(s1, iptr->val.i, s1);
1633 else if ((iptr->val.i > -256) && (iptr->val.i < 0)) {
1634 M_ISUB_IMM(s1, (-iptr->val.i), s1);
1637 M_LDA (s1, s1, iptr->val.i);
1638 M_IADD(s1, REG_ZERO, s1);
1640 if (var->flags & INMEMORY)
1641 M_LST(s1, REG_SP, 8 * var->regoff);
1645 /* floating operations ************************************************/
1647 case ICMD_FNEG: /* ..., value ==> ..., - value */
1649 var_to_reg_flt(s1, src, REG_FTMP1);
1650 d = reg_of_var(iptr->dst, REG_FTMP3);
1652 store_reg_to_var_flt(iptr->dst, d);
1655 case ICMD_DNEG: /* ..., value ==> ..., - value */
1657 var_to_reg_flt(s1, src, REG_FTMP1);
1658 d = reg_of_var(iptr->dst, REG_FTMP3);
1660 store_reg_to_var_flt(iptr->dst, d);
1663 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1665 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1666 var_to_reg_flt(s2, src, REG_FTMP2);
1667 d = reg_of_var(iptr->dst, REG_FTMP3);
1672 if (d == s1 || d == s2) {
1673 M_FADDS(s1, s2, REG_FTMP3);
1675 M_FMOV(REG_FTMP3, d);
1682 store_reg_to_var_flt(iptr->dst, d);
1685 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1687 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1688 var_to_reg_flt(s2, src, REG_FTMP2);
1689 d = reg_of_var(iptr->dst, REG_FTMP3);
1694 if (d == s1 || d == s2) {
1695 M_DADDS(s1, s2, REG_FTMP3);
1697 M_FMOV(REG_FTMP3, d);
1704 store_reg_to_var_flt(iptr->dst, d);
1707 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1709 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1710 var_to_reg_flt(s2, src, REG_FTMP2);
1711 d = reg_of_var(iptr->dst, REG_FTMP3);
1716 if (d == s1 || d == s2) {
1717 M_FSUBS(s1, s2, REG_FTMP3);
1719 M_FMOV(REG_FTMP3, d);
1726 store_reg_to_var_flt(iptr->dst, d);
1729 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1731 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1732 var_to_reg_flt(s2, src, REG_FTMP2);
1733 d = reg_of_var(iptr->dst, REG_FTMP3);
1738 if (d == s1 || d == s2) {
1739 M_DSUBS(s1, s2, REG_FTMP3);
1741 M_FMOV(REG_FTMP3, d);
1748 store_reg_to_var_flt(iptr->dst, d);
1751 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1753 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1754 var_to_reg_flt(s2, src, REG_FTMP2);
1755 d = reg_of_var(iptr->dst, REG_FTMP3);
1760 if (d == s1 || d == s2) {
1761 M_FMULS(s1, s2, REG_FTMP3);
1763 M_FMOV(REG_FTMP3, d);
1770 store_reg_to_var_flt(iptr->dst, d);
1773 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1775 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1776 var_to_reg_flt(s2, src, REG_FTMP2);
1777 d = reg_of_var(iptr->dst, REG_FTMP3);
1782 if (d == s1 || d == s2) {
1783 M_DMULS(s1, s2, REG_FTMP3);
1785 M_FMOV(REG_FTMP3, d);
1792 store_reg_to_var_flt(iptr->dst, d);
1795 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1797 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1798 var_to_reg_flt(s2, src, REG_FTMP2);
1799 d = reg_of_var(iptr->dst, REG_FTMP3);
1804 if (d == s1 || d == s2) {
1805 M_FDIVS(s1, s2, REG_FTMP3);
1807 M_FMOV(REG_FTMP3, d);
1814 store_reg_to_var_flt(iptr->dst, d);
1817 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1819 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1820 var_to_reg_flt(s2, src, REG_FTMP2);
1821 d = reg_of_var(iptr->dst, REG_FTMP3);
1826 if (d == s1 || d == s2) {
1827 M_DDIVS(s1, s2, REG_FTMP3);
1829 M_FMOV(REG_FTMP3, d);
1836 store_reg_to_var_flt(iptr->dst, d);
1839 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1841 var_to_reg_int(s1, src, REG_ITMP1);
1842 d = reg_of_var(iptr->dst, REG_FTMP3);
1843 a = dseg_adddouble(0.0);
1844 M_LST (s1, REG_PV, a);
1845 M_DLD (d, REG_PV, a);
1847 store_reg_to_var_flt(iptr->dst, d);
1850 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1852 var_to_reg_int(s1, src, REG_ITMP1);
1853 d = reg_of_var(iptr->dst, REG_FTMP3);
1854 a = dseg_adddouble(0.0);
1855 M_LST (s1, REG_PV, a);
1856 M_DLD (d, REG_PV, a);
1858 store_reg_to_var_flt(iptr->dst, d);
1861 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1863 var_to_reg_flt(s1, src, REG_FTMP1);
1864 d = reg_of_var(iptr->dst, REG_ITMP3);
1865 a = dseg_adddouble(0.0);
1866 M_CVTDL_C(s1, REG_FTMP2);
1867 M_CVTLI(REG_FTMP2, REG_FTMP3);
1868 M_DST (REG_FTMP3, REG_PV, a);
1869 M_ILD (d, REG_PV, a);
1870 store_reg_to_var_int(iptr->dst, d);
1873 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1875 var_to_reg_flt(s1, src, REG_FTMP1);
1876 d = reg_of_var(iptr->dst, REG_ITMP3);
1877 a = dseg_adddouble(0.0);
1878 M_CVTDL_C(s1, REG_FTMP2);
1879 M_DST (REG_FTMP2, REG_PV, a);
1880 M_LLD (d, REG_PV, a);
1881 store_reg_to_var_int(iptr->dst, d);
1884 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1886 var_to_reg_flt(s1, src, REG_FTMP1);
1887 d = reg_of_var(iptr->dst, REG_FTMP3);
1890 store_reg_to_var_flt(iptr->dst, d);
1893 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1895 var_to_reg_flt(s1, src, REG_FTMP1);
1896 d = reg_of_var(iptr->dst, REG_FTMP3);
1904 store_reg_to_var_flt(iptr->dst, d);
1907 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1909 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1910 var_to_reg_flt(s2, src, REG_FTMP2);
1911 d = reg_of_var(iptr->dst, REG_ITMP3);
1913 M_LSUB_IMM(REG_ZERO, 1, d);
1914 M_FCMPEQ(s1, s2, REG_FTMP3);
1915 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1917 M_FCMPLT(s2, s1, REG_FTMP3);
1918 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1919 M_LADD_IMM(REG_ZERO, 1, d);
1922 M_LSUB_IMM(REG_ZERO, 1, d);
1923 M_FCMPEQS(s1, s2, REG_FTMP3);
1925 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1927 M_FCMPLTS(s2, s1, REG_FTMP3);
1929 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1930 M_LADD_IMM(REG_ZERO, 1, d);
1932 store_reg_to_var_int(iptr->dst, d);
1935 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1937 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1938 var_to_reg_flt(s2, src, REG_FTMP2);
1939 d = reg_of_var(iptr->dst, REG_ITMP3);
1941 M_LADD_IMM(REG_ZERO, 1, d);
1942 M_FCMPEQ(s1, s2, REG_FTMP3);
1943 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1945 M_FCMPLT(s1, s2, REG_FTMP3);
1946 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1947 M_LSUB_IMM(REG_ZERO, 1, d);
1950 M_LADD_IMM(REG_ZERO, 1, d);
1951 M_FCMPEQS(s1, s2, REG_FTMP3);
1953 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1955 M_FCMPLTS(s1, s2, REG_FTMP3);
1957 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1958 M_LSUB_IMM(REG_ZERO, 1, d);
1960 store_reg_to_var_int(iptr->dst, d);
1964 /* memory operations **************************************************/
1966 /* #define gen_bound_check \
1968 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1969 M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
1970 M_BEQZ(REG_ITMP3, 0);\
1971 codegen_addxboundrefs(mcodeptr);\
1975 #define gen_bound_check \
1976 if (checkbounds) { \
1977 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1978 M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
1979 M_BEQZ(REG_ITMP3, 0);\
1980 codegen_addxboundrefs(mcodeptr, s2); \
1983 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1985 var_to_reg_int(s1, src, REG_ITMP1);
1986 d = reg_of_var(iptr->dst, REG_ITMP3);
1987 gen_nullptr_check(s1);
1988 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1989 store_reg_to_var_int(iptr->dst, d);
1992 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1994 var_to_reg_int(s1, src->prev, REG_ITMP1);
1995 var_to_reg_int(s2, src, REG_ITMP2);
1996 d = reg_of_var(iptr->dst, REG_ITMP3);
1997 if (iptr->op1 == 0) {
1998 gen_nullptr_check(s1);
2001 M_SAADDQ(s2, s1, REG_ITMP1);
2002 M_ALD( d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2003 store_reg_to_var_int(iptr->dst, d);
2006 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2008 var_to_reg_int(s1, src->prev, REG_ITMP1);
2009 var_to_reg_int(s2, src, REG_ITMP2);
2010 d = reg_of_var(iptr->dst, REG_ITMP3);
2011 if (iptr->op1 == 0) {
2012 gen_nullptr_check(s1);
2015 M_S8ADDQ(s2, s1, REG_ITMP1);
2016 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
2017 store_reg_to_var_int(iptr->dst, d);
2020 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2022 var_to_reg_int(s1, src->prev, REG_ITMP1);
2023 var_to_reg_int(s2, src, REG_ITMP2);
2024 d = reg_of_var(iptr->dst, REG_ITMP3);
2025 if (iptr->op1 == 0) {
2026 gen_nullptr_check(s1);
2030 M_S4ADDQ(s2, s1, REG_ITMP1);
2031 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
2032 store_reg_to_var_int(iptr->dst, d);
2035 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2037 var_to_reg_int(s1, src->prev, REG_ITMP1);
2038 var_to_reg_int(s2, src, REG_ITMP2);
2039 d = reg_of_var(iptr->dst, REG_FTMP3);
2040 if (iptr->op1 == 0) {
2041 gen_nullptr_check(s1);
2044 M_S4ADDQ(s2, s1, REG_ITMP1);
2045 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2046 store_reg_to_var_flt(iptr->dst, d);
2049 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2051 var_to_reg_int(s1, src->prev, REG_ITMP1);
2052 var_to_reg_int(s2, src, REG_ITMP2);
2053 d = reg_of_var(iptr->dst, REG_FTMP3);
2054 if (iptr->op1 == 0) {
2055 gen_nullptr_check(s1);
2058 M_S8ADDQ(s2, s1, REG_ITMP1);
2059 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2060 store_reg_to_var_flt(iptr->dst, d);
2063 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2065 var_to_reg_int(s1, src->prev, REG_ITMP1);
2066 var_to_reg_int(s2, src, REG_ITMP2);
2067 d = reg_of_var(iptr->dst, REG_ITMP3);
2068 if (iptr->op1 == 0) {
2069 gen_nullptr_check(s1);
2072 if (has_ext_instr_set) {
2073 M_LADD(s2, s1, REG_ITMP1);
2074 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2075 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2078 M_LADD (s2, s1, REG_ITMP1);
2079 M_LADD (s2, REG_ITMP1, REG_ITMP1);
2080 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
2081 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
2082 M_EXTWL(REG_ITMP2, REG_ITMP1, d);
2084 store_reg_to_var_int(iptr->dst, d);
2087 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2089 var_to_reg_int(s1, src->prev, REG_ITMP1);
2090 var_to_reg_int(s2, src, REG_ITMP2);
2091 d = reg_of_var(iptr->dst, REG_ITMP3);
2092 if (iptr->op1 == 0) {
2093 gen_nullptr_check(s1);
2096 if (has_ext_instr_set) {
2097 M_LADD(s2, s1, REG_ITMP1);
2098 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2099 M_SLDU( d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
2103 M_LADD(s2, s1, REG_ITMP1);
2104 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2105 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2106 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0])+2);
2107 M_EXTQH(REG_ITMP2, REG_ITMP1, d);
2108 M_SRA_IMM(d, 48, d);
2110 store_reg_to_var_int(iptr->dst, d);
2113 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2115 var_to_reg_int(s1, src->prev, REG_ITMP1);
2116 var_to_reg_int(s2, src, REG_ITMP2);
2117 d = reg_of_var(iptr->dst, REG_ITMP3);
2118 if (iptr->op1 == 0) {
2119 gen_nullptr_check(s1);
2122 if (has_ext_instr_set) {
2123 M_LADD (s2, s1, REG_ITMP1);
2124 M_BLDU (d, REG_ITMP1, OFFSET (java_bytearray, data[0]));
2128 M_LADD(s2, s1, REG_ITMP1);
2129 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2130 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0])+1);
2131 M_EXTQH(REG_ITMP2, REG_ITMP1, d);
2132 M_SRA_IMM(d, 56, d);
2134 store_reg_to_var_int(iptr->dst, d);
2138 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2140 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2141 var_to_reg_int(s2, src->prev, REG_ITMP2);
2142 if (iptr->op1 == 0) {
2143 gen_nullptr_check(s1);
2146 var_to_reg_int(s3, src, REG_ITMP3);
2147 M_SAADDQ(s2, s1, REG_ITMP1);
2148 M_AST (s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2151 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2153 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2154 var_to_reg_int(s2, src->prev, REG_ITMP2);
2155 if (iptr->op1 == 0) {
2156 gen_nullptr_check(s1);
2159 var_to_reg_int(s3, src, REG_ITMP3);
2160 M_S8ADDQ(s2, s1, REG_ITMP1);
2161 M_LST (s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
2164 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2166 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2167 var_to_reg_int(s2, src->prev, REG_ITMP2);
2168 if (iptr->op1 == 0) {
2169 gen_nullptr_check(s1);
2173 var_to_reg_int(s3, src, REG_ITMP3);
2174 M_S4ADDQ(s2, s1, REG_ITMP1);
2175 M_IST (s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
2178 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2180 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2181 var_to_reg_int(s2, src->prev, REG_ITMP2);
2182 if (iptr->op1 == 0) {
2183 gen_nullptr_check(s1);
2186 var_to_reg_flt(s3, src, REG_FTMP3);
2187 M_S4ADDQ(s2, s1, REG_ITMP1);
2188 M_FST (s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2191 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2193 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2194 var_to_reg_int(s2, src->prev, REG_ITMP2);
2195 if (iptr->op1 == 0) {
2196 gen_nullptr_check(s1);
2199 var_to_reg_flt(s3, src, REG_FTMP3);
2200 M_S8ADDQ(s2, s1, REG_ITMP1);
2201 M_DST (s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2204 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2206 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2207 var_to_reg_int(s2, src->prev, REG_ITMP2);
2208 if (iptr->op1 == 0) {
2209 gen_nullptr_check(s1);
2212 var_to_reg_int(s3, src, REG_ITMP3);
2213 if (has_ext_instr_set) {
2214 M_LADD(s2, s1, REG_ITMP1);
2215 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2216 M_SST (s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
2219 M_LADD (s2, s1, REG_ITMP1);
2220 M_LADD (s2, REG_ITMP1, REG_ITMP1);
2221 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
2222 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
2223 M_INSWL(s3, REG_ITMP1, REG_ITMP3);
2224 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2225 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2226 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2230 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2232 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2233 var_to_reg_int(s2, src->prev, REG_ITMP2);
2234 if (iptr->op1 == 0) {
2235 gen_nullptr_check(s1);
2238 var_to_reg_int(s3, src, REG_ITMP3);
2239 if (has_ext_instr_set) {
2240 M_LADD(s2, s1, REG_ITMP1);
2241 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2242 M_SST (s3, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2245 M_LADD (s2, s1, REG_ITMP1);
2246 M_LADD (s2, REG_ITMP1, REG_ITMP1);
2247 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2248 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2249 M_INSWL(s3, REG_ITMP1, REG_ITMP3);
2250 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2251 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2252 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2256 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2258 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2259 var_to_reg_int(s2, src->prev, REG_ITMP2);
2260 if (iptr->op1 == 0) {
2261 gen_nullptr_check(s1);
2264 var_to_reg_int(s3, src, REG_ITMP3);
2265 if (has_ext_instr_set) {
2266 M_LADD(s2, s1, REG_ITMP1);
2267 M_BST (s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2270 M_LADD (s2, s1, REG_ITMP1);
2271 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2272 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2273 M_INSBL(s3, REG_ITMP1, REG_ITMP3);
2274 M_MSKBL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2275 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2);
2276 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2281 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2282 /* op1 = type, val.a = field address */
2284 /* if class isn't yet initialized, do it */
2285 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2286 /* call helper function which patches this code */
2287 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
2288 M_ALD(REG_ITMP1, REG_PV, a);
2289 a = dseg_addaddress(asm_check_clinit);
2290 M_ALD(REG_PV, REG_PV, a);
2291 M_JSR(REG_RA, REG_PV);
2294 s1 = (int) ((u1*) mcodeptr - mcodebase);
2296 M_LDA(REG_PV, REG_RA, -s1);
2300 s4 ml = -s1, mh = 0;
2301 while (ml < -32768) { ml += 65536; mh--; }
2302 M_LDA(REG_PV, REG_RA, ml);
2303 M_LDAH(REG_PV, REG_PV, mh);
2307 a = dseg_addaddress(&(((fieldinfo *)(iptr->val.a))->value));
2308 M_ALD(REG_ITMP1, REG_PV, a);
2309 switch (iptr->op1) {
2311 var_to_reg_int(s2, src, REG_ITMP2);
2312 M_IST(s2, REG_ITMP1, 0);
2315 var_to_reg_int(s2, src, REG_ITMP2);
2316 M_LST(s2, REG_ITMP1, 0);
2319 var_to_reg_int(s2, src, REG_ITMP2);
2320 M_AST(s2, REG_ITMP1, 0);
2323 var_to_reg_flt(s2, src, REG_FTMP2);
2324 M_FST(s2, REG_ITMP1, 0);
2327 var_to_reg_flt(s2, src, REG_FTMP2);
2328 M_DST(s2, REG_ITMP1, 0);
2330 default: panic ("internal error");
2334 case ICMD_GETSTATIC: /* ... ==> ..., value */
2335 /* op1 = type, val.a = field address */
2337 /* if class isn't yet initialized, do it */
2338 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2339 /* call helper function which patches this code */
2340 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
2341 M_ALD(REG_ITMP1, REG_PV, a);
2342 a = dseg_addaddress(asm_check_clinit);
2343 M_ALD(REG_PV, REG_PV, a);
2344 M_JSR(REG_RA, REG_PV);
2347 s1 = (int) ((u1*) mcodeptr - mcodebase);
2349 M_LDA(REG_PV, REG_RA, -s1);
2353 s4 ml = -s1, mh = 0;
2354 while (ml < -32768) { ml += 65536; mh--; }
2355 M_LDA(REG_PV, REG_RA, ml);
2356 M_LDAH(REG_PV, REG_PV, mh);
2360 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2361 M_ALD(REG_ITMP1, REG_PV, a);
2362 switch (iptr->op1) {
2364 d = reg_of_var(iptr->dst, REG_ITMP3);
2365 M_ILD(d, REG_ITMP1, 0);
2366 store_reg_to_var_int(iptr->dst, d);
2369 d = reg_of_var(iptr->dst, REG_ITMP3);
2370 M_LLD(d, REG_ITMP1, 0);
2371 store_reg_to_var_int(iptr->dst, d);
2374 d = reg_of_var(iptr->dst, REG_ITMP3);
2375 M_ALD(d, REG_ITMP1, 0);
2376 store_reg_to_var_int(iptr->dst, d);
2379 d = reg_of_var(iptr->dst, REG_FTMP1);
2380 M_FLD(d, REG_ITMP1, 0);
2381 store_reg_to_var_flt(iptr->dst, d);
2384 d = reg_of_var(iptr->dst, REG_FTMP1);
2385 M_DLD(d, REG_ITMP1, 0);
2386 store_reg_to_var_flt(iptr->dst, d);
2388 default: panic ("internal error");
2393 case ICMD_PUTFIELD: /* ..., value ==> ... */
2394 /* op1 = type, val.i = field offset */
2396 a = ((fieldinfo *)(iptr->val.a))->offset;
2397 switch (iptr->op1) {
2399 var_to_reg_int(s1, src->prev, REG_ITMP1);
2400 var_to_reg_int(s2, src, REG_ITMP2);
2401 gen_nullptr_check(s1);
2405 var_to_reg_int(s1, src->prev, REG_ITMP1);
2406 var_to_reg_int(s2, src, REG_ITMP2);
2407 gen_nullptr_check(s1);
2411 var_to_reg_int(s1, src->prev, REG_ITMP1);
2412 var_to_reg_int(s2, src, REG_ITMP2);
2413 gen_nullptr_check(s1);
2417 var_to_reg_int(s1, src->prev, REG_ITMP1);
2418 var_to_reg_flt(s2, src, REG_FTMP2);
2419 gen_nullptr_check(s1);
2423 var_to_reg_int(s1, src->prev, REG_ITMP1);
2424 var_to_reg_flt(s2, src, REG_FTMP2);
2425 gen_nullptr_check(s1);
2428 default: panic ("internal error");
2432 case ICMD_GETFIELD: /* ... ==> ..., value */
2433 /* op1 = type, val.i = field offset */
2435 a = ((fieldinfo *)(iptr->val.a))->offset;
2436 switch (iptr->op1) {
2438 var_to_reg_int(s1, src, REG_ITMP1);
2439 d = reg_of_var(iptr->dst, REG_ITMP3);
2440 gen_nullptr_check(s1);
2442 store_reg_to_var_int(iptr->dst, d);
2445 var_to_reg_int(s1, src, REG_ITMP1);
2446 d = reg_of_var(iptr->dst, REG_ITMP3);
2447 gen_nullptr_check(s1);
2449 store_reg_to_var_int(iptr->dst, d);
2452 var_to_reg_int(s1, src, REG_ITMP1);
2453 d = reg_of_var(iptr->dst, REG_ITMP3);
2454 gen_nullptr_check(s1);
2456 store_reg_to_var_int(iptr->dst, d);
2459 var_to_reg_int(s1, src, REG_ITMP1);
2460 d = reg_of_var(iptr->dst, REG_FTMP1);
2461 gen_nullptr_check(s1);
2463 store_reg_to_var_flt(iptr->dst, d);
2466 var_to_reg_int(s1, src, REG_ITMP1);
2467 d = reg_of_var(iptr->dst, REG_FTMP1);
2468 gen_nullptr_check(s1);
2470 store_reg_to_var_flt(iptr->dst, d);
2472 default: panic ("internal error");
2477 /* branch operations **************************************************/
2479 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2481 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2483 var_to_reg_int(s1, src, REG_ITMP1);
2484 M_INTMOVE(s1, REG_ITMP1_XPTR);
2485 a = dseg_addaddress(asm_handle_exception);
2486 M_ALD(REG_ITMP2, REG_PV, a);
2487 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2488 M_NOP; /* nop ensures that XPC is less than the end */
2489 /* of basic block */
2493 case ICMD_GOTO: /* ... ==> ... */
2494 /* op1 = target JavaVM pc */
2496 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2500 case ICMD_JSR: /* ... ==> ... */
2501 /* op1 = target JavaVM pc */
2503 M_BSR(REG_ITMP1, 0);
2504 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2507 case ICMD_RET: /* ... ==> ... */
2508 /* op1 = local variable */
2510 var = &(locals[iptr->op1][TYPE_ADR]);
2511 if (var->flags & INMEMORY) {
2512 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2513 M_RET(REG_ZERO, REG_ITMP1);
2516 M_RET(REG_ZERO, var->regoff);
2520 case ICMD_IFNULL: /* ..., value ==> ... */
2521 /* op1 = target JavaVM pc */
2523 var_to_reg_int(s1, src, REG_ITMP1);
2525 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2528 case ICMD_IFNONNULL: /* ..., value ==> ... */
2529 /* op1 = target JavaVM pc */
2531 var_to_reg_int(s1, src, REG_ITMP1);
2533 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2536 case ICMD_IFEQ: /* ..., value ==> ... */
2537 /* op1 = target JavaVM pc, val.i = constant */
2539 var_to_reg_int(s1, src, REG_ITMP1);
2540 if (iptr->val.i == 0) {
2544 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2545 M_CMPEQ_IMM(s1, iptr->val.i, REG_ITMP1);
2548 ICONST(REG_ITMP2, iptr->val.i);
2549 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2551 M_BNEZ(REG_ITMP1, 0);
2553 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2556 case ICMD_IFLT: /* ..., value ==> ... */
2557 /* op1 = target JavaVM pc, val.i = constant */
2559 var_to_reg_int(s1, src, REG_ITMP1);
2560 if (iptr->val.i == 0) {
2564 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2565 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2568 ICONST(REG_ITMP2, iptr->val.i);
2569 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2571 M_BNEZ(REG_ITMP1, 0);
2573 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2576 case ICMD_IFLE: /* ..., value ==> ... */
2577 /* op1 = target JavaVM pc, val.i = constant */
2579 var_to_reg_int(s1, src, REG_ITMP1);
2580 if (iptr->val.i == 0) {
2584 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2585 M_CMPLE_IMM(s1, iptr->val.i, REG_ITMP1);
2588 ICONST(REG_ITMP2, iptr->val.i);
2589 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2591 M_BNEZ(REG_ITMP1, 0);
2593 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2596 case ICMD_IFNE: /* ..., value ==> ... */
2597 /* op1 = target JavaVM pc, val.i = constant */
2599 var_to_reg_int(s1, src, REG_ITMP1);
2600 if (iptr->val.i == 0) {
2604 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2605 M_CMPEQ_IMM(s1, iptr->val.i, REG_ITMP1);
2608 ICONST(REG_ITMP2, iptr->val.i);
2609 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2611 M_BEQZ(REG_ITMP1, 0);
2613 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2616 case ICMD_IFGT: /* ..., value ==> ... */
2617 /* op1 = target JavaVM pc, val.i = constant */
2619 var_to_reg_int(s1, src, REG_ITMP1);
2620 if (iptr->val.i == 0) {
2624 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2625 M_CMPLE_IMM(s1, iptr->val.i, REG_ITMP1);
2628 ICONST(REG_ITMP2, iptr->val.i);
2629 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2631 M_BEQZ(REG_ITMP1, 0);
2633 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2636 case ICMD_IFGE: /* ..., value ==> ... */
2637 /* op1 = target JavaVM pc, val.i = constant */
2639 var_to_reg_int(s1, src, REG_ITMP1);
2640 if (iptr->val.i == 0) {
2644 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2645 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2648 ICONST(REG_ITMP2, iptr->val.i);
2649 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2651 M_BEQZ(REG_ITMP1, 0);
2653 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2656 case ICMD_IF_LEQ: /* ..., value ==> ... */
2657 /* op1 = target JavaVM pc, val.l = constant */
2659 var_to_reg_int(s1, src, REG_ITMP1);
2660 if (iptr->val.l == 0) {
2664 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2665 M_CMPEQ_IMM(s1, iptr->val.l, REG_ITMP1);
2668 LCONST(REG_ITMP2, iptr->val.l);
2669 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2671 M_BNEZ(REG_ITMP1, 0);
2673 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2676 case ICMD_IF_LLT: /* ..., value ==> ... */
2677 /* op1 = target JavaVM pc, val.l = constant */
2679 var_to_reg_int(s1, src, REG_ITMP1);
2680 if (iptr->val.l == 0) {
2684 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2685 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2688 LCONST(REG_ITMP2, iptr->val.l);
2689 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2691 M_BNEZ(REG_ITMP1, 0);
2693 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2696 case ICMD_IF_LLE: /* ..., value ==> ... */
2697 /* op1 = target JavaVM pc, val.l = constant */
2699 var_to_reg_int(s1, src, REG_ITMP1);
2700 if (iptr->val.l == 0) {
2704 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2705 M_CMPLE_IMM(s1, iptr->val.l, REG_ITMP1);
2708 LCONST(REG_ITMP2, iptr->val.l);
2709 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2711 M_BNEZ(REG_ITMP1, 0);
2713 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2716 case ICMD_IF_LNE: /* ..., value ==> ... */
2717 /* op1 = target JavaVM pc, val.l = constant */
2719 var_to_reg_int(s1, src, REG_ITMP1);
2720 if (iptr->val.l == 0) {
2724 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2725 M_CMPEQ_IMM(s1, iptr->val.l, REG_ITMP1);
2728 LCONST(REG_ITMP2, iptr->val.l);
2729 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2731 M_BEQZ(REG_ITMP1, 0);
2733 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2736 case ICMD_IF_LGT: /* ..., value ==> ... */
2737 /* op1 = target JavaVM pc, val.l = constant */
2739 var_to_reg_int(s1, src, REG_ITMP1);
2740 if (iptr->val.l == 0) {
2744 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2745 M_CMPLE_IMM(s1, iptr->val.l, REG_ITMP1);
2748 LCONST(REG_ITMP2, iptr->val.l);
2749 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2751 M_BEQZ(REG_ITMP1, 0);
2753 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2756 case ICMD_IF_LGE: /* ..., value ==> ... */
2757 /* op1 = target JavaVM pc, val.l = constant */
2759 var_to_reg_int(s1, src, REG_ITMP1);
2760 if (iptr->val.l == 0) {
2764 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2765 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2768 LCONST(REG_ITMP2, iptr->val.l);
2769 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2771 M_BEQZ(REG_ITMP1, 0);
2773 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2776 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2777 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2778 case ICMD_IF_ACMPEQ:
2780 var_to_reg_int(s1, src->prev, REG_ITMP1);
2781 var_to_reg_int(s2, src, REG_ITMP2);
2782 M_CMPEQ(s1, s2, REG_ITMP1);
2783 M_BNEZ(REG_ITMP1, 0);
2784 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2787 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2788 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2789 case ICMD_IF_ACMPNE:
2791 var_to_reg_int(s1, src->prev, REG_ITMP1);
2792 var_to_reg_int(s2, src, REG_ITMP2);
2793 M_CMPEQ(s1, s2, REG_ITMP1);
2794 M_BEQZ(REG_ITMP1, 0);
2795 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2798 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2799 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2801 var_to_reg_int(s1, src->prev, REG_ITMP1);
2802 var_to_reg_int(s2, src, REG_ITMP2);
2803 M_CMPLT(s1, s2, REG_ITMP1);
2804 M_BNEZ(REG_ITMP1, 0);
2805 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2808 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2809 case ICMD_IF_LCMPGT: /* 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_CMPLE(s1, s2, REG_ITMP1);
2814 M_BEQZ(REG_ITMP1, 0);
2815 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2818 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2819 case ICMD_IF_LCMPLE: /* 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_BNEZ(REG_ITMP1, 0);
2825 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2828 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2829 case ICMD_IF_LCMPGE: /* 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_CMPLT(s1, s2, REG_ITMP1);
2834 M_BEQZ(REG_ITMP1, 0);
2835 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2838 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2840 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2843 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2844 /* val.i = constant */
2846 var_to_reg_int(s1, src, REG_ITMP1);
2847 d = reg_of_var(iptr->dst, REG_ITMP3);
2849 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2850 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2851 M_CMPEQ(s1, REG_ZERO, d);
2852 store_reg_to_var_int(iptr->dst, d);
2855 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2856 M_CMPEQ(s1, REG_ZERO, d);
2858 store_reg_to_var_int(iptr->dst, d);
2862 M_MOV(s1, REG_ITMP1);
2865 ICONST(d, iptr[1].val.i);
2867 if ((s3 >= 0) && (s3 <= 255)) {
2868 M_CMOVEQ_IMM(s1, s3, d);
2871 ICONST(REG_ITMP2, s3);
2872 M_CMOVEQ(s1, REG_ITMP2, d);
2874 store_reg_to_var_int(iptr->dst, d);
2877 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2878 /* val.i = constant */
2880 var_to_reg_int(s1, src, REG_ITMP1);
2881 d = reg_of_var(iptr->dst, REG_ITMP3);
2883 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2884 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2885 M_CMPEQ(s1, REG_ZERO, d);
2886 store_reg_to_var_int(iptr->dst, d);
2889 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2890 M_CMPEQ(s1, REG_ZERO, d);
2892 store_reg_to_var_int(iptr->dst, d);
2896 M_MOV(s1, REG_ITMP1);
2899 ICONST(d, iptr[1].val.i);
2901 if ((s3 >= 0) && (s3 <= 255)) {
2902 M_CMOVNE_IMM(s1, s3, d);
2905 ICONST(REG_ITMP2, s3);
2906 M_CMOVNE(s1, REG_ITMP2, d);
2908 store_reg_to_var_int(iptr->dst, d);
2911 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2912 /* val.i = constant */
2914 var_to_reg_int(s1, src, REG_ITMP1);
2915 d = reg_of_var(iptr->dst, REG_ITMP3);
2917 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2918 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2919 M_CMPLT(s1, REG_ZERO, d);
2920 store_reg_to_var_int(iptr->dst, d);
2923 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2924 M_CMPLE(REG_ZERO, s1, d);
2925 store_reg_to_var_int(iptr->dst, d);
2929 M_MOV(s1, REG_ITMP1);
2932 ICONST(d, iptr[1].val.i);
2934 if ((s3 >= 0) && (s3 <= 255)) {
2935 M_CMOVLT_IMM(s1, s3, d);
2938 ICONST(REG_ITMP2, s3);
2939 M_CMOVLT(s1, REG_ITMP2, d);
2941 store_reg_to_var_int(iptr->dst, d);
2944 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2945 /* val.i = constant */
2947 var_to_reg_int(s1, src, REG_ITMP1);
2948 d = reg_of_var(iptr->dst, REG_ITMP3);
2950 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2951 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2952 M_CMPLE(REG_ZERO, s1, d);
2953 store_reg_to_var_int(iptr->dst, d);
2956 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2957 M_CMPLT(s1, REG_ZERO, d);
2958 store_reg_to_var_int(iptr->dst, d);
2962 M_MOV(s1, REG_ITMP1);
2965 ICONST(d, iptr[1].val.i);
2967 if ((s3 >= 0) && (s3 <= 255)) {
2968 M_CMOVGE_IMM(s1, s3, d);
2971 ICONST(REG_ITMP2, s3);
2972 M_CMOVGE(s1, REG_ITMP2, d);
2974 store_reg_to_var_int(iptr->dst, d);
2977 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2978 /* val.i = constant */
2980 var_to_reg_int(s1, src, REG_ITMP1);
2981 d = reg_of_var(iptr->dst, REG_ITMP3);
2983 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2984 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2985 M_CMPLT(REG_ZERO, s1, d);
2986 store_reg_to_var_int(iptr->dst, d);
2989 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2990 M_CMPLE(s1, REG_ZERO, d);
2991 store_reg_to_var_int(iptr->dst, d);
2995 M_MOV(s1, REG_ITMP1);
2998 ICONST(d, iptr[1].val.i);
3000 if ((s3 >= 0) && (s3 <= 255)) {
3001 M_CMOVGT_IMM(s1, s3, d);
3004 ICONST(REG_ITMP2, s3);
3005 M_CMOVGT(s1, REG_ITMP2, d);
3007 store_reg_to_var_int(iptr->dst, d);
3010 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3011 /* val.i = constant */
3013 var_to_reg_int(s1, src, REG_ITMP1);
3014 d = reg_of_var(iptr->dst, REG_ITMP3);
3016 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
3017 if ((s3 == 1) && (iptr[1].val.i == 0)) {
3018 M_CMPLE(s1, REG_ZERO, d);
3019 store_reg_to_var_int(iptr->dst, d);
3022 if ((s3 == 0) && (iptr[1].val.i == 1)) {
3023 M_CMPLT(REG_ZERO, s1, d);
3024 store_reg_to_var_int(iptr->dst, d);
3028 M_MOV(s1, REG_ITMP1);
3031 ICONST(d, iptr[1].val.i);
3033 if ((s3 >= 0) && (s3 <= 255)) {
3034 M_CMOVLE_IMM(s1, s3, d);
3037 ICONST(REG_ITMP2, s3);
3038 M_CMOVLE(s1, REG_ITMP2, d);
3040 store_reg_to_var_int(iptr->dst, d);
3044 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3049 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3051 a = dseg_addaddress ((void*) (builtin_monitorexit));
3052 M_ALD(REG_PV, REG_PV, a);
3053 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
3054 M_JSR(REG_RA, REG_PV);
3055 disp = -(int)((u1*) mcodeptr - mcodebase);
3056 M_LDA(REG_PV, REG_RA, disp);
3059 var_to_reg_int(s1, src, REG_RESULT);
3060 M_INTMOVE(s1, REG_RESULT);
3061 goto nowperformreturn;
3063 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3067 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3069 a = dseg_addaddress ((void*) (builtin_monitorexit));
3070 M_ALD(REG_PV, REG_PV, a);
3071 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
3072 M_JSR(REG_RA, REG_PV);
3073 disp = -(int)((u1*) mcodeptr - mcodebase);
3074 M_LDA(REG_PV, REG_RA, disp);
3077 var_to_reg_flt(s1, src, REG_FRESULT);
3078 M_FLTMOVE(s1, REG_FRESULT);
3079 goto nowperformreturn;
3081 case ICMD_RETURN: /* ... ==> ... */
3084 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3086 a = dseg_addaddress ((void*) (builtin_monitorexit));
3087 M_ALD(REG_PV, REG_PV, a);
3088 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
3089 M_JSR(REG_RA, REG_PV);
3090 disp = -(int)((u1*) mcodeptr - mcodebase);
3091 M_LDA(REG_PV, REG_RA, disp);
3099 p = parentargs_base;
3101 /* restore return address */
3104 {p--; M_LLD (REG_RA, REG_SP, 8 * p);}
3106 /* restore saved registers */
3108 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
3109 {p--; M_LLD(savintregs[r], REG_SP, 8 * p);}
3110 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
3111 {p--; M_DLD(savfltregs[r], REG_SP, 8 * p);}
3113 /* deallocate stack */
3115 if (parentargs_base)
3116 {M_LDA(REG_SP, REG_SP, parentargs_base*8);}
3118 /* call trace function */
3121 M_LDA (REG_SP, REG_SP, -24);
3122 M_AST(REG_RA, REG_SP, 0);
3123 M_LST(REG_RESULT, REG_SP, 8);
3124 M_DST(REG_FRESULT, REG_SP,16);
3125 a = dseg_addaddress(method);
3126 M_ALD(argintregs[0], REG_PV, a);
3127 M_MOV(REG_RESULT, argintregs[1]);
3128 M_FLTMOVE(REG_FRESULT, argfltregs[2]);
3129 M_FLTMOVE(REG_FRESULT, argfltregs[3]);
3130 a = dseg_addaddress((void *) builtin_displaymethodstop);
3131 M_ALD(REG_PV, REG_PV, a);
3132 M_JSR (REG_RA, REG_PV);
3133 s1 = (int)((u1*) mcodeptr - mcodebase);
3134 if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
3137 while (ml<-32768) { ml+=65536; mh--; }
3138 M_LDA (REG_PV, REG_RA, ml );
3139 M_LDAH (REG_PV, REG_PV, mh );
3141 M_DLD(REG_FRESULT, REG_SP,16);
3142 M_LLD(REG_RESULT, REG_SP, 8);
3143 M_ALD(REG_RA, REG_SP, 0);
3144 M_LDA (REG_SP, REG_SP, 24);
3147 M_RET(REG_ZERO, REG_RA);
3153 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3158 tptr = (void **) iptr->target;
3160 s4ptr = iptr->val.a;
3161 l = s4ptr[1]; /* low */
3162 i = s4ptr[2]; /* high */
3164 var_to_reg_int(s1, src, REG_ITMP1);
3166 {M_INTMOVE(s1, REG_ITMP1);}
3167 else if (l <= 32768) {
3168 M_LDA(REG_ITMP1, s1, -l);
3171 ICONST(REG_ITMP2, l);
3172 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3179 M_CMPULE_IMM(REG_ITMP1, i - 1, REG_ITMP2);
3181 M_LDA(REG_ITMP2, REG_ZERO, i - 1);
3182 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3184 M_BEQZ(REG_ITMP2, 0);
3187 /* codegen_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr); */
3188 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3190 /* build jump table top down and use address of lowest entry */
3192 /* s4ptr += 3 + i; */
3196 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3197 dseg_addtarget((basicblock *) tptr[0]);
3202 /* length of dataseg after last dseg_addtarget is used by load */
3204 M_SAADDQ(REG_ITMP1, REG_PV, REG_ITMP2);
3205 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
3206 M_JMP(REG_ZERO, REG_ITMP2);
3211 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3213 s4 i, l, val, *s4ptr;
3216 tptr = (void **) iptr->target;
3218 s4ptr = iptr->val.a;
3219 l = s4ptr[0]; /* default */
3220 i = s4ptr[1]; /* count */
3222 MCODECHECK((i<<2)+8);
3223 var_to_reg_int(s1, src, REG_ITMP1);
3229 if ((val >= 0) && (val <= 255)) {
3230 M_CMPEQ_IMM(s1, val, REG_ITMP2);
3233 if ((val >= -32768) && (val <= 32767)) {
3234 M_LDA(REG_ITMP2, REG_ZERO, val);
3237 a = dseg_adds4 (val);
3238 M_ILD(REG_ITMP2, REG_PV, a);
3240 M_CMPEQ(s1, REG_ITMP2, REG_ITMP2);
3242 M_BNEZ(REG_ITMP2, 0);
3243 /* codegen_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr); */
3244 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3248 /* codegen_addreference(BlockPtrOfPC(l), mcodeptr); */
3250 tptr = (void **) iptr->target;
3251 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3258 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3259 /* op1 = return type, val.a = function pointer*/
3263 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3264 /* op1 = return type, val.a = function pointer*/
3268 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3269 /* op1 = return type, val.a = function pointer*/
3273 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3274 /* op1 = arg count, val.a = method pointer */
3276 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3277 /* op1 = arg count, val.a = method pointer */
3279 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3280 /* op1 = arg count, val.a = method pointer */
3282 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3283 /* op1 = arg count, val.a = method pointer */
3291 MCODECHECK((s3 << 1) + 64);
3293 /* copy arguments to registers or stack location */
3295 for (; --s3 >= 0; src = src->prev) {
3296 if (src->varkind == ARGVAR)
3298 if (IS_INT_LNG_TYPE(src->type)) {
3299 if (s3 < INT_ARG_CNT) {
3300 s1 = argintregs[s3];
3301 var_to_reg_int(d, src, s1);
3305 var_to_reg_int(d, src, REG_ITMP1);
3306 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3310 if (s3 < FLT_ARG_CNT) {
3311 s1 = argfltregs[s3];
3312 var_to_reg_flt(d, src, s1);
3316 var_to_reg_flt(d, src, REG_FTMP1);
3317 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3322 switch (iptr->opc) {
3326 a = dseg_addaddress ((void*) (m));
3328 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
3330 goto makeactualcall;
3332 case ICMD_INVOKESTATIC:
3333 case ICMD_INVOKESPECIAL:
3334 a = dseg_addaddress (m->stubroutine);
3336 M_ALD(REG_PV, REG_PV, a ); /* method pointer in r27 */
3339 goto makeactualcall;
3341 case ICMD_INVOKEVIRTUAL:
3343 gen_nullptr_check(argintregs[0]);
3344 M_ALD(REG_METHODPTR, argintregs[0],
3345 OFFSET(java_objectheader, vftbl));
3346 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
3347 sizeof(methodptr) * m->vftblindex);
3350 goto makeactualcall;
3352 case ICMD_INVOKEINTERFACE:
3355 gen_nullptr_check(argintregs[0]);
3356 M_ALD(REG_METHODPTR, argintregs[0],
3357 OFFSET(java_objectheader, vftbl));
3358 M_ALD(REG_METHODPTR, REG_METHODPTR,
3359 OFFSET(vftbl, interfacetable[0]) -
3360 sizeof(methodptr*) * ci->index);
3361 M_ALD(REG_PV, REG_METHODPTR,
3362 sizeof(methodptr) * (m - ci->methods));
3365 goto makeactualcall;
3369 error ("Unkown ICMD-Command: %d", iptr->opc);
3374 M_JSR (REG_RA, REG_PV);
3378 s1 = (int)((u1*) mcodeptr - mcodebase);
3379 if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
3382 while (ml<-32768) { ml+=65536; mh--; }
3383 M_LDA (REG_PV, REG_RA, ml );
3384 M_LDAH (REG_PV, REG_PV, mh );
3387 /* d contains return type */
3389 if (d != TYPE_VOID) {
3390 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3391 s1 = reg_of_var(iptr->dst, REG_RESULT);
3392 M_INTMOVE(REG_RESULT, s1);
3393 store_reg_to_var_int(iptr->dst, s1);
3396 s1 = reg_of_var(iptr->dst, REG_FRESULT);
3397 M_FLTMOVE(REG_FRESULT, s1);
3398 store_reg_to_var_flt(iptr->dst, s1);
3405 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3407 /* op1: 0 == array, 1 == class */
3408 /* val.a: (classinfo*) superclass */
3410 /* superclass is an interface:
3412 * return (sub != NULL) &&
3413 * (sub->vftbl->interfacetablelength > super->index) &&
3414 * (sub->vftbl->interfacetable[-super->index] != NULL);
3416 * superclass is a class:
3418 * return ((sub != NULL) && (0
3419 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3420 * super->vftbl->diffvall));
3424 classinfo *super = (classinfo*) iptr->val.a;
3426 var_to_reg_int(s1, src, REG_ITMP1);
3427 d = reg_of_var(iptr->dst, REG_ITMP3);
3429 M_MOV(s1, REG_ITMP1);
3433 if (iptr->op1) { /* class/interface */
3434 if (super->flags & ACC_INTERFACE) { /* interface */
3436 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3437 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3438 M_LDA(REG_ITMP2, REG_ITMP2, - super->index);
3439 M_BLEZ(REG_ITMP2, 2);
3440 M_ALD(REG_ITMP1, REG_ITMP1,
3441 OFFSET(vftbl, interfacetable[0]) -
3442 super->index * sizeof(methodptr*));
3443 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3447 s2 = super->vftbl->diffval;
3448 M_BEQZ(s1, 4 + (s2 > 255));
3449 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3450 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3451 M_LDA(REG_ITMP1, REG_ITMP1, - super->vftbl->baseval);
3453 M_CMPULE_IMM(REG_ITMP1, s2, d);
3455 M_LDA(REG_ITMP2, REG_ZERO, s2);
3456 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3460 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3461 a = dseg_addaddress ((void*) super->vftbl);
3462 M_ALD(REG_ITMP2, REG_PV, a);
3463 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3464 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3465 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3466 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3467 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3471 panic ("internal error: no inlined array instanceof");
3473 store_reg_to_var_int(iptr->dst, d);
3476 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3478 /* op1: 0 == array, 1 == class */
3479 /* val.a: (classinfo*) superclass */
3481 /* superclass is an interface:
3483 * OK if ((sub == NULL) ||
3484 * (sub->vftbl->interfacetablelength > super->index) &&
3485 * (sub->vftbl->interfacetable[-super->index] != NULL));
3487 * superclass is a class:
3489 * OK if ((sub == NULL) || (0
3490 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3491 * super->vftbl->diffvall));
3495 classinfo *super = (classinfo*) iptr->val.a;
3497 d = reg_of_var(iptr->dst, REG_ITMP3);
3498 var_to_reg_int(s1, src, d);
3499 if (iptr->op1) { /* class/interface */
3500 if (super->flags & ACC_INTERFACE) { /* interface */
3502 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3503 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3504 M_LDA(REG_ITMP2, REG_ITMP2, - super->index);
3505 M_BLEZ(REG_ITMP2, 0);
3506 codegen_addxcastrefs(mcodeptr);
3507 M_ALD(REG_ITMP2, REG_ITMP1,
3508 OFFSET(vftbl, interfacetable[0]) -
3509 super->index * sizeof(methodptr*));
3510 M_BEQZ(REG_ITMP2, 0);
3511 codegen_addxcastrefs(mcodeptr);
3515 s2 = super->vftbl->diffval;
3516 M_BEQZ(s1, 4 + (s2 != 0) + (s2 > 255));
3517 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3518 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3519 M_LDA(REG_ITMP1, REG_ITMP1, - super->vftbl->baseval);
3521 M_BNEZ(REG_ITMP1, 0);
3523 else if (s2 <= 255) {
3524 M_CMPULE_IMM(REG_ITMP1, s2, REG_ITMP2);
3525 M_BEQZ(REG_ITMP2, 0);
3528 M_LDA(REG_ITMP2, REG_ZERO, s2);
3529 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3530 M_BEQZ(REG_ITMP2, 0);
3533 M_BEQZ(s1, 8 + (d == REG_ITMP3));
3534 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3535 a = dseg_addaddress ((void*) super->vftbl);
3536 M_ALD(REG_ITMP2, REG_PV, a);
3537 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3538 if (d != REG_ITMP3) {
3539 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3540 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3541 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3544 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, baseval));
3545 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3546 M_ALD(REG_ITMP2, REG_PV, a);
3547 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3549 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3550 M_BEQZ(REG_ITMP2, 0);
3551 codegen_addxcastrefs(mcodeptr);
3555 panic ("internal error: no inlined array checkcast");
3558 store_reg_to_var_int(iptr->dst, d);
3561 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3563 var_to_reg_int(s1, src, REG_ITMP1);
3565 codegen_addxcheckarefs(mcodeptr);
3568 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3569 /* op1 = dimension, val.a = array descriptor */
3571 /* check for negative sizes and copy sizes to stack if necessary */
3573 MCODECHECK((iptr->op1 << 1) + 64);
3575 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3576 var_to_reg_int(s2, src, REG_ITMP1);
3578 codegen_addxcheckarefs(mcodeptr);
3580 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3582 if (src->varkind != ARGVAR) {
3583 M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
3587 /* a0 = dimension count */
3589 ICONST(argintregs[0], iptr->op1);
3591 /* a1 = arraydescriptor */
3593 a = dseg_addaddress(iptr->val.a);
3594 M_ALD(argintregs[1], REG_PV, a);
3596 /* a2 = pointer to dimensions = stack pointer */
3598 M_INTMOVE(REG_SP, argintregs[2]);
3600 a = dseg_addaddress((void*) (builtin_nmultianewarray));
3601 M_ALD(REG_PV, REG_PV, a);
3602 M_JSR(REG_RA, REG_PV);
3603 s1 = (int)((u1*) mcodeptr - mcodebase);
3605 M_LDA (REG_PV, REG_RA, -s1);
3607 s4 ml = -s1, mh = 0;
3608 while (ml < -32768) {ml += 65536; mh--;}
3609 M_LDA(REG_PV, REG_RA, ml);
3610 M_LDAH(REG_PV, REG_PV, mh);
3612 s1 = reg_of_var(iptr->dst, REG_RESULT);
3613 M_INTMOVE(REG_RESULT, s1);
3614 store_reg_to_var_int(iptr->dst, s1);
3618 default: error ("Unknown pseudo command: %d", iptr->opc);
3624 } /* for instruction */
3626 /* copy values to interface registers */
3628 src = bptr->outstack;
3629 len = bptr->outdepth;
3633 if ((src->varkind != STACKVAR)) {
3635 if (IS_FLT_DBL_TYPE(s2)) {
3636 var_to_reg_flt(s1, src, REG_FTMP1);
3637 if (!(interfaces[len][s2].flags & INMEMORY)) {
3638 M_FLTMOVE(s1,interfaces[len][s2].regoff);
3641 M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3645 var_to_reg_int(s1, src, REG_ITMP1);
3646 if (!(interfaces[len][s2].flags & INMEMORY)) {
3647 M_INTMOVE(s1,interfaces[len][s2].regoff);
3650 M_LST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3656 } /* if (bptr -> flags >= BBREACHED) */
3657 } /* for basic block */
3659 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3662 /* generate bound check stubs */
3664 s4 *xcodeptr = NULL;
3666 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3667 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3668 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3669 xboundrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - (4 + 4));
3674 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3675 xboundrefs->branchpos, (u1*) mcodeptr - mcodebase);
3679 M_MOV(xboundrefs->reg, REG_ITMP1);
3680 M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos - 4);
3682 if (xcodeptr != NULL) {
3683 M_BR(xcodeptr - mcodeptr - 1);
3686 xcodeptr = mcodeptr;
3688 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3689 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3691 a = dseg_addaddress(string_java_lang_ArrayIndexOutOfBoundsException);
3692 M_ALD(argintregs[0], REG_PV, a);
3693 M_MOV(REG_ITMP1, argintregs[1]);
3695 a = dseg_addaddress(new_exception_int);
3696 M_ALD(REG_PV, REG_PV, a);
3697 M_JSR(REG_RA, REG_PV);
3700 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3701 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3703 s4 ml = -s1, mh = 0;
3704 while (ml < -32768) { ml += 65536; mh--; }
3705 M_LDA(REG_PV, REG_RA, ml);
3706 M_LDAH(REG_PV, REG_PV, mh);
3709 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3711 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3712 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3714 a = dseg_addaddress(asm_handle_exception);
3715 M_ALD(REG_ITMP3, REG_PV, a);
3717 M_JMP(REG_ZERO, REG_ITMP3);
3721 /* generate negative array size check stubs */
3725 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3726 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3727 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3728 xcheckarefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3732 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3733 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
3737 M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos - 4);
3739 if (xcodeptr != NULL) {
3740 M_BR(xcodeptr - mcodeptr - 1);
3743 xcodeptr = mcodeptr;
3745 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3746 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3748 a = dseg_addaddress(string_java_lang_NegativeArraySizeException);
3749 M_ALD(argintregs[0], REG_PV, a);
3751 a = dseg_addaddress(new_exception);
3752 M_ALD(REG_PV, REG_PV, a);
3753 M_JSR(REG_RA, REG_PV);
3756 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3757 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3759 s4 ml = -s1, mh = 0;
3760 while (ml < -32768) { ml += 65536; mh--; }
3761 M_LDA(REG_PV, REG_RA, ml);
3762 M_LDAH(REG_PV, REG_PV, mh);
3765 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3767 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3768 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3770 a = dseg_addaddress(asm_handle_exception);
3771 M_ALD(REG_ITMP3, REG_PV, a);
3773 M_JMP(REG_ZERO, REG_ITMP3);
3777 /* generate cast check stubs */
3781 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3782 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3783 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3784 xcastrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3788 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3789 xcastrefs->branchpos, (u1*) mcodeptr - mcodebase);
3793 M_LDA(REG_ITMP2_XPC, REG_PV, xcastrefs->branchpos - 4);
3795 if (xcodeptr != NULL) {
3796 M_BR(xcodeptr - mcodeptr - 1);
3799 xcodeptr = mcodeptr;
3801 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3802 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3804 a = dseg_addaddress(string_java_lang_ClassCastException);
3805 M_ALD(argintregs[0], REG_PV, a);
3807 a = dseg_addaddress(new_exception);
3808 M_ALD(REG_PV, REG_PV, a);
3809 M_JSR(REG_RA, REG_PV);
3812 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3813 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3815 s4 ml = -s1, mh = 0;
3816 while (ml < -32768) { ml += 65536; mh--; }
3817 M_LDA(REG_PV, REG_RA, ml);
3818 M_LDAH(REG_PV, REG_PV, mh);
3821 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3823 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3824 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3826 a = dseg_addaddress(asm_handle_exception);
3827 M_ALD(REG_ITMP3, REG_PV, a);
3829 M_JMP(REG_ZERO, REG_ITMP3);
3833 /* generate null pointer check stubs */
3837 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3838 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3839 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3840 xnullrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3844 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3845 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
3849 M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
3851 if (xcodeptr != NULL) {
3852 M_BR(xcodeptr - mcodeptr - 1);
3855 xcodeptr = mcodeptr;
3857 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3858 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3860 a = dseg_addaddress(string_java_lang_NullPointerException);
3861 M_ALD(argintregs[0], REG_PV, a);
3863 a = dseg_addaddress(new_exception);
3864 M_ALD(REG_PV, REG_PV, a);
3865 M_JSR(REG_RA, REG_PV);
3868 s1 = (s4) ((u1 *) mcodeptr - mcodebase);
3869 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3871 s4 ml = -s1, mh = 0;
3872 while (ml < -32768) { ml += 65536; mh--; }
3873 M_LDA(REG_PV, REG_RA, ml);
3874 M_LDAH(REG_PV, REG_PV, mh);
3877 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3879 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3880 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3882 a = dseg_addaddress(asm_handle_exception);
3883 M_ALD(REG_ITMP3, REG_PV, a);
3885 M_JMP(REG_ZERO, REG_ITMP3);
3890 codegen_finish((int)((u1*) mcodeptr - mcodebase));
3894 /* function createcompilerstub *************************************************
3896 creates a stub routine which calls the compiler
3898 *******************************************************************************/
3900 #define COMPSTUBSIZE 3
3902 u1 *createcompilerstub(methodinfo *m)
3904 u8 *s = CNEW(u8, COMPSTUBSIZE); /* memory to hold the stub */
3905 s4 *mcodeptr = (s4 *) s; /* code generation pointer */
3907 /* code for the stub */
3908 M_ALD(REG_PV, REG_PV, 16); /* load pointer to the compiler */
3909 M_JMP(0, REG_PV); /* jump to the compiler, return address
3910 in reg 0 is used as method pointer */
3911 s[1] = (u8) m; /* literals to be adressed */
3912 s[2] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3915 count_cstub_len += COMPSTUBSIZE * 8;
3922 /* function removecompilerstub *************************************************
3924 deletes a compilerstub from memory (simply by freeing it)
3926 *******************************************************************************/
3928 void removecompilerstub(u1 *stub)
3930 CFREE(stub, COMPSTUBSIZE * 8);
3934 /* function: createnativestub **************************************************
3936 creates a stub routine which calls a native method
3938 *******************************************************************************/
3940 #define NATIVESTUBSIZE 44
3941 #define NATIVEVERBOSESIZE 39 + 13
3942 #define NATIVESTUBOFFSET 8
3944 u1 *createnativestub(functionptr f, methodinfo *m)
3946 u8 *s; /* memory pointer to hold the stub */
3948 s4 *mcodeptr; /* code generation pointer */
3949 int stackframesize = 0; /* size of stackframe if needed */
3954 descriptor2types(m); /* set paramcount and paramtypes */
3956 stubsize = runverbose ? NATIVESTUBSIZE + NATIVEVERBOSESIZE : NATIVESTUBSIZE;
3957 s = CNEW(u8, stubsize); /* memory to hold the stub */
3958 cs = s + NATIVESTUBOFFSET;
3959 mcodeptr = (s4 *) (cs); /* code generation pointer */
3961 *(cs-1) = (u8) f; /* address of native method */
3962 *(cs-2) = (u8) (&_exceptionptr); /* address of exceptionptr */
3963 *(cs-3) = (u8) asm_handle_nat_exception; /* addr of asm exception handler */
3964 *(cs-4) = (u8) (&env); /* addr of jni_environement */
3965 *(cs-5) = (u8) builtin_trace_args;
3967 *(cs-7) = (u8) builtin_displaymethodstop;
3968 *(cs-8) = (u8) m->class;
3970 M_LDA(REG_SP, REG_SP, -8); /* build up stackframe */
3971 M_AST(REG_RA, REG_SP, 0); /* store return address */
3973 /* max. 39 instructions */
3977 M_LDA(REG_SP, REG_SP, -(14 * 8));
3978 M_AST(REG_RA, REG_SP, 1 * 8);
3980 /* save integer argument registers */
3981 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3982 M_LST(argintregs[p], REG_SP, (2 + p) * 8);
3985 /* save and copy float arguments into integer registers */
3986 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3987 t = m->paramtypes[p];
3989 if (IS_FLT_DBL_TYPE(t)) {
3990 if (IS_2_WORD_TYPE(t)) {
3991 M_DST(argfltregs[p], REG_SP, (8 + p) * 8);
3992 M_LLD(argintregs[p], REG_SP, (8 + p) * 8);
3995 M_FST(argfltregs[p], REG_SP, (8 + p) * 8);
3996 M_ILD(argintregs[p], REG_SP, (8 + p) * 8);
4000 M_DST(argfltregs[p], REG_SP, (8 + p) * 8);
4004 M_ALD(REG_ITMP1, REG_PV, -6 * 8);
4005 M_AST(REG_ITMP1, REG_SP, 0);
4006 M_ALD(REG_PV, REG_PV, -5 * 8);
4007 M_JSR(REG_RA, REG_PV);
4008 disp = -(int) (mcodeptr - (s4*) cs) * 4;
4009 M_LDA(REG_PV, REG_RA, disp);
4011 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
4012 M_LLD(argintregs[p], REG_SP, (2 + p) * 8);
4015 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
4016 t = m->paramtypes[p];
4018 if (IS_FLT_DBL_TYPE(t)) {
4019 if (IS_2_WORD_TYPE(t)) {
4020 M_DLD(argfltregs[p], REG_SP, (8 + p) * 8);
4023 M_FLD(argfltregs[p], REG_SP, (8 + p) * 8);
4027 M_DLD(argfltregs[p], REG_SP, (8 + p) * 8);
4031 M_ALD(REG_RA, REG_SP, 1 * 8);
4032 M_LDA(REG_SP, REG_SP, 14 * 8);
4035 /* save argument registers on stack -- if we have to */
4036 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
4038 int paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
4039 int stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
4041 stackframesize = stackparamcnt + paramshiftcnt;
4043 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
4045 /* copy stack arguments into new stack frame -- if any */
4046 for (i = 0; i < stackparamcnt; i++) {
4047 M_LLD(REG_ITMP1, REG_SP, (stackparamcnt + 1 + i) * 8);
4048 M_LST(REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
4051 if (m->flags & ACC_STATIC) {
4052 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4053 M_DST(argfltregs[5], REG_SP, 1 * 8);
4055 M_LST(argintregs[5], REG_SP, 1 * 8);
4058 if (IS_FLT_DBL_TYPE(m->paramtypes[4])) {
4059 M_DST(argfltregs[4], REG_SP, 0 * 8);
4061 M_LST(argintregs[4], REG_SP, 0 * 8);
4065 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4066 M_DST(argfltregs[5], REG_SP, 0 * 8);
4068 M_LST(argintregs[5], REG_SP, 0 * 8);
4073 if (m->flags & ACC_STATIC) {
4074 M_MOV(argintregs[3], argintregs[5]);
4075 M_MOV(argintregs[2], argintregs[4]);
4076 M_MOV(argintregs[1], argintregs[3]);
4077 M_MOV(argintregs[0], argintregs[2]);
4078 M_FMOV(argfltregs[3], argfltregs[5]);
4079 M_FMOV(argfltregs[2], argfltregs[4]);
4080 M_FMOV(argfltregs[1], argfltregs[3]);
4081 M_FMOV(argfltregs[0], argfltregs[2]);
4083 /* put class into second argument register */
4084 M_ALD(argintregs[1], REG_PV, -8 * 8);
4087 M_MOV(argintregs[4], argintregs[5]);
4088 M_MOV(argintregs[3], argintregs[4]);
4089 M_MOV(argintregs[2], argintregs[3]);
4090 M_MOV(argintregs[1], argintregs[2]);
4091 M_MOV(argintregs[0], argintregs[1]);
4092 M_FMOV(argfltregs[4], argfltregs[5]);
4093 M_FMOV(argfltregs[3], argfltregs[4]);
4094 M_FMOV(argfltregs[2], argfltregs[3]);
4095 M_FMOV(argfltregs[1], argfltregs[2]);
4096 M_FMOV(argfltregs[0], argfltregs[1]);
4099 /* put env into first argument register */
4100 M_ALD(argintregs[0], REG_PV, -4 * 8);
4102 M_ALD(REG_PV, REG_PV, -1 * 8); /* load adress of native method */
4103 M_JSR(REG_RA, REG_PV); /* call native method */
4104 disp = -(int) (mcodeptr - (s4*) cs) * 4;
4105 M_LDA(REG_PV, REG_RA, disp); /* recompute pv from ra */
4107 /* remove stackframe if there is one */
4108 if (stackframesize) {
4109 M_LDA(REG_SP, REG_SP, stackframesize * 8);
4112 /* 13 instructions */
4114 M_LDA(REG_SP, REG_SP, -(2 * 8));
4115 M_ALD(argintregs[0], REG_PV, -6 * 8); /* load method adress */
4116 M_LST(REG_RESULT, REG_SP, 0 * 8);
4117 M_DST(REG_FRESULT, REG_SP, 1 * 8);
4118 M_MOV(REG_RESULT, argintregs[1]);
4119 M_FMOV(REG_FRESULT, argfltregs[2]);
4120 M_FMOV(REG_FRESULT, argfltregs[3]);
4121 M_ALD(REG_PV, REG_PV, -7 * 8); /* builtin_displaymethodstop */
4122 M_JSR(REG_RA, REG_PV);
4123 disp = -(int) (mcodeptr - (s4*) cs) * 4;
4124 M_LDA(REG_PV, REG_RA, disp);
4125 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4126 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
4127 M_LDA(REG_SP, REG_SP, 2 * 8);
4130 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* get address of exceptionptr */
4131 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4132 M_BNEZ(REG_ITMP1, 3); /* if no exception then return */
4134 M_ALD(REG_RA, REG_SP, 0); /* load return address */
4135 M_LDA(REG_SP, REG_SP, 8); /* remove stackframe */
4136 M_RET(REG_ZERO, REG_RA); /* return to caller */
4138 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4140 M_ALD(REG_RA, REG_SP, 0); /* load return address */
4141 M_LDA(REG_SP, REG_SP, 8); /* remove stackframe */
4142 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4143 M_ALD(REG_ITMP3, REG_PV, -3 * 8); /* load asm exception handler address */
4144 M_JMP(REG_ZERO, REG_ITMP3); /* jump to asm exception handler */
4147 dolog_plain("stubsize: %d (for %d params)\n", (int) (mcodeptr - (s4*) s), m->paramcount);
4151 count_nstub_len += NATIVESTUBSIZE * 8;
4154 return (u1*) (s + NATIVESTUBOFFSET);
4158 /* function: removenativestub **************************************************
4160 removes a previously created native-stub from memory
4162 *******************************************************************************/
4164 void removenativestub(u1 *stub)
4166 CFREE((u8*) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 8);
4171 * These are local overrides for various environment variables in Emacs.
4172 * Please do not remove this and leave it at the end of the file, where
4173 * Emacs will automagically detect them.
4174 * ---------------------------------------------------------------------
4177 * indent-tabs-mode: t