1 /* jit/powerpc/codegen.c - machine code generator for 32-bit powerpc
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 862 2004-01-06 23:42:01Z stefan $
49 /* include independent code generation stuff */
50 #include "codegen.inc"
54 /* register descripton - array ************************************************/
56 /* #define REG_RES 0 reserved register for OS or code generator */
57 /* #define REG_RET 1 return value register */
58 /* #define REG_EXC 2 exception value register (only old jit) */
59 /* #define REG_SAV 3 (callee) saved register */
60 /* #define REG_TMP 4 scratch temporary register (caller saved) */
61 /* #define REG_ARG 5 argument register (caller saved) */
63 /* #define REG_END -1 last entry in tables */
66 REG_RES, REG_RES, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
67 REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV,
68 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
69 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
72 /* for use of reserved registers, see comment above */
74 int nregdescfloat[] = {
75 REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
76 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV,
77 REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
78 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
81 /* for use of reserved registers, see comment above */
84 /* stackframe-infos ***********************************************************/
86 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
88 /* -> see file 'calling.doc' */
91 /* additional functions and macros to generate code ***************************/
93 #define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
97 #define COUNT_SPILLS count_spills++
103 /* gen_nullptr_check(objreg) */
105 #ifdef SOFTNULLPTRCHECK
106 #define gen_nullptr_check(objreg) \
110 codegen_addxnullrefs(mcodeptr);\
113 #define gen_nullptr_check(objreg)
117 /* MCODECHECK(icnt) */
119 #define MCODECHECK(icnt) \
120 if((mcodeptr+(icnt))>mcodeend)mcodeptr=codegen_increase((u1*)mcodeptr)
123 generates an integer-move from register a to b.
124 if a and b are the same int-register, no code will be generated.
127 #define M_INTMOVE(a,b) if((a)!=(b)){M_MOV(a,b);}
129 #define M_TINTMOVE(t,a,b) \
131 {if (a<=b)M_INTMOVE(secondregs[a],secondregs[b]);\
132 M_INTMOVE(a,b); if (a>b)M_INTMOVE(secondregs[a],secondregs[b]);} \
138 generates a floating-point-move from register a to b.
139 if a and b are the same float-register, no code will be generated
142 #define M_FLTMOVE(a,b) if((a)!=(b)){M_FMOV(a,b);}
146 this function generates code to fetch data from a pseudo-register
147 into a real register.
148 If the pseudo-register has actually been assigned to a real
149 register, no code will be emitted, since following operations
150 can use this register directly.
152 v: pseudoregister to be fetched from
153 tempregnum: temporary register to be used if v is actually spilled to ram
155 return: the register number, where the operand can be found after
156 fetching (this wil be either tempregnum or the register
157 number allready given to v)
160 #define var_to_reg_int0(regnr,v,tempnr,a,b) { \
161 if ((v)->flags & INMEMORY) \
162 {COUNT_SPILLS;if (a) M_ILD(tempnr,REG_SP,4*(v)->regoff); \
164 if ((b) && IS_2_WORD_TYPE((v)->type)) \
165 M_ILD((a)?secondregs[tempnr]:tempnr,REG_SP,4*(v)->regoff+4);} \
166 else regnr=(!(a)&&(b)) ? secondregs[(v)->regoff] : (v)->regoff; \
168 #define var_to_reg_int(regnr,v,tempnr) var_to_reg_int0(regnr,v,tempnr,1,1)
171 #define var_to_reg_flt(regnr,v,tempnr) { \
172 if ((v)->flags & INMEMORY) { \
174 if ((v)->type==TYPE_DBL) \
175 M_DLD(tempnr,REG_SP,4*(v)->regoff); \
177 M_FLD(tempnr,REG_SP,4*(v)->regoff); \
179 } else regnr=(v)->regoff; \
184 This function determines a register, to which the result of an operation
185 should go, when it is ultimatively intended to store the result in
187 If v is assigned to an actual register, this register will be returned.
188 Otherwise (when v is spilled) this function returns tempregnum.
189 If not already done, regoff and flags are set in the stack location.
192 static int reg_of_var(stackptr v, int tempregnum)
196 switch (v->varkind) {
198 if (!(v->flags & INMEMORY))
202 var = &(interfaces[v->varnum][v->type]);
203 v->regoff = var->regoff;
204 if (!(var->flags & INMEMORY))
208 var = &(locals[v->varnum][v->type]);
209 v->regoff = var->regoff;
210 if (!(var->flags & INMEMORY))
214 v->regoff = v->varnum;
215 if (IS_FLT_DBL_TYPE(v->type)) {
216 if (v->varnum < fltreg_argnum) {
217 v->regoff = argfltregs[v->varnum];
218 return(argfltregs[v->varnum]);
222 if (v->varnum < intreg_argnum - (IS_2_WORD_TYPE(v->type)!=0)) {
223 v->regoff = argintregs[v->varnum];
224 return(argintregs[v->varnum]);
229 v->flags |= INMEMORY;
234 /* store_reg_to_var_xxx:
235 This function generates the code to store the result of an operation
236 back into a spilled pseudo-variable.
237 If the pseudo-variable has not been spilled in the first place, this
238 function will generate nothing.
240 v ............ Pseudovariable
241 tempregnum ... Number of the temporary registers as returned by
245 #define store_reg_to_var_int0(sptr, tempregnum, a, b) { \
246 if ((sptr)->flags & INMEMORY) { \
248 if (a) M_IST(tempregnum, REG_SP, 4 * (sptr)->regoff); \
249 if ((b) && IS_2_WORD_TYPE((sptr)->type)) \
250 M_IST(secondregs[tempregnum], REG_SP, 4 * (sptr)->regoff + 4); \
254 #define store_reg_to_var_int(sptr, tempregnum) \
255 store_reg_to_var_int0(sptr, tempregnum, 1, 1)
257 #define store_reg_to_var_flt(sptr, tempregnum) { \
258 if ((sptr)->flags & INMEMORY) { \
260 if ((sptr)->type==TYPE_DBL) \
261 M_DST(tempregnum, REG_SP, 4 * (sptr)->regoff); \
263 M_FST(tempregnum, REG_SP, 4 * (sptr)->regoff); \
268 //#include <architecture/ppc/cframe.h>
270 /* NullPointerException signal handler for hardware null pointer check */
272 void asm_sighandler();
277 int catch_Handler(int *regs)
282 instr = *(int *) crashpc;
283 reg = (instr>>16) & 31;
287 sigaddset(&nsig, lastsig);
288 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
290 regs[REG_ITMP2_XPC] = crashpc;
291 regs[REG_ITMP1_XPTR] = (int) proto_java_lang_NullPointerException;
299 void catch_NullPointerException(int sig, void *code, struct sigcontext *ctx)
301 int oldsp = ctx->sc_sp;
304 crashpc = ctx->sc_ir;
305 ctx->sc_ir = (int) asm_sighandler;
309 void init_exceptions(void)
311 /* install signal handlers we need to convert to exceptions */
316 signal(SIGSEGV, (void*) catch_NullPointerException);
320 signal(SIGBUS, (void*) catch_NullPointerException);
326 void adjust_argvars(stackptr s, int d, int *fa, int *ia)
332 adjust_argvars(s->prev, d-1, fa, ia);
333 if (s->varkind == ARGVAR)
334 s->varnum = (IS_FLT_DBL_TYPE(s->type)) ? *fa : *ia;
335 *fa += (IS_FLT_DBL_TYPE(s->type) != 0);
336 *ia += (IS_2_WORD_TYPE(s->type)) ? 2 : 1;
346 #define intmaxf(a,b) (((a)<(b)) ? (b) : (a))
357 for (bptr = block; bptr != NULL; bptr = bptr->next) {
359 for (iptr = bptr->iinstr, src = bptr->instack;
361 src = iptr->dst, len--, iptr++)
363 if (bptr->flags < BBREACHED)
376 case ICMD_INVOKEVIRTUAL:
377 case ICMD_INVOKESPECIAL:
378 case ICMD_INVOKESTATIC:
379 case ICMD_INVOKEINTERFACE:
384 adjust_argvars(src, s3, &fa, &ia);
387 for (; --s3 >= 0; src = src->prev) {
388 paramsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
390 ifmemuse = intmaxf(ifmemuse, paramsize);
393 case ICMD_MULTIANEWARRAY:
395 paramsize = intreg_argnum + s3;
396 ifmemuse = intmaxf(ifmemuse, paramsize);
403 maxmemuse = ifmemuse;
406 /* function gen_mcode **********************************************************
408 generates machine code
410 *******************************************************************************/
412 #define MethodPointer -8
413 #define FrameSize -12
418 #define ExTableSize -32
419 #define ExTableStart -32
421 #define ExEntrySize -16
424 #define ExHandlerPC -12
425 #define ExCatchType -16
430 int len, s1, s2, s3, d;
444 /* space to save used callee saved registers */
446 savedregs_num += (savintregcnt - maxsavintreguse);
447 savedregs_num += 2*(savfltregcnt - maxsavfltreguse);
449 parentargs_base = maxmemuse + savedregs_num;
451 #ifdef USE_THREADS /* space to save argument of monitor_enter */
453 if (checksync && (method->flags & ACC_SYNCHRONIZED))
458 /* create method header */
460 parentargs_base = (parentargs_base+3) & ~3;
463 (void) dseg_addaddress(method); /* Filler */
465 (void) dseg_addaddress(method); /* MethodPointer */
466 (void) dseg_adds4(parentargs_base * 4); /* FrameSize */
470 /* IsSync contains the offset relative to the stack pointer for the
471 argument of monitor_exit used in the exception handler. Since the
472 offset could be zero and give a wrong meaning of the flag it is
476 if (checksync && (method->flags & ACC_SYNCHRONIZED))
477 (void) dseg_adds4((maxmemuse + 1) * 4); /* IsSync */
482 (void) dseg_adds4(0); /* IsSync */
484 (void) dseg_adds4(isleafmethod); /* IsLeaf */
485 (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
486 (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
487 (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
489 /* create exception table */
491 for (ex = extable; ex != NULL; ex = ex->down) {
494 if (ex->start != NULL)
495 printf("adding start - %d - ", ex->start->debug_nr);
497 printf("PANIC - start is NULL");
502 dseg_addtarget(ex->start);
506 printf("adding end - %d - ", ex->end->debug_nr);
508 printf("PANIC - end is NULL");
513 dseg_addtarget(ex->end);
516 if (ex->handler != NULL)
517 printf("adding handler - %d\n", ex->handler->debug_nr);
519 printf("PANIC - handler is NULL");
524 dseg_addtarget(ex->handler);
526 (void) dseg_addaddress(ex->catchtype);
529 /* initialize mcode variables */
531 mcodeptr = (s4*) mcodebase;
532 mcodeend = (s4*) (mcodebase + mcodesize);
533 MCODECHECK(128 + mparamcount);
535 /* create stack frame (if necessary) */
539 M_AST(REG_ITMP3, REG_SP, 8);
542 {M_LDA (REG_SP, REG_SP, -parentargs_base * 4);}
544 /* save return address and used callee saved registers */
547 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
548 {p--; M_IST (savintregs[r], REG_SP, 4 * p);}
549 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
550 {p-=2; M_DST (savfltregs[r], REG_SP, 4 * p);}
552 /* save monitorenter argument */
555 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
556 if (method->flags & ACC_STATIC) {
557 p = dseg_addaddress (class);
558 M_ALD(REG_ITMP1, REG_PV, p);
559 M_AST(REG_ITMP1, REG_SP, 4 * maxmemuse);
562 M_AST (argintregs[0], REG_SP, 4 * maxmemuse);
567 /* copy argument registers to stack and call trace function with pointer
568 to arguments on stack. ToDo: save floating point registers !!!!!!!!!
574 M_LDA (REG_SP, REG_SP, -208);
576 M_IST(REG_ITMP3, REG_SP, 13*8 + 96);
577 M_IST(argintregs[0], REG_SP, 0*4 + 64);
578 M_IST(argintregs[1], REG_SP, 1*4 + 64);
579 M_IST(argintregs[2], REG_SP, 2*4 + 64);
580 M_IST(argintregs[3], REG_SP, 3*4 + 64);
581 M_IST(argintregs[4], REG_SP, 4*4 + 64);
582 M_IST(argintregs[5], REG_SP, 5*4 + 64);
583 M_IST(argintregs[6], REG_SP, 6*4 + 64);
584 M_IST(argintregs[7], REG_SP, 7*4 + 64);
586 M_DST(argfltregs[0], REG_SP, 0*8 + 96);
587 M_DST(argfltregs[1], REG_SP, 1*8 + 96);
588 M_DST(argfltregs[2], REG_SP, 2*8 + 96);
589 M_DST(argfltregs[3], REG_SP, 3*8 + 96);
590 M_DST(argfltregs[4], REG_SP, 4*8 + 96);
591 M_DST(argfltregs[5], REG_SP, 5*8 + 96);
592 M_DST(argfltregs[6], REG_SP, 6*8 + 96);
593 M_DST(argfltregs[7], REG_SP, 7*8 + 96);
594 M_DST(argfltregs[8], REG_SP, 8*8 + 96);
595 M_DST(argfltregs[9], REG_SP, 9*8 + 96);
596 M_DST(argfltregs[10], REG_SP, 10*8 + 96);
597 M_DST(argfltregs[11], REG_SP, 11*8 + 96);
598 M_DST(argfltregs[12], REG_SP, 12*8 + 96);
600 p = dseg_addaddress (method);
601 M_ALD(REG_ITMP1, REG_PV, p);
602 M_AST(REG_ITMP1, REG_SP, 56);
603 p = dseg_addaddress ((void*) (builtin_trace_args));
604 M_ALD(REG_ITMP2, REG_PV, p);
608 M_ILD(REG_ITMP3, REG_SP, 13*8 + 96);
609 M_ILD(argintregs[0], REG_SP, 0*4 + 64);
610 M_ILD(argintregs[1], REG_SP, 1*4 + 64);
611 M_ILD(argintregs[2], REG_SP, 2*4 + 64);
612 M_ILD(argintregs[3], REG_SP, 3*4 + 64);
613 M_ILD(argintregs[4], REG_SP, 4*4 + 64);
614 M_ILD(argintregs[5], REG_SP, 5*4 + 64);
615 M_ILD(argintregs[6], REG_SP, 6*4 + 64);
616 M_ILD(argintregs[7], REG_SP, 7*4 + 64);
618 M_DLD(argfltregs[0], REG_SP, 0*8 + 96);
619 M_DLD(argfltregs[1], REG_SP, 1*8 + 96);
620 M_DLD(argfltregs[2], REG_SP, 2*8 + 96);
621 M_DLD(argfltregs[3], REG_SP, 3*8 + 96);
622 M_DLD(argfltregs[4], REG_SP, 4*8 + 96);
623 M_DLD(argfltregs[5], REG_SP, 5*8 + 96);
624 M_DLD(argfltregs[6], REG_SP, 6*8 + 96);
625 M_DLD(argfltregs[7], REG_SP, 7*8 + 96);
626 M_DLD(argfltregs[8], REG_SP, 8*8 + 96);
627 M_DLD(argfltregs[9], REG_SP, 9*8 + 96);
628 M_DLD(argfltregs[10], REG_SP, 10*8 + 96);
629 M_DLD(argfltregs[11], REG_SP, 11*8 + 96);
630 M_DLD(argfltregs[12], REG_SP, 12*8 + 96);
632 M_LDA (REG_SP, REG_SP, 208);
637 /* take arguments out of register or stack frame */
642 for (p = 0, l = 0; p < mparamcount; p++) {
643 arg = narg; iarg = niarg;
645 var = &(locals[l][t]);
647 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
652 if (IS_INT_LNG_TYPE(t)) { /* integer args */
653 if (iarg < INT_ARG_CNT -
654 (IS_2_WORD_TYPE(t)!=0)) { /* register arguments */
655 if (!(var->flags & INMEMORY)) /* reg arg -> register */
656 {M_TINTMOVE (t, argintregs[iarg], r);}
657 else /* reg arg -> spilled */
659 M_IST (argintregs[iarg], REG_SP, 4 * r);
660 if (IS_2_WORD_TYPE(t))
661 M_IST (secondregs[argintregs[iarg]], REG_SP, 4 * r + 4);
664 else { /* stack arguments */
666 if (!(var->flags & INMEMORY)) /* stack arg -> register */
668 M_ILD (r, REG_SP, 4 * (parentargs_base + pa));
669 if (IS_2_WORD_TYPE(t))
670 M_ILD (secondregs[r], REG_SP, 4 * (parentargs_base + pa) + 4);
672 else { /* stack arg -> spilled */
673 M_ILD (REG_ITMP1, REG_SP, 4 * (parentargs_base + pa));
674 M_IST (REG_ITMP1, REG_SP, 4 * r);
675 if (IS_2_WORD_TYPE(t)) {
676 M_ILD (REG_ITMP1, REG_SP, 4 * (parentargs_base + pa) + 4);
677 M_IST (REG_ITMP1, REG_SP, 4 * r + 4);
682 else { /* floating args */
684 if (arg < FLT_ARG_CNT) { /* register arguments */
685 if (!(var->flags & INMEMORY)) /* reg arg -> register */
686 {M_FLTMOVE (argfltregs[arg], r);}
687 else /* reg arg -> spilled */
688 M_DST (argfltregs[arg], REG_SP, 4 * r);
690 else { /* stack arguments */
692 if (!(var->flags & INMEMORY)) /* stack-arg -> register */
693 if (IS_2_WORD_TYPE(t))
694 M_DLD (r, REG_SP, 4 * (parentargs_base + pa) );
696 M_FLD (r, REG_SP, 4 * (parentargs_base + pa) );
697 else { /* stack-arg -> spilled */
698 if (IS_2_WORD_TYPE(t))
699 M_DLD (REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
701 M_FLD (REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
702 M_DST (REG_FTMP1, REG_SP, 4 * r);
709 /* call monitorenter function */
712 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
713 p = dseg_addaddress ((void*) (builtin_monitorenter));
714 M_ALD(REG_ITMP3, REG_PV, p);
716 M_ALD(argintregs[0], REG_SP, 4 * maxmemuse);
722 /* end of header generation */
724 /* walk through all basic blocks */
725 for (/* bbs = block_count, */ bptr = block; /* --bbs >= 0 */ bptr != NULL; bptr = bptr->next) {
727 bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
729 if (bptr->flags >= BBREACHED) {
731 /* branch resolving */
735 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
736 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
737 brefs->branchpos, bptr->mpc);
741 /* copy interface registers to their destination */
746 while (src != NULL) {
748 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
749 d = reg_of_var(src, REG_ITMP1);
750 M_INTMOVE(REG_ITMP1, d);
751 store_reg_to_var_int(src, d);
754 d = reg_of_var(src, REG_IFTMP);
755 if ((src->varkind != STACKVAR)) {
757 if (IS_FLT_DBL_TYPE(s2)) {
758 if (!(interfaces[len][s2].flags & INMEMORY)) {
759 s1 = interfaces[len][s2].regoff;
763 if (IS_2_WORD_TYPE(s2))
764 M_DLD(d, REG_SP, 4 * interfaces[len][s2].regoff);
766 M_FLD(d, REG_SP, 4 * interfaces[len][s2].regoff);
768 store_reg_to_var_flt(src, d);
771 if (!(interfaces[len][s2].flags & INMEMORY)) {
772 s1 = interfaces[len][s2].regoff;
776 M_ILD(d, REG_SP, 4 * interfaces[len][s2].regoff);
777 if (IS_2_WORD_TYPE(s2))
778 M_ILD(secondregs[d], REG_SP, 4 * interfaces[len][s2].regoff + 4);
780 store_reg_to_var_int(src, d);
787 /* walk through all instructions */
791 for (iptr = bptr->iinstr;
793 src = iptr->dst, len--, iptr++) {
795 MCODECHECK(64); /* an instruction usually needs < 64 words */
798 case ICMD_NOP: /* ... ==> ... */
801 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
803 var_to_reg_int(s1, src, REG_ITMP1);
806 codegen_addxnullrefs(mcodeptr);
809 /* constant operations ************************************************/
811 #define ICONST(r,c) if(((c)>=0&&(c)<=32767)||((c)>=-32768&&(c)<0)){M_LDA(r,REG_ZERO,c);} \
812 else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
814 #define LCONST(r,c) ICONST(r,(s4)((s8)(c)>>32)); ICONST(secondregs[r],(s4)((s8)(c)));
816 case ICMD_ICONST: /* ... ==> ..., constant */
817 /* op1 = 0, val.i = constant */
819 d = reg_of_var(iptr->dst, REG_ITMP1);
820 ICONST(d, iptr->val.i);
821 store_reg_to_var_int(iptr->dst, d);
824 case ICMD_LCONST: /* ... ==> ..., constant */
825 /* op1 = 0, val.l = constant */
827 d = reg_of_var(iptr->dst, REG_ITMP1);
828 LCONST(d, iptr->val.l);
829 store_reg_to_var_int(iptr->dst, d);
832 case ICMD_FCONST: /* ... ==> ..., constant */
833 /* op1 = 0, val.f = constant */
835 d = reg_of_var (iptr->dst, REG_FTMP1);
836 a = dseg_addfloat (iptr->val.f);
838 store_reg_to_var_flt (iptr->dst, d);
841 case ICMD_DCONST: /* ... ==> ..., constant */
842 /* op1 = 0, val.d = constant */
844 d = reg_of_var (iptr->dst, REG_FTMP1);
845 a = dseg_adddouble (iptr->val.d);
847 store_reg_to_var_flt (iptr->dst, d);
850 case ICMD_ACONST: /* ... ==> ..., constant */
851 /* op1 = 0, val.a = constant */
853 d = reg_of_var(iptr->dst, REG_ITMP1);
854 ICONST(d, (u4) iptr->val.a);
855 store_reg_to_var_int(iptr->dst, d);
859 /* load/store operations **********************************************/
861 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
862 case ICMD_LLOAD: /* op1 = local variable */
865 d = reg_of_var(iptr->dst, REG_ITMP1);
866 if ((iptr->dst->varkind == LOCALVAR) &&
867 (iptr->dst->varnum == iptr->op1))
869 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
870 if (var->flags & INMEMORY) {
871 M_ILD(d, REG_SP, 4 * var->regoff);
872 if (IS_2_WORD_TYPE(var->type))
873 M_ILD(secondregs[d], REG_SP, 4 * var->regoff + 4);
875 {M_TINTMOVE(var->type,var->regoff,d);}
876 store_reg_to_var_int(iptr->dst, d);
879 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
880 case ICMD_DLOAD: /* op1 = local variable */
882 d = reg_of_var(iptr->dst, REG_FTMP1);
883 if ((iptr->dst->varkind == LOCALVAR) &&
884 (iptr->dst->varnum == iptr->op1))
886 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
887 if (var->flags & INMEMORY)
888 if (IS_2_WORD_TYPE(var->type))
889 M_DLD(d, REG_SP, 4 * var->regoff);
891 M_FLD(d, REG_SP, 4 * var->regoff);
893 {M_FLTMOVE(var->regoff,d);}
894 store_reg_to_var_flt(iptr->dst, d);
898 case ICMD_ISTORE: /* ..., value ==> ... */
899 case ICMD_LSTORE: /* op1 = local variable */
902 if ((src->varkind == LOCALVAR) &&
903 (src->varnum == iptr->op1))
905 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
906 if (var->flags & INMEMORY) {
907 var_to_reg_int(s1, src, REG_ITMP1);
908 M_IST(s1, REG_SP, 4 * var->regoff);
909 if (IS_2_WORD_TYPE(var->type))
910 M_IST(secondregs[s1], REG_SP, 4 * var->regoff + 4);
913 var_to_reg_int(s1, src, var->regoff);
914 M_TINTMOVE(var->type, s1, var->regoff);
918 case ICMD_FSTORE: /* ..., value ==> ... */
919 case ICMD_DSTORE: /* op1 = local variable */
921 if ((src->varkind == LOCALVAR) &&
922 (src->varnum == iptr->op1))
924 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
925 if (var->flags & INMEMORY) {
926 var_to_reg_flt(s1, src, REG_FTMP1);
927 if (var->type==TYPE_DBL)
928 M_DST(s1, REG_SP, 4 * var->regoff);
930 M_FST(s1, REG_SP, 4 * var->regoff);
933 var_to_reg_flt(s1, src, var->regoff);
934 M_FLTMOVE(s1, var->regoff);
939 /* pop/dup/swap operations ********************************************/
941 /* attention: double and longs are only one entry in CACAO ICMDs */
943 case ICMD_POP: /* ..., value ==> ... */
944 case ICMD_POP2: /* ..., value, value ==> ... */
947 #define M_COPY(from,to) \
948 d = reg_of_var(to, REG_IFTMP); \
949 if ((from->regoff != to->regoff) || \
950 ((from->flags ^ to->flags) & INMEMORY)) { \
951 if (IS_FLT_DBL_TYPE(from->type)) { \
952 var_to_reg_flt(s1, from, d); \
954 store_reg_to_var_flt(to, d); \
957 var_to_reg_int(s1, from, d); \
958 M_TINTMOVE(from->type,s1,d); \
959 store_reg_to_var_int(to, d); \
963 case ICMD_DUP: /* ..., a ==> ..., a, a */
964 M_COPY(src, iptr->dst);
967 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
969 M_COPY(src, iptr->dst->prev->prev);
971 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
973 M_COPY(src, iptr->dst);
974 M_COPY(src->prev, iptr->dst->prev);
977 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
979 M_COPY(src->prev, iptr->dst->prev->prev->prev);
981 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
983 M_COPY(src, iptr->dst);
984 M_COPY(src->prev, iptr->dst->prev);
985 M_COPY(src->prev->prev, iptr->dst->prev->prev);
986 M_COPY(src, iptr->dst->prev->prev->prev);
989 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
991 M_COPY(src, iptr->dst);
992 M_COPY(src->prev, iptr->dst->prev);
993 M_COPY(src->prev->prev, iptr->dst->prev->prev);
994 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
995 M_COPY(src, iptr->dst->prev->prev->prev->prev);
996 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
999 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1001 M_COPY(src, iptr->dst->prev);
1002 M_COPY(src->prev, iptr->dst);
1006 /* integer operations *************************************************/
1008 case ICMD_INEG: /* ..., value ==> ..., - value */
1010 var_to_reg_int(s1, src, REG_ITMP1);
1011 d = reg_of_var(iptr->dst, REG_ITMP3);
1013 store_reg_to_var_int(iptr->dst, d);
1016 case ICMD_LNEG: /* ..., value ==> ..., - value */
1018 var_to_reg_int(s1, src, REG_ITMP1);
1019 d = reg_of_var(iptr->dst, REG_ITMP3);
1020 M_SUBFIC(secondregs[s1], 0, secondregs[d]);
1022 store_reg_to_var_int(iptr->dst, d);
1025 case ICMD_I2L: /* ..., value ==> ..., value */
1027 var_to_reg_int(s1, src, REG_ITMP2);
1028 d = reg_of_var(iptr->dst, REG_ITMP3);
1029 M_INTMOVE(s1, secondregs[d]);
1030 M_SRA_IMM(secondregs[d], 31, d);
1031 store_reg_to_var_int(iptr->dst, d);
1034 case ICMD_L2I: /* ..., value ==> ..., value */
1036 var_to_reg_int0(s1, src, REG_ITMP2, 0, 1);
1037 d = reg_of_var(iptr->dst, REG_ITMP2);
1039 store_reg_to_var_int(iptr->dst, d);
1042 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1044 var_to_reg_int(s1, src, REG_ITMP1);
1045 d = reg_of_var(iptr->dst, REG_ITMP3);
1047 store_reg_to_var_int(iptr->dst, d);
1050 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1052 var_to_reg_int(s1, src, REG_ITMP1);
1053 d = reg_of_var(iptr->dst, REG_ITMP3);
1055 store_reg_to_var_int(iptr->dst, d);
1058 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1060 var_to_reg_int(s1, src, REG_ITMP1);
1061 d = reg_of_var(iptr->dst, REG_ITMP3);
1063 store_reg_to_var_int(iptr->dst, d);
1067 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1069 var_to_reg_int(s1, src->prev, REG_ITMP1);
1070 var_to_reg_int(s2, src, REG_ITMP2);
1071 d = reg_of_var(iptr->dst, REG_ITMP3);
1073 store_reg_to_var_int(iptr->dst, d);
1076 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1077 /* val.i = constant */
1079 var_to_reg_int(s1, src, REG_ITMP1);
1080 d = reg_of_var(iptr->dst, REG_ITMP3);
1081 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1082 M_IADD_IMM(s1, iptr->val.i, d);
1085 ICONST(REG_ITMP2, iptr->val.i);
1086 M_IADD(s1, REG_ITMP2, d);
1088 store_reg_to_var_int(iptr->dst, d);
1091 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1093 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1094 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1095 d = reg_of_var(iptr->dst, REG_ITMP3);
1096 M_ADDC(s1, s2, secondregs[d]);
1097 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1098 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1100 store_reg_to_var_int(iptr->dst, d);
1103 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1104 /* val.l = constant */
1106 s3 = iptr->val.l & 0xffffffff;
1107 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1108 d = reg_of_var(iptr->dst, REG_ITMP3);
1109 if ((s3 >= -32768) && (s3 <= 32767)) {
1110 M_ADDIC(s1, s3, secondregs[d]);
1113 ICONST(REG_ITMP2, s3);
1114 M_ADDC(s1, REG_ITMP2, secondregs[d]);
1116 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1117 s3 = iptr->val.l >> 32;
1123 ICONST(REG_ITMP3, s3);
1124 M_ADDE(s1, REG_ITMP3, d);
1126 store_reg_to_var_int(iptr->dst, d);
1129 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1131 var_to_reg_int(s1, src->prev, REG_ITMP1);
1132 var_to_reg_int(s2, src, REG_ITMP2);
1133 d = reg_of_var(iptr->dst, REG_ITMP3);
1135 store_reg_to_var_int(iptr->dst, d);
1138 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1139 /* val.i = constant */
1141 var_to_reg_int(s1, src, REG_ITMP1);
1142 d = reg_of_var(iptr->dst, REG_ITMP3);
1143 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
1144 M_IADD_IMM(s1, -iptr->val.i, d);
1147 ICONST(REG_ITMP2, -iptr->val.i);
1148 M_IADD(s1, REG_ITMP2, d);
1150 store_reg_to_var_int(iptr->dst, d);
1153 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1155 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1156 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1157 d = reg_of_var(iptr->dst, REG_ITMP3);
1158 M_SUBC(s1, s2, secondregs[d]);
1159 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1160 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1162 store_reg_to_var_int(iptr->dst, d);
1165 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1166 /* val.l = constant */
1168 s3 = (-iptr->val.l) & 0xffffffff;
1169 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1170 d = reg_of_var(iptr->dst, REG_ITMP3);
1171 if ((s3 >= -32768) && (s3 <= 32767)) {
1172 M_ADDIC(s1, s3, secondregs[d]);
1175 ICONST(REG_ITMP2, s3);
1176 M_ADDC(s1, REG_ITMP2, secondregs[d]);
1178 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1179 s3 = (-iptr->val.l) >> 32;
1185 ICONST(REG_ITMP3, s3);
1186 M_ADDE(s1, REG_ITMP3, d);
1188 store_reg_to_var_int(iptr->dst, d);
1191 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1192 var_to_reg_int(s1, src->prev, REG_ITMP1);
1193 var_to_reg_int(s2, src, REG_ITMP2);
1194 d = reg_of_var(iptr->dst, REG_ITMP3);
1196 store_reg_to_var_int(iptr->dst, d);
1199 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1200 var_to_reg_int(s1, src->prev, REG_ITMP1);
1201 var_to_reg_int(s2, src, REG_ITMP2);
1202 d = reg_of_var(iptr->dst, REG_ITMP3);
1206 store_reg_to_var_int(iptr->dst, d);
1209 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1211 var_to_reg_int(s1, src->prev, REG_ITMP1);
1212 var_to_reg_int(s2, src, REG_ITMP2);
1213 d = reg_of_var(iptr->dst, REG_ITMP3);
1215 store_reg_to_var_int(iptr->dst, d);
1218 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1219 /* val.i = constant */
1221 var_to_reg_int(s1, src, REG_ITMP1);
1222 d = reg_of_var(iptr->dst, REG_ITMP3);
1223 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1224 M_IMUL_IMM(s1, iptr->val.i, d);
1227 ICONST(REG_ITMP2, iptr->val.i);
1228 M_IMUL(s1, REG_ITMP2, d);
1230 store_reg_to_var_int(iptr->dst, d);
1233 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1235 var_to_reg_int(s1, src, REG_ITMP1);
1236 d = reg_of_var(iptr->dst, REG_ITMP3);
1237 M_SRA_IMM(s1, iptr->val.i, d);
1239 store_reg_to_var_int(iptr->dst, d);
1242 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1244 var_to_reg_int(s1, src->prev, REG_ITMP1);
1245 var_to_reg_int(s2, src, REG_ITMP2);
1246 d = reg_of_var(iptr->dst, REG_ITMP3);
1247 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1248 M_SLL(s1, REG_ITMP3, d);
1249 store_reg_to_var_int(iptr->dst, d);
1252 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1253 /* val.i = constant */
1255 var_to_reg_int(s1, src, REG_ITMP1);
1256 d = reg_of_var(iptr->dst, REG_ITMP3);
1257 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1258 store_reg_to_var_int(iptr->dst, d);
1261 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1263 var_to_reg_int(s1, src->prev, REG_ITMP1);
1264 var_to_reg_int(s2, src, REG_ITMP2);
1265 d = reg_of_var(iptr->dst, REG_ITMP3);
1266 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1267 M_SRA(s1, REG_ITMP3, d);
1268 store_reg_to_var_int(iptr->dst, d);
1271 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1272 /* val.i = constant */
1274 var_to_reg_int(s1, src, REG_ITMP1);
1275 d = reg_of_var(iptr->dst, REG_ITMP3);
1276 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1277 store_reg_to_var_int(iptr->dst, d);
1280 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1282 var_to_reg_int(s1, src->prev, REG_ITMP1);
1283 var_to_reg_int(s2, src, REG_ITMP2);
1284 d = reg_of_var(iptr->dst, REG_ITMP3);
1285 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1286 M_SRL(s1, REG_ITMP2, d);
1287 store_reg_to_var_int(iptr->dst, d);
1290 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1291 /* val.i = constant */
1293 var_to_reg_int(s1, src, REG_ITMP1);
1294 d = reg_of_var(iptr->dst, REG_ITMP3);
1295 if (iptr->val.i & 0x1f)
1296 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1299 store_reg_to_var_int(iptr->dst, d);
1302 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1304 var_to_reg_int(s1, src->prev, REG_ITMP1);
1305 var_to_reg_int(s2, src, REG_ITMP2);
1306 d = reg_of_var(iptr->dst, REG_ITMP3);
1308 store_reg_to_var_int(iptr->dst, d);
1311 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1312 /* val.i = constant */
1314 var_to_reg_int(s1, src, REG_ITMP1);
1315 d = reg_of_var(iptr->dst, REG_ITMP3);
1316 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1317 M_AND_IMM(s1, iptr->val.i, d);
1320 else if (iptr->val.i == 0xffffff) {
1321 M_RLWINM(s1, 0, 8, 31, d);
1325 ICONST(REG_ITMP2, iptr->val.i);
1326 M_AND(s1, REG_ITMP2, d);
1328 store_reg_to_var_int(iptr->dst, d);
1331 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1333 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1334 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1335 d = reg_of_var(iptr->dst, REG_ITMP3);
1336 M_AND(s1, s2, secondregs[d]);
1337 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1338 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1340 store_reg_to_var_int(iptr->dst, d);
1343 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1344 /* val.l = constant */
1346 s3 = iptr->val.l & 0xffffffff;
1347 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1348 d = reg_of_var(iptr->dst, REG_ITMP3);
1349 if ((s3 >= 0) && (s3 <= 65535)) {
1350 M_AND_IMM(s1, s3, secondregs[d]);
1353 ICONST(REG_ITMP2, s3);
1354 M_AND(s1, REG_ITMP2, secondregs[d]);
1356 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1357 s3 = iptr->val.l >> 32;
1358 if ((s3 >= 0) && (s3 <= 65535)) {
1359 M_AND_IMM(s1, s3, d);
1362 ICONST(REG_ITMP3, s3);
1363 M_AND(s1, REG_ITMP3, d);
1365 store_reg_to_var_int(iptr->dst, d);
1368 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1369 /* val.i = constant */
1371 var_to_reg_int(s1, src, REG_ITMP1);
1372 d = reg_of_var(iptr->dst, REG_ITMP3);
1373 M_MOV(s1, REG_ITMP2);
1375 M_BGE(1 + 2*(iptr->val.i >= 32768));
1376 if (iptr->val.i >= 32768) {
1377 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1378 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1379 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1382 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1384 int b=0, m = iptr->val.i;
1387 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1389 M_ISUB(s1, REG_ITMP2, d);
1390 store_reg_to_var_int(iptr->dst, d);
1393 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1395 var_to_reg_int(s1, src->prev, REG_ITMP1);
1396 var_to_reg_int(s2, src, REG_ITMP2);
1397 d = reg_of_var(iptr->dst, REG_ITMP3);
1399 store_reg_to_var_int(iptr->dst, d);
1402 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1403 /* val.i = constant */
1405 var_to_reg_int(s1, src, REG_ITMP1);
1406 d = reg_of_var(iptr->dst, REG_ITMP3);
1407 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1408 M_OR_IMM(s1, iptr->val.i, d);
1411 ICONST(REG_ITMP2, iptr->val.i);
1412 M_OR(s1, REG_ITMP2, d);
1414 store_reg_to_var_int(iptr->dst, d);
1417 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1419 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1420 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1421 d = reg_of_var(iptr->dst, REG_ITMP3);
1422 M_OR(s1, s2, secondregs[d]);
1423 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1424 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1426 store_reg_to_var_int(iptr->dst, d);
1429 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1430 /* val.l = constant */
1432 s3 = iptr->val.l & 0xffffffff;
1433 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1434 d = reg_of_var(iptr->dst, REG_ITMP3);
1435 if ((s3 >= 0) && (s3 <= 65535)) {
1436 M_OR_IMM(s1, s3, secondregs[d]);
1439 ICONST(REG_ITMP2, s3);
1440 M_OR(s1, REG_ITMP2, secondregs[d]);
1442 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1443 s3 = iptr->val.l >> 32;
1444 if ((s3 >= 0) && (s3 <= 65535)) {
1445 M_OR_IMM(s1, s3, d);
1448 ICONST(REG_ITMP3, s3);
1449 M_OR(s1, REG_ITMP3, d);
1451 store_reg_to_var_int(iptr->dst, d);
1454 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1456 var_to_reg_int(s1, src->prev, REG_ITMP1);
1457 var_to_reg_int(s2, src, REG_ITMP2);
1458 d = reg_of_var(iptr->dst, REG_ITMP3);
1460 store_reg_to_var_int(iptr->dst, d);
1463 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1464 /* val.i = constant */
1466 var_to_reg_int(s1, src, REG_ITMP1);
1467 d = reg_of_var(iptr->dst, REG_ITMP3);
1468 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1469 M_XOR_IMM(s1, iptr->val.i, d);
1472 ICONST(REG_ITMP2, iptr->val.i);
1473 M_XOR(s1, REG_ITMP2, d);
1475 store_reg_to_var_int(iptr->dst, d);
1478 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1480 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1481 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1482 d = reg_of_var(iptr->dst, REG_ITMP3);
1483 M_XOR(s1, s2, secondregs[d]);
1484 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1485 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1487 store_reg_to_var_int(iptr->dst, d);
1490 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1491 /* val.l = constant */
1493 s3 = iptr->val.l & 0xffffffff;
1494 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1495 d = reg_of_var(iptr->dst, REG_ITMP3);
1496 if ((s3 >= 0) && (s3 <= 65535)) {
1497 M_XOR_IMM(s1, s3, secondregs[d]);
1500 ICONST(REG_ITMP2, s3);
1501 M_XOR(s1, REG_ITMP2, secondregs[d]);
1503 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1504 s3 = iptr->val.l >> 32;
1505 if ((s3 >= 0) && (s3 <= 65535)) {
1506 M_XOR_IMM(s1, s3, d);
1509 ICONST(REG_ITMP3, s3);
1510 M_XOR(s1, REG_ITMP3, d);
1512 store_reg_to_var_int(iptr->dst, d);
1515 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1517 var_to_reg_int0(s1, src->prev, REG_ITMP3, 1, 0);
1518 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
1519 d = reg_of_var(iptr->dst, REG_ITMP1);
1522 (d==s1 || d==s2 || d==secondregs[s1] || d==secondregs[s2]);
1523 int dreg = tempreg ? REG_ITMP1 : d;
1525 M_IADD_IMM(REG_ZERO, 1, dreg);
1530 var_to_reg_int0(s1, src->prev, REG_ITMP3, 0, 1);
1531 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1535 M_IADD_IMM(dreg, -1, dreg);
1536 M_IADD_IMM(dreg, -1, dreg);
1537 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1538 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1541 store_reg_to_var_int(iptr->dst, d);
1544 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1545 /* op1 = variable, val.i = constant */
1547 var = &(locals[iptr->op1][TYPE_INT]);
1548 if (var->flags & INMEMORY) {
1550 M_ILD(s1, REG_SP, 4 * var->regoff);
1559 M_ADDIS(s1, m>>16, s1);
1561 M_IADD_IMM(s1, m&0xffff, s1);
1563 if (var->flags & INMEMORY)
1564 M_IST(s1, REG_SP, 4 * var->regoff);
1568 /* floating operations ************************************************/
1570 case ICMD_FNEG: /* ..., value ==> ..., - value */
1572 var_to_reg_flt(s1, src, REG_FTMP1);
1573 d = reg_of_var(iptr->dst, REG_FTMP3);
1575 store_reg_to_var_flt(iptr->dst, d);
1578 case ICMD_DNEG: /* ..., value ==> ..., - value */
1580 var_to_reg_flt(s1, src, REG_FTMP1);
1581 d = reg_of_var(iptr->dst, REG_FTMP3);
1583 store_reg_to_var_flt(iptr->dst, d);
1586 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1588 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1589 var_to_reg_flt(s2, src, REG_FTMP2);
1590 d = reg_of_var(iptr->dst, REG_FTMP3);
1592 store_reg_to_var_flt(iptr->dst, d);
1595 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1597 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1598 var_to_reg_flt(s2, src, REG_FTMP2);
1599 d = reg_of_var(iptr->dst, REG_FTMP3);
1601 store_reg_to_var_flt(iptr->dst, d);
1604 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1606 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1607 var_to_reg_flt(s2, src, REG_FTMP2);
1608 d = reg_of_var(iptr->dst, REG_FTMP3);
1610 store_reg_to_var_flt(iptr->dst, d);
1613 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1615 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1616 var_to_reg_flt(s2, src, REG_FTMP2);
1617 d = reg_of_var(iptr->dst, REG_FTMP3);
1619 store_reg_to_var_flt(iptr->dst, d);
1622 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1624 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1625 var_to_reg_flt(s2, src, REG_FTMP2);
1626 d = reg_of_var(iptr->dst, REG_FTMP3);
1628 store_reg_to_var_flt(iptr->dst, d);
1631 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1633 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1634 var_to_reg_flt(s2, src, REG_FTMP2);
1635 d = reg_of_var(iptr->dst, REG_FTMP3);
1637 store_reg_to_var_flt(iptr->dst, d);
1640 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1642 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1643 var_to_reg_flt(s2, src, REG_FTMP2);
1644 d = reg_of_var(iptr->dst, REG_FTMP3);
1646 store_reg_to_var_flt(iptr->dst, d);
1649 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1651 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1652 var_to_reg_flt(s2, src, REG_FTMP2);
1653 d = reg_of_var(iptr->dst, REG_FTMP3);
1655 store_reg_to_var_flt(iptr->dst, d);
1658 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1660 var_to_reg_flt(s1, src, REG_FTMP1);
1661 d = reg_of_var(iptr->dst, REG_ITMP3);
1663 a = dseg_addfloat(0.0);
1664 M_FLD(REG_FTMP2, REG_PV, a);
1665 M_FCMPU(s1, REG_FTMP2);
1668 M_CVTDL_C(s1, REG_FTMP1);
1669 M_LDA (REG_ITMP1, REG_PV, a);
1670 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1671 M_ILD (d, REG_PV, a);
1672 store_reg_to_var_int(iptr->dst, d);
1675 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1677 var_to_reg_flt(s1, src, REG_FTMP1);
1678 d = reg_of_var(iptr->dst, REG_FTMP3);
1680 store_reg_to_var_flt(iptr->dst, d);
1683 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1685 var_to_reg_flt(s1, src, REG_FTMP1);
1686 d = reg_of_var(iptr->dst, REG_FTMP3);
1688 store_reg_to_var_flt(iptr->dst, d);
1691 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1693 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1694 var_to_reg_flt(s2, src, REG_FTMP2);
1695 d = reg_of_var(iptr->dst, REG_ITMP3);
1697 M_IADD_IMM(0, -1, d);
1700 M_IADD_IMM(0, 0, d);
1702 M_IADD_IMM(0, 1, d);
1703 store_reg_to_var_int(iptr->dst, d);
1706 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1708 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1709 var_to_reg_flt(s2, src, REG_FTMP2);
1710 d = reg_of_var(iptr->dst, REG_ITMP3);
1712 M_IADD_IMM(0, 1, d);
1715 M_IADD_IMM(0, 0, d);
1717 M_IADD_IMM(0, -1, d);
1718 store_reg_to_var_int(iptr->dst, d);
1722 /* memory operations **************************************************/
1724 #define gen_bound_check \
1725 if (checkbounds) { \
1726 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1727 M_CMPU(s2, REG_ITMP3);\
1729 codegen_addxboundrefs(mcodeptr); \
1732 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1734 var_to_reg_int(s1, src, REG_ITMP1);
1735 d = reg_of_var(iptr->dst, REG_ITMP3);
1736 gen_nullptr_check(s1);
1737 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1738 store_reg_to_var_int(iptr->dst, d);
1741 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1743 var_to_reg_int(s1, src->prev, REG_ITMP1);
1744 var_to_reg_int(s2, src, REG_ITMP2);
1745 d = reg_of_var(iptr->dst, REG_ITMP3);
1746 if (iptr->op1 == 0) {
1747 gen_nullptr_check(s1);
1750 M_SLL_IMM(s2, 2, REG_ITMP2);
1751 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1752 M_LWZX(d, s1, REG_ITMP2);
1753 store_reg_to_var_int(iptr->dst, d);
1756 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1758 var_to_reg_int(s1, src->prev, REG_ITMP1);
1759 var_to_reg_int(s2, src, REG_ITMP2);
1760 d = reg_of_var(iptr->dst, REG_ITMP3);
1761 if (iptr->op1 == 0) {
1762 gen_nullptr_check(s1);
1765 M_SLL_IMM(s2, 3, REG_ITMP2);
1766 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1767 M_ILD(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
1768 M_ILD(secondregs[d], REG_ITMP2, OFFSET(java_longarray, data[0])+4);
1769 store_reg_to_var_int(iptr->dst, d);
1772 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1774 var_to_reg_int(s1, src->prev, REG_ITMP1);
1775 var_to_reg_int(s2, src, REG_ITMP2);
1776 d = reg_of_var(iptr->dst, REG_ITMP3);
1777 if (iptr->op1 == 0) {
1778 gen_nullptr_check(s1);
1781 M_SLL_IMM(s2, 2, REG_ITMP2);
1782 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1783 M_LWZX(d, s1, REG_ITMP2);
1784 store_reg_to_var_int(iptr->dst, d);
1787 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1789 var_to_reg_int(s1, src->prev, REG_ITMP1);
1790 var_to_reg_int(s2, src, REG_ITMP2);
1791 d = reg_of_var(iptr->dst, REG_FTMP3);
1792 if (iptr->op1 == 0) {
1793 gen_nullptr_check(s1);
1796 M_SLL_IMM(s2, 2, REG_ITMP2);
1797 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1798 M_LFSX(d, s1, REG_ITMP2);
1799 store_reg_to_var_flt(iptr->dst, d);
1802 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1804 var_to_reg_int(s1, src->prev, REG_ITMP1);
1805 var_to_reg_int(s2, src, REG_ITMP2);
1806 d = reg_of_var(iptr->dst, REG_FTMP3);
1807 if (iptr->op1 == 0) {
1808 gen_nullptr_check(s1);
1811 M_SLL_IMM(s2, 3, REG_ITMP2);
1812 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1813 M_LFDX(d, s1, REG_ITMP2);
1814 store_reg_to_var_flt(iptr->dst, d);
1817 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1819 var_to_reg_int(s1, src->prev, REG_ITMP1);
1820 var_to_reg_int(s2, src, REG_ITMP2);
1821 d = reg_of_var(iptr->dst, REG_ITMP3);
1822 if (iptr->op1 == 0) {
1823 gen_nullptr_check(s1);
1826 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1827 M_LBZX(d, s1, REG_ITMP2);
1829 store_reg_to_var_int(iptr->dst, d);
1832 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1834 var_to_reg_int(s1, src->prev, REG_ITMP1);
1835 var_to_reg_int(s2, src, REG_ITMP2);
1836 d = reg_of_var(iptr->dst, REG_ITMP3);
1837 if (iptr->op1 == 0) {
1838 gen_nullptr_check(s1);
1841 M_SLL_IMM(s2, 1, REG_ITMP2);
1842 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1843 M_LHAX(d, s1, REG_ITMP2);
1844 store_reg_to_var_int(iptr->dst, d);
1847 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1849 var_to_reg_int(s1, src->prev, REG_ITMP1);
1850 var_to_reg_int(s2, src, REG_ITMP2);
1851 d = reg_of_var(iptr->dst, REG_ITMP3);
1852 if (iptr->op1 == 0) {
1853 gen_nullptr_check(s1);
1856 M_SLL_IMM(s2, 1, REG_ITMP2);
1857 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1858 M_LHZX(d, s1, REG_ITMP2);
1859 store_reg_to_var_int(iptr->dst, d);
1862 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1864 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1865 var_to_reg_int(s2, src->prev, REG_ITMP2);
1866 if (iptr->op1 == 0) {
1867 gen_nullptr_check(s1);
1870 var_to_reg_int0(s3, src, REG_ITMP3, 1, 0);
1871 M_SLL_IMM(s2, 3, REG_ITMP2);
1872 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1873 M_STWX(s3, s1, REG_ITMP2);
1874 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1875 var_to_reg_int0(s3, src, REG_ITMP3, 0, 1);
1876 M_STWX(s3, s1, REG_ITMP2);
1879 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1881 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1882 var_to_reg_int(s2, src->prev, REG_ITMP2);
1883 if (iptr->op1 == 0) {
1884 gen_nullptr_check(s1);
1887 var_to_reg_int(s3, src, REG_ITMP3);
1888 M_SLL_IMM(s2, 2, REG_ITMP2);
1889 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1890 M_STWX(s3, s1, REG_ITMP2);
1893 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1895 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1896 var_to_reg_int(s2, src->prev, REG_ITMP2);
1897 if (iptr->op1 == 0) {
1898 gen_nullptr_check(s1);
1901 var_to_reg_flt(s3, src, REG_FTMP3);
1902 M_SLL_IMM(s2, 2, REG_ITMP2);
1903 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1904 M_STFSX(s3, s1, REG_ITMP2);
1907 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1909 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1910 var_to_reg_int(s2, src->prev, REG_ITMP2);
1911 if (iptr->op1 == 0) {
1912 gen_nullptr_check(s1);
1915 var_to_reg_flt(s3, src, REG_FTMP3);
1916 M_SLL_IMM(s2, 3, REG_ITMP2);
1917 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1918 M_STFDX(s3, s1, REG_ITMP2);
1921 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1923 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1924 var_to_reg_int(s2, src->prev, REG_ITMP2);
1925 if (iptr->op1 == 0) {
1926 gen_nullptr_check(s1);
1929 var_to_reg_int(s3, src, REG_ITMP3);
1930 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1931 M_STBX(s3, s1, REG_ITMP2);
1934 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1936 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1937 var_to_reg_int(s2, src->prev, REG_ITMP2);
1938 if (iptr->op1 == 0) {
1939 gen_nullptr_check(s1);
1942 var_to_reg_int(s3, src, REG_ITMP3);
1943 M_SLL_IMM(s2, 1, REG_ITMP2);
1944 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1945 M_STHX(s3, s1, REG_ITMP2);
1948 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1950 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1951 var_to_reg_int(s2, src->prev, REG_ITMP2);
1952 if (iptr->op1 == 0) {
1953 gen_nullptr_check(s1);
1956 var_to_reg_int(s3, src, REG_ITMP3);
1957 M_SLL_IMM(s2, 1, REG_ITMP2);
1958 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1959 M_STHX(s3, s1, REG_ITMP2);
1962 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1963 /* op1 = type, val.a = field address */
1965 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
1966 M_ALD(REG_ITMP1, REG_PV, a);
1967 switch (iptr->op1) {
1969 var_to_reg_int(s2, src, REG_ITMP2);
1970 M_IST(s2, REG_ITMP1, 0);
1973 var_to_reg_int(s2, src, REG_ITMP3);
1974 M_IST(s2, REG_ITMP1, 0);
1975 M_IST(secondregs[s2], REG_ITMP1, 4);
1978 var_to_reg_int(s2, src, REG_ITMP2);
1979 M_AST(s2, REG_ITMP1, 0);
1982 var_to_reg_flt(s2, src, REG_FTMP2);
1983 M_FST(s2, REG_ITMP1, 0);
1986 var_to_reg_flt(s2, src, REG_FTMP2);
1987 M_DST(s2, REG_ITMP1, 0);
1989 default: panic ("internal error");
1993 case ICMD_GETSTATIC: /* ... ==> ..., value */
1994 /* op1 = type, val.a = field address */
1996 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
1997 M_ALD(REG_ITMP1, REG_PV, a);
1998 switch (iptr->op1) {
2000 d = reg_of_var(iptr->dst, REG_ITMP3);
2001 M_ILD(d, REG_ITMP1, 0);
2002 store_reg_to_var_int(iptr->dst, d);
2005 d = reg_of_var(iptr->dst, REG_ITMP3);
2006 M_ILD(d, REG_ITMP1, 0);
2007 M_ILD(secondregs[d], REG_ITMP1, 4);
2008 store_reg_to_var_int(iptr->dst, d);
2011 d = reg_of_var(iptr->dst, REG_ITMP3);
2012 M_ALD(d, REG_ITMP1, 0);
2013 store_reg_to_var_int(iptr->dst, d);
2016 d = reg_of_var(iptr->dst, REG_FTMP1);
2017 M_FLD(d, REG_ITMP1, 0);
2018 store_reg_to_var_flt(iptr->dst, d);
2021 d = reg_of_var(iptr->dst, REG_FTMP1);
2022 M_DLD(d, REG_ITMP1, 0);
2023 store_reg_to_var_flt(iptr->dst, d);
2025 default: panic ("internal error");
2030 case ICMD_PUTFIELD: /* ..., value ==> ... */
2031 /* op1 = type, val.i = field offset */
2033 a = ((fieldinfo *)(iptr->val.a))->offset;
2034 switch (iptr->op1) {
2036 var_to_reg_int(s1, src->prev, REG_ITMP1);
2037 var_to_reg_int(s2, src, REG_ITMP2);
2038 gen_nullptr_check(s1);
2042 var_to_reg_int(s1, src->prev, REG_ITMP1);
2043 var_to_reg_int(s2, src, REG_ITMP3);
2044 gen_nullptr_check(s1);
2046 M_IST(secondregs[s2], s1, a+4);
2049 var_to_reg_int(s1, src->prev, REG_ITMP1);
2050 var_to_reg_int(s2, src, REG_ITMP2);
2051 gen_nullptr_check(s1);
2055 var_to_reg_int(s1, src->prev, REG_ITMP1);
2056 var_to_reg_flt(s2, src, REG_FTMP2);
2057 gen_nullptr_check(s1);
2061 var_to_reg_int(s1, src->prev, REG_ITMP1);
2062 var_to_reg_flt(s2, src, REG_FTMP2);
2063 gen_nullptr_check(s1);
2066 default: panic ("internal error");
2070 case ICMD_GETFIELD: /* ... ==> ..., value */
2071 /* op1 = type, val.i = field offset */
2073 a = ((fieldinfo *)(iptr->val.a))->offset;
2074 switch (iptr->op1) {
2076 var_to_reg_int(s1, src, REG_ITMP1);
2077 d = reg_of_var(iptr->dst, REG_ITMP3);
2078 gen_nullptr_check(s1);
2080 store_reg_to_var_int(iptr->dst, d);
2083 var_to_reg_int(s1, src, REG_ITMP1);
2084 d = reg_of_var(iptr->dst, REG_ITMP3);
2085 gen_nullptr_check(s1);
2087 M_ILD(secondregs[d], s1, a+4);
2088 store_reg_to_var_int(iptr->dst, d);
2091 var_to_reg_int(s1, src, REG_ITMP1);
2092 d = reg_of_var(iptr->dst, REG_ITMP3);
2093 gen_nullptr_check(s1);
2095 store_reg_to_var_int(iptr->dst, d);
2098 var_to_reg_int(s1, src, REG_ITMP1);
2099 d = reg_of_var(iptr->dst, REG_FTMP1);
2100 gen_nullptr_check(s1);
2102 store_reg_to_var_flt(iptr->dst, d);
2105 var_to_reg_int(s1, src, REG_ITMP1);
2106 d = reg_of_var(iptr->dst, REG_FTMP1);
2107 gen_nullptr_check(s1);
2109 store_reg_to_var_flt(iptr->dst, d);
2111 default: panic ("internal error");
2116 /* branch operations **************************************************/
2118 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2120 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2122 a = dseg_addaddress(asm_handle_exception);
2123 M_ALD(REG_ITMP2, REG_PV, a);
2125 var_to_reg_int(s1, src, REG_ITMP1);
2126 M_INTMOVE(s1, REG_ITMP1_XPTR);
2128 if (isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
2129 M_BL(0); /* get current PC */
2130 M_MFLR(REG_ITMP2_XPC);
2131 if (isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
2132 M_RTS; /* jump to CTR */
2137 case ICMD_GOTO: /* ... ==> ... */
2138 /* op1 = target JavaVM pc */
2140 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2144 case ICMD_JSR: /* ... ==> ... */
2145 /* op1 = target JavaVM pc */
2147 if (isleafmethod) M_MFLR(REG_ITMP2);
2150 M_IADD_IMM(REG_ITMP1, isleafmethod?16:12, REG_ITMP1);
2151 if (isleafmethod) M_MTLR(REG_ITMP2);
2153 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2156 case ICMD_RET: /* ... ==> ... */
2157 /* op1 = local variable */
2159 var = &(locals[iptr->op1][TYPE_ADR]);
2160 if (var->flags & INMEMORY) {
2161 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
2165 M_MTCTR(var->regoff);
2170 case ICMD_IFNULL: /* ..., value ==> ... */
2171 /* op1 = target JavaVM pc */
2173 var_to_reg_int(s1, src, REG_ITMP1);
2176 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2179 case ICMD_IFNONNULL: /* ..., value ==> ... */
2180 /* op1 = target JavaVM pc */
2182 var_to_reg_int(s1, src, REG_ITMP1);
2185 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2193 case ICMD_IFEQ: /* ..., value ==> ... */
2194 /* op1 = target JavaVM pc, val.i = constant */
2196 var_to_reg_int(s1, src, REG_ITMP1);
2197 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2198 M_CMPI(s1, iptr->val.i);
2201 ICONST(REG_ITMP2, iptr->val.i);
2202 M_CMP(s1, REG_ITMP2);
2225 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2229 case ICMD_IF_LEQ: /* ..., value ==> ... */
2230 /* op1 = target JavaVM pc, val.l = constant */
2232 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2233 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2234 if (iptr->val.l == 0) {
2235 M_OR(s1, s2, REG_ITMP3);
2236 M_CMPI(REG_ITMP3, 0);
2238 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2239 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2241 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2244 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2245 M_CMP(s2, REG_ITMP3);
2247 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2248 M_CMP(s1, REG_ITMP3)
2251 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2254 case ICMD_IF_LLT: /* ..., value ==> ... */
2255 /* op1 = target JavaVM pc, val.l = constant */
2256 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2257 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2258 /* if (iptr->val.l == 0) { */
2259 /* M_OR(s1, s2, REG_ITMP3); */
2260 /* M_CMPI(REG_ITMP3, 0); */
2263 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2264 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2266 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2268 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2271 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2272 M_CMP(s2, REG_ITMP3);
2274 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2276 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2277 M_CMP(s1, REG_ITMP3)
2280 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2283 case ICMD_IF_LLE: /* ..., value ==> ... */
2284 /* op1 = target JavaVM pc, val.l = constant */
2286 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2287 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2288 /* if (iptr->val.l == 0) { */
2289 /* M_OR(s1, s2, REG_ITMP3); */
2290 /* M_CMPI(REG_ITMP3, 0); */
2293 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2294 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2296 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2298 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2301 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2302 M_CMP(s2, REG_ITMP3);
2304 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2306 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2307 M_CMP(s1, REG_ITMP3)
2310 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2313 case ICMD_IF_LNE: /* ..., value ==> ... */
2314 /* op1 = target JavaVM pc, val.l = constant */
2316 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2317 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2318 if (iptr->val.l == 0) {
2319 M_OR(s1, s2, REG_ITMP3);
2320 M_CMPI(REG_ITMP3, 0);
2322 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2323 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2325 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2328 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2329 M_CMP(s2, REG_ITMP3);
2331 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2332 M_CMP(s1, REG_ITMP3)
2335 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2338 case ICMD_IF_LGT: /* ..., value ==> ... */
2339 /* op1 = target JavaVM pc, val.l = constant */
2341 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2342 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2343 /* if (iptr->val.l == 0) { */
2344 /* M_OR(s1, s2, REG_ITMP3); */
2345 /* M_CMPI(REG_ITMP3, 0); */
2348 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2349 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2351 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2353 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2356 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2357 M_CMP(s2, REG_ITMP3);
2359 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2361 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2362 M_CMP(s1, REG_ITMP3)
2365 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2368 case ICMD_IF_LGE: /* ..., value ==> ... */
2369 /* op1 = target JavaVM pc, val.l = constant */
2370 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2371 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2372 /* if (iptr->val.l == 0) { */
2373 /* M_OR(s1, s2, REG_ITMP3); */
2374 /* M_CMPI(REG_ITMP3, 0); */
2377 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2378 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2380 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2382 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2385 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2386 M_CMP(s2, REG_ITMP3);
2388 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2390 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2391 M_CMP(s1, REG_ITMP3)
2394 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2398 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2399 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2400 case ICMD_IF_ACMPEQ:
2402 var_to_reg_int(s1, src->prev, REG_ITMP1);
2403 var_to_reg_int(s2, src, REG_ITMP2);
2406 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2409 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2410 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2411 case ICMD_IF_ACMPNE:
2413 var_to_reg_int(s1, src->prev, REG_ITMP1);
2414 var_to_reg_int(s2, src, REG_ITMP2);
2417 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2420 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2421 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2423 var_to_reg_int(s1, src->prev, REG_ITMP1);
2424 var_to_reg_int(s2, src, REG_ITMP2);
2427 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2430 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2431 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2433 var_to_reg_int(s1, src->prev, REG_ITMP1);
2434 var_to_reg_int(s2, src, REG_ITMP2);
2437 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2440 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2441 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2443 var_to_reg_int(s1, src->prev, REG_ITMP1);
2444 var_to_reg_int(s2, src, REG_ITMP2);
2447 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2450 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2451 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2453 var_to_reg_int(s1, src->prev, REG_ITMP1);
2454 var_to_reg_int(s2, src, REG_ITMP2);
2457 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2460 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2464 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2467 case ICMD_RETURN: /* ... ==> ... */
2470 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2471 a = dseg_addaddress ((void*) (builtin_monitorexit));
2472 M_ALD(REG_ITMP3, REG_PV, a);
2474 M_ALD(argintregs[0], REG_SP, 4 * maxmemuse);
2478 switch (iptr->opc) {
2482 var_to_reg_int(s1, src, REG_RESULT);
2483 M_TINTMOVE(src->type, s1, REG_RESULT);
2484 goto nowperformreturn;
2488 var_to_reg_flt(s1, src, REG_FRESULT);
2489 M_FLTMOVE(s1, REG_FRESULT);
2490 goto nowperformreturn;
2497 p = parentargs_base;
2499 /* restore return address */
2501 if (!isleafmethod) {
2502 M_ALD (REG_ITMP3, REG_SP, 4 * p + 8);
2506 /* restore saved registers */
2508 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
2509 {p--; M_ILD(savintregs[r], REG_SP, 4 * p);}
2510 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
2511 {p-=2; M_DLD(savfltregs[r], REG_SP, 4 * p);}
2513 /* deallocate stack */
2515 if (parentargs_base)
2516 {M_LDA(REG_SP, REG_SP, parentargs_base*4);}
2518 /* call trace function */
2523 M_LDA (REG_SP, REG_SP, -80);
2524 M_DST(REG_FRESULT, REG_SP, 48+0);
2525 M_IST(REG_RESULT, REG_SP, 48+8);
2526 M_AST(REG_ITMP3, REG_SP, 48+12);
2527 M_IST(REG_RESULT+1, REG_SP, 48+16);
2528 a = dseg_addaddress (method);
2529 M_MOV(REG_RESULT+1, argintregs[2]);
2530 M_MOV(REG_RESULT, argintregs[1]);
2531 M_ALD(argintregs[0], REG_PV, a);
2532 M_FLTMOVE(REG_FRESULT, argfltregs[0]);
2533 M_FLTMOVE(REG_FRESULT, argfltregs[1]);
2534 a = dseg_addaddress ((void*) (builtin_displaymethodstop));
2535 M_ALD(REG_ITMP2, REG_PV, a);
2538 M_DLD(REG_FRESULT, REG_SP, 48+0);
2539 M_ILD(REG_RESULT, REG_SP, 48+8);
2540 M_ALD(REG_ITMP3, REG_SP, 48+12);
2541 M_ILD(REG_RESULT+1, REG_SP, 48+16);
2542 M_LDA (REG_SP, REG_SP, 80);
2553 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2558 tptr = (void **) iptr->target;
2560 s4ptr = iptr->val.a;
2561 l = s4ptr[1]; /* low */
2562 i = s4ptr[2]; /* high */
2564 var_to_reg_int(s1, src, REG_ITMP1);
2566 {M_INTMOVE(s1, REG_ITMP1);}
2567 else if (l <= 32768) {
2568 M_LDA(REG_ITMP1, s1, -l);
2571 ICONST(REG_ITMP2, l);
2572 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2578 M_CMPUI(REG_ITMP1, i - 1);
2582 /* codegen_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2583 codegen_addreference((basicblock *) tptr[0], mcodeptr);
2585 /* build jump table top down and use address of lowest entry */
2587 /* s4ptr += 3 + i; */
2591 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
2592 dseg_addtarget((basicblock *) tptr[0]);
2597 /* length of dataseg after last dseg_addtarget is used by load */
2599 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2600 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2601 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
2608 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2610 s4 i, l, val, *s4ptr;
2613 tptr = (void **) iptr->target;
2615 s4ptr = iptr->val.a;
2616 l = s4ptr[0]; /* default */
2617 i = s4ptr[1]; /* count */
2619 MCODECHECK((i<<2)+8);
2620 var_to_reg_int(s1, src, REG_ITMP1);
2626 if ((val >= -32768) && (val <= 32767)) {
2630 a = dseg_adds4 (val);
2631 M_ILD(REG_ITMP2, REG_PV, a);
2632 M_CMP(s1, REG_ITMP2);
2635 /* codegen_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2636 codegen_addreference((basicblock *) tptr[0], mcodeptr);
2640 /* codegen_addreference(BlockPtrOfPC(l), mcodeptr); */
2642 tptr = (void **) iptr->target;
2643 codegen_addreference((basicblock *) tptr[0], mcodeptr);
2650 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2651 /* op1 = return type, val.a = function pointer*/
2655 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2656 /* op1 = return type, val.a = function pointer*/
2660 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2661 /* op1 = return type, val.a = function pointer*/
2665 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2666 /* op1 = arg count, val.a = method pointer */
2668 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2669 /* op1 = arg count, val.a = method pointer */
2671 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2672 /* op1 = arg count, val.a = method pointer */
2674 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2675 /* op1 = arg count, val.a = method pointer */
2683 MCODECHECK((s3 << 1) + 64);
2686 /* copy arguments to registers or stack location */
2688 stackptr srcsave = src;
2692 for (; --s3 >= 0; src = src->prev) {
2693 argsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
2694 if (IS_FLT_DBL_TYPE(src->type))
2698 for (s3=s3save, src=srcsave; --s3 >= 0; src = src->prev) {
2699 argsize -= IS_2_WORD_TYPE(src->type) ? 2 : 1;
2700 if (IS_FLT_DBL_TYPE(src->type))
2702 if (src->varkind == ARGVAR)
2704 if (IS_INT_LNG_TYPE(src->type)) {
2705 if (argsize < INT_ARG_CNT) {
2706 s1 = argintregs[argsize];
2707 var_to_reg_int(d, src, s1);
2708 if (argsize < INT_ARG_CNT-1)
2709 {M_TINTMOVE(src->type, d, s1);}
2712 if (IS_2_WORD_TYPE(src->type))
2713 M_IST(secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2717 var_to_reg_int(d, src, REG_ITMP1);
2718 M_IST(d, REG_SP, 4 * (argsize + 6));
2719 if (IS_2_WORD_TYPE(src->type))
2720 M_IST(secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2724 if (fltcnt < FLT_ARG_CNT) {
2725 s1 = argfltregs[fltcnt];
2726 var_to_reg_flt(d, src, s1);
2730 var_to_reg_flt(d, src, REG_FTMP1);
2731 if (IS_2_WORD_TYPE(src->type))
2732 M_DST(d, REG_SP, 4 * (argsize + 6));
2734 M_FST(d, REG_SP, 4 * (argsize + 6));
2740 switch (iptr->opc) {
2744 a = dseg_addaddress ((void*) (m));
2746 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2748 goto makeactualcall;
2750 case ICMD_INVOKESTATIC:
2751 case ICMD_INVOKESPECIAL:
2752 a = dseg_addaddress (m->stubroutine);
2754 M_ALD(REG_PV, REG_PV, a ); /* method pointer in r27 */
2757 goto makeactualcall;
2759 case ICMD_INVOKEVIRTUAL:
2761 gen_nullptr_check(argintregs[0]);
2762 M_ALD(REG_METHODPTR, argintregs[0],
2763 OFFSET(java_objectheader, vftbl));
2764 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
2765 sizeof(methodptr) * m->vftblindex);
2768 goto makeactualcall;
2770 case ICMD_INVOKEINTERFACE:
2773 gen_nullptr_check(argintregs[0]);
2774 M_ALD(REG_METHODPTR, argintregs[0],
2775 OFFSET(java_objectheader, vftbl));
2776 M_ALD(REG_METHODPTR, REG_METHODPTR,
2777 OFFSET(vftbl, interfacetable[0]) -
2778 sizeof(methodptr*) * ci->index);
2779 M_ALD(REG_PV, REG_METHODPTR,
2780 sizeof(methodptr) * (m - ci->methods));
2783 goto makeactualcall;
2787 error ("Unkown ICMD-Command: %d", iptr->opc);
2797 s1 = (int)((u1*) mcodeptr - mcodebase);
2799 if (s1<=32768) M_LDA (REG_PV, REG_ITMP1, -s1);
2802 while (ml<-32768) { ml+=65536; mh--; }
2803 M_LDA (REG_PV, REG_ITMP1, ml );
2804 M_LDAH (REG_PV, REG_PV, mh );
2807 /* d contains return type */
2809 if (d != TYPE_VOID) {
2810 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2811 s1 = reg_of_var(iptr->dst, REG_RESULT);
2812 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2813 store_reg_to_var_int(iptr->dst, s1);
2816 s1 = reg_of_var(iptr->dst, REG_FRESULT);
2817 M_FLTMOVE(REG_FRESULT, s1);
2818 store_reg_to_var_flt(iptr->dst, s1);
2825 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2827 /* op1: 0 == array, 1 == class */
2828 /* val.a: (classinfo*) superclass */
2830 /* superclass is an interface:
2832 * return (sub != NULL) &&
2833 * (sub->vftbl->interfacetablelength > super->index) &&
2834 * (sub->vftbl->interfacetable[-super->index] != NULL);
2836 * superclass is a class:
2838 * return ((sub != NULL) && (0
2839 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2840 * super->vftbl->diffvall));
2844 classinfo *super = (classinfo*) iptr->val.a;
2846 var_to_reg_int(s1, src, REG_ITMP1);
2847 d = reg_of_var(iptr->dst, REG_ITMP3);
2849 M_MOV(s1, REG_ITMP1);
2853 if (iptr->op1) { /* class/interface */
2855 if (super->flags & ACC_INTERFACE) { /* interface */
2857 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2858 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
2859 M_LDATST(REG_ITMP2, REG_ITMP2, - super->index);
2861 M_ALD(REG_ITMP1, REG_ITMP1,
2862 OFFSET(vftbl, interfacetable[0]) -
2863 super->index * sizeof(methodptr*));
2867 M_IADD_IMM(REG_ZERO, 1, d);
2871 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2872 a = dseg_addaddress ((void*) super->vftbl);
2873 M_ALD(REG_ITMP2, REG_PV, a);
2874 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
2875 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
2876 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
2877 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2878 M_CMPU(REG_ITMP1, REG_ITMP2);
2881 M_IADD_IMM(REG_ZERO, 1, d);
2885 panic ("internal error: no inlined array instanceof");
2887 store_reg_to_var_int(iptr->dst, d);
2890 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2892 /* op1: 0 == array, 1 == class */
2893 /* val.a: (classinfo*) superclass */
2895 /* superclass is an interface:
2897 * OK if ((sub == NULL) ||
2898 * (sub->vftbl->interfacetablelength > super->index) &&
2899 * (sub->vftbl->interfacetable[-super->index] != NULL));
2901 * superclass is a class:
2903 * OK if ((sub == NULL) || (0
2904 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2905 * super->vftbl->diffvall));
2909 classinfo *super = (classinfo*) iptr->val.a;
2911 d = reg_of_var(iptr->dst, REG_ITMP1);
2912 var_to_reg_int(s1, src, d);
2913 if (iptr->op1) { /* class/interface */
2915 if (super->flags & ACC_INTERFACE) { /* interface */
2917 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2918 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, interfacetablelength));
2919 M_LDATST(REG_ITMP3, REG_ITMP3, - super->index);
2921 codegen_addxcastrefs(mcodeptr);
2922 M_ALD(REG_ITMP3, REG_ITMP2,
2923 OFFSET(vftbl, interfacetable[0]) -
2924 super->index * sizeof(methodptr*));
2927 codegen_addxcastrefs(mcodeptr);
2930 M_BEQ(8 + (s1 == REG_ITMP1));
2931 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2932 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
2933 a = dseg_addaddress ((void*) super->vftbl);
2934 M_ALD(REG_ITMP2, REG_PV, a);
2935 if (d != REG_ITMP1) {
2936 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl, baseval));
2937 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
2938 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2941 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, baseval));
2942 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2943 M_ALD(REG_ITMP2, REG_PV, a);
2944 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
2946 M_CMPU(REG_ITMP3, REG_ITMP2);
2948 codegen_addxcastrefs(mcodeptr);
2952 panic ("internal error: no inlined array checkcast");
2955 store_reg_to_var_int(iptr->dst, d);
2958 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
2960 var_to_reg_int(s1, src, REG_ITMP1);
2963 codegen_addxcheckarefs(mcodeptr);
2966 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2967 /* op1 = dimension, val.a = array descriptor */
2969 /* check for negative sizes and copy sizes to stack if necessary */
2971 MCODECHECK((iptr->op1 << 1) + 64);
2973 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
2974 var_to_reg_int(s2, src, REG_ITMP1);
2977 codegen_addxcheckarefs(mcodeptr);
2979 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
2981 if (src->varkind != ARGVAR) {
2982 M_IST(s2, REG_SP, 4 * (s1 + INT_ARG_CNT + 6));
2986 /* a0 = dimension count */
2988 ICONST(argintregs[0], iptr->op1);
2990 /* a1 = arraydescriptor */
2992 a = dseg_addaddress(iptr->val.a);
2993 M_ALD(argintregs[1], REG_PV, a);
2995 /* a2 = pointer to dimensions = stack pointer */
2997 M_LDA(argintregs[2], REG_SP, (INT_ARG_CNT + 6)*4);
2999 a = dseg_addaddress((void*) (builtin_nmultianewarray));
3000 M_ALD(REG_PV, REG_PV, a);
3003 s1 = (int)((u1*) mcodeptr - mcodebase);
3006 M_LDA (REG_PV, REG_ITMP1, -s1);
3008 s4 ml = -s1, mh = 0;
3009 while (ml < -32768) {ml += 65536; mh--;}
3010 M_LDA(REG_PV, REG_ITMP1, ml);
3011 M_LDAH(REG_PV, REG_PV, mh);
3013 s1 = reg_of_var(iptr->dst, REG_RESULT);
3014 M_INTMOVE(REG_RESULT, s1);
3015 store_reg_to_var_int(iptr->dst, s1);
3019 default: error ("Unknown pseudo command: %d", iptr->opc);
3025 } /* for instruction */
3027 /* copy values to interface registers */
3029 src = bptr->outstack;
3030 len = bptr->outdepth;
3034 if ((src->varkind != STACKVAR)) {
3036 if (IS_FLT_DBL_TYPE(s2)) {
3037 var_to_reg_flt(s1, src, REG_FTMP1);
3038 if (!(interfaces[len][s2].flags & INMEMORY)) {
3039 M_FLTMOVE(s1,interfaces[len][s2].regoff);
3042 M_DST(s1, REG_SP, 4 * interfaces[len][s2].regoff);
3046 var_to_reg_int(s1, src, REG_ITMP1);
3047 if (!(interfaces[len][s2].flags & INMEMORY)) {
3048 M_TINTMOVE(s2,s1,interfaces[len][s2].regoff);
3051 M_IST(s1, REG_SP, 4 * interfaces[len][s2].regoff);
3052 if (IS_2_WORD_TYPE(s2))
3053 M_IST(secondregs[s1], REG_SP, 4 * interfaces[len][s2].regoff + 4);
3059 } /* if (bptr -> flags >= BBREACHED) */
3060 } /* for basic block */
3062 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3065 /* generate bound check stubs */
3067 s4 *xcodeptr = NULL;
3069 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3070 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3071 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3072 xboundrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3077 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3078 xboundrefs->branchpos, (u1*) mcodeptr - mcodebase);
3082 M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos - 4);
3084 if (xcodeptr != NULL) {
3085 M_BR((xcodeptr-mcodeptr)-1);
3088 xcodeptr = mcodeptr;
3090 a = dseg_addaddress(proto_java_lang_ArrayIndexOutOfBoundsException);
3091 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3093 a = dseg_addaddress(asm_handle_exception);
3094 M_ALD(REG_ITMP3, REG_PV, a);
3101 /* generate negative array size check stubs */
3105 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3106 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3107 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3108 xcheckarefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3112 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3113 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
3117 M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos - 4);
3119 if (xcodeptr != NULL) {
3120 M_BR((xcodeptr-mcodeptr)-1);
3123 xcodeptr = mcodeptr;
3125 a = dseg_addaddress(proto_java_lang_NegativeArraySizeException);
3126 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3128 a = dseg_addaddress(asm_handle_exception);
3129 M_ALD(REG_ITMP3, REG_PV, a);
3136 /* generate cast check stubs */
3140 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3141 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3142 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3143 xcastrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3147 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3148 xcastrefs->branchpos, (u1*) mcodeptr - mcodebase);
3152 M_LDA(REG_ITMP2_XPC, REG_PV, xcastrefs->branchpos - 4);
3154 if (xcodeptr != NULL) {
3155 M_BR((xcodeptr-mcodeptr)-1);
3158 xcodeptr = mcodeptr;
3160 a = dseg_addaddress(proto_java_lang_ClassCastException);
3161 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3163 a = dseg_addaddress(asm_handle_exception);
3164 M_ALD(REG_ITMP3, REG_PV, a);
3172 #ifdef SOFTNULLPTRCHECK
3174 /* generate null pointer check stubs */
3178 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3179 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3180 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3181 xnullrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3185 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3186 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
3190 M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
3192 if (xcodeptr != NULL) {
3193 M_BR((xcodeptr-mcodeptr)-1);
3196 xcodeptr = mcodeptr;
3198 a = dseg_addaddress(proto_java_lang_NullPointerException);
3199 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3201 a = dseg_addaddress(asm_handle_exception);
3202 M_ALD(REG_ITMP3, REG_PV, a);
3212 codegen_finish((int)((u1*) mcodeptr - mcodebase));
3214 docacheflush((void*) method->entrypoint, ((u1*) mcodeptr - mcodebase));
3218 /* function createcompilerstub *************************************************
3220 creates a stub routine which calls the compiler
3222 *******************************************************************************/
3224 #define COMPSTUBSIZE 6
3226 u1 *createcompilerstub (methodinfo *m)
3228 s4 *s = CNEW (s4, COMPSTUBSIZE); /* memory to hold the stub */
3229 s4 *mcodeptr = s; /* code generation pointer */
3231 M_LDA(2, REG_PV, 4*4);
3232 M_ALD(REG_PV, REG_PV, 5*4);
3236 s[4] = (s4) m; /* literals to be adressed */
3237 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3239 docacheflush((void*) s, (char*) mcodeptr - (char*) s);
3242 count_cstub_len += COMPSTUBSIZE * 4;
3249 /* function removecompilerstub *************************************************
3251 deletes a compilerstub from memory (simply by freeing it)
3253 *******************************************************************************/
3255 void removecompilerstub (u1 *stub)
3257 CFREE (stub, COMPSTUBSIZE * 4);
3260 /* function: createnativestub **************************************************
3262 creates a stub routine which calls a native method
3264 *******************************************************************************/
3266 #define NATIVESTUBSIZE 80
3267 #define NATIVESTUBOFFSET 8
3269 u1 *createnativestub (functionptr f, methodinfo *m)
3272 s4 *s = CNEW (s4, NATIVESTUBSIZE); /* memory to hold the stub */
3273 s4 *cs = s + NATIVESTUBOFFSET;
3274 s4 *mcodeptr = cs; /* code generation pointer */
3276 *(cs-1) = (s4) f; /* address of native method */
3277 *(cs-2) = (s4) (&_exceptionptr); /* address of exceptionptr */
3278 *(cs-3) = (s4) asm_handle_nat_exception; /* addr of asm exception handler */
3279 *(cs-4) = (s4) (&env); /* addr of jni_environement */
3280 // *(cs-5) = (s4) asm_builtin_trace;
3282 // *(cs-7) = (s4) asm_builtin_exittrace;
3283 *(cs-8) = (s4) builtin_trace_exception;
3287 utf_display(m->class->name);
3289 utf_display(m->name);
3290 printf(" 0x%p\n", cs);
3294 M_AST (REG_ITMP1, REG_SP, 8); /* store return address */
3295 M_LDA (REG_SP, REG_SP, -64); /* build up stackframe */
3299 M_ALD(REG_ITMP1, REG_PV, -6*4);
3300 M_ALD(REG_PV, REG_PV, -5*4);
3302 // M_JSR(REG_RA, REG_PV);
3303 disp = -(int) (mcodeptr - (s4*) cs)*4;
3304 M_LDA(REG_PV, REG_ITMP1, disp);
3310 M_MOV (argintregs[6],argintregs[7]);
3311 M_MOV (argintregs[5],argintregs[6]);
3312 M_MOV (argintregs[4],argintregs[5]);
3313 M_MOV (argintregs[3],argintregs[4]);
3314 M_MOV (argintregs[2],argintregs[3]);
3315 M_MOV (argintregs[1],argintregs[2]);
3316 M_MOV (argintregs[0],argintregs[1]);
3318 M_ALD (argintregs[0], REG_PV, -4*4);/* load adress of jni_environement */
3320 M_ALD (REG_PV, REG_PV, -1*4); /* load adress of native method */
3324 disp = -(int) (mcodeptr - cs)*4;
3326 M_LDA (REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3327 M_ALD (REG_ITMP2, REG_PV, -2*4); /* get address of exceptionptr */
3329 M_ALD (REG_ITMP1, REG_ITMP2, 0); /* load exception into reg. itmp1 */
3331 M_BNE (4 + (runverbose ? 0 : 0)); /* if no exception then return */
3335 M_ALD(argintregs[0], REG_PV, -6*4);
3336 M_MOV(REG_RESULT, argintregs[1]);
3337 M_FMOV(REG_FRESULT, argfltregs[2]);
3338 M_FMOV(REG_FRESULT, argfltregs[3]);
3339 M_ALD(REG_PV, REG_PV, -7*4);
3340 // M_JSR(REG_RA, REG_PV);
3344 M_ALD (REG_ITMP1, REG_SP, 64+8); /* load return address */
3346 M_LDA (REG_SP, REG_SP, 64); /* remove stackframe */
3351 M_AST (REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
3355 M_LDA(REG_SP, REG_SP, -8);
3356 M_AST(REG_ITMP1, REG_SP, 0);
3357 M_MOV(REG_ITMP1, argintregs[0]);
3358 M_ALD(argintregs[1], REG_PV, -6*4);
3359 M_ALD(argintregs[2], REG_SP, 0);
3360 M_CLR(argintregs[3]);
3361 M_ALD(REG_PV, REG_PV, -8*4);
3362 // M_JSR(REG_RA, REG_PV);
3363 disp = -(int) (mcodeptr - cs)*4;
3364 M_LDA (REG_PV, REG_ITMP1, disp);
3365 M_ALD(REG_ITMP1, REG_SP, 0);
3366 M_LDA(REG_SP, REG_SP, 8);
3370 M_ALD (REG_ITMP3, REG_SP, 64+8); /* load return address */
3372 M_LDA (REG_SP, REG_SP, 64); /* remove stackframe */
3374 M_LDA (REG_ITMP2, REG_ITMP1, -4); /* move fault address into reg. itmp2 */
3376 M_ALD (REG_ITMP3, REG_PV, -3*4); /* load asm exception handler address */
3382 static int stubprinted;
3384 printf("stubsize: %d/2\n", (int) (p - (s4*) s));
3389 docacheflush((void*) s, (char*) mcodeptr - (char*) s);
3392 count_nstub_len += NATIVESTUBSIZE * 4;
3395 return (u1*) (s + NATIVESTUBOFFSET);
3398 /* function: removenativestub **************************************************
3400 removes a previously created native-stub from memory
3402 *******************************************************************************/
3404 void removenativestub(u1 *stub)
3406 CFREE ((s4*) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 4);
3410 java_objectheader *asm_docalljavamethod(methodinfo *m, void *arg1, void *arg2,
3411 void *arg3, void *arg4);
3413 java_objectheader *asm_calljavafunction(methodinfo *m, void *arg1, void *arg2,
3414 void *arg3, void *arg4)
3416 return asm_docalljavamethod(m, arg1, arg2, arg3, arg4);
3420 void asm_cacheflush(u1 *p, long bytelen);
3423 void docacheflush(u1 *p, long bytelen)
3425 asm_cacheflush(p, bytelen);
3430 * These are local overrides for various environment variables in Emacs.
3431 * Please do not remove this and leave it at the end of the file, where
3432 * Emacs will automagically detect them.
3433 * ---------------------------------------------------------------------
3436 * indent-tabs-mode: t