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 1309 2004-07-12 23:21:33Z stefan $
47 #include "jit/parse.h"
49 #include "jit/powerpc/codegen.h"
51 /* include independent code generation stuff */
52 #include "jit/codegen.inc"
53 #include "jit/reg.inc"
56 /* register descripton - array ************************************************/
58 /* #define REG_RES 0 reserved register for OS or code generator */
59 /* #define REG_RET 1 return value register */
60 /* #define REG_EXC 2 exception value register (only old jit) */
61 /* #define REG_SAV 3 (callee) saved register */
62 /* #define REG_TMP 4 scratch temporary register (caller saved) */
63 /* #define REG_ARG 5 argument register (caller saved) */
65 /* #define REG_END -1 last entry in tables */
68 REG_RES, REG_RES, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
69 REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV,
70 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
71 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
74 /* for use of reserved registers, see comment above */
76 int nregdescfloat[] = {
77 REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
78 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV,
79 REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
80 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
83 /* for use of reserved registers, see comment above */
86 /* stackframe-infos ***********************************************************/
88 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
90 /* -> see file 'calling.doc' */
93 /* additional functions and macros to generate code ***************************/
95 #define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
99 #define COUNT_SPILLS count_spills++
105 /* gen_nullptr_check(objreg) */
107 #define gen_nullptr_check(objreg) \
111 codegen_addxnullrefs(mcodeptr); \
115 /* MCODECHECK(icnt) */
117 #define MCODECHECK(icnt) \
118 if((mcodeptr+(icnt))>mcodeend)mcodeptr=codegen_increase((u1*)mcodeptr)
121 generates an integer-move from register a to b.
122 if a and b are the same int-register, no code will be generated.
125 #define M_INTMOVE(a,b) if((a)!=(b)){M_MOV(a,b);}
127 #define M_TINTMOVE(t,a,b) \
129 {if (a<=b)M_INTMOVE(r->secondregs[a],r->secondregs[b]);\
130 M_INTMOVE(a,b); if (a>b)M_INTMOVE(r->secondregs[a],r->secondregs[b]);} \
136 generates a floating-point-move from register a to b.
137 if a and b are the same float-register, no code will be generated
140 #define M_FLTMOVE(a,b) if((a)!=(b)){M_FMOV(a,b);}
144 this function generates code to fetch data from a pseudo-register
145 into a real register.
146 If the pseudo-register has actually been assigned to a real
147 register, no code will be emitted, since following operations
148 can use this register directly.
150 v: pseudoregister to be fetched from
151 tempregnum: temporary register to be used if v is actually spilled to ram
153 return: the register number, where the operand can be found after
154 fetching (this wil be either tempregnum or the register
155 number allready given to v)
158 #define var_to_reg_int0(regnr,v,tempnr,a,b) { \
159 if ((v)->flags & INMEMORY) \
160 {COUNT_SPILLS;if (a) M_ILD(tempnr,REG_SP,4*(v)->regoff); \
162 if ((b) && IS_2_WORD_TYPE((v)->type)) \
163 M_ILD((a)?r->secondregs[tempnr]:tempnr,REG_SP,4*(v)->regoff+4);} \
164 else regnr=(!(a)&&(b)) ? r->secondregs[(v)->regoff] : (v)->regoff; \
166 #define var_to_reg_int(regnr,v,tempnr) var_to_reg_int0(regnr,v,tempnr,1,1)
169 #define var_to_reg_flt(regnr,v,tempnr) { \
170 if ((v)->flags & INMEMORY) { \
172 if ((v)->type==TYPE_DBL) \
173 M_DLD(tempnr,REG_SP,4*(v)->regoff); \
175 M_FLD(tempnr,REG_SP,4*(v)->regoff); \
177 } else regnr=(v)->regoff; \
182 This function determines a register, to which the result of an operation
183 should go, when it is ultimatively intended to store the result in
185 If v is assigned to an actual register, this register will be returned.
186 Otherwise (when v is spilled) this function returns tempregnum.
187 If not already done, regoff and flags are set in the stack location.
190 static int reg_of_var(methodinfo *m, stackptr v, int tempregnum)
194 switch (v->varkind) {
196 if (!(v->flags & INMEMORY))
200 var = &(m->registerdata->interfaces[v->varnum][v->type]);
201 v->regoff = var->regoff;
202 if (!(var->flags & INMEMORY))
206 var = &(m->registerdata->locals[v->varnum][v->type]);
207 v->regoff = var->regoff;
208 if (!(var->flags & INMEMORY))
212 v->regoff = v->varnum;
213 if (IS_FLT_DBL_TYPE(v->type)) {
214 if (v->varnum < m->registerdata->fltreg_argnum) {
215 v->regoff = m->registerdata->argfltregs[v->varnum];
216 return(m->registerdata->argfltregs[v->varnum]);
219 if (v->varnum < m->registerdata->intreg_argnum - (IS_2_WORD_TYPE(v->type)!=0)) {
220 v->regoff = m->registerdata->argintregs[v->varnum];
221 return(m->registerdata->argintregs[v->varnum]);
226 v->flags |= INMEMORY;
231 /* store_reg_to_var_xxx:
232 This function generates the code to store the result of an operation
233 back into a spilled pseudo-variable.
234 If the pseudo-variable has not been spilled in the first place, this
235 function will generate nothing.
237 v ............ Pseudovariable
238 tempregnum ... Number of the temporary registers as returned by
242 #define store_reg_to_var_int0(sptr, tempregnum, a, b) { \
243 if ((sptr)->flags & INMEMORY) { \
245 if (a) M_IST(tempregnum, REG_SP, 4 * (sptr)->regoff); \
246 if ((b) && IS_2_WORD_TYPE((sptr)->type)) \
247 M_IST(r->secondregs[tempregnum], REG_SP, 4 * (sptr)->regoff + 4); \
251 #define store_reg_to_var_int(sptr, tempregnum) \
252 store_reg_to_var_int0(sptr, tempregnum, 1, 1)
254 #define store_reg_to_var_flt(sptr, tempregnum) { \
255 if ((sptr)->flags & INMEMORY) { \
257 if ((sptr)->type==TYPE_DBL) \
258 M_DST(tempregnum, REG_SP, 4 * (sptr)->regoff); \
260 M_FST(tempregnum, REG_SP, 4 * (sptr)->regoff); \
265 void asm_cacheflush(void *, long);
267 //#include <architecture/ppc/cframe.h>
269 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
270 void thread_restartcriticalsection(void *u)
272 /* XXX set pc to restart address */
276 int cacao_catch_Handler(mach_port_t thread)
279 unsigned int crashpc;
281 java_objectheader *xptr;
284 thread_state_flavor_t flavor = PPC_THREAD_STATE;
285 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
286 ppc_thread_state_t thread_state;
292 r = thread_get_state(thread, flavor,
293 (natural_t*)&thread_state, &thread_state_count);
294 if (r != KERN_SUCCESS)
295 panic("thread_get_state failed");
297 regs = &thread_state.r0;
298 crashpc = thread_state.srr0;
300 instr = *(s4*) crashpc;
301 reg = (instr >> 16) & 31;
304 xptr = new_exception(string_java_lang_NullPointerException);
306 regs[REG_ITMP2_XPC] = crashpc;
307 regs[REG_ITMP1_XPTR] = (u4) xptr;
308 thread_state.srr0 = (u4) asm_handle_exception;
310 r = thread_set_state(thread, flavor,
311 (natural_t*)&thread_state, thread_state_count);
312 if (r != KERN_SUCCESS)
313 panic("thread_set_state failed");
322 void init_exceptions(void)
327 void adjust_argvars(stackptr s, int d, int *fa, int *ia)
333 adjust_argvars(s->prev, d-1, fa, ia);
334 if (s->varkind == ARGVAR)
335 s->varnum = (IS_FLT_DBL_TYPE(s->type)) ? *fa : *ia;
336 *fa += (IS_FLT_DBL_TYPE(s->type) != 0);
337 *ia += (IS_2_WORD_TYPE(s->type)) ? 2 : 1;
341 #define intmaxf(a,b) (((a)<(b)) ? (b) : (a))
343 void preregpass(methodinfo *m)
350 registerdata *r = m->registerdata;
353 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
355 for (iptr = bptr->iinstr, src = bptr->instack;
357 src = iptr->dst, len--, iptr++)
359 if (bptr->flags < BBREACHED)
372 case ICMD_INVOKEVIRTUAL:
373 case ICMD_INVOKESPECIAL:
374 case ICMD_INVOKESTATIC:
375 case ICMD_INVOKEINTERFACE:
380 adjust_argvars(src, s3, &fa, &ia);
383 for (; --s3 >= 0; src = src->prev) {
384 paramsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
386 r->ifmemuse = intmaxf(r->ifmemuse, paramsize);
389 case ICMD_MULTIANEWARRAY:
391 paramsize = r->intreg_argnum + s3;
392 r->ifmemuse = intmaxf(r->ifmemuse, paramsize);
399 r->maxmemuse = r->ifmemuse;
403 /* function gen_mcode **********************************************************
405 generates machine code
407 *******************************************************************************/
409 void codegen(methodinfo *m)
411 s4 len, s1, s2, s3, d;
426 /* keep code size smaller */
431 /* space to save used callee saved registers */
433 savedregs_num += (r->savintregcnt - r->maxsavintreguse);
434 savedregs_num += 2*(r->savfltregcnt - r->maxsavfltreguse);
436 parentargs_base = r->maxmemuse + savedregs_num;
438 #ifdef USE_THREADS /* space to save argument of monitor_enter */
440 if (checksync && (m->flags & ACC_SYNCHRONIZED))
445 /* create method header */
447 parentargs_base = (parentargs_base+3) & ~3;
450 (void) dseg_addaddress(m); /* Filler */
452 (void) dseg_addaddress(m); /* MethodPointer */
453 (void) dseg_adds4(parentargs_base * 4); /* FrameSize */
457 /* IsSync contains the offset relative to the stack pointer for the
458 argument of monitor_exit used in the exception handler. Since the
459 offset could be zero and give a wrong meaning of the flag it is
463 if (checksync && (m->flags & ACC_SYNCHRONIZED))
464 (void) dseg_adds4((r->maxmemuse + 1) * 4); /* IsSync */
469 (void) dseg_adds4(0); /* IsSync */
471 (void) dseg_adds4(m->isleafmethod); /* IsLeaf */
472 (void) dseg_adds4(r->savintregcnt - r->maxsavintreguse);/* IntSave */
473 (void) dseg_adds4(r->savfltregcnt - r->maxsavfltreguse);/* FltSave */
474 (void) dseg_adds4(m->exceptiontablelength); /* ExTableSize */
476 /* create exception table */
478 for (ex = m->exceptiontable; ex != NULL; ex = ex->down) {
479 dseg_addtarget(ex->start);
480 dseg_addtarget(ex->end);
481 dseg_addtarget(ex->handler);
482 (void) dseg_addaddress(ex->catchtype);
485 /* initialize mcode variables */
487 mcodeptr = (s4*) mcodebase;
488 mcodeend = (s4*) (mcodebase + mcodesize);
489 MCODECHECK(128 + m->paramcount);
491 /* create stack frame (if necessary) */
493 if (!m->isleafmethod) {
495 M_AST(REG_ITMP3, REG_SP, 8);
497 if (parentargs_base) {
498 M_LDA (REG_SP, REG_SP, -parentargs_base * 4);
501 /* save return address and used callee saved registers */
504 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
505 p--; M_IST (r->savintregs[i], REG_SP, 4 * p);
507 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
508 p-=2; M_DST (r->savfltregs[i], REG_SP, 4 * p);
511 /* save monitorenter argument */
514 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
515 if (m->flags & ACC_STATIC) {
516 p = dseg_addaddress (m->class);
517 M_ALD(REG_ITMP1, REG_PV, p);
518 M_AST(REG_ITMP1, REG_SP, 4 * r->maxmemuse);
521 M_AST (r->argintregs[0], REG_SP, 4 * r->maxmemuse);
526 /* copy argument registers to stack and call trace function with pointer
527 to arguments on stack.
536 /* XXX must be a multiple of 16 */
537 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
539 M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
541 M_CLR(REG_ITMP1); /* clear help register */
543 /* save all arguments into the reserved stack space */
544 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
545 t = m->paramtypes[p];
547 if (IS_INT_LNG_TYPE(t)) {
548 /* overlapping u8's are on the stack */
549 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
550 s1 = r->argintregs[p + longargs + dblargs];
552 if (!IS_2_WORD_TYPE(t)) {
553 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
554 M_IST(s1, REG_SP, 24 + p * 8 + 4);
557 M_IST(s1, REG_SP, 24 + p * 8);
558 M_IST(r->secondregs[s1], REG_SP, 24 + p * 8 + 4);
563 a = dseg_adds4(0xdeadbeef);
564 M_ILD(REG_ITMP1, REG_PV, a);
565 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
566 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
570 if ((fltargs + dblargs) < FLT_ARG_CNT) {
571 s1 = r->argfltregs[fltargs + dblargs];
573 if (!IS_2_WORD_TYPE(t)) {
574 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
575 M_FST(s1, REG_SP, 24 + p * 8 + 4);
579 M_DST(s1, REG_SP, 24 + p * 8);
584 /* this should not happen */
589 /* TODO: save remaining integer and flaot argument registers */
591 /* load first 4 arguments into integer argument registers */
592 for (p = 0; p < 8; p++) {
593 d = r->argintregs[p];
594 M_ILD(d, REG_SP, 24 + p * 4);
597 p = dseg_addaddress(m);
598 M_ALD(REG_ITMP1, REG_PV, p);
599 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
600 p = dseg_addaddress((void*) builtin_trace_args);
601 M_ALD(REG_ITMP2, REG_PV, p);
609 /* restore arguments into the reserved stack space */
610 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
611 t = m->paramtypes[p];
613 if (IS_INT_LNG_TYPE(t)) {
614 if ((p + longargs + dblargs) < INT_ARG_CNT) {
615 s1 = r->argintregs[p + longargs + dblargs];
617 if (!IS_2_WORD_TYPE(t)) {
618 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
621 M_ILD(s1, REG_SP, 24 + p * 8);
622 M_ILD(r->secondregs[s1], REG_SP, 24 + p * 8 + 4);
628 if ((fltargs + dblargs) < FLT_ARG_CNT) {
629 s1 = r->argfltregs[fltargs + dblargs];
631 if (!IS_2_WORD_TYPE(t)) {
632 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
636 M_DLD(s1, REG_SP, 24 + p * 8);
643 M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
645 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
649 /* take arguments out of register or stack frame */
654 for (p = 0, l = 0; p < m->paramcount; p++) {
656 arg = narg; iarg = niarg;
657 t = m->paramtypes[p];
658 var = &(r->locals[l][t]);
660 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
665 if (IS_INT_LNG_TYPE(t)) { /* integer args */
666 if (iarg < INT_ARG_CNT -
667 (IS_2_WORD_TYPE(t)!=0)) { /* register arguments */
668 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
669 M_TINTMOVE (t, r->argintregs[iarg], reg);
670 } else { /* reg arg -> spilled */
671 M_IST (r->argintregs[iarg], REG_SP, 4 * reg);
672 if (IS_2_WORD_TYPE(t))
673 M_IST (r->secondregs[r->argintregs[iarg]], REG_SP, 4 * reg + 4);
675 } else { /* stack arguments */
677 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
678 M_ILD (reg, REG_SP, 4 * (parentargs_base + pa));
679 if (IS_2_WORD_TYPE(t))
680 M_ILD (r->secondregs[reg], REG_SP, 4 * (parentargs_base + pa) + 4);
681 } else { /* stack arg -> spilled */
682 M_ILD (REG_ITMP1, REG_SP, 4 * (parentargs_base + pa));
683 M_IST (REG_ITMP1, REG_SP, 4 * reg);
684 if (IS_2_WORD_TYPE(t)) {
685 M_ILD (REG_ITMP1, REG_SP, 4 * (parentargs_base + pa) + 4);
686 M_IST (REG_ITMP1, REG_SP, 4 * reg + 4);
690 } else { /* floating args */
692 if (arg < FLT_ARG_CNT) { /* register arguments */
693 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
694 M_FLTMOVE (r->argfltregs[arg], reg);
695 } else { /* reg arg -> spilled */
696 M_DST (r->argfltregs[arg], REG_SP, 4 * reg);
698 } else { /* stack arguments */
700 if (!(var->flags & INMEMORY)) /* stack-arg -> register */
701 if (IS_2_WORD_TYPE(t))
702 M_DLD (reg, REG_SP, 4 * (parentargs_base + pa) );
704 M_FLD (reg, REG_SP, 4 * (parentargs_base + pa) );
705 else { /* stack-arg -> spilled */
706 if (IS_2_WORD_TYPE(t))
707 M_DLD (REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
709 M_FLD (REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
710 M_DST (REG_FTMP1, REG_SP, 4 * reg);
717 /* call monitorenter function */
720 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
721 s4 func_enter = (m->flags & ACC_STATIC) ?
722 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
723 p = dseg_addaddress ((void*) func_enter);
724 M_ALD(REG_ITMP3, REG_PV, p);
726 M_ALD(r->argintregs[0], REG_SP, 4 * r->maxmemuse);
732 /* end of header generation */
734 /* walk through all basic blocks */
735 for (/* bbs = block_count, */ bptr = m->basicblocks; /* --bbs >= 0 */ bptr != NULL; bptr = bptr->next) {
737 bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
739 if (bptr->flags >= BBREACHED) {
741 /* branch resolving */
745 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
746 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
747 brefs->branchpos, bptr->mpc);
751 /* copy interface registers to their destination */
756 while (src != NULL) {
758 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
759 d = reg_of_var(m, src, REG_ITMP1);
760 M_INTMOVE(REG_ITMP1, d);
761 store_reg_to_var_int(src, d);
763 d = reg_of_var(m, src, REG_IFTMP);
764 if ((src->varkind != STACKVAR)) {
766 if (IS_FLT_DBL_TYPE(s2)) {
767 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
768 s1 = r->interfaces[len][s2].regoff;
771 if (IS_2_WORD_TYPE(s2))
772 M_DLD(d, REG_SP, 4 * r->interfaces[len][s2].regoff);
774 M_FLD(d, REG_SP, 4 * r->interfaces[len][s2].regoff);
776 store_reg_to_var_flt(src, d);
778 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
779 s1 = r->interfaces[len][s2].regoff;
782 M_ILD(d, REG_SP, 4 * r->interfaces[len][s2].regoff);
783 if (IS_2_WORD_TYPE(s2))
784 M_ILD(r->secondregs[d], REG_SP, 4 * r->interfaces[len][s2].regoff + 4);
786 store_reg_to_var_int(src, d);
793 /* walk through all instructions */
797 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
799 MCODECHECK(64); /* an instruction usually needs < 64 words */
802 case ICMD_NOP: /* ... ==> ... */
805 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
807 var_to_reg_int(s1, src, REG_ITMP1);
810 codegen_addxnullrefs(mcodeptr);
813 /* constant operations ************************************************/
815 #define ICONST(r,c) if(((c)>=0&&(c)<=32767)||((c)>=-32768&&(c)<0)){M_LDA(r,REG_ZERO,c);} \
816 else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
818 #define LCONST(rr,c) ICONST(rr,(s4)((s8)(c)>>32)); ICONST(r->secondregs[rr],(s4)((s8)(c)));
820 case ICMD_ICONST: /* ... ==> ..., constant */
821 /* op1 = 0, val.i = constant */
823 d = reg_of_var(m, iptr->dst, REG_ITMP1);
824 ICONST(d, iptr->val.i);
825 store_reg_to_var_int(iptr->dst, d);
828 case ICMD_LCONST: /* ... ==> ..., constant */
829 /* op1 = 0, val.l = constant */
831 d = reg_of_var(m, iptr->dst, REG_ITMP1);
832 LCONST(d, iptr->val.l);
833 store_reg_to_var_int(iptr->dst, d);
836 case ICMD_FCONST: /* ... ==> ..., constant */
837 /* op1 = 0, val.f = constant */
839 d = reg_of_var(m, iptr->dst, REG_FTMP1);
840 a = dseg_addfloat(iptr->val.f);
842 store_reg_to_var_flt (iptr->dst, d);
845 case ICMD_DCONST: /* ... ==> ..., constant */
846 /* op1 = 0, val.d = constant */
848 d = reg_of_var(m, iptr->dst, REG_FTMP1);
849 a = dseg_adddouble(iptr->val.d);
851 store_reg_to_var_flt (iptr->dst, d);
854 case ICMD_ACONST: /* ... ==> ..., constant */
855 /* op1 = 0, val.a = constant */
857 d = reg_of_var(m, iptr->dst, REG_ITMP1);
858 ICONST(d, (u4) iptr->val.a);
859 store_reg_to_var_int(iptr->dst, d);
863 /* load/store operations **********************************************/
865 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
866 case ICMD_LLOAD: /* op1 = local variable */
869 d = reg_of_var(m, iptr->dst, REG_ITMP1);
870 if ((iptr->dst->varkind == LOCALVAR) &&
871 (iptr->dst->varnum == iptr->op1))
873 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
874 if (var->flags & INMEMORY) {
875 M_ILD(d, REG_SP, 4 * var->regoff);
876 if (IS_2_WORD_TYPE(var->type))
877 M_ILD(r->secondregs[d], REG_SP, 4 * var->regoff + 4);
879 M_TINTMOVE(var->type,var->regoff,d);
881 store_reg_to_var_int(iptr->dst, d);
884 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
885 case ICMD_DLOAD: /* op1 = local variable */
887 d = reg_of_var(m, iptr->dst, REG_FTMP1);
888 if ((iptr->dst->varkind == LOCALVAR) &&
889 (iptr->dst->varnum == iptr->op1))
891 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
892 if (var->flags & INMEMORY)
893 if (IS_2_WORD_TYPE(var->type))
894 M_DLD(d, REG_SP, 4 * var->regoff);
896 M_FLD(d, REG_SP, 4 * var->regoff);
898 M_FLTMOVE(var->regoff,d);
900 store_reg_to_var_flt(iptr->dst, d);
904 case ICMD_ISTORE: /* ..., value ==> ... */
905 case ICMD_LSTORE: /* op1 = local variable */
908 if ((src->varkind == LOCALVAR) &&
909 (src->varnum == iptr->op1))
911 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
912 if (var->flags & INMEMORY) {
913 var_to_reg_int(s1, src, REG_ITMP1);
914 M_IST(s1, REG_SP, 4 * var->regoff);
915 if (IS_2_WORD_TYPE(var->type))
916 M_IST(r->secondregs[s1], REG_SP, 4 * var->regoff + 4);
919 var_to_reg_int(s1, src, var->regoff);
920 M_TINTMOVE(var->type, s1, var->regoff);
924 case ICMD_FSTORE: /* ..., value ==> ... */
925 case ICMD_DSTORE: /* op1 = local variable */
927 if ((src->varkind == LOCALVAR) &&
928 (src->varnum == iptr->op1))
930 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
931 if (var->flags & INMEMORY) {
932 var_to_reg_flt(s1, src, REG_FTMP1);
933 if (var->type==TYPE_DBL)
934 M_DST(s1, REG_SP, 4 * var->regoff);
936 M_FST(s1, REG_SP, 4 * var->regoff);
939 var_to_reg_flt(s1, src, var->regoff);
940 M_FLTMOVE(s1, var->regoff);
945 /* pop/dup/swap operations ********************************************/
947 /* attention: double and longs are only one entry in CACAO ICMDs */
949 case ICMD_POP: /* ..., value ==> ... */
950 case ICMD_POP2: /* ..., value, value ==> ... */
953 #define M_COPY(from,to) \
954 d = reg_of_var(m, to, REG_IFTMP); \
955 if ((from->regoff != to->regoff) || \
956 ((from->flags ^ to->flags) & INMEMORY)) { \
957 if (IS_FLT_DBL_TYPE(from->type)) { \
958 var_to_reg_flt(s1, from, d); \
960 store_reg_to_var_flt(to, d); \
963 var_to_reg_int(s1, from, d); \
964 M_TINTMOVE(from->type,s1,d); \
965 store_reg_to_var_int(to, d); \
969 case ICMD_DUP: /* ..., a ==> ..., a, a */
970 M_COPY(src, iptr->dst);
973 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
975 M_COPY(src, iptr->dst->prev->prev);
977 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
979 M_COPY(src, iptr->dst);
980 M_COPY(src->prev, iptr->dst->prev);
983 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
985 M_COPY(src->prev, iptr->dst->prev->prev->prev);
987 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
989 M_COPY(src, iptr->dst);
990 M_COPY(src->prev, iptr->dst->prev);
991 M_COPY(src->prev->prev, iptr->dst->prev->prev);
992 M_COPY(src, iptr->dst->prev->prev->prev);
995 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
997 M_COPY(src, iptr->dst);
998 M_COPY(src->prev, iptr->dst->prev);
999 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1000 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
1001 M_COPY(src, iptr->dst->prev->prev->prev->prev);
1002 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
1005 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1007 M_COPY(src, iptr->dst->prev);
1008 M_COPY(src->prev, iptr->dst);
1012 /* integer operations *************************************************/
1014 case ICMD_INEG: /* ..., value ==> ..., - value */
1016 var_to_reg_int(s1, src, REG_ITMP1);
1017 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1019 store_reg_to_var_int(iptr->dst, d);
1022 case ICMD_LNEG: /* ..., value ==> ..., - value */
1024 var_to_reg_int(s1, src, REG_ITMP1);
1025 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1026 M_SUBFIC(r->secondregs[s1], 0, r->secondregs[d]);
1028 store_reg_to_var_int(iptr->dst, d);
1031 case ICMD_I2L: /* ..., value ==> ..., value */
1033 var_to_reg_int(s1, src, REG_ITMP2);
1034 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1035 M_INTMOVE(s1, r->secondregs[d]);
1036 M_SRA_IMM(r->secondregs[d], 31, d);
1037 store_reg_to_var_int(iptr->dst, d);
1040 case ICMD_L2I: /* ..., value ==> ..., value */
1042 var_to_reg_int0(s1, src, REG_ITMP2, 0, 1);
1043 d = reg_of_var(m, iptr->dst, REG_ITMP2);
1045 store_reg_to_var_int(iptr->dst, d);
1048 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1050 var_to_reg_int(s1, src, REG_ITMP1);
1051 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1053 store_reg_to_var_int(iptr->dst, d);
1056 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1058 var_to_reg_int(s1, src, REG_ITMP1);
1059 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1061 store_reg_to_var_int(iptr->dst, d);
1064 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1066 var_to_reg_int(s1, src, REG_ITMP1);
1067 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1069 store_reg_to_var_int(iptr->dst, d);
1073 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1075 var_to_reg_int(s1, src->prev, REG_ITMP1);
1076 var_to_reg_int(s2, src, REG_ITMP2);
1077 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1079 store_reg_to_var_int(iptr->dst, d);
1082 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1083 /* val.i = constant */
1085 var_to_reg_int(s1, src, REG_ITMP1);
1086 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1087 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1088 M_IADD_IMM(s1, iptr->val.i, d);
1091 ICONST(REG_ITMP2, iptr->val.i);
1092 M_IADD(s1, REG_ITMP2, d);
1094 store_reg_to_var_int(iptr->dst, d);
1097 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1099 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1100 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1101 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1102 M_ADDC(s1, s2, r->secondregs[d]);
1103 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1104 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1106 store_reg_to_var_int(iptr->dst, d);
1109 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1110 /* val.l = constant */
1112 s3 = iptr->val.l & 0xffffffff;
1113 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1114 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1115 if ((s3 >= -32768) && (s3 <= 32767)) {
1116 M_ADDIC(s1, s3, r->secondregs[d]);
1119 ICONST(REG_ITMP2, s3);
1120 M_ADDC(s1, REG_ITMP2, r->secondregs[d]);
1122 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1123 s3 = iptr->val.l >> 32;
1129 ICONST(REG_ITMP3, s3);
1130 M_ADDE(s1, REG_ITMP3, d);
1132 store_reg_to_var_int(iptr->dst, d);
1135 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1137 var_to_reg_int(s1, src->prev, REG_ITMP1);
1138 var_to_reg_int(s2, src, REG_ITMP2);
1139 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1141 store_reg_to_var_int(iptr->dst, d);
1144 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1145 /* val.i = constant */
1147 var_to_reg_int(s1, src, REG_ITMP1);
1148 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1149 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
1150 M_IADD_IMM(s1, -iptr->val.i, d);
1153 ICONST(REG_ITMP2, -iptr->val.i);
1154 M_IADD(s1, REG_ITMP2, d);
1156 store_reg_to_var_int(iptr->dst, d);
1159 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1161 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1162 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1163 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1164 M_SUBC(s1, s2, r->secondregs[d]);
1165 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1166 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1168 store_reg_to_var_int(iptr->dst, d);
1171 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1172 /* val.l = constant */
1174 s3 = (-iptr->val.l) & 0xffffffff;
1175 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1176 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1177 if ((s3 >= -32768) && (s3 <= 32767)) {
1178 M_ADDIC(s1, s3, r->secondregs[d]);
1181 ICONST(REG_ITMP2, s3);
1182 M_ADDC(s1, REG_ITMP2, r->secondregs[d]);
1184 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1185 s3 = (-iptr->val.l) >> 32;
1191 ICONST(REG_ITMP3, s3);
1192 M_ADDE(s1, REG_ITMP3, d);
1194 store_reg_to_var_int(iptr->dst, d);
1197 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1198 var_to_reg_int(s1, src->prev, REG_ITMP1);
1199 var_to_reg_int(s2, src, REG_ITMP2);
1200 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1202 store_reg_to_var_int(iptr->dst, d);
1205 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1206 var_to_reg_int(s1, src->prev, REG_ITMP1);
1207 var_to_reg_int(s2, src, REG_ITMP2);
1208 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1212 store_reg_to_var_int(iptr->dst, d);
1215 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1217 var_to_reg_int(s1, src->prev, REG_ITMP1);
1218 var_to_reg_int(s2, src, REG_ITMP2);
1219 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1221 store_reg_to_var_int(iptr->dst, d);
1224 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1225 /* val.i = constant */
1227 var_to_reg_int(s1, src, REG_ITMP1);
1228 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1229 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1230 M_IMUL_IMM(s1, iptr->val.i, d);
1233 ICONST(REG_ITMP2, iptr->val.i);
1234 M_IMUL(s1, REG_ITMP2, d);
1236 store_reg_to_var_int(iptr->dst, d);
1239 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1241 var_to_reg_int(s1, src, REG_ITMP1);
1242 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1243 M_SRA_IMM(s1, iptr->val.i, d);
1245 store_reg_to_var_int(iptr->dst, d);
1248 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1250 var_to_reg_int(s1, src->prev, REG_ITMP1);
1251 var_to_reg_int(s2, src, REG_ITMP2);
1252 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1253 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1254 M_SLL(s1, REG_ITMP3, d);
1255 store_reg_to_var_int(iptr->dst, d);
1258 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1259 /* val.i = constant */
1261 var_to_reg_int(s1, src, REG_ITMP1);
1262 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1263 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1264 store_reg_to_var_int(iptr->dst, d);
1267 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1269 var_to_reg_int(s1, src->prev, REG_ITMP1);
1270 var_to_reg_int(s2, src, REG_ITMP2);
1271 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1272 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1273 M_SRA(s1, REG_ITMP3, d);
1274 store_reg_to_var_int(iptr->dst, d);
1277 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1278 /* val.i = constant */
1280 var_to_reg_int(s1, src, REG_ITMP1);
1281 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1282 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1283 store_reg_to_var_int(iptr->dst, d);
1286 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1288 var_to_reg_int(s1, src->prev, REG_ITMP1);
1289 var_to_reg_int(s2, src, REG_ITMP2);
1290 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1291 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1292 M_SRL(s1, REG_ITMP2, d);
1293 store_reg_to_var_int(iptr->dst, d);
1296 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1297 /* val.i = constant */
1299 var_to_reg_int(s1, src, REG_ITMP1);
1300 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1301 if (iptr->val.i & 0x1f)
1302 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1305 store_reg_to_var_int(iptr->dst, d);
1308 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1310 var_to_reg_int(s1, src->prev, REG_ITMP1);
1311 var_to_reg_int(s2, src, REG_ITMP2);
1312 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1314 store_reg_to_var_int(iptr->dst, d);
1317 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1318 /* val.i = constant */
1320 var_to_reg_int(s1, src, REG_ITMP1);
1321 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1322 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1323 M_AND_IMM(s1, iptr->val.i, d);
1326 else if (iptr->val.i == 0xffffff) {
1327 M_RLWINM(s1, 0, 8, 31, d);
1331 ICONST(REG_ITMP2, iptr->val.i);
1332 M_AND(s1, REG_ITMP2, d);
1334 store_reg_to_var_int(iptr->dst, d);
1337 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1339 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1340 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1341 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1342 M_AND(s1, s2, r->secondregs[d]);
1343 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1344 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1346 store_reg_to_var_int(iptr->dst, d);
1349 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1350 /* val.l = constant */
1352 s3 = iptr->val.l & 0xffffffff;
1353 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1354 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1355 if ((s3 >= 0) && (s3 <= 65535)) {
1356 M_AND_IMM(s1, s3, r->secondregs[d]);
1359 ICONST(REG_ITMP2, s3);
1360 M_AND(s1, REG_ITMP2, r->secondregs[d]);
1362 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1363 s3 = iptr->val.l >> 32;
1364 if ((s3 >= 0) && (s3 <= 65535)) {
1365 M_AND_IMM(s1, s3, d);
1368 ICONST(REG_ITMP3, s3);
1369 M_AND(s1, REG_ITMP3, d);
1371 store_reg_to_var_int(iptr->dst, d);
1374 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1375 /* val.i = constant */
1377 var_to_reg_int(s1, src, REG_ITMP1);
1378 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1379 M_MOV(s1, REG_ITMP2);
1381 M_BGE(1 + 2*(iptr->val.i >= 32768));
1382 if (iptr->val.i >= 32768) {
1383 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1384 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1385 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1388 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1390 int b=0, m = iptr->val.i;
1393 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1395 M_ISUB(s1, REG_ITMP2, d);
1396 store_reg_to_var_int(iptr->dst, d);
1399 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1401 var_to_reg_int(s1, src->prev, REG_ITMP1);
1402 var_to_reg_int(s2, src, REG_ITMP2);
1403 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1405 store_reg_to_var_int(iptr->dst, d);
1408 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1409 /* val.i = constant */
1411 var_to_reg_int(s1, src, REG_ITMP1);
1412 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1413 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1414 M_OR_IMM(s1, iptr->val.i, d);
1417 ICONST(REG_ITMP2, iptr->val.i);
1418 M_OR(s1, REG_ITMP2, d);
1420 store_reg_to_var_int(iptr->dst, d);
1423 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1425 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1426 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1427 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1428 M_OR(s1, s2, r->secondregs[d]);
1429 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1430 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1432 store_reg_to_var_int(iptr->dst, d);
1435 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1436 /* val.l = constant */
1438 s3 = iptr->val.l & 0xffffffff;
1439 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1440 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1441 if ((s3 >= 0) && (s3 <= 65535)) {
1442 M_OR_IMM(s1, s3, r->secondregs[d]);
1445 ICONST(REG_ITMP2, s3);
1446 M_OR(s1, REG_ITMP2, r->secondregs[d]);
1448 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1449 s3 = iptr->val.l >> 32;
1450 if ((s3 >= 0) && (s3 <= 65535)) {
1451 M_OR_IMM(s1, s3, d);
1454 ICONST(REG_ITMP3, s3);
1455 M_OR(s1, REG_ITMP3, d);
1457 store_reg_to_var_int(iptr->dst, d);
1460 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1462 var_to_reg_int(s1, src->prev, REG_ITMP1);
1463 var_to_reg_int(s2, src, REG_ITMP2);
1464 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1466 store_reg_to_var_int(iptr->dst, d);
1469 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1470 /* val.i = constant */
1472 var_to_reg_int(s1, src, REG_ITMP1);
1473 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1474 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1475 M_XOR_IMM(s1, iptr->val.i, d);
1478 ICONST(REG_ITMP2, iptr->val.i);
1479 M_XOR(s1, REG_ITMP2, d);
1481 store_reg_to_var_int(iptr->dst, d);
1484 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1486 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1487 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1488 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1489 M_XOR(s1, s2, r->secondregs[d]);
1490 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1491 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1493 store_reg_to_var_int(iptr->dst, d);
1496 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1497 /* val.l = constant */
1499 s3 = iptr->val.l & 0xffffffff;
1500 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1501 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1502 if ((s3 >= 0) && (s3 <= 65535)) {
1503 M_XOR_IMM(s1, s3, r->secondregs[d]);
1506 ICONST(REG_ITMP2, s3);
1507 M_XOR(s1, REG_ITMP2, r->secondregs[d]);
1509 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1510 s3 = iptr->val.l >> 32;
1511 if ((s3 >= 0) && (s3 <= 65535)) {
1512 M_XOR_IMM(s1, s3, d);
1515 ICONST(REG_ITMP3, s3);
1516 M_XOR(s1, REG_ITMP3, d);
1518 store_reg_to_var_int(iptr->dst, d);
1521 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1523 var_to_reg_int0(s1, src->prev, REG_ITMP3, 1, 0);
1524 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
1525 d = reg_of_var(m, iptr->dst, REG_ITMP1);
1528 (d==s1 || d==s2 || d==r->secondregs[s1] || d==r->secondregs[s2]);
1529 int dreg = tempreg ? REG_ITMP1 : d;
1531 M_IADD_IMM(REG_ZERO, 1, dreg);
1536 var_to_reg_int0(s1, src->prev, REG_ITMP3, 0, 1);
1537 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1541 M_IADD_IMM(dreg, -1, dreg);
1542 M_IADD_IMM(dreg, -1, dreg);
1543 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1544 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1547 store_reg_to_var_int(iptr->dst, d);
1550 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1551 /* op1 = variable, val.i = constant */
1553 var = &(r->locals[iptr->op1][TYPE_INT]);
1554 if (var->flags & INMEMORY) {
1556 M_ILD(s1, REG_SP, 4 * var->regoff);
1565 M_ADDIS(s1, m>>16, s1);
1567 M_IADD_IMM(s1, m&0xffff, s1);
1569 if (var->flags & INMEMORY)
1570 M_IST(s1, REG_SP, 4 * var->regoff);
1574 /* floating operations ************************************************/
1576 case ICMD_FNEG: /* ..., value ==> ..., - value */
1578 var_to_reg_flt(s1, src, REG_FTMP1);
1579 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1581 store_reg_to_var_flt(iptr->dst, d);
1584 case ICMD_DNEG: /* ..., value ==> ..., - value */
1586 var_to_reg_flt(s1, src, REG_FTMP1);
1587 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1589 store_reg_to_var_flt(iptr->dst, d);
1592 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1594 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1595 var_to_reg_flt(s2, src, REG_FTMP2);
1596 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1598 store_reg_to_var_flt(iptr->dst, d);
1601 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1603 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1604 var_to_reg_flt(s2, src, REG_FTMP2);
1605 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1607 store_reg_to_var_flt(iptr->dst, d);
1610 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1612 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1613 var_to_reg_flt(s2, src, REG_FTMP2);
1614 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1616 store_reg_to_var_flt(iptr->dst, d);
1619 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1621 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1622 var_to_reg_flt(s2, src, REG_FTMP2);
1623 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1625 store_reg_to_var_flt(iptr->dst, d);
1628 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1630 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1631 var_to_reg_flt(s2, src, REG_FTMP2);
1632 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1634 store_reg_to_var_flt(iptr->dst, d);
1637 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1639 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1640 var_to_reg_flt(s2, src, REG_FTMP2);
1641 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1643 store_reg_to_var_flt(iptr->dst, d);
1646 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1648 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1649 var_to_reg_flt(s2, src, REG_FTMP2);
1650 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1652 store_reg_to_var_flt(iptr->dst, d);
1655 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1657 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1658 var_to_reg_flt(s2, src, REG_FTMP2);
1659 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1661 store_reg_to_var_flt(iptr->dst, d);
1664 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1666 var_to_reg_flt(s1, src, REG_FTMP1);
1667 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1669 a = dseg_addfloat(0.0);
1670 M_FLD(REG_FTMP2, REG_PV, a);
1671 M_FCMPU(s1, REG_FTMP2);
1674 M_CVTDL_C(s1, REG_FTMP1);
1675 M_LDA (REG_ITMP1, REG_PV, a);
1676 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1677 M_ILD (d, REG_PV, a);
1678 store_reg_to_var_int(iptr->dst, d);
1681 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1683 var_to_reg_flt(s1, src, REG_FTMP1);
1684 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1686 store_reg_to_var_flt(iptr->dst, d);
1689 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1691 var_to_reg_flt(s1, src, REG_FTMP1);
1692 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1694 store_reg_to_var_flt(iptr->dst, d);
1697 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1699 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1700 var_to_reg_flt(s2, src, REG_FTMP2);
1701 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1703 M_IADD_IMM(0, -1, d);
1706 M_IADD_IMM(0, 0, d);
1708 M_IADD_IMM(0, 1, d);
1709 store_reg_to_var_int(iptr->dst, d);
1712 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1714 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1715 var_to_reg_flt(s2, src, REG_FTMP2);
1716 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1718 M_IADD_IMM(0, 1, d);
1721 M_IADD_IMM(0, 0, d);
1723 M_IADD_IMM(0, -1, d);
1724 store_reg_to_var_int(iptr->dst, d);
1728 /* memory operations **************************************************/
1730 #define gen_bound_check \
1731 if (checkbounds) { \
1732 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1733 M_CMPU(s2, REG_ITMP3);\
1735 codegen_addxboundrefs(mcodeptr, s2); \
1738 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1740 var_to_reg_int(s1, src, REG_ITMP1);
1741 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1742 gen_nullptr_check(s1);
1743 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1744 store_reg_to_var_int(iptr->dst, d);
1747 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1749 var_to_reg_int(s1, src->prev, REG_ITMP1);
1750 var_to_reg_int(s2, src, REG_ITMP2);
1751 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1752 if (iptr->op1 == 0) {
1753 gen_nullptr_check(s1);
1756 M_SLL_IMM(s2, 2, REG_ITMP2);
1757 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1758 M_LWZX(d, s1, REG_ITMP2);
1759 store_reg_to_var_int(iptr->dst, d);
1762 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1764 var_to_reg_int(s1, src->prev, REG_ITMP1);
1765 var_to_reg_int(s2, src, REG_ITMP2);
1766 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1767 if (iptr->op1 == 0) {
1768 gen_nullptr_check(s1);
1771 M_SLL_IMM(s2, 3, REG_ITMP2);
1772 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1773 M_ILD(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
1774 M_ILD(r->secondregs[d], REG_ITMP2, OFFSET(java_longarray, data[0])+4);
1775 store_reg_to_var_int(iptr->dst, d);
1778 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1780 var_to_reg_int(s1, src->prev, REG_ITMP1);
1781 var_to_reg_int(s2, src, REG_ITMP2);
1782 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1783 if (iptr->op1 == 0) {
1784 gen_nullptr_check(s1);
1787 M_SLL_IMM(s2, 2, REG_ITMP2);
1788 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1789 M_LWZX(d, s1, REG_ITMP2);
1790 store_reg_to_var_int(iptr->dst, d);
1793 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1795 var_to_reg_int(s1, src->prev, REG_ITMP1);
1796 var_to_reg_int(s2, src, REG_ITMP2);
1797 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1798 if (iptr->op1 == 0) {
1799 gen_nullptr_check(s1);
1802 M_SLL_IMM(s2, 2, REG_ITMP2);
1803 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1804 M_LFSX(d, s1, REG_ITMP2);
1805 store_reg_to_var_flt(iptr->dst, d);
1808 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1810 var_to_reg_int(s1, src->prev, REG_ITMP1);
1811 var_to_reg_int(s2, src, REG_ITMP2);
1812 d = reg_of_var(m, iptr->dst, REG_FTMP3);
1813 if (iptr->op1 == 0) {
1814 gen_nullptr_check(s1);
1817 M_SLL_IMM(s2, 3, REG_ITMP2);
1818 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1819 M_LFDX(d, s1, REG_ITMP2);
1820 store_reg_to_var_flt(iptr->dst, d);
1823 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1825 var_to_reg_int(s1, src->prev, REG_ITMP1);
1826 var_to_reg_int(s2, src, REG_ITMP2);
1827 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1828 if (iptr->op1 == 0) {
1829 gen_nullptr_check(s1);
1832 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1833 M_LBZX(d, s1, REG_ITMP2);
1835 store_reg_to_var_int(iptr->dst, d);
1838 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1840 var_to_reg_int(s1, src->prev, REG_ITMP1);
1841 var_to_reg_int(s2, src, REG_ITMP2);
1842 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1843 if (iptr->op1 == 0) {
1844 gen_nullptr_check(s1);
1847 M_SLL_IMM(s2, 1, REG_ITMP2);
1848 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1849 M_LHAX(d, s1, REG_ITMP2);
1850 store_reg_to_var_int(iptr->dst, d);
1853 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1855 var_to_reg_int(s1, src->prev, REG_ITMP1);
1856 var_to_reg_int(s2, src, REG_ITMP2);
1857 d = reg_of_var(m, iptr->dst, REG_ITMP3);
1858 if (iptr->op1 == 0) {
1859 gen_nullptr_check(s1);
1862 M_SLL_IMM(s2, 1, REG_ITMP2);
1863 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1864 M_LHZX(d, s1, REG_ITMP2);
1865 store_reg_to_var_int(iptr->dst, d);
1868 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1870 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1871 var_to_reg_int(s2, src->prev, REG_ITMP2);
1872 if (iptr->op1 == 0) {
1873 gen_nullptr_check(s1);
1876 var_to_reg_int0(s3, src, REG_ITMP3, 1, 0);
1877 M_SLL_IMM(s2, 3, REG_ITMP2);
1878 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1879 M_STWX(s3, s1, REG_ITMP2);
1880 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1881 var_to_reg_int0(s3, src, REG_ITMP3, 0, 1);
1882 M_STWX(s3, s1, REG_ITMP2);
1885 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1887 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1888 var_to_reg_int(s2, src->prev, REG_ITMP2);
1889 if (iptr->op1 == 0) {
1890 gen_nullptr_check(s1);
1893 var_to_reg_int(s3, src, REG_ITMP3);
1894 M_SLL_IMM(s2, 2, REG_ITMP2);
1895 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1896 M_STWX(s3, s1, REG_ITMP2);
1899 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1901 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1902 var_to_reg_int(s2, src->prev, REG_ITMP2);
1903 if (iptr->op1 == 0) {
1904 gen_nullptr_check(s1);
1907 var_to_reg_flt(s3, src, REG_FTMP3);
1908 M_SLL_IMM(s2, 2, REG_ITMP2);
1909 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1910 M_STFSX(s3, s1, REG_ITMP2);
1913 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1915 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1916 var_to_reg_int(s2, src->prev, REG_ITMP2);
1917 if (iptr->op1 == 0) {
1918 gen_nullptr_check(s1);
1921 var_to_reg_flt(s3, src, REG_FTMP3);
1922 M_SLL_IMM(s2, 3, REG_ITMP2);
1923 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1924 M_STFDX(s3, s1, REG_ITMP2);
1927 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1929 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1930 var_to_reg_int(s2, src->prev, REG_ITMP2);
1931 if (iptr->op1 == 0) {
1932 gen_nullptr_check(s1);
1935 var_to_reg_int(s3, src, REG_ITMP3);
1936 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1937 M_STBX(s3, s1, REG_ITMP2);
1940 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1942 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1943 var_to_reg_int(s2, src->prev, REG_ITMP2);
1944 if (iptr->op1 == 0) {
1945 gen_nullptr_check(s1);
1948 var_to_reg_int(s3, src, REG_ITMP3);
1949 M_SLL_IMM(s2, 1, REG_ITMP2);
1950 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1951 M_STHX(s3, s1, REG_ITMP2);
1954 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1956 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1957 var_to_reg_int(s2, src->prev, REG_ITMP2);
1958 if (iptr->op1 == 0) {
1959 gen_nullptr_check(s1);
1962 var_to_reg_int(s3, src, REG_ITMP3);
1963 M_SLL_IMM(s2, 1, REG_ITMP2);
1964 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1965 M_STHX(s3, s1, REG_ITMP2);
1968 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1969 /* op1 = type, val.a = field address */
1971 /* if class isn't yet initialized, do it */
1972 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1973 /* call helper function which patches this code */
1974 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
1975 M_ALD(REG_ITMP1, REG_PV, a);
1976 a = dseg_addaddress(asm_check_clinit);
1977 M_ALD(REG_PV, REG_PV, a);
1982 s1 = (int) ((u1*) mcodeptr - mcodebase);
1984 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1986 s4 ml = -s1, mh = 0;
1987 while (ml < -32768) { ml += 65536; mh--; }
1988 M_LDA(REG_PV, REG_ITMP1, ml);
1989 M_LDAH(REG_PV, REG_PV, mh);
1993 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
1994 M_ALD(REG_ITMP1, REG_PV, a);
1995 switch (iptr->op1) {
1997 var_to_reg_int(s2, src, REG_ITMP2);
1998 M_IST(s2, REG_ITMP1, 0);
2001 var_to_reg_int(s2, src, REG_ITMP3);
2002 M_IST(s2, REG_ITMP1, 0);
2003 M_IST(r->secondregs[s2], REG_ITMP1, 4);
2006 var_to_reg_int(s2, src, REG_ITMP2);
2007 M_AST(s2, REG_ITMP1, 0);
2010 var_to_reg_flt(s2, src, REG_FTMP2);
2011 M_FST(s2, REG_ITMP1, 0);
2014 var_to_reg_flt(s2, src, REG_FTMP2);
2015 M_DST(s2, REG_ITMP1, 0);
2017 default: panic ("internal error");
2021 case ICMD_GETSTATIC: /* ... ==> ..., value */
2022 /* op1 = type, val.a = field address */
2024 /* if class isn't yet initialized, do it */
2025 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2026 /* call helper function which patches this code */
2027 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
2028 M_ALD(REG_ITMP1, REG_PV, a);
2029 a = dseg_addaddress(asm_check_clinit);
2030 M_ALD(REG_PV, REG_PV, a);
2035 s1 = (int) ((u1*) mcodeptr - mcodebase);
2037 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2039 s4 ml = -s1, mh = 0;
2040 while (ml < -32768) { ml += 65536; mh--; }
2041 M_LDA(REG_PV, REG_ITMP1, ml);
2042 M_LDAH(REG_PV, REG_PV, mh);
2046 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2047 M_ALD(REG_ITMP1, REG_PV, a);
2048 switch (iptr->op1) {
2050 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2051 M_ILD(d, REG_ITMP1, 0);
2052 store_reg_to_var_int(iptr->dst, d);
2055 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2056 M_ILD(d, REG_ITMP1, 0);
2057 M_ILD(r->secondregs[d], REG_ITMP1, 4);
2058 store_reg_to_var_int(iptr->dst, d);
2061 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2062 M_ALD(d, REG_ITMP1, 0);
2063 store_reg_to_var_int(iptr->dst, d);
2066 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2067 M_FLD(d, REG_ITMP1, 0);
2068 store_reg_to_var_flt(iptr->dst, d);
2071 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2072 M_DLD(d, REG_ITMP1, 0);
2073 store_reg_to_var_flt(iptr->dst, d);
2075 default: panic ("internal error");
2080 case ICMD_PUTFIELD: /* ..., value ==> ... */
2081 /* op1 = type, val.i = field offset */
2083 a = ((fieldinfo *)(iptr->val.a))->offset;
2084 switch (iptr->op1) {
2086 var_to_reg_int(s1, src->prev, REG_ITMP1);
2087 var_to_reg_int(s2, src, REG_ITMP2);
2088 gen_nullptr_check(s1);
2092 var_to_reg_int(s1, src->prev, REG_ITMP1);
2093 var_to_reg_int(s2, src, REG_ITMP3);
2094 gen_nullptr_check(s1);
2096 M_IST(r->secondregs[s2], s1, a+4);
2099 var_to_reg_int(s1, src->prev, REG_ITMP1);
2100 var_to_reg_int(s2, src, REG_ITMP2);
2101 gen_nullptr_check(s1);
2105 var_to_reg_int(s1, src->prev, REG_ITMP1);
2106 var_to_reg_flt(s2, src, REG_FTMP2);
2107 gen_nullptr_check(s1);
2111 var_to_reg_int(s1, src->prev, REG_ITMP1);
2112 var_to_reg_flt(s2, src, REG_FTMP2);
2113 gen_nullptr_check(s1);
2116 default: panic ("internal error");
2120 case ICMD_GETFIELD: /* ... ==> ..., value */
2121 /* op1 = type, val.i = field offset */
2123 a = ((fieldinfo *)(iptr->val.a))->offset;
2124 switch (iptr->op1) {
2126 var_to_reg_int(s1, src, REG_ITMP1);
2127 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2128 gen_nullptr_check(s1);
2130 store_reg_to_var_int(iptr->dst, d);
2133 var_to_reg_int(s1, src, REG_ITMP1);
2134 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2135 gen_nullptr_check(s1);
2137 M_ILD(r->secondregs[d], s1, a+4);
2138 store_reg_to_var_int(iptr->dst, d);
2141 var_to_reg_int(s1, src, REG_ITMP1);
2142 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2143 gen_nullptr_check(s1);
2145 store_reg_to_var_int(iptr->dst, d);
2148 var_to_reg_int(s1, src, REG_ITMP1);
2149 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2150 gen_nullptr_check(s1);
2152 store_reg_to_var_flt(iptr->dst, d);
2155 var_to_reg_int(s1, src, REG_ITMP1);
2156 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2157 gen_nullptr_check(s1);
2159 store_reg_to_var_flt(iptr->dst, d);
2161 default: panic ("internal error");
2166 /* branch operations **************************************************/
2168 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2170 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2172 a = dseg_addaddress(asm_handle_exception);
2173 M_ALD(REG_ITMP2, REG_PV, a);
2175 var_to_reg_int(s1, src, REG_ITMP1);
2176 M_INTMOVE(s1, REG_ITMP1_XPTR);
2178 if (m->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
2179 M_BL(0); /* get current PC */
2180 M_MFLR(REG_ITMP2_XPC);
2181 if (m->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
2182 M_RTS; /* jump to CTR */
2187 case ICMD_GOTO: /* ... ==> ... */
2188 /* op1 = target JavaVM pc */
2190 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2194 case ICMD_JSR: /* ... ==> ... */
2195 /* op1 = target JavaVM pc */
2197 if (m->isleafmethod) M_MFLR(REG_ITMP2);
2200 M_IADD_IMM(REG_ITMP1, m->isleafmethod?16:12, REG_ITMP1);
2201 if (m->isleafmethod) M_MTLR(REG_ITMP2);
2203 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2206 case ICMD_RET: /* ... ==> ... */
2207 /* op1 = local variable */
2209 var = &(r->locals[iptr->op1][TYPE_ADR]);
2210 if (var->flags & INMEMORY) {
2211 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
2215 M_MTCTR(var->regoff);
2220 case ICMD_IFNULL: /* ..., value ==> ... */
2221 /* op1 = target JavaVM pc */
2223 var_to_reg_int(s1, src, REG_ITMP1);
2226 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2229 case ICMD_IFNONNULL: /* ..., value ==> ... */
2230 /* op1 = target JavaVM pc */
2232 var_to_reg_int(s1, src, REG_ITMP1);
2235 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2243 case ICMD_IFEQ: /* ..., value ==> ... */
2244 /* op1 = target JavaVM pc, val.i = constant */
2246 var_to_reg_int(s1, src, REG_ITMP1);
2247 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2248 M_CMPI(s1, iptr->val.i);
2251 ICONST(REG_ITMP2, iptr->val.i);
2252 M_CMP(s1, REG_ITMP2);
2275 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2279 case ICMD_IF_LEQ: /* ..., value ==> ... */
2280 /* op1 = target JavaVM pc, val.l = constant */
2282 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2283 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2284 if (iptr->val.l == 0) {
2285 M_OR(s1, s2, REG_ITMP3);
2286 M_CMPI(REG_ITMP3, 0);
2288 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2289 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2291 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2294 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2295 M_CMP(s2, REG_ITMP3);
2297 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2298 M_CMP(s1, REG_ITMP3)
2301 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2304 case ICMD_IF_LLT: /* ..., value ==> ... */
2305 /* op1 = target JavaVM pc, val.l = constant */
2306 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2307 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2308 /* if (iptr->val.l == 0) { */
2309 /* M_OR(s1, s2, REG_ITMP3); */
2310 /* M_CMPI(REG_ITMP3, 0); */
2313 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2314 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2316 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2318 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2321 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2322 M_CMP(s2, REG_ITMP3);
2324 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2326 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2327 M_CMP(s1, REG_ITMP3)
2330 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2333 case ICMD_IF_LLE: /* ..., value ==> ... */
2334 /* op1 = target JavaVM pc, val.l = constant */
2336 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2337 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2338 /* if (iptr->val.l == 0) { */
2339 /* M_OR(s1, s2, REG_ITMP3); */
2340 /* M_CMPI(REG_ITMP3, 0); */
2343 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2344 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2346 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2348 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2351 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2352 M_CMP(s2, REG_ITMP3);
2354 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2356 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2357 M_CMP(s1, REG_ITMP3)
2360 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2363 case ICMD_IF_LNE: /* ..., value ==> ... */
2364 /* op1 = target JavaVM pc, val.l = constant */
2366 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2367 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2368 if (iptr->val.l == 0) {
2369 M_OR(s1, s2, REG_ITMP3);
2370 M_CMPI(REG_ITMP3, 0);
2372 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2373 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2375 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2378 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2379 M_CMP(s2, REG_ITMP3);
2381 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2382 M_CMP(s1, REG_ITMP3)
2385 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2388 case ICMD_IF_LGT: /* ..., value ==> ... */
2389 /* op1 = target JavaVM pc, val.l = constant */
2391 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2392 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2393 /* if (iptr->val.l == 0) { */
2394 /* M_OR(s1, s2, REG_ITMP3); */
2395 /* M_CMPI(REG_ITMP3, 0); */
2398 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2399 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2401 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2403 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2406 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2407 M_CMP(s2, REG_ITMP3);
2409 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2411 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2412 M_CMP(s1, REG_ITMP3)
2415 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2418 case ICMD_IF_LGE: /* ..., value ==> ... */
2419 /* op1 = target JavaVM pc, val.l = constant */
2420 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2421 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2422 /* if (iptr->val.l == 0) { */
2423 /* M_OR(s1, s2, REG_ITMP3); */
2424 /* M_CMPI(REG_ITMP3, 0); */
2427 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2428 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2430 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2432 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2435 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2436 M_CMP(s2, REG_ITMP3);
2438 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2440 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2441 M_CMP(s1, REG_ITMP3)
2444 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2448 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2449 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2450 case ICMD_IF_ACMPEQ:
2452 var_to_reg_int(s1, src->prev, REG_ITMP1);
2453 var_to_reg_int(s2, src, REG_ITMP2);
2456 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2459 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2460 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2461 case ICMD_IF_ACMPNE:
2463 var_to_reg_int(s1, src->prev, REG_ITMP1);
2464 var_to_reg_int(s2, src, REG_ITMP2);
2467 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2470 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2471 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2473 var_to_reg_int(s1, src->prev, REG_ITMP1);
2474 var_to_reg_int(s2, src, REG_ITMP2);
2477 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2480 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2481 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2483 var_to_reg_int(s1, src->prev, REG_ITMP1);
2484 var_to_reg_int(s2, src, REG_ITMP2);
2487 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2490 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2491 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2493 var_to_reg_int(s1, src->prev, REG_ITMP1);
2494 var_to_reg_int(s2, src, REG_ITMP2);
2497 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2500 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2501 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2503 var_to_reg_int(s1, src->prev, REG_ITMP1);
2504 var_to_reg_int(s2, src, REG_ITMP2);
2507 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2510 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2514 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2517 case ICMD_RETURN: /* ... ==> ... */
2520 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2521 a = dseg_addaddress ((void*) (builtin_monitorexit));
2522 M_ALD(REG_ITMP3, REG_PV, a);
2524 M_ALD(r->argintregs[0], REG_SP, 4 * r->maxmemuse);
2528 switch (iptr->opc) {
2532 var_to_reg_int(s1, src, REG_RESULT);
2533 M_TINTMOVE(src->type, s1, REG_RESULT);
2534 goto nowperformreturn;
2538 var_to_reg_flt(s1, src, REG_FRESULT);
2539 M_FLTMOVE(s1, REG_FRESULT);
2540 goto nowperformreturn;
2547 p = parentargs_base;
2549 /* restore return address */
2551 if (!m->isleafmethod) {
2552 M_ALD (REG_ITMP3, REG_SP, 4 * p + 8);
2556 /* restore saved registers */
2558 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
2559 p--; M_ILD(r->savintregs[i], REG_SP, 4 * p);
2561 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
2562 p -= 2; M_DLD(r->savfltregs[i], REG_SP, 4 * p);
2565 /* deallocate stack */
2567 if (parentargs_base) {
2568 M_LDA(REG_SP, REG_SP, parentargs_base*4);
2571 /* call trace function */
2575 M_LDA(REG_SP, REG_SP, -10 * 8);
2576 M_DST(REG_FRESULT, REG_SP, 48+0);
2577 M_IST(REG_RESULT, REG_SP, 48+8);
2578 M_AST(REG_ITMP3, REG_SP, 48+12);
2579 M_IST(REG_RESULT2, REG_SP, 48+16);
2580 a = dseg_addaddress(m);
2582 /* keep this order */
2583 switch (iptr->opc) {
2586 M_MOV(REG_RESULT, r->argintregs[2]);
2587 M_CLR(r->argintregs[1]);
2591 M_MOV(REG_RESULT2, r->argintregs[2]);
2592 M_MOV(REG_RESULT, r->argintregs[1]);
2595 M_ALD(r->argintregs[0], REG_PV, a);
2597 M_FLTMOVE(REG_FRESULT, r->argfltregs[0]);
2598 M_FLTMOVE(REG_FRESULT, r->argfltregs[1]);
2599 a = dseg_addaddress((void *) (builtin_displaymethodstop));
2600 M_ALD(REG_ITMP2, REG_PV, a);
2603 M_DLD(REG_FRESULT, REG_SP, 48+0);
2604 M_ILD(REG_RESULT, REG_SP, 48+8);
2605 M_ALD(REG_ITMP3, REG_SP, 48+12);
2606 M_ILD(REG_RESULT2, REG_SP, 48+16);
2607 M_LDA(REG_SP, REG_SP, 10 * 8);
2617 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2622 tptr = (void **) iptr->target;
2624 s4ptr = iptr->val.a;
2625 l = s4ptr[1]; /* low */
2626 i = s4ptr[2]; /* high */
2628 var_to_reg_int(s1, src, REG_ITMP1);
2630 M_INTMOVE(s1, REG_ITMP1);
2631 } else if (l <= 32768) {
2632 M_LDA(REG_ITMP1, s1, -l);
2634 ICONST(REG_ITMP2, l);
2635 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2641 M_CMPUI(REG_ITMP1, i - 1);
2644 /* codegen_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2645 codegen_addreference((basicblock *) tptr[0], mcodeptr);
2647 /* build jump table top down and use address of lowest entry */
2649 /* s4ptr += 3 + i; */
2653 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
2654 dseg_addtarget((basicblock *) tptr[0]);
2659 /* length of dataseg after last dseg_addtarget is used by load */
2661 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2662 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2663 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
2670 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2672 s4 i, l, val, *s4ptr;
2675 tptr = (void **) iptr->target;
2677 s4ptr = iptr->val.a;
2678 l = s4ptr[0]; /* default */
2679 i = s4ptr[1]; /* count */
2681 MCODECHECK((i<<2)+8);
2682 var_to_reg_int(s1, src, REG_ITMP1);
2688 if ((val >= -32768) && (val <= 32767)) {
2692 a = dseg_adds4 (val);
2693 M_ILD(REG_ITMP2, REG_PV, a);
2694 M_CMP(s1, REG_ITMP2);
2697 /* codegen_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2698 codegen_addreference((basicblock *) tptr[0], mcodeptr);
2702 /* codegen_addreference(BlockPtrOfPC(l), mcodeptr); */
2704 tptr = (void **) iptr->target;
2705 codegen_addreference((basicblock *) tptr[0], mcodeptr);
2712 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2713 /* op1 = return type, val.a = function pointer*/
2717 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2718 /* op1 = return type, val.a = function pointer*/
2722 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2723 /* op1 = return type, val.a = function pointer*/
2727 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2728 /* op1 = arg count, val.a = method pointer */
2730 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2731 /* op1 = arg count, val.a = method pointer */
2733 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2734 /* op1 = arg count, val.a = method pointer */
2736 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2737 /* op1 = arg count, val.a = method pointer */
2745 MCODECHECK((s3 << 1) + 64);
2748 /* copy arguments to registers or stack location */
2750 stackptr srcsave = src;
2754 for (; --s3 >= 0; src = src->prev) {
2755 argsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
2756 if (IS_FLT_DBL_TYPE(src->type))
2760 for (s3=s3save, src=srcsave; --s3 >= 0; src = src->prev) {
2761 argsize -= IS_2_WORD_TYPE(src->type) ? 2 : 1;
2762 if (IS_FLT_DBL_TYPE(src->type))
2764 if (src->varkind == ARGVAR)
2766 if (IS_INT_LNG_TYPE(src->type)) {
2767 if (argsize < INT_ARG_CNT) {
2768 s1 = r->argintregs[argsize];
2769 var_to_reg_int(d, src, s1);
2770 if (argsize < INT_ARG_CNT-1) {
2771 M_TINTMOVE(src->type, d, s1);
2774 if (IS_2_WORD_TYPE(src->type))
2775 M_IST(r->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2778 var_to_reg_int(d, src, REG_ITMP1);
2779 M_IST(d, REG_SP, 4 * (argsize + 6));
2780 if (IS_2_WORD_TYPE(src->type))
2781 M_IST(r->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2784 if (fltcnt < FLT_ARG_CNT) {
2785 s1 = r->argfltregs[fltcnt];
2786 var_to_reg_flt(d, src, s1);
2789 var_to_reg_flt(d, src, REG_FTMP1);
2790 if (IS_2_WORD_TYPE(src->type))
2791 M_DST(d, REG_SP, 4 * (argsize + 6));
2793 M_FST(d, REG_SP, 4 * (argsize + 6));
2799 switch (iptr->opc) {
2803 a = dseg_addaddress ((void*) (lm));
2805 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2807 goto makeactualcall;
2809 case ICMD_INVOKESTATIC:
2810 case ICMD_INVOKESPECIAL:
2811 a = dseg_addaddress (lm->stubroutine);
2813 M_ALD(REG_PV, REG_PV, a ); /* method pointer in r27 */
2816 goto makeactualcall;
2818 case ICMD_INVOKEVIRTUAL:
2820 gen_nullptr_check(r->argintregs[0]);
2821 M_ALD(REG_METHODPTR, r->argintregs[0],
2822 OFFSET(java_objectheader, vftbl));
2823 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) +
2824 sizeof(methodptr) * lm->vftblindex);
2827 goto makeactualcall;
2829 case ICMD_INVOKEINTERFACE:
2832 gen_nullptr_check(r->argintregs[0]);
2833 M_ALD(REG_METHODPTR, r->argintregs[0],
2834 OFFSET(java_objectheader, vftbl));
2835 M_ALD(REG_METHODPTR, REG_METHODPTR,
2836 OFFSET(vftbl_t, interfacetable[0]) -
2837 sizeof(methodptr*) * ci->index);
2838 M_ALD(REG_PV, REG_METHODPTR,
2839 sizeof(methodptr) * (lm - ci->methods));
2842 goto makeactualcall;
2846 error ("Unkown ICMD-Command: %d", iptr->opc);
2855 s1 = (int) ((u1 *) mcodeptr - mcodebase);
2857 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2859 s4 ml = -s1, mh = 0;
2860 while (ml < -32768) { ml += 65536; mh--; }
2861 M_LDA(REG_PV, REG_ITMP1, ml);
2862 M_LDAH(REG_PV, REG_PV, mh);
2865 /* d contains return type */
2867 if (d != TYPE_VOID) {
2868 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2869 s1 = reg_of_var(m, iptr->dst, REG_RESULT);
2870 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2871 store_reg_to_var_int(iptr->dst, s1);
2874 s1 = reg_of_var(m, iptr->dst, REG_FRESULT);
2875 M_FLTMOVE(REG_FRESULT, s1);
2876 store_reg_to_var_flt(iptr->dst, s1);
2883 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2885 /* op1: 0 == array, 1 == class */
2886 /* val.a: (classinfo*) superclass */
2888 /* superclass is an interface:
2890 * return (sub != NULL) &&
2891 * (sub->vftbl->interfacetablelength > super->index) &&
2892 * (sub->vftbl->interfacetable[-super->index] != NULL);
2894 * superclass is a class:
2896 * return ((sub != NULL) && (0
2897 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2898 * super->vftbl->diffvall));
2902 classinfo *super = (classinfo*) iptr->val.a;
2904 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2905 codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
2907 var_to_reg_int(s1, src, REG_ITMP1);
2908 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2910 M_MOV(s1, REG_ITMP1);
2914 if (iptr->op1) { /* class/interface */
2916 if (super->flags & ACC_INTERFACE) { /* interface */
2918 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2919 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2920 M_LDATST(REG_ITMP2, REG_ITMP2, - super->index);
2922 M_ALD(REG_ITMP1, REG_ITMP1,
2923 OFFSET(vftbl_t, interfacetable[0]) -
2924 super->index * sizeof(methodptr*));
2928 M_IADD_IMM(REG_ZERO, 1, d);
2932 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2933 a = dseg_addaddress ((void*) super->vftbl);
2934 M_ALD(REG_ITMP2, REG_PV, a);
2935 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2936 codegen_threadcritstart((u1*) mcodeptr - mcodebase);
2938 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2939 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2940 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2941 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2942 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
2944 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2945 M_CMPU(REG_ITMP1, REG_ITMP2);
2948 M_IADD_IMM(REG_ZERO, 1, d);
2952 panic ("internal error: no inlined array instanceof");
2954 store_reg_to_var_int(iptr->dst, d);
2957 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2959 /* op1: 0 == array, 1 == class */
2960 /* val.a: (classinfo*) superclass */
2962 /* superclass is an interface:
2964 * OK if ((sub == NULL) ||
2965 * (sub->vftbl->interfacetablelength > super->index) &&
2966 * (sub->vftbl->interfacetable[-super->index] != NULL));
2968 * superclass is a class:
2970 * OK if ((sub == NULL) || (0
2971 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2972 * super->vftbl->diffvall));
2976 classinfo *super = (classinfo*) iptr->val.a;
2978 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2979 codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
2981 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2982 var_to_reg_int(s1, src, d);
2983 if (iptr->op1) { /* class/interface */
2985 if (super->flags & ACC_INTERFACE) { /* interface */
2987 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2988 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2989 M_LDATST(REG_ITMP3, REG_ITMP3, - super->index);
2991 codegen_addxcastrefs(mcodeptr);
2992 M_ALD(REG_ITMP3, REG_ITMP2,
2993 OFFSET(vftbl_t, interfacetable[0]) -
2994 super->index * sizeof(methodptr*));
2997 codegen_addxcastrefs(mcodeptr);
3000 M_BEQ(8 + (s1 == REG_ITMP1));
3001 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3002 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3003 codegen_threadcritstart((u1*) mcodeptr - mcodebase);
3005 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3006 a = dseg_addaddress ((void*) super->vftbl);
3007 M_ALD(REG_ITMP2, REG_PV, a);
3008 if (d != REG_ITMP1) {
3009 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
3010 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3011 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3012 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
3014 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
3017 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3018 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3019 M_ALD(REG_ITMP2, REG_PV, a);
3020 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3021 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3022 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
3025 M_CMPU(REG_ITMP3, REG_ITMP2);
3027 codegen_addxcastrefs(mcodeptr);
3031 panic ("internal error: no inlined array checkcast");
3034 store_reg_to_var_int(iptr->dst, d);
3037 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3039 var_to_reg_int(s1, src, REG_ITMP1);
3042 codegen_addxcheckarefs(mcodeptr);
3045 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3047 M_CMPI(REG_RESULT, 0);
3049 codegen_addxexceptionrefs(mcodeptr);
3052 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3053 /* op1 = dimension, val.a = array descriptor */
3055 /* check for negative sizes and copy sizes to stack if necessary */
3057 MCODECHECK((iptr->op1 << 1) + 64);
3059 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3060 var_to_reg_int(s2, src, REG_ITMP1);
3063 codegen_addxcheckarefs(mcodeptr);
3065 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3067 if (src->varkind != ARGVAR) {
3068 M_IST(s2, REG_SP, 4 * (s1 + INT_ARG_CNT + 6));
3072 /* a0 = dimension count */
3074 ICONST(r->argintregs[0], iptr->op1);
3076 /* a1 = arraydescriptor */
3078 a = dseg_addaddress(iptr->val.a);
3079 M_ALD(r->argintregs[1], REG_PV, a);
3081 /* a2 = pointer to dimensions = stack pointer */
3083 M_LDA(r->argintregs[2], REG_SP, (INT_ARG_CNT + 6)*4);
3085 a = dseg_addaddress((void*) (builtin_nmultianewarray));
3086 M_ALD(REG_PV, REG_PV, a);
3089 s1 = (int)((u1*) mcodeptr - mcodebase);
3092 M_LDA (REG_PV, REG_ITMP1, -s1);
3094 s4 ml = -s1, mh = 0;
3095 while (ml < -32768) {ml += 65536; mh--;}
3096 M_LDA(REG_PV, REG_ITMP1, ml);
3097 M_LDAH(REG_PV, REG_PV, mh);
3099 s1 = reg_of_var(m, iptr->dst, REG_RESULT);
3100 M_INTMOVE(REG_RESULT, s1);
3101 store_reg_to_var_int(iptr->dst, s1);
3105 default: error ("Unknown pseudo command: %d", iptr->opc);
3109 } /* for instruction */
3111 /* copy values to interface registers */
3113 src = bptr->outstack;
3114 len = bptr->outdepth;
3118 if ((src->varkind != STACKVAR)) {
3120 if (IS_FLT_DBL_TYPE(s2)) {
3121 var_to_reg_flt(s1, src, REG_FTMP1);
3122 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
3123 M_FLTMOVE(s1,r->interfaces[len][s2].regoff);
3125 M_DST(s1, REG_SP, 4 * r->interfaces[len][s2].regoff);
3128 var_to_reg_int(s1, src, REG_ITMP1);
3129 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
3130 M_TINTMOVE(s2,s1,r->interfaces[len][s2].regoff);
3132 M_IST(s1, REG_SP, 4 * r->interfaces[len][s2].regoff);
3133 if (IS_2_WORD_TYPE(s2))
3134 M_IST(r->secondregs[s1], REG_SP, 4 * r->interfaces[len][s2].regoff + 4);
3140 } /* if (bptr -> flags >= BBREACHED) */
3141 } /* for basic block */
3143 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3146 /* generate bound check stubs */
3148 s4 *xcodeptr = NULL;
3150 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3151 gen_resolvebranch((u1 *) mcodebase + xboundrefs->branchpos,
3152 xboundrefs->branchpos,
3153 (u1 *) mcodeptr - mcodebase);
3157 M_MOV(xboundrefs->reg, REG_ITMP1);
3158 M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos - 4);
3160 if (xcodeptr != NULL) {
3161 M_BR(xcodeptr - mcodeptr - 1);
3164 xcodeptr = mcodeptr;
3166 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3167 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3169 a = dseg_addaddress(string_java_lang_ArrayIndexOutOfBoundsException);
3170 M_ALD(r->argintregs[0], REG_PV, a);
3171 M_MOV(REG_ITMP1, r->argintregs[1]);
3173 a = dseg_addaddress(new_exception_int);
3174 M_ALD(REG_ITMP2, REG_PV, a);
3177 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3179 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3180 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3182 a = dseg_addaddress(asm_handle_exception);
3183 M_ALD(REG_ITMP3, REG_PV, a);
3190 /* generate negative array size check stubs */
3194 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3195 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3196 gen_resolvebranch((u1 *) mcodebase + xcheckarefs->branchpos,
3197 xcheckarefs->branchpos,
3198 (u1 *) xcodeptr - (u1 *) mcodebase - 4);
3202 gen_resolvebranch((u1 *) mcodebase + xcheckarefs->branchpos,
3203 xcheckarefs->branchpos,
3204 (u1 *) mcodeptr - mcodebase);
3208 M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos - 4);
3210 if (xcodeptr != NULL) {
3211 M_BR(xcodeptr - mcodeptr - 1);
3214 xcodeptr = mcodeptr;
3216 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3217 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3219 a = dseg_addaddress(string_java_lang_NegativeArraySizeException);
3220 M_ALD(r->argintregs[0], REG_PV, a);
3222 a = dseg_addaddress(new_exception);
3223 M_ALD(REG_ITMP2, REG_PV, a);
3226 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3228 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3229 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3231 a = dseg_addaddress(asm_handle_exception);
3232 M_ALD(REG_ITMP3, REG_PV, a);
3239 /* generate cast check stubs */
3243 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3244 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3245 gen_resolvebranch((u1 *) mcodebase + xcastrefs->branchpos,
3246 xcastrefs->branchpos,
3247 (u1 *) xcodeptr - (u1 *) mcodebase - 4);
3251 gen_resolvebranch((u1 *) mcodebase + xcastrefs->branchpos,
3252 xcastrefs->branchpos,
3253 (u1 *) mcodeptr - mcodebase);
3257 M_LDA(REG_ITMP2_XPC, REG_PV, xcastrefs->branchpos - 4);
3259 if (xcodeptr != NULL) {
3260 M_BR(xcodeptr - mcodeptr - 1);
3263 xcodeptr = mcodeptr;
3265 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3266 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3268 a = dseg_addaddress(string_java_lang_ClassCastException);
3269 M_ALD(r->argintregs[0], REG_PV, a);
3271 a = dseg_addaddress(new_exception);
3272 M_ALD(REG_ITMP2, REG_PV, a);
3275 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3277 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3278 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3280 a = dseg_addaddress(asm_handle_exception);
3281 M_ALD(REG_ITMP3, REG_PV, a);
3288 /* generate exception check stubs */
3292 for (; xexceptionrefs != NULL; xexceptionrefs = xexceptionrefs->next) {
3293 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3294 gen_resolvebranch((u1 *) mcodebase + xexceptionrefs->branchpos,
3295 xexceptionrefs->branchpos,
3296 (u1 *) xcodeptr - (u1 *) mcodebase - 4);
3300 gen_resolvebranch((u1 *) mcodebase + xexceptionrefs->branchpos,
3301 xexceptionrefs->branchpos,
3302 (u1 *) mcodeptr - mcodebase);
3306 M_LDA(REG_ITMP2_XPC, REG_PV, xexceptionrefs->branchpos - 4);
3308 if (xcodeptr != NULL) {
3309 M_BR(xcodeptr - mcodeptr - 1);
3312 xcodeptr = mcodeptr;
3314 /* XXX this cannot work - there is no link area */
3315 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3316 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3318 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3319 a = dseg_addaddress(builtin_get_exceptionptrptr);
3320 M_ALD(REG_ITMP2, REG_PV, a);
3323 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3325 a = dseg_addaddress(&_exceptionptr);
3326 M_ALD(REG_ITMP2, REG_PV, a);
3328 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);
3330 M_AST(REG_ITMP3, REG_ITMP2, 0);
3333 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3334 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3336 a = dseg_addaddress(asm_handle_exception);
3337 M_ALD(REG_ITMP3, REG_PV, a);
3343 /* generate null pointer check stubs */
3347 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3348 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3349 gen_resolvebranch((u1 *) mcodebase + xnullrefs->branchpos,
3350 xnullrefs->branchpos,
3351 (u1 *) xcodeptr - (u1 *) mcodebase - 4);
3355 gen_resolvebranch((u1 *) mcodebase + xnullrefs->branchpos,
3356 xnullrefs->branchpos,
3357 (u1 *) mcodeptr - mcodebase);
3361 M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
3363 if (xcodeptr != NULL) {
3364 M_BR(xcodeptr - mcodeptr - 1);
3367 xcodeptr = mcodeptr;
3369 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3370 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3372 a = dseg_addaddress(string_java_lang_NullPointerException);
3373 M_ALD(r->argintregs[0], REG_PV, a);
3375 a = dseg_addaddress(new_exception);
3376 M_ALD(REG_ITMP2, REG_PV, a);
3379 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3381 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3382 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3384 a = dseg_addaddress(asm_handle_exception);
3385 M_ALD(REG_ITMP3, REG_PV, a);
3392 codegen_finish(m, (s4)((u1*) mcodeptr - mcodebase));
3394 asm_cacheflush((void*) m->entrypoint, ((u1*) mcodeptr - mcodebase));
3398 /* function createcompilerstub *************************************************
3400 creates a stub routine which calls the compiler
3402 *******************************************************************************/
3404 #define COMPSTUBSIZE 6
3406 u1 *createcompilerstub (methodinfo *m)
3408 s4 *s = CNEW (s4, COMPSTUBSIZE); /* memory to hold the stub */
3409 s4 *mcodeptr = s; /* code generation pointer */
3411 M_LDA(2, REG_PV, 4*4);
3412 M_ALD(REG_PV, REG_PV, 5*4);
3416 s[4] = (s4) m; /* literals to be adressed */
3417 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3419 asm_cacheflush((void*) s, (u1*) mcodeptr - (u1*) s);
3422 count_cstub_len += COMPSTUBSIZE * 4;
3429 /* function removecompilerstub *************************************************
3431 deletes a compilerstub from memory (simply by freeing it)
3433 *******************************************************************************/
3435 void removecompilerstub(u1 *stub)
3437 CFREE (stub, COMPSTUBSIZE * 4);
3441 /* function: createnativestub **************************************************
3443 creates a stub routine which calls a native method
3445 *******************************************************************************/
3447 #define NATIVESTUBSIZE 200
3448 #define NATIVESTUBOFFSET 9
3450 u1 *createnativestub(functionptr f, methodinfo *m)
3452 s4 *s; /* memory to hold the stub */
3454 s4 *mcodeptr; /* code generation pointer */
3455 s4 stackframesize = 0; /* size of stackframe if needed */
3459 /* init registers before using it */
3462 /* keep code size smaller */
3463 r = m->registerdata;
3465 descriptor2types(m); /* set paramcount and paramtypes */
3467 s = CNEW(s4, NATIVESTUBSIZE);
3468 cs = s + NATIVESTUBOFFSET;
3471 *(cs-1) = (u4) f; /* address of native method */
3472 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3473 *(cs-2) = (u4) builtin_get_exceptionptrptr;
3475 *(cs-2) = (u4) (&_exceptionptr); /* address of exceptionptr */
3477 *(cs-3) = (u4) asm_handle_nat_exception; /* addr of asm exception handler */
3478 *(cs-4) = (u4) (&env); /* addr of jni_environement */
3479 *(cs-5) = (u4) builtin_trace_args;
3481 *(cs-7) = (u4) builtin_displaymethodstop;
3482 *(cs-8) = (u4) m->class;
3483 *(cs-9) = (u4) asm_check_clinit;
3486 M_AST(REG_ITMP1, REG_SP, 8); /* store return address */
3487 M_LDA(REG_SP, REG_SP, -64); /* build up stackframe */
3489 /* if function is static, check for initialized */
3491 if (m->flags & ACC_STATIC) {
3492 /* if class isn't yet initialized, do it */
3493 if (!m->class->initialized) {
3494 /* call helper function which patches this code */
3495 M_ALD(REG_ITMP1, REG_PV, -8 * 4); /* class */
3496 M_ALD(REG_PV, REG_PV, -9 * 4); /* asm_check_clinit */
3499 disp = -(s4) (mcodeptr - cs) * 4;
3501 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3511 /* M_MFLR(REG_ITMP3); */
3512 /* XXX must be a multiple of 16 */
3513 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
3515 /* M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3519 /* save all arguments into the reserved stack space */
3520 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3521 t = m->paramtypes[p];
3523 if (IS_INT_LNG_TYPE(t)) {
3524 /* overlapping u8's are on the stack */
3525 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
3526 s1 = r->argintregs[p + longargs + dblargs];
3528 if (!IS_2_WORD_TYPE(t)) {
3529 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3530 M_IST(s1, REG_SP, 24 + p * 8 + 4);
3533 M_IST(s1, REG_SP, 24 + p * 8);
3534 M_IST(r->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3539 a = dseg_adds4(0xdeadbeef);
3540 M_ILD(REG_ITMP1, REG_PV, a);
3541 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3542 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
3546 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3547 s1 = r->argfltregs[fltargs + dblargs];
3549 if (!IS_2_WORD_TYPE(t)) {
3550 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3551 M_FST(s1, REG_SP, 24 + p * 8 + 4);
3555 M_DST(s1, REG_SP, 24 + p * 8);
3560 /* this should not happen */
3565 /* TODO: save remaining integer and flaot argument registers */
3567 /* load first 4 arguments into integer argument registers */
3568 for (p = 0; p < 8; p++) {
3569 d = r->argintregs[p];
3570 M_ILD(d, REG_SP, 24 + p * 4);
3573 M_ALD(REG_ITMP1, REG_PV, -6 * 4);
3574 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
3575 M_ALD(REG_ITMP2, REG_PV, -5 * 4);
3583 /* restore arguments into the reserved stack space */
3584 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3585 t = m->paramtypes[p];
3587 if (IS_INT_LNG_TYPE(t)) {
3588 if ((p + longargs + dblargs) < INT_ARG_CNT) {
3589 s1 = r->argintregs[p + longargs + dblargs];
3591 if (!IS_2_WORD_TYPE(t)) {
3592 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
3595 M_ILD(s1, REG_SP, 24 + p * 8);
3596 M_ILD(r->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3602 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3603 s1 = r->argfltregs[fltargs + dblargs];
3605 if (!IS_2_WORD_TYPE(t)) {
3606 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
3610 M_DLD(s1, REG_SP, 24 + p * 8);
3617 /* M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3619 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
3620 /* M_MTLR(REG_ITMP3); */
3623 /* save argument registers on stack -- if we have to */
3624 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) ||
3625 m->paramcount > (INT_ARG_CNT - 1)) {
3627 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3628 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3630 stackframesize = stackparamcnt + paramshiftcnt;
3632 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
3634 panic("nativestub");
3637 if (m->flags & ACC_STATIC) {
3638 M_MOV(r->argintregs[5], r->argintregs[7]);
3639 M_MOV(r->argintregs[4], r->argintregs[6]);
3640 M_MOV(r->argintregs[3], r->argintregs[5]);
3641 M_MOV(r->argintregs[2], r->argintregs[4]);
3642 M_MOV(r->argintregs[1], r->argintregs[3]);
3643 M_MOV(r->argintregs[0], r->argintregs[2]);
3645 /* put class into second argument register */
3646 M_ALD(r->argintregs[1], REG_PV, -8 * 4);
3649 M_MOV(r->argintregs[6], r->argintregs[7]);
3650 M_MOV(r->argintregs[5], r->argintregs[6]);
3651 M_MOV(r->argintregs[4], r->argintregs[5]);
3652 M_MOV(r->argintregs[3], r->argintregs[4]);
3653 M_MOV(r->argintregs[2], r->argintregs[3]);
3654 M_MOV(r->argintregs[1], r->argintregs[2]);
3655 M_MOV(r->argintregs[0], r->argintregs[1]);
3658 /* put env into first argument register */
3659 M_ALD(r->argintregs[0], REG_PV, -4 * 4);
3661 M_ALD(REG_PV, REG_PV, -1 * 4); /* load adress of native method */
3664 disp = -(s4) (mcodeptr - cs) * 4;
3666 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3668 /* remove stackframe if there is one */
3669 if (stackframesize) {
3670 M_LDA(REG_SP, REG_SP, stackframesize * 8);
3673 /* 20 instructions */
3676 M_LDA(REG_SP, REG_SP, -10 * 8);
3677 M_DST(REG_FRESULT, REG_SP, 48+0);
3678 M_IST(REG_RESULT, REG_SP, 48+8);
3679 M_AST(REG_ITMP3, REG_SP, 48+12);
3680 M_IST(REG_RESULT2, REG_SP, 48+16);
3682 /* keep this order */
3683 switch (m->returntype) {
3686 M_MOV(REG_RESULT, r->argintregs[2]);
3687 M_CLR(r->argintregs[1]);
3691 M_MOV(REG_RESULT2, r->argintregs[2]);
3692 M_MOV(REG_RESULT, r->argintregs[1]);
3695 M_ALD(r->argintregs[0], REG_PV, -6 * 4);
3697 M_FLTMOVE(REG_FRESULT, r->argfltregs[0]);
3698 M_FLTMOVE(REG_FRESULT, r->argfltregs[1]);
3699 M_ALD(REG_ITMP2, REG_PV, -7 * 4);/* builtin_displaymethodstop */
3702 M_DLD(REG_FRESULT, REG_SP, 48+0);
3703 M_ILD(REG_RESULT, REG_SP, 48+8);
3704 M_ALD(REG_ITMP3, REG_SP, 48+12);
3705 M_ILD(REG_RESULT2, REG_SP, 48+16);
3706 M_LDA(REG_SP, REG_SP, 10 * 8);
3710 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3711 if (IS_FLT_DBL_TYPE(m->returntype))
3712 if (IS_2_WORD_TYPE(m->returntype))
3713 M_DST(REG_FRESULT, REG_SP, 56);
3715 M_FST(REG_FRESULT, REG_SP, 56);
3717 M_IST(REG_RESULT, REG_SP, 56);
3718 if (IS_2_WORD_TYPE(m->returntype))
3719 M_IST(REG_RESULT2, REG_SP, 60);
3722 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* builtin_get_exceptionptrptr */
3725 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3727 M_LDA(REG_PV, REG_ITMP1, disp);
3728 M_MOV(REG_RESULT, REG_ITMP2);
3730 if (IS_FLT_DBL_TYPE(m->returntype))
3731 if (IS_2_WORD_TYPE(m->returntype))
3732 M_DLD(REG_FRESULT, REG_SP, 56);
3734 M_FLD(REG_FRESULT, REG_SP, 56);
3736 M_ILD(REG_RESULT, REG_SP, 56);
3737 if (IS_2_WORD_TYPE(m->returntype))
3738 M_ILD(REG_RESULT2, REG_SP, 60);
3741 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* get address of exceptionptr */
3743 M_ALD(REG_ITMP1, REG_ITMP2, 0); /* load exception into reg. itmp1 */
3745 M_BNE(4); /* if no exception then return */
3747 M_ALD(REG_ITMP1, REG_SP, 64 + 8); /* load return address */
3749 M_LDA(REG_SP, REG_SP, 64); /* remove stackframe */
3754 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
3756 M_ALD(REG_ITMP3, REG_SP, 64 + 8); /* load return address */
3758 M_LDA(REG_SP, REG_SP, 64); /* remove stackframe */
3760 M_LDA(REG_ITMP2, REG_ITMP1, -4); /* move fault address into reg. itmp2 */
3762 M_ALD(REG_ITMP3, REG_PV, -3 * 4); /* load asm exception handler address */
3767 dolog_plain("stubsize: %d (for %d params)\n", (int) (mcodeptr - (s4 *) s), m->paramcount);
3770 asm_cacheflush((void *) s, (u1*) mcodeptr - (u1*) s);
3773 count_nstub_len += NATIVESTUBSIZE * 4;
3776 return (u1*) (s + NATIVESTUBOFFSET);
3779 /* function: removenativestub **************************************************
3781 removes a previously created native-stub from memory
3783 *******************************************************************************/
3785 void removenativestub(u1 *stub)
3787 CFREE ((s4*) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 4);
3792 * These are local overrides for various environment variables in Emacs.
3793 * Please do not remove this and leave it at the end of the file, where
3794 * Emacs will automagically detect them.
3795 * ---------------------------------------------------------------------
3798 * indent-tabs-mode: t