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 1138 2004-06-05 20:39:49Z twisti $
50 /* include independent code generation stuff */
51 #include "codegen.inc"
55 /* register descripton - array ************************************************/
57 /* #define REG_RES 0 reserved register for OS or code generator */
58 /* #define REG_RET 1 return value register */
59 /* #define REG_EXC 2 exception value register (only old jit) */
60 /* #define REG_SAV 3 (callee) saved register */
61 /* #define REG_TMP 4 scratch temporary register (caller saved) */
62 /* #define REG_ARG 5 argument register (caller saved) */
64 /* #define REG_END -1 last entry in tables */
67 REG_RES, REG_RES, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
68 REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV,
69 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
70 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
73 /* for use of reserved registers, see comment above */
75 int nregdescfloat[] = {
76 REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
77 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV,
78 REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
79 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
82 /* for use of reserved registers, see comment above */
85 /* stackframe-infos ***********************************************************/
87 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
89 /* -> see file 'calling.doc' */
92 /* additional functions and macros to generate code ***************************/
94 #define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
98 #define COUNT_SPILLS count_spills++
104 /* gen_nullptr_check(objreg) */
106 #define gen_nullptr_check(objreg) \
110 codegen_addxnullrefs(mcodeptr); \
114 /* MCODECHECK(icnt) */
116 #define MCODECHECK(icnt) \
117 if((mcodeptr+(icnt))>mcodeend)mcodeptr=codegen_increase((u1*)mcodeptr)
120 generates an integer-move from register a to b.
121 if a and b are the same int-register, no code will be generated.
124 #define M_INTMOVE(a,b) if((a)!=(b)){M_MOV(a,b);}
126 #define M_TINTMOVE(t,a,b) \
128 {if (a<=b)M_INTMOVE(secondregs[a],secondregs[b]);\
129 M_INTMOVE(a,b); if (a>b)M_INTMOVE(secondregs[a],secondregs[b]);} \
135 generates a floating-point-move from register a to b.
136 if a and b are the same float-register, no code will be generated
139 #define M_FLTMOVE(a,b) if((a)!=(b)){M_FMOV(a,b);}
143 this function generates code to fetch data from a pseudo-register
144 into a real register.
145 If the pseudo-register has actually been assigned to a real
146 register, no code will be emitted, since following operations
147 can use this register directly.
149 v: pseudoregister to be fetched from
150 tempregnum: temporary register to be used if v is actually spilled to ram
152 return: the register number, where the operand can be found after
153 fetching (this wil be either tempregnum or the register
154 number allready given to v)
157 #define var_to_reg_int0(regnr,v,tempnr,a,b) { \
158 if ((v)->flags & INMEMORY) \
159 {COUNT_SPILLS;if (a) M_ILD(tempnr,REG_SP,4*(v)->regoff); \
161 if ((b) && IS_2_WORD_TYPE((v)->type)) \
162 M_ILD((a)?secondregs[tempnr]:tempnr,REG_SP,4*(v)->regoff+4);} \
163 else regnr=(!(a)&&(b)) ? secondregs[(v)->regoff] : (v)->regoff; \
165 #define var_to_reg_int(regnr,v,tempnr) var_to_reg_int0(regnr,v,tempnr,1,1)
168 #define var_to_reg_flt(regnr,v,tempnr) { \
169 if ((v)->flags & INMEMORY) { \
171 if ((v)->type==TYPE_DBL) \
172 M_DLD(tempnr,REG_SP,4*(v)->regoff); \
174 M_FLD(tempnr,REG_SP,4*(v)->regoff); \
176 } else regnr=(v)->regoff; \
181 This function determines a register, to which the result of an operation
182 should go, when it is ultimatively intended to store the result in
184 If v is assigned to an actual register, this register will be returned.
185 Otherwise (when v is spilled) this function returns tempregnum.
186 If not already done, regoff and flags are set in the stack location.
189 static int reg_of_var(stackptr v, int tempregnum)
193 switch (v->varkind) {
195 if (!(v->flags & INMEMORY))
199 var = &(interfaces[v->varnum][v->type]);
200 v->regoff = var->regoff;
201 if (!(var->flags & INMEMORY))
205 var = &(locals[v->varnum][v->type]);
206 v->regoff = var->regoff;
207 if (!(var->flags & INMEMORY))
211 v->regoff = v->varnum;
212 if (IS_FLT_DBL_TYPE(v->type)) {
213 if (v->varnum < fltreg_argnum) {
214 v->regoff = argfltregs[v->varnum];
215 return(argfltregs[v->varnum]);
219 if (v->varnum < intreg_argnum - (IS_2_WORD_TYPE(v->type)!=0)) {
220 v->regoff = argintregs[v->varnum];
221 return(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(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 //#include <architecture/ppc/cframe.h>
267 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
268 void thread_restartcriticalsection(void *u)
273 int cacao_catch_Handler(mach_port_t thread)
276 unsigned int crashpc;
278 java_objectheader *xptr;
281 thread_state_flavor_t flavor = PPC_THREAD_STATE;
282 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
283 ppc_thread_state_t thread_state;
286 r = thread_get_state(thread, flavor,
287 (natural_t*)&thread_state, &thread_state_count);
288 if (r != KERN_SUCCESS)
289 panic("thread_get_state failed");
291 regs = &thread_state.r0;
292 crashpc = thread_state.srr0;
294 instr = *(s4*) crashpc;
295 reg = (instr >> 16) & 31;
298 xptr = new_exception(string_java_lang_NullPointerException);
300 regs[REG_ITMP2_XPC] = crashpc;
301 regs[REG_ITMP1_XPTR] = (u4) xptr;
303 r = thread_set_state(thread, flavor,
304 (natural_t*)&thread_state, thread_state_count);
305 if (r != KERN_SUCCESS)
306 panic("thread_set_state failed");
315 void init_exceptions(void)
319 void adjust_argvars(stackptr s, int d, int *fa, int *ia)
325 adjust_argvars(s->prev, d-1, fa, ia);
326 if (s->varkind == ARGVAR)
327 s->varnum = (IS_FLT_DBL_TYPE(s->type)) ? *fa : *ia;
328 *fa += (IS_FLT_DBL_TYPE(s->type) != 0);
329 *ia += (IS_2_WORD_TYPE(s->type)) ? 2 : 1;
333 #define intmaxf(a,b) (((a)<(b)) ? (b) : (a))
344 for (bptr = block; bptr != NULL; bptr = bptr->next) {
346 for (iptr = bptr->iinstr, src = bptr->instack;
348 src = iptr->dst, len--, iptr++)
350 if (bptr->flags < BBREACHED)
363 case ICMD_INVOKEVIRTUAL:
364 case ICMD_INVOKESPECIAL:
365 case ICMD_INVOKESTATIC:
366 case ICMD_INVOKEINTERFACE:
371 adjust_argvars(src, s3, &fa, &ia);
374 for (; --s3 >= 0; src = src->prev) {
375 paramsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
377 ifmemuse = intmaxf(ifmemuse, paramsize);
380 case ICMD_MULTIANEWARRAY:
382 paramsize = intreg_argnum + s3;
383 ifmemuse = intmaxf(ifmemuse, paramsize);
390 maxmemuse = ifmemuse;
394 /* function gen_mcode **********************************************************
396 generates machine code
398 *******************************************************************************/
402 int len, s1, s2, s3, d;
416 /* space to save used callee saved registers */
418 savedregs_num += (savintregcnt - maxsavintreguse);
419 savedregs_num += 2*(savfltregcnt - maxsavfltreguse);
421 parentargs_base = maxmemuse + savedregs_num;
423 #ifdef USE_THREADS /* space to save argument of monitor_enter */
425 if (checksync && (method->flags & ACC_SYNCHRONIZED))
430 /* create method header */
432 parentargs_base = (parentargs_base+3) & ~3;
435 (void) dseg_addaddress(method); /* Filler */
437 (void) dseg_addaddress(method); /* MethodPointer */
438 (void) dseg_adds4(parentargs_base * 4); /* FrameSize */
442 /* IsSync contains the offset relative to the stack pointer for the
443 argument of monitor_exit used in the exception handler. Since the
444 offset could be zero and give a wrong meaning of the flag it is
448 if (checksync && (method->flags & ACC_SYNCHRONIZED))
449 (void) dseg_adds4((maxmemuse + 1) * 4); /* IsSync */
454 (void) dseg_adds4(0); /* IsSync */
456 (void) dseg_adds4(isleafmethod); /* IsLeaf */
457 (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
458 (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
459 (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
461 /* create exception table */
463 for (ex = extable; ex != NULL; ex = ex->down) {
466 if (ex->start != NULL)
467 printf("adding start - %d - ", ex->start->debug_nr);
469 printf("PANIC - start is NULL");
474 dseg_addtarget(ex->start);
478 printf("adding end - %d - ", ex->end->debug_nr);
480 printf("PANIC - end is NULL");
485 dseg_addtarget(ex->end);
488 if (ex->handler != NULL)
489 printf("adding handler - %d\n", ex->handler->debug_nr);
491 printf("PANIC - handler is NULL");
496 dseg_addtarget(ex->handler);
498 (void) dseg_addaddress(ex->catchtype);
501 /* initialize mcode variables */
503 mcodeptr = (s4*) mcodebase;
504 mcodeend = (s4*) (mcodebase + mcodesize);
505 MCODECHECK(128 + mparamcount);
507 /* create stack frame (if necessary) */
511 M_AST(REG_ITMP3, REG_SP, 8);
514 {M_LDA (REG_SP, REG_SP, -parentargs_base * 4);}
516 /* save return address and used callee saved registers */
519 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
520 {p--; M_IST (savintregs[r], REG_SP, 4 * p);}
521 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
522 {p-=2; M_DST (savfltregs[r], REG_SP, 4 * p);}
524 /* save monitorenter argument */
527 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
528 if (method->flags & ACC_STATIC) {
529 p = dseg_addaddress (class);
530 M_ALD(REG_ITMP1, REG_PV, p);
531 M_AST(REG_ITMP1, REG_SP, 4 * maxmemuse);
534 M_AST (argintregs[0], REG_SP, 4 * maxmemuse);
539 /* copy argument registers to stack and call trace function with pointer
540 to arguments on stack.
549 /* XXX must be a multiple of 16 */
550 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
552 M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
554 M_CLR(REG_ITMP1); /* clear help register */
556 /* save all arguments into the reserved stack space */
557 for (p = 0; p < mparamcount && p < TRACE_ARGS_NUM; p++) {
560 if (IS_INT_LNG_TYPE(t)) {
561 /* overlapping u8's are on the stack */
562 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
563 s1 = argintregs[p + longargs + dblargs];
565 if (!IS_2_WORD_TYPE(t)) {
566 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
567 M_IST(s1, REG_SP, 24 + p * 8 + 4);
570 M_IST(s1, REG_SP, 24 + p * 8);
571 M_IST(secondregs[s1], REG_SP, 24 + p * 8 + 4);
576 a = dseg_adds4(0xdeadbeef);
577 M_ILD(REG_ITMP1, REG_PV, a);
578 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
579 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
583 if ((fltargs + dblargs) < FLT_ARG_CNT) {
584 s1 = argfltregs[fltargs + dblargs];
586 if (!IS_2_WORD_TYPE(t)) {
587 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
588 M_FST(s1, REG_SP, 24 + p * 8 + 4);
592 M_DST(s1, REG_SP, 24 + p * 8);
597 /* this should not happen */
602 /* TODO: save remaining integer and flaot argument registers */
604 /* load first 4 arguments into integer argument registers */
605 for (p = 0; p < 8; p++) {
607 M_ILD(d, REG_SP, 24 + p * 4);
610 p = dseg_addaddress(method);
611 M_ALD(REG_ITMP1, REG_PV, p);
612 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
613 p = dseg_addaddress((void*) builtin_trace_args);
614 M_ALD(REG_ITMP2, REG_PV, p);
622 /* restore arguments into the reserved stack space */
623 for (p = 0; p < mparamcount && p < TRACE_ARGS_NUM; p++) {
626 if (IS_INT_LNG_TYPE(t)) {
627 if ((p + longargs + dblargs) < INT_ARG_CNT) {
628 s1 = argintregs[p + longargs + dblargs];
630 if (!IS_2_WORD_TYPE(t)) {
631 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
634 M_ILD(s1, REG_SP, 24 + p * 8);
635 M_ILD(secondregs[s1], REG_SP, 24 + p * 8 + 4);
641 if ((fltargs + dblargs) < FLT_ARG_CNT) {
642 s1 = argfltregs[fltargs + dblargs];
644 if (!IS_2_WORD_TYPE(t)) {
645 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
649 M_DLD(s1, REG_SP, 24 + p * 8);
656 M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
658 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
662 /* take arguments out of register or stack frame */
667 for (p = 0, l = 0; p < mparamcount; p++) {
668 arg = narg; iarg = niarg;
670 var = &(locals[l][t]);
672 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
677 if (IS_INT_LNG_TYPE(t)) { /* integer args */
678 if (iarg < INT_ARG_CNT -
679 (IS_2_WORD_TYPE(t)!=0)) { /* register arguments */
680 if (!(var->flags & INMEMORY)) /* reg arg -> register */
681 {M_TINTMOVE (t, argintregs[iarg], r);}
682 else /* reg arg -> spilled */
684 M_IST (argintregs[iarg], REG_SP, 4 * r);
685 if (IS_2_WORD_TYPE(t))
686 M_IST (secondregs[argintregs[iarg]], REG_SP, 4 * r + 4);
689 else { /* stack arguments */
691 if (!(var->flags & INMEMORY)) /* stack arg -> register */
693 M_ILD (r, REG_SP, 4 * (parentargs_base + pa));
694 if (IS_2_WORD_TYPE(t))
695 M_ILD (secondregs[r], REG_SP, 4 * (parentargs_base + pa) + 4);
697 else { /* stack arg -> spilled */
698 M_ILD (REG_ITMP1, REG_SP, 4 * (parentargs_base + pa));
699 M_IST (REG_ITMP1, REG_SP, 4 * r);
700 if (IS_2_WORD_TYPE(t)) {
701 M_ILD (REG_ITMP1, REG_SP, 4 * (parentargs_base + pa) + 4);
702 M_IST (REG_ITMP1, REG_SP, 4 * r + 4);
707 else { /* floating args */
709 if (arg < FLT_ARG_CNT) { /* register arguments */
710 if (!(var->flags & INMEMORY)) /* reg arg -> register */
711 {M_FLTMOVE (argfltregs[arg], r);}
712 else /* reg arg -> spilled */
713 M_DST (argfltregs[arg], REG_SP, 4 * r);
715 else { /* stack arguments */
717 if (!(var->flags & INMEMORY)) /* stack-arg -> register */
718 if (IS_2_WORD_TYPE(t))
719 M_DLD (r, REG_SP, 4 * (parentargs_base + pa) );
721 M_FLD (r, REG_SP, 4 * (parentargs_base + pa) );
722 else { /* stack-arg -> spilled */
723 if (IS_2_WORD_TYPE(t))
724 M_DLD (REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
726 M_FLD (REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
727 M_DST (REG_FTMP1, REG_SP, 4 * r);
734 /* call monitorenter function */
737 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
738 p = dseg_addaddress ((void*) (builtin_monitorenter));
739 M_ALD(REG_ITMP3, REG_PV, p);
741 M_ALD(argintregs[0], REG_SP, 4 * maxmemuse);
747 /* end of header generation */
749 /* walk through all basic blocks */
750 for (/* bbs = block_count, */ bptr = block; /* --bbs >= 0 */ bptr != NULL; bptr = bptr->next) {
752 bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
754 if (bptr->flags >= BBREACHED) {
756 /* branch resolving */
760 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
761 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
762 brefs->branchpos, bptr->mpc);
766 /* copy interface registers to their destination */
771 while (src != NULL) {
773 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
774 d = reg_of_var(src, REG_ITMP1);
775 M_INTMOVE(REG_ITMP1, d);
776 store_reg_to_var_int(src, d);
779 d = reg_of_var(src, REG_IFTMP);
780 if ((src->varkind != STACKVAR)) {
782 if (IS_FLT_DBL_TYPE(s2)) {
783 if (!(interfaces[len][s2].flags & INMEMORY)) {
784 s1 = interfaces[len][s2].regoff;
788 if (IS_2_WORD_TYPE(s2))
789 M_DLD(d, REG_SP, 4 * interfaces[len][s2].regoff);
791 M_FLD(d, REG_SP, 4 * interfaces[len][s2].regoff);
793 store_reg_to_var_flt(src, d);
796 if (!(interfaces[len][s2].flags & INMEMORY)) {
797 s1 = interfaces[len][s2].regoff;
801 M_ILD(d, REG_SP, 4 * interfaces[len][s2].regoff);
802 if (IS_2_WORD_TYPE(s2))
803 M_ILD(secondregs[d], REG_SP, 4 * interfaces[len][s2].regoff + 4);
805 store_reg_to_var_int(src, d);
812 /* walk through all instructions */
816 for (iptr = bptr->iinstr;
818 src = iptr->dst, len--, iptr++) {
820 MCODECHECK(64); /* an instruction usually needs < 64 words */
823 case ICMD_NOP: /* ... ==> ... */
826 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
828 var_to_reg_int(s1, src, REG_ITMP1);
831 codegen_addxnullrefs(mcodeptr);
834 /* constant operations ************************************************/
836 #define ICONST(r,c) if(((c)>=0&&(c)<=32767)||((c)>=-32768&&(c)<0)){M_LDA(r,REG_ZERO,c);} \
837 else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
839 #define LCONST(r,c) ICONST(r,(s4)((s8)(c)>>32)); ICONST(secondregs[r],(s4)((s8)(c)));
841 case ICMD_ICONST: /* ... ==> ..., constant */
842 /* op1 = 0, val.i = constant */
844 d = reg_of_var(iptr->dst, REG_ITMP1);
845 ICONST(d, iptr->val.i);
846 store_reg_to_var_int(iptr->dst, d);
849 case ICMD_LCONST: /* ... ==> ..., constant */
850 /* op1 = 0, val.l = constant */
852 d = reg_of_var(iptr->dst, REG_ITMP1);
853 LCONST(d, iptr->val.l);
854 store_reg_to_var_int(iptr->dst, d);
857 case ICMD_FCONST: /* ... ==> ..., constant */
858 /* op1 = 0, val.f = constant */
860 d = reg_of_var (iptr->dst, REG_FTMP1);
861 a = dseg_addfloat (iptr->val.f);
863 store_reg_to_var_flt (iptr->dst, d);
866 case ICMD_DCONST: /* ... ==> ..., constant */
867 /* op1 = 0, val.d = constant */
869 d = reg_of_var (iptr->dst, REG_FTMP1);
870 a = dseg_adddouble (iptr->val.d);
872 store_reg_to_var_flt (iptr->dst, d);
875 case ICMD_ACONST: /* ... ==> ..., constant */
876 /* op1 = 0, val.a = constant */
878 d = reg_of_var(iptr->dst, REG_ITMP1);
879 ICONST(d, (u4) iptr->val.a);
880 store_reg_to_var_int(iptr->dst, d);
884 /* load/store operations **********************************************/
886 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
887 case ICMD_LLOAD: /* op1 = local variable */
890 d = reg_of_var(iptr->dst, REG_ITMP1);
891 if ((iptr->dst->varkind == LOCALVAR) &&
892 (iptr->dst->varnum == iptr->op1))
894 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
895 if (var->flags & INMEMORY) {
896 M_ILD(d, REG_SP, 4 * var->regoff);
897 if (IS_2_WORD_TYPE(var->type))
898 M_ILD(secondregs[d], REG_SP, 4 * var->regoff + 4);
900 {M_TINTMOVE(var->type,var->regoff,d);}
901 store_reg_to_var_int(iptr->dst, d);
904 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
905 case ICMD_DLOAD: /* op1 = local variable */
907 d = reg_of_var(iptr->dst, REG_FTMP1);
908 if ((iptr->dst->varkind == LOCALVAR) &&
909 (iptr->dst->varnum == iptr->op1))
911 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
912 if (var->flags & INMEMORY)
913 if (IS_2_WORD_TYPE(var->type))
914 M_DLD(d, REG_SP, 4 * var->regoff);
916 M_FLD(d, REG_SP, 4 * var->regoff);
918 {M_FLTMOVE(var->regoff,d);}
919 store_reg_to_var_flt(iptr->dst, d);
923 case ICMD_ISTORE: /* ..., value ==> ... */
924 case ICMD_LSTORE: /* op1 = local variable */
927 if ((src->varkind == LOCALVAR) &&
928 (src->varnum == iptr->op1))
930 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
931 if (var->flags & INMEMORY) {
932 var_to_reg_int(s1, src, REG_ITMP1);
933 M_IST(s1, REG_SP, 4 * var->regoff);
934 if (IS_2_WORD_TYPE(var->type))
935 M_IST(secondregs[s1], REG_SP, 4 * var->regoff + 4);
938 var_to_reg_int(s1, src, var->regoff);
939 M_TINTMOVE(var->type, s1, var->regoff);
943 case ICMD_FSTORE: /* ..., value ==> ... */
944 case ICMD_DSTORE: /* op1 = local variable */
946 if ((src->varkind == LOCALVAR) &&
947 (src->varnum == iptr->op1))
949 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
950 if (var->flags & INMEMORY) {
951 var_to_reg_flt(s1, src, REG_FTMP1);
952 if (var->type==TYPE_DBL)
953 M_DST(s1, REG_SP, 4 * var->regoff);
955 M_FST(s1, REG_SP, 4 * var->regoff);
958 var_to_reg_flt(s1, src, var->regoff);
959 M_FLTMOVE(s1, var->regoff);
964 /* pop/dup/swap operations ********************************************/
966 /* attention: double and longs are only one entry in CACAO ICMDs */
968 case ICMD_POP: /* ..., value ==> ... */
969 case ICMD_POP2: /* ..., value, value ==> ... */
972 #define M_COPY(from,to) \
973 d = reg_of_var(to, REG_IFTMP); \
974 if ((from->regoff != to->regoff) || \
975 ((from->flags ^ to->flags) & INMEMORY)) { \
976 if (IS_FLT_DBL_TYPE(from->type)) { \
977 var_to_reg_flt(s1, from, d); \
979 store_reg_to_var_flt(to, d); \
982 var_to_reg_int(s1, from, d); \
983 M_TINTMOVE(from->type,s1,d); \
984 store_reg_to_var_int(to, d); \
988 case ICMD_DUP: /* ..., a ==> ..., a, a */
989 M_COPY(src, iptr->dst);
992 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
994 M_COPY(src, iptr->dst->prev->prev);
996 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
998 M_COPY(src, iptr->dst);
999 M_COPY(src->prev, iptr->dst->prev);
1002 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
1004 M_COPY(src->prev, iptr->dst->prev->prev->prev);
1006 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
1008 M_COPY(src, iptr->dst);
1009 M_COPY(src->prev, iptr->dst->prev);
1010 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1011 M_COPY(src, iptr->dst->prev->prev->prev);
1014 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
1016 M_COPY(src, iptr->dst);
1017 M_COPY(src->prev, iptr->dst->prev);
1018 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1019 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
1020 M_COPY(src, iptr->dst->prev->prev->prev->prev);
1021 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
1024 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1026 M_COPY(src, iptr->dst->prev);
1027 M_COPY(src->prev, iptr->dst);
1031 /* integer operations *************************************************/
1033 case ICMD_INEG: /* ..., value ==> ..., - value */
1035 var_to_reg_int(s1, src, REG_ITMP1);
1036 d = reg_of_var(iptr->dst, REG_ITMP3);
1038 store_reg_to_var_int(iptr->dst, d);
1041 case ICMD_LNEG: /* ..., value ==> ..., - value */
1043 var_to_reg_int(s1, src, REG_ITMP1);
1044 d = reg_of_var(iptr->dst, REG_ITMP3);
1045 M_SUBFIC(secondregs[s1], 0, secondregs[d]);
1047 store_reg_to_var_int(iptr->dst, d);
1050 case ICMD_I2L: /* ..., value ==> ..., value */
1052 var_to_reg_int(s1, src, REG_ITMP2);
1053 d = reg_of_var(iptr->dst, REG_ITMP3);
1054 M_INTMOVE(s1, secondregs[d]);
1055 M_SRA_IMM(secondregs[d], 31, d);
1056 store_reg_to_var_int(iptr->dst, d);
1059 case ICMD_L2I: /* ..., value ==> ..., value */
1061 var_to_reg_int0(s1, src, REG_ITMP2, 0, 1);
1062 d = reg_of_var(iptr->dst, REG_ITMP2);
1064 store_reg_to_var_int(iptr->dst, d);
1067 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1069 var_to_reg_int(s1, src, REG_ITMP1);
1070 d = reg_of_var(iptr->dst, REG_ITMP3);
1072 store_reg_to_var_int(iptr->dst, d);
1075 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1077 var_to_reg_int(s1, src, REG_ITMP1);
1078 d = reg_of_var(iptr->dst, REG_ITMP3);
1080 store_reg_to_var_int(iptr->dst, d);
1083 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1085 var_to_reg_int(s1, src, REG_ITMP1);
1086 d = reg_of_var(iptr->dst, REG_ITMP3);
1088 store_reg_to_var_int(iptr->dst, d);
1092 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1094 var_to_reg_int(s1, src->prev, REG_ITMP1);
1095 var_to_reg_int(s2, src, REG_ITMP2);
1096 d = reg_of_var(iptr->dst, REG_ITMP3);
1098 store_reg_to_var_int(iptr->dst, d);
1101 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1102 /* val.i = constant */
1104 var_to_reg_int(s1, src, REG_ITMP1);
1105 d = reg_of_var(iptr->dst, REG_ITMP3);
1106 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1107 M_IADD_IMM(s1, iptr->val.i, d);
1110 ICONST(REG_ITMP2, iptr->val.i);
1111 M_IADD(s1, REG_ITMP2, d);
1113 store_reg_to_var_int(iptr->dst, d);
1116 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1118 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1119 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1120 d = reg_of_var(iptr->dst, REG_ITMP3);
1121 M_ADDC(s1, s2, secondregs[d]);
1122 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1123 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1125 store_reg_to_var_int(iptr->dst, d);
1128 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1129 /* val.l = constant */
1131 s3 = iptr->val.l & 0xffffffff;
1132 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1133 d = reg_of_var(iptr->dst, REG_ITMP3);
1134 if ((s3 >= -32768) && (s3 <= 32767)) {
1135 M_ADDIC(s1, s3, secondregs[d]);
1138 ICONST(REG_ITMP2, s3);
1139 M_ADDC(s1, REG_ITMP2, secondregs[d]);
1141 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1142 s3 = iptr->val.l >> 32;
1148 ICONST(REG_ITMP3, s3);
1149 M_ADDE(s1, REG_ITMP3, d);
1151 store_reg_to_var_int(iptr->dst, d);
1154 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1156 var_to_reg_int(s1, src->prev, REG_ITMP1);
1157 var_to_reg_int(s2, src, REG_ITMP2);
1158 d = reg_of_var(iptr->dst, REG_ITMP3);
1160 store_reg_to_var_int(iptr->dst, d);
1163 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1164 /* val.i = constant */
1166 var_to_reg_int(s1, src, REG_ITMP1);
1167 d = reg_of_var(iptr->dst, REG_ITMP3);
1168 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
1169 M_IADD_IMM(s1, -iptr->val.i, d);
1172 ICONST(REG_ITMP2, -iptr->val.i);
1173 M_IADD(s1, REG_ITMP2, d);
1175 store_reg_to_var_int(iptr->dst, d);
1178 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1180 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1181 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1182 d = reg_of_var(iptr->dst, REG_ITMP3);
1183 M_SUBC(s1, s2, secondregs[d]);
1184 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1185 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1187 store_reg_to_var_int(iptr->dst, d);
1190 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1191 /* val.l = constant */
1193 s3 = (-iptr->val.l) & 0xffffffff;
1194 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1195 d = reg_of_var(iptr->dst, REG_ITMP3);
1196 if ((s3 >= -32768) && (s3 <= 32767)) {
1197 M_ADDIC(s1, s3, secondregs[d]);
1200 ICONST(REG_ITMP2, s3);
1201 M_ADDC(s1, REG_ITMP2, secondregs[d]);
1203 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1204 s3 = (-iptr->val.l) >> 32;
1210 ICONST(REG_ITMP3, s3);
1211 M_ADDE(s1, REG_ITMP3, d);
1213 store_reg_to_var_int(iptr->dst, d);
1216 case ICMD_IDIV: /* ..., 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(iptr->dst, REG_ITMP3);
1221 store_reg_to_var_int(iptr->dst, d);
1224 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1225 var_to_reg_int(s1, src->prev, REG_ITMP1);
1226 var_to_reg_int(s2, src, REG_ITMP2);
1227 d = reg_of_var(iptr->dst, REG_ITMP3);
1231 store_reg_to_var_int(iptr->dst, d);
1234 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1236 var_to_reg_int(s1, src->prev, REG_ITMP1);
1237 var_to_reg_int(s2, src, REG_ITMP2);
1238 d = reg_of_var(iptr->dst, REG_ITMP3);
1240 store_reg_to_var_int(iptr->dst, d);
1243 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1244 /* val.i = constant */
1246 var_to_reg_int(s1, src, REG_ITMP1);
1247 d = reg_of_var(iptr->dst, REG_ITMP3);
1248 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1249 M_IMUL_IMM(s1, iptr->val.i, d);
1252 ICONST(REG_ITMP2, iptr->val.i);
1253 M_IMUL(s1, REG_ITMP2, d);
1255 store_reg_to_var_int(iptr->dst, d);
1258 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1260 var_to_reg_int(s1, src, REG_ITMP1);
1261 d = reg_of_var(iptr->dst, REG_ITMP3);
1262 M_SRA_IMM(s1, iptr->val.i, d);
1264 store_reg_to_var_int(iptr->dst, d);
1267 case ICMD_ISHL: /* ..., 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(iptr->dst, REG_ITMP3);
1272 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1273 M_SLL(s1, REG_ITMP3, d);
1274 store_reg_to_var_int(iptr->dst, d);
1277 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1278 /* val.i = constant */
1280 var_to_reg_int(s1, src, REG_ITMP1);
1281 d = reg_of_var(iptr->dst, REG_ITMP3);
1282 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1283 store_reg_to_var_int(iptr->dst, d);
1286 case ICMD_ISHR: /* ..., 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(iptr->dst, REG_ITMP3);
1291 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1292 M_SRA(s1, REG_ITMP3, d);
1293 store_reg_to_var_int(iptr->dst, d);
1296 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1297 /* val.i = constant */
1299 var_to_reg_int(s1, src, REG_ITMP1);
1300 d = reg_of_var(iptr->dst, REG_ITMP3);
1301 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1302 store_reg_to_var_int(iptr->dst, d);
1305 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1307 var_to_reg_int(s1, src->prev, REG_ITMP1);
1308 var_to_reg_int(s2, src, REG_ITMP2);
1309 d = reg_of_var(iptr->dst, REG_ITMP3);
1310 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1311 M_SRL(s1, REG_ITMP2, d);
1312 store_reg_to_var_int(iptr->dst, d);
1315 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1316 /* val.i = constant */
1318 var_to_reg_int(s1, src, REG_ITMP1);
1319 d = reg_of_var(iptr->dst, REG_ITMP3);
1320 if (iptr->val.i & 0x1f)
1321 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1324 store_reg_to_var_int(iptr->dst, d);
1327 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1329 var_to_reg_int(s1, src->prev, REG_ITMP1);
1330 var_to_reg_int(s2, src, REG_ITMP2);
1331 d = reg_of_var(iptr->dst, REG_ITMP3);
1333 store_reg_to_var_int(iptr->dst, d);
1336 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1337 /* val.i = constant */
1339 var_to_reg_int(s1, src, REG_ITMP1);
1340 d = reg_of_var(iptr->dst, REG_ITMP3);
1341 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1342 M_AND_IMM(s1, iptr->val.i, d);
1345 else if (iptr->val.i == 0xffffff) {
1346 M_RLWINM(s1, 0, 8, 31, d);
1350 ICONST(REG_ITMP2, iptr->val.i);
1351 M_AND(s1, REG_ITMP2, d);
1353 store_reg_to_var_int(iptr->dst, d);
1356 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1358 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1359 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1360 d = reg_of_var(iptr->dst, REG_ITMP3);
1361 M_AND(s1, s2, secondregs[d]);
1362 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1363 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1365 store_reg_to_var_int(iptr->dst, d);
1368 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1369 /* val.l = constant */
1371 s3 = iptr->val.l & 0xffffffff;
1372 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1373 d = reg_of_var(iptr->dst, REG_ITMP3);
1374 if ((s3 >= 0) && (s3 <= 65535)) {
1375 M_AND_IMM(s1, s3, secondregs[d]);
1378 ICONST(REG_ITMP2, s3);
1379 M_AND(s1, REG_ITMP2, secondregs[d]);
1381 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1382 s3 = iptr->val.l >> 32;
1383 if ((s3 >= 0) && (s3 <= 65535)) {
1384 M_AND_IMM(s1, s3, d);
1387 ICONST(REG_ITMP3, s3);
1388 M_AND(s1, REG_ITMP3, d);
1390 store_reg_to_var_int(iptr->dst, d);
1393 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1394 /* val.i = constant */
1396 var_to_reg_int(s1, src, REG_ITMP1);
1397 d = reg_of_var(iptr->dst, REG_ITMP3);
1398 M_MOV(s1, REG_ITMP2);
1400 M_BGE(1 + 2*(iptr->val.i >= 32768));
1401 if (iptr->val.i >= 32768) {
1402 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1403 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1404 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1407 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1409 int b=0, m = iptr->val.i;
1412 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1414 M_ISUB(s1, REG_ITMP2, d);
1415 store_reg_to_var_int(iptr->dst, d);
1418 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1420 var_to_reg_int(s1, src->prev, REG_ITMP1);
1421 var_to_reg_int(s2, src, REG_ITMP2);
1422 d = reg_of_var(iptr->dst, REG_ITMP3);
1424 store_reg_to_var_int(iptr->dst, d);
1427 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1428 /* val.i = constant */
1430 var_to_reg_int(s1, src, REG_ITMP1);
1431 d = reg_of_var(iptr->dst, REG_ITMP3);
1432 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1433 M_OR_IMM(s1, iptr->val.i, d);
1436 ICONST(REG_ITMP2, iptr->val.i);
1437 M_OR(s1, REG_ITMP2, d);
1439 store_reg_to_var_int(iptr->dst, d);
1442 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1444 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1445 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1446 d = reg_of_var(iptr->dst, REG_ITMP3);
1447 M_OR(s1, s2, secondregs[d]);
1448 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1449 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1451 store_reg_to_var_int(iptr->dst, d);
1454 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1455 /* val.l = constant */
1457 s3 = iptr->val.l & 0xffffffff;
1458 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1459 d = reg_of_var(iptr->dst, REG_ITMP3);
1460 if ((s3 >= 0) && (s3 <= 65535)) {
1461 M_OR_IMM(s1, s3, secondregs[d]);
1464 ICONST(REG_ITMP2, s3);
1465 M_OR(s1, REG_ITMP2, secondregs[d]);
1467 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1468 s3 = iptr->val.l >> 32;
1469 if ((s3 >= 0) && (s3 <= 65535)) {
1470 M_OR_IMM(s1, s3, d);
1473 ICONST(REG_ITMP3, s3);
1474 M_OR(s1, REG_ITMP3, d);
1476 store_reg_to_var_int(iptr->dst, d);
1479 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1481 var_to_reg_int(s1, src->prev, REG_ITMP1);
1482 var_to_reg_int(s2, src, REG_ITMP2);
1483 d = reg_of_var(iptr->dst, REG_ITMP3);
1485 store_reg_to_var_int(iptr->dst, d);
1488 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1489 /* val.i = constant */
1491 var_to_reg_int(s1, src, REG_ITMP1);
1492 d = reg_of_var(iptr->dst, REG_ITMP3);
1493 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1494 M_XOR_IMM(s1, iptr->val.i, d);
1497 ICONST(REG_ITMP2, iptr->val.i);
1498 M_XOR(s1, REG_ITMP2, d);
1500 store_reg_to_var_int(iptr->dst, d);
1503 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1505 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1506 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1507 d = reg_of_var(iptr->dst, REG_ITMP3);
1508 M_XOR(s1, s2, secondregs[d]);
1509 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1510 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1512 store_reg_to_var_int(iptr->dst, d);
1515 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1516 /* val.l = constant */
1518 s3 = iptr->val.l & 0xffffffff;
1519 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1520 d = reg_of_var(iptr->dst, REG_ITMP3);
1521 if ((s3 >= 0) && (s3 <= 65535)) {
1522 M_XOR_IMM(s1, s3, secondregs[d]);
1525 ICONST(REG_ITMP2, s3);
1526 M_XOR(s1, REG_ITMP2, secondregs[d]);
1528 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1529 s3 = iptr->val.l >> 32;
1530 if ((s3 >= 0) && (s3 <= 65535)) {
1531 M_XOR_IMM(s1, s3, d);
1534 ICONST(REG_ITMP3, s3);
1535 M_XOR(s1, REG_ITMP3, d);
1537 store_reg_to_var_int(iptr->dst, d);
1540 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1542 var_to_reg_int0(s1, src->prev, REG_ITMP3, 1, 0);
1543 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
1544 d = reg_of_var(iptr->dst, REG_ITMP1);
1547 (d==s1 || d==s2 || d==secondregs[s1] || d==secondregs[s2]);
1548 int dreg = tempreg ? REG_ITMP1 : d;
1550 M_IADD_IMM(REG_ZERO, 1, dreg);
1555 var_to_reg_int0(s1, src->prev, REG_ITMP3, 0, 1);
1556 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1560 M_IADD_IMM(dreg, -1, dreg);
1561 M_IADD_IMM(dreg, -1, dreg);
1562 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1563 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1566 store_reg_to_var_int(iptr->dst, d);
1569 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1570 /* op1 = variable, val.i = constant */
1572 var = &(locals[iptr->op1][TYPE_INT]);
1573 if (var->flags & INMEMORY) {
1575 M_ILD(s1, REG_SP, 4 * var->regoff);
1584 M_ADDIS(s1, m>>16, s1);
1586 M_IADD_IMM(s1, m&0xffff, s1);
1588 if (var->flags & INMEMORY)
1589 M_IST(s1, REG_SP, 4 * var->regoff);
1593 /* floating operations ************************************************/
1595 case ICMD_FNEG: /* ..., value ==> ..., - value */
1597 var_to_reg_flt(s1, src, REG_FTMP1);
1598 d = reg_of_var(iptr->dst, REG_FTMP3);
1600 store_reg_to_var_flt(iptr->dst, d);
1603 case ICMD_DNEG: /* ..., value ==> ..., - value */
1605 var_to_reg_flt(s1, src, REG_FTMP1);
1606 d = reg_of_var(iptr->dst, REG_FTMP3);
1608 store_reg_to_var_flt(iptr->dst, d);
1611 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1613 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1614 var_to_reg_flt(s2, src, REG_FTMP2);
1615 d = reg_of_var(iptr->dst, REG_FTMP3);
1617 store_reg_to_var_flt(iptr->dst, d);
1620 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1622 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1623 var_to_reg_flt(s2, src, REG_FTMP2);
1624 d = reg_of_var(iptr->dst, REG_FTMP3);
1626 store_reg_to_var_flt(iptr->dst, d);
1629 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1631 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1632 var_to_reg_flt(s2, src, REG_FTMP2);
1633 d = reg_of_var(iptr->dst, REG_FTMP3);
1635 store_reg_to_var_flt(iptr->dst, d);
1638 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1640 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1641 var_to_reg_flt(s2, src, REG_FTMP2);
1642 d = reg_of_var(iptr->dst, REG_FTMP3);
1644 store_reg_to_var_flt(iptr->dst, d);
1647 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1649 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1650 var_to_reg_flt(s2, src, REG_FTMP2);
1651 d = reg_of_var(iptr->dst, REG_FTMP3);
1653 store_reg_to_var_flt(iptr->dst, d);
1656 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1658 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1659 var_to_reg_flt(s2, src, REG_FTMP2);
1660 d = reg_of_var(iptr->dst, REG_FTMP3);
1662 store_reg_to_var_flt(iptr->dst, d);
1665 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1667 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1668 var_to_reg_flt(s2, src, REG_FTMP2);
1669 d = reg_of_var(iptr->dst, REG_FTMP3);
1671 store_reg_to_var_flt(iptr->dst, d);
1674 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1676 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1677 var_to_reg_flt(s2, src, REG_FTMP2);
1678 d = reg_of_var(iptr->dst, REG_FTMP3);
1680 store_reg_to_var_flt(iptr->dst, d);
1683 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1685 var_to_reg_flt(s1, src, REG_FTMP1);
1686 d = reg_of_var(iptr->dst, REG_ITMP3);
1688 a = dseg_addfloat(0.0);
1689 M_FLD(REG_FTMP2, REG_PV, a);
1690 M_FCMPU(s1, REG_FTMP2);
1693 M_CVTDL_C(s1, REG_FTMP1);
1694 M_LDA (REG_ITMP1, REG_PV, a);
1695 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1696 M_ILD (d, REG_PV, a);
1697 store_reg_to_var_int(iptr->dst, d);
1700 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1702 var_to_reg_flt(s1, src, REG_FTMP1);
1703 d = reg_of_var(iptr->dst, REG_FTMP3);
1705 store_reg_to_var_flt(iptr->dst, d);
1708 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1710 var_to_reg_flt(s1, src, REG_FTMP1);
1711 d = reg_of_var(iptr->dst, REG_FTMP3);
1713 store_reg_to_var_flt(iptr->dst, d);
1716 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1718 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1719 var_to_reg_flt(s2, src, REG_FTMP2);
1720 d = reg_of_var(iptr->dst, REG_ITMP3);
1722 M_IADD_IMM(0, -1, d);
1725 M_IADD_IMM(0, 0, d);
1727 M_IADD_IMM(0, 1, d);
1728 store_reg_to_var_int(iptr->dst, d);
1731 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1733 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1734 var_to_reg_flt(s2, src, REG_FTMP2);
1735 d = reg_of_var(iptr->dst, REG_ITMP3);
1737 M_IADD_IMM(0, 1, d);
1740 M_IADD_IMM(0, 0, d);
1742 M_IADD_IMM(0, -1, d);
1743 store_reg_to_var_int(iptr->dst, d);
1747 /* memory operations **************************************************/
1749 #define gen_bound_check \
1750 if (checkbounds) { \
1751 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1752 M_CMPU(s2, REG_ITMP3);\
1754 codegen_addxboundrefs(mcodeptr, s2); \
1757 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1759 var_to_reg_int(s1, src, REG_ITMP1);
1760 d = reg_of_var(iptr->dst, REG_ITMP3);
1761 gen_nullptr_check(s1);
1762 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1763 store_reg_to_var_int(iptr->dst, d);
1766 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1768 var_to_reg_int(s1, src->prev, REG_ITMP1);
1769 var_to_reg_int(s2, src, REG_ITMP2);
1770 d = reg_of_var(iptr->dst, REG_ITMP3);
1771 if (iptr->op1 == 0) {
1772 gen_nullptr_check(s1);
1775 M_SLL_IMM(s2, 2, REG_ITMP2);
1776 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1777 M_LWZX(d, s1, REG_ITMP2);
1778 store_reg_to_var_int(iptr->dst, d);
1781 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1783 var_to_reg_int(s1, src->prev, REG_ITMP1);
1784 var_to_reg_int(s2, src, REG_ITMP2);
1785 d = reg_of_var(iptr->dst, REG_ITMP3);
1786 if (iptr->op1 == 0) {
1787 gen_nullptr_check(s1);
1790 M_SLL_IMM(s2, 3, REG_ITMP2);
1791 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1792 M_ILD(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
1793 M_ILD(secondregs[d], REG_ITMP2, OFFSET(java_longarray, data[0])+4);
1794 store_reg_to_var_int(iptr->dst, d);
1797 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1799 var_to_reg_int(s1, src->prev, REG_ITMP1);
1800 var_to_reg_int(s2, src, REG_ITMP2);
1801 d = reg_of_var(iptr->dst, REG_ITMP3);
1802 if (iptr->op1 == 0) {
1803 gen_nullptr_check(s1);
1806 M_SLL_IMM(s2, 2, REG_ITMP2);
1807 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1808 M_LWZX(d, s1, REG_ITMP2);
1809 store_reg_to_var_int(iptr->dst, d);
1812 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1814 var_to_reg_int(s1, src->prev, REG_ITMP1);
1815 var_to_reg_int(s2, src, REG_ITMP2);
1816 d = reg_of_var(iptr->dst, REG_FTMP3);
1817 if (iptr->op1 == 0) {
1818 gen_nullptr_check(s1);
1821 M_SLL_IMM(s2, 2, REG_ITMP2);
1822 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1823 M_LFSX(d, s1, REG_ITMP2);
1824 store_reg_to_var_flt(iptr->dst, d);
1827 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1829 var_to_reg_int(s1, src->prev, REG_ITMP1);
1830 var_to_reg_int(s2, src, REG_ITMP2);
1831 d = reg_of_var(iptr->dst, REG_FTMP3);
1832 if (iptr->op1 == 0) {
1833 gen_nullptr_check(s1);
1836 M_SLL_IMM(s2, 3, REG_ITMP2);
1837 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1838 M_LFDX(d, s1, REG_ITMP2);
1839 store_reg_to_var_flt(iptr->dst, d);
1842 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1844 var_to_reg_int(s1, src->prev, REG_ITMP1);
1845 var_to_reg_int(s2, src, REG_ITMP2);
1846 d = reg_of_var(iptr->dst, REG_ITMP3);
1847 if (iptr->op1 == 0) {
1848 gen_nullptr_check(s1);
1851 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1852 M_LBZX(d, s1, REG_ITMP2);
1854 store_reg_to_var_int(iptr->dst, d);
1857 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1859 var_to_reg_int(s1, src->prev, REG_ITMP1);
1860 var_to_reg_int(s2, src, REG_ITMP2);
1861 d = reg_of_var(iptr->dst, REG_ITMP3);
1862 if (iptr->op1 == 0) {
1863 gen_nullptr_check(s1);
1866 M_SLL_IMM(s2, 1, REG_ITMP2);
1867 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1868 M_LHAX(d, s1, REG_ITMP2);
1869 store_reg_to_var_int(iptr->dst, d);
1872 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1874 var_to_reg_int(s1, src->prev, REG_ITMP1);
1875 var_to_reg_int(s2, src, REG_ITMP2);
1876 d = reg_of_var(iptr->dst, REG_ITMP3);
1877 if (iptr->op1 == 0) {
1878 gen_nullptr_check(s1);
1881 M_SLL_IMM(s2, 1, REG_ITMP2);
1882 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1883 M_LHZX(d, s1, REG_ITMP2);
1884 store_reg_to_var_int(iptr->dst, d);
1887 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1889 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1890 var_to_reg_int(s2, src->prev, REG_ITMP2);
1891 if (iptr->op1 == 0) {
1892 gen_nullptr_check(s1);
1895 var_to_reg_int0(s3, src, REG_ITMP3, 1, 0);
1896 M_SLL_IMM(s2, 3, REG_ITMP2);
1897 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1898 M_STWX(s3, s1, REG_ITMP2);
1899 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1900 var_to_reg_int0(s3, src, REG_ITMP3, 0, 1);
1901 M_STWX(s3, s1, REG_ITMP2);
1904 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1906 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1907 var_to_reg_int(s2, src->prev, REG_ITMP2);
1908 if (iptr->op1 == 0) {
1909 gen_nullptr_check(s1);
1912 var_to_reg_int(s3, src, REG_ITMP3);
1913 M_SLL_IMM(s2, 2, REG_ITMP2);
1914 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1915 M_STWX(s3, s1, REG_ITMP2);
1918 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1920 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1921 var_to_reg_int(s2, src->prev, REG_ITMP2);
1922 if (iptr->op1 == 0) {
1923 gen_nullptr_check(s1);
1926 var_to_reg_flt(s3, src, REG_FTMP3);
1927 M_SLL_IMM(s2, 2, REG_ITMP2);
1928 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1929 M_STFSX(s3, s1, REG_ITMP2);
1932 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1934 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1935 var_to_reg_int(s2, src->prev, REG_ITMP2);
1936 if (iptr->op1 == 0) {
1937 gen_nullptr_check(s1);
1940 var_to_reg_flt(s3, src, REG_FTMP3);
1941 M_SLL_IMM(s2, 3, REG_ITMP2);
1942 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1943 M_STFDX(s3, s1, REG_ITMP2);
1946 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1948 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1949 var_to_reg_int(s2, src->prev, REG_ITMP2);
1950 if (iptr->op1 == 0) {
1951 gen_nullptr_check(s1);
1954 var_to_reg_int(s3, src, REG_ITMP3);
1955 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1956 M_STBX(s3, s1, REG_ITMP2);
1959 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1961 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1962 var_to_reg_int(s2, src->prev, REG_ITMP2);
1963 if (iptr->op1 == 0) {
1964 gen_nullptr_check(s1);
1967 var_to_reg_int(s3, src, REG_ITMP3);
1968 M_SLL_IMM(s2, 1, REG_ITMP2);
1969 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1970 M_STHX(s3, s1, REG_ITMP2);
1973 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1975 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1976 var_to_reg_int(s2, src->prev, REG_ITMP2);
1977 if (iptr->op1 == 0) {
1978 gen_nullptr_check(s1);
1981 var_to_reg_int(s3, src, REG_ITMP3);
1982 M_SLL_IMM(s2, 1, REG_ITMP2);
1983 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1984 M_STHX(s3, s1, REG_ITMP2);
1987 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1988 /* op1 = type, val.a = field address */
1990 /* if class isn't yet initialized, do it */
1991 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1992 /* call helper function which patches this code */
1993 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
1994 M_ALD(REG_ITMP1, REG_PV, a);
1995 a = dseg_addaddress(asm_check_clinit);
1996 M_ALD(REG_PV, REG_PV, a);
2001 s1 = (int) ((u1*) mcodeptr - mcodebase);
2003 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2005 s4 ml = -s1, mh = 0;
2006 while (ml < -32768) { ml += 65536; mh--; }
2007 M_LDA(REG_PV, REG_ITMP1, ml);
2008 M_LDAH(REG_PV, REG_PV, mh);
2012 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2013 M_ALD(REG_ITMP1, REG_PV, a);
2014 switch (iptr->op1) {
2016 var_to_reg_int(s2, src, REG_ITMP2);
2017 M_IST(s2, REG_ITMP1, 0);
2020 var_to_reg_int(s2, src, REG_ITMP3);
2021 M_IST(s2, REG_ITMP1, 0);
2022 M_IST(secondregs[s2], REG_ITMP1, 4);
2025 var_to_reg_int(s2, src, REG_ITMP2);
2026 M_AST(s2, REG_ITMP1, 0);
2029 var_to_reg_flt(s2, src, REG_FTMP2);
2030 M_FST(s2, REG_ITMP1, 0);
2033 var_to_reg_flt(s2, src, REG_FTMP2);
2034 M_DST(s2, REG_ITMP1, 0);
2036 default: panic ("internal error");
2040 case ICMD_GETSTATIC: /* ... ==> ..., value */
2041 /* op1 = type, val.a = field address */
2043 /* if class isn't yet initialized, do it */
2044 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2045 /* call helper function which patches this code */
2046 a = dseg_addaddress(((fieldinfo *) iptr->val.a)->class);
2047 M_ALD(REG_ITMP1, REG_PV, a);
2048 a = dseg_addaddress(asm_check_clinit);
2049 M_ALD(REG_PV, REG_PV, a);
2054 s1 = (int) ((u1*) mcodeptr - mcodebase);
2056 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2058 s4 ml = -s1, mh = 0;
2059 while (ml < -32768) { ml += 65536; mh--; }
2060 M_LDA(REG_PV, REG_ITMP1, ml);
2061 M_LDAH(REG_PV, REG_PV, mh);
2065 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2066 M_ALD(REG_ITMP1, REG_PV, a);
2067 switch (iptr->op1) {
2069 d = reg_of_var(iptr->dst, REG_ITMP3);
2070 M_ILD(d, REG_ITMP1, 0);
2071 store_reg_to_var_int(iptr->dst, d);
2074 d = reg_of_var(iptr->dst, REG_ITMP3);
2075 M_ILD(d, REG_ITMP1, 0);
2076 M_ILD(secondregs[d], REG_ITMP1, 4);
2077 store_reg_to_var_int(iptr->dst, d);
2080 d = reg_of_var(iptr->dst, REG_ITMP3);
2081 M_ALD(d, REG_ITMP1, 0);
2082 store_reg_to_var_int(iptr->dst, d);
2085 d = reg_of_var(iptr->dst, REG_FTMP1);
2086 M_FLD(d, REG_ITMP1, 0);
2087 store_reg_to_var_flt(iptr->dst, d);
2090 d = reg_of_var(iptr->dst, REG_FTMP1);
2091 M_DLD(d, REG_ITMP1, 0);
2092 store_reg_to_var_flt(iptr->dst, d);
2094 default: panic ("internal error");
2099 case ICMD_PUTFIELD: /* ..., value ==> ... */
2100 /* op1 = type, val.i = field offset */
2102 a = ((fieldinfo *)(iptr->val.a))->offset;
2103 switch (iptr->op1) {
2105 var_to_reg_int(s1, src->prev, REG_ITMP1);
2106 var_to_reg_int(s2, src, REG_ITMP2);
2107 gen_nullptr_check(s1);
2111 var_to_reg_int(s1, src->prev, REG_ITMP1);
2112 var_to_reg_int(s2, src, REG_ITMP3);
2113 gen_nullptr_check(s1);
2115 M_IST(secondregs[s2], s1, a+4);
2118 var_to_reg_int(s1, src->prev, REG_ITMP1);
2119 var_to_reg_int(s2, src, REG_ITMP2);
2120 gen_nullptr_check(s1);
2124 var_to_reg_int(s1, src->prev, REG_ITMP1);
2125 var_to_reg_flt(s2, src, REG_FTMP2);
2126 gen_nullptr_check(s1);
2130 var_to_reg_int(s1, src->prev, REG_ITMP1);
2131 var_to_reg_flt(s2, src, REG_FTMP2);
2132 gen_nullptr_check(s1);
2135 default: panic ("internal error");
2139 case ICMD_GETFIELD: /* ... ==> ..., value */
2140 /* op1 = type, val.i = field offset */
2142 a = ((fieldinfo *)(iptr->val.a))->offset;
2143 switch (iptr->op1) {
2145 var_to_reg_int(s1, src, REG_ITMP1);
2146 d = reg_of_var(iptr->dst, REG_ITMP3);
2147 gen_nullptr_check(s1);
2149 store_reg_to_var_int(iptr->dst, d);
2152 var_to_reg_int(s1, src, REG_ITMP1);
2153 d = reg_of_var(iptr->dst, REG_ITMP3);
2154 gen_nullptr_check(s1);
2156 M_ILD(secondregs[d], s1, a+4);
2157 store_reg_to_var_int(iptr->dst, d);
2160 var_to_reg_int(s1, src, REG_ITMP1);
2161 d = reg_of_var(iptr->dst, REG_ITMP3);
2162 gen_nullptr_check(s1);
2164 store_reg_to_var_int(iptr->dst, d);
2167 var_to_reg_int(s1, src, REG_ITMP1);
2168 d = reg_of_var(iptr->dst, REG_FTMP1);
2169 gen_nullptr_check(s1);
2171 store_reg_to_var_flt(iptr->dst, d);
2174 var_to_reg_int(s1, src, REG_ITMP1);
2175 d = reg_of_var(iptr->dst, REG_FTMP1);
2176 gen_nullptr_check(s1);
2178 store_reg_to_var_flt(iptr->dst, d);
2180 default: panic ("internal error");
2185 /* branch operations **************************************************/
2187 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2189 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2191 a = dseg_addaddress(asm_handle_exception);
2192 M_ALD(REG_ITMP2, REG_PV, a);
2194 var_to_reg_int(s1, src, REG_ITMP1);
2195 M_INTMOVE(s1, REG_ITMP1_XPTR);
2197 if (isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
2198 M_BL(0); /* get current PC */
2199 M_MFLR(REG_ITMP2_XPC);
2200 if (isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
2201 M_RTS; /* jump to CTR */
2206 case ICMD_GOTO: /* ... ==> ... */
2207 /* op1 = target JavaVM pc */
2209 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2213 case ICMD_JSR: /* ... ==> ... */
2214 /* op1 = target JavaVM pc */
2216 if (isleafmethod) M_MFLR(REG_ITMP2);
2219 M_IADD_IMM(REG_ITMP1, isleafmethod?16:12, REG_ITMP1);
2220 if (isleafmethod) M_MTLR(REG_ITMP2);
2222 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2225 case ICMD_RET: /* ... ==> ... */
2226 /* op1 = local variable */
2228 var = &(locals[iptr->op1][TYPE_ADR]);
2229 if (var->flags & INMEMORY) {
2230 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
2234 M_MTCTR(var->regoff);
2239 case ICMD_IFNULL: /* ..., value ==> ... */
2240 /* op1 = target JavaVM pc */
2242 var_to_reg_int(s1, src, REG_ITMP1);
2245 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2248 case ICMD_IFNONNULL: /* ..., value ==> ... */
2249 /* op1 = target JavaVM pc */
2251 var_to_reg_int(s1, src, REG_ITMP1);
2254 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2262 case ICMD_IFEQ: /* ..., value ==> ... */
2263 /* op1 = target JavaVM pc, val.i = constant */
2265 var_to_reg_int(s1, src, REG_ITMP1);
2266 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2267 M_CMPI(s1, iptr->val.i);
2270 ICONST(REG_ITMP2, iptr->val.i);
2271 M_CMP(s1, REG_ITMP2);
2294 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2298 case ICMD_IF_LEQ: /* ..., value ==> ... */
2299 /* op1 = target JavaVM pc, val.l = constant */
2301 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2302 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2303 if (iptr->val.l == 0) {
2304 M_OR(s1, s2, REG_ITMP3);
2305 M_CMPI(REG_ITMP3, 0);
2307 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2308 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2310 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2313 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2314 M_CMP(s2, REG_ITMP3);
2316 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2317 M_CMP(s1, REG_ITMP3)
2320 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2323 case ICMD_IF_LLT: /* ..., value ==> ... */
2324 /* op1 = target JavaVM pc, val.l = constant */
2325 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2326 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2327 /* if (iptr->val.l == 0) { */
2328 /* M_OR(s1, s2, REG_ITMP3); */
2329 /* M_CMPI(REG_ITMP3, 0); */
2332 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2333 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2335 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2337 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2340 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2341 M_CMP(s2, REG_ITMP3);
2343 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2345 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2346 M_CMP(s1, REG_ITMP3)
2349 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2352 case ICMD_IF_LLE: /* ..., value ==> ... */
2353 /* op1 = target JavaVM pc, val.l = constant */
2355 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2356 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2357 /* if (iptr->val.l == 0) { */
2358 /* M_OR(s1, s2, REG_ITMP3); */
2359 /* M_CMPI(REG_ITMP3, 0); */
2362 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2363 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2365 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2367 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2370 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2371 M_CMP(s2, REG_ITMP3);
2373 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2375 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2376 M_CMP(s1, REG_ITMP3)
2379 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2382 case ICMD_IF_LNE: /* ..., value ==> ... */
2383 /* op1 = target JavaVM pc, val.l = constant */
2385 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2386 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2387 if (iptr->val.l == 0) {
2388 M_OR(s1, s2, REG_ITMP3);
2389 M_CMPI(REG_ITMP3, 0);
2391 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2392 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2394 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2397 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2398 M_CMP(s2, REG_ITMP3);
2400 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2401 M_CMP(s1, REG_ITMP3)
2404 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2407 case ICMD_IF_LGT: /* ..., value ==> ... */
2408 /* op1 = target JavaVM pc, val.l = constant */
2410 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2411 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2412 /* if (iptr->val.l == 0) { */
2413 /* M_OR(s1, s2, REG_ITMP3); */
2414 /* M_CMPI(REG_ITMP3, 0); */
2417 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2418 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2420 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2422 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2425 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2426 M_CMP(s2, REG_ITMP3);
2428 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2430 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2431 M_CMP(s1, REG_ITMP3)
2434 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2437 case ICMD_IF_LGE: /* ..., value ==> ... */
2438 /* op1 = target JavaVM pc, val.l = constant */
2439 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2440 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2441 /* if (iptr->val.l == 0) { */
2442 /* M_OR(s1, s2, REG_ITMP3); */
2443 /* M_CMPI(REG_ITMP3, 0); */
2446 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2447 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2449 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2451 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2454 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2455 M_CMP(s2, REG_ITMP3);
2457 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2459 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2460 M_CMP(s1, REG_ITMP3)
2463 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2467 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2468 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2469 case ICMD_IF_ACMPEQ:
2471 var_to_reg_int(s1, src->prev, REG_ITMP1);
2472 var_to_reg_int(s2, src, REG_ITMP2);
2475 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2478 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2479 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2480 case ICMD_IF_ACMPNE:
2482 var_to_reg_int(s1, src->prev, REG_ITMP1);
2483 var_to_reg_int(s2, src, REG_ITMP2);
2486 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2489 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2490 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2492 var_to_reg_int(s1, src->prev, REG_ITMP1);
2493 var_to_reg_int(s2, src, REG_ITMP2);
2496 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2499 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2500 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2502 var_to_reg_int(s1, src->prev, REG_ITMP1);
2503 var_to_reg_int(s2, src, REG_ITMP2);
2506 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2509 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2510 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2512 var_to_reg_int(s1, src->prev, REG_ITMP1);
2513 var_to_reg_int(s2, src, REG_ITMP2);
2516 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2519 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2520 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2522 var_to_reg_int(s1, src->prev, REG_ITMP1);
2523 var_to_reg_int(s2, src, REG_ITMP2);
2526 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2529 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2533 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2536 case ICMD_RETURN: /* ... ==> ... */
2539 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2540 a = dseg_addaddress ((void*) (builtin_monitorexit));
2541 M_ALD(REG_ITMP3, REG_PV, a);
2543 M_ALD(argintregs[0], REG_SP, 4 * maxmemuse);
2547 switch (iptr->opc) {
2551 var_to_reg_int(s1, src, REG_RESULT);
2552 M_TINTMOVE(src->type, s1, REG_RESULT);
2553 goto nowperformreturn;
2557 var_to_reg_flt(s1, src, REG_FRESULT);
2558 M_FLTMOVE(s1, REG_FRESULT);
2559 goto nowperformreturn;
2566 p = parentargs_base;
2568 /* restore return address */
2570 if (!isleafmethod) {
2571 M_ALD (REG_ITMP3, REG_SP, 4 * p + 8);
2575 /* restore saved registers */
2577 for (r = savintregcnt - 1; r >= maxsavintreguse; r--) {
2578 p--; M_ILD(savintregs[r], REG_SP, 4 * p);
2580 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--) {
2581 p -= 2; M_DLD(savfltregs[r], REG_SP, 4 * p);
2584 /* deallocate stack */
2586 if (parentargs_base) {
2587 M_LDA(REG_SP, REG_SP, parentargs_base*4);
2590 /* call trace function */
2594 M_LDA(REG_SP, REG_SP, -10 * 8);
2595 M_DST(REG_FRESULT, REG_SP, 48+0);
2596 M_IST(REG_RESULT, REG_SP, 48+8);
2597 M_AST(REG_ITMP3, REG_SP, 48+12);
2598 M_IST(REG_RESULT2, REG_SP, 48+16);
2599 a = dseg_addaddress(method);
2601 /* keep this order */
2602 switch (iptr->opc) {
2605 M_MOV(REG_RESULT, argintregs[2]);
2606 M_CLR(argintregs[1]);
2610 M_MOV(REG_RESULT2, argintregs[2]);
2611 M_MOV(REG_RESULT, argintregs[1]);
2614 M_ALD(argintregs[0], REG_PV, a);
2616 M_FLTMOVE(REG_FRESULT, argfltregs[0]);
2617 M_FLTMOVE(REG_FRESULT, argfltregs[1]);
2618 a = dseg_addaddress((void *) (builtin_displaymethodstop));
2619 M_ALD(REG_ITMP2, REG_PV, a);
2622 M_DLD(REG_FRESULT, REG_SP, 48+0);
2623 M_ILD(REG_RESULT, REG_SP, 48+8);
2624 M_ALD(REG_ITMP3, REG_SP, 48+12);
2625 M_ILD(REG_RESULT2, REG_SP, 48+16);
2626 M_LDA(REG_SP, REG_SP, 10 * 8);
2636 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2641 tptr = (void **) iptr->target;
2643 s4ptr = iptr->val.a;
2644 l = s4ptr[1]; /* low */
2645 i = s4ptr[2]; /* high */
2647 var_to_reg_int(s1, src, REG_ITMP1);
2649 {M_INTMOVE(s1, REG_ITMP1);}
2650 else if (l <= 32768) {
2651 M_LDA(REG_ITMP1, s1, -l);
2654 ICONST(REG_ITMP2, l);
2655 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2661 M_CMPUI(REG_ITMP1, i - 1);
2665 /* codegen_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2666 codegen_addreference((basicblock *) tptr[0], mcodeptr);
2668 /* build jump table top down and use address of lowest entry */
2670 /* s4ptr += 3 + i; */
2674 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
2675 dseg_addtarget((basicblock *) tptr[0]);
2680 /* length of dataseg after last dseg_addtarget is used by load */
2682 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2683 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2684 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
2691 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2693 s4 i, l, val, *s4ptr;
2696 tptr = (void **) iptr->target;
2698 s4ptr = iptr->val.a;
2699 l = s4ptr[0]; /* default */
2700 i = s4ptr[1]; /* count */
2702 MCODECHECK((i<<2)+8);
2703 var_to_reg_int(s1, src, REG_ITMP1);
2709 if ((val >= -32768) && (val <= 32767)) {
2713 a = dseg_adds4 (val);
2714 M_ILD(REG_ITMP2, REG_PV, a);
2715 M_CMP(s1, REG_ITMP2);
2718 /* codegen_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2719 codegen_addreference((basicblock *) tptr[0], mcodeptr);
2723 /* codegen_addreference(BlockPtrOfPC(l), mcodeptr); */
2725 tptr = (void **) iptr->target;
2726 codegen_addreference((basicblock *) tptr[0], mcodeptr);
2733 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2734 /* op1 = return type, val.a = function pointer*/
2738 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2739 /* op1 = return type, val.a = function pointer*/
2743 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2744 /* op1 = return type, val.a = function pointer*/
2748 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2749 /* op1 = arg count, val.a = method pointer */
2751 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2752 /* op1 = arg count, val.a = method pointer */
2754 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2755 /* op1 = arg count, val.a = method pointer */
2757 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2758 /* op1 = arg count, val.a = method pointer */
2766 MCODECHECK((s3 << 1) + 64);
2769 /* copy arguments to registers or stack location */
2771 stackptr srcsave = src;
2775 for (; --s3 >= 0; src = src->prev) {
2776 argsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
2777 if (IS_FLT_DBL_TYPE(src->type))
2781 for (s3=s3save, src=srcsave; --s3 >= 0; src = src->prev) {
2782 argsize -= IS_2_WORD_TYPE(src->type) ? 2 : 1;
2783 if (IS_FLT_DBL_TYPE(src->type))
2785 if (src->varkind == ARGVAR)
2787 if (IS_INT_LNG_TYPE(src->type)) {
2788 if (argsize < INT_ARG_CNT) {
2789 s1 = argintregs[argsize];
2790 var_to_reg_int(d, src, s1);
2791 if (argsize < INT_ARG_CNT-1)
2792 {M_TINTMOVE(src->type, d, s1);}
2795 if (IS_2_WORD_TYPE(src->type))
2796 M_IST(secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2800 var_to_reg_int(d, src, REG_ITMP1);
2801 M_IST(d, REG_SP, 4 * (argsize + 6));
2802 if (IS_2_WORD_TYPE(src->type))
2803 M_IST(secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2807 if (fltcnt < FLT_ARG_CNT) {
2808 s1 = argfltregs[fltcnt];
2809 var_to_reg_flt(d, src, s1);
2813 var_to_reg_flt(d, src, REG_FTMP1);
2814 if (IS_2_WORD_TYPE(src->type))
2815 M_DST(d, REG_SP, 4 * (argsize + 6));
2817 M_FST(d, REG_SP, 4 * (argsize + 6));
2823 switch (iptr->opc) {
2827 a = dseg_addaddress ((void*) (m));
2829 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2831 goto makeactualcall;
2833 case ICMD_INVOKESTATIC:
2834 case ICMD_INVOKESPECIAL:
2835 a = dseg_addaddress (m->stubroutine);
2837 M_ALD(REG_PV, REG_PV, a ); /* method pointer in r27 */
2840 goto makeactualcall;
2842 case ICMD_INVOKEVIRTUAL:
2844 gen_nullptr_check(argintregs[0]);
2845 M_ALD(REG_METHODPTR, argintregs[0],
2846 OFFSET(java_objectheader, vftbl));
2847 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
2848 sizeof(methodptr) * m->vftblindex);
2851 goto makeactualcall;
2853 case ICMD_INVOKEINTERFACE:
2856 gen_nullptr_check(argintregs[0]);
2857 M_ALD(REG_METHODPTR, argintregs[0],
2858 OFFSET(java_objectheader, vftbl));
2859 M_ALD(REG_METHODPTR, REG_METHODPTR,
2860 OFFSET(vftbl, interfacetable[0]) -
2861 sizeof(methodptr*) * ci->index);
2862 M_ALD(REG_PV, REG_METHODPTR,
2863 sizeof(methodptr) * (m - ci->methods));
2866 goto makeactualcall;
2870 error ("Unkown ICMD-Command: %d", iptr->opc);
2879 s1 = (int) ((u1 *) mcodeptr - mcodebase);
2881 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2883 s4 ml = -s1, mh = 0;
2884 while (ml < -32768) { ml += 65536; mh--; }
2885 M_LDA(REG_PV, REG_ITMP1, ml);
2886 M_LDAH(REG_PV, REG_PV, mh);
2889 /* d contains return type */
2891 if (d != TYPE_VOID) {
2892 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2893 s1 = reg_of_var(iptr->dst, REG_RESULT);
2894 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2895 store_reg_to_var_int(iptr->dst, s1);
2898 s1 = reg_of_var(iptr->dst, REG_FRESULT);
2899 M_FLTMOVE(REG_FRESULT, s1);
2900 store_reg_to_var_flt(iptr->dst, s1);
2907 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2909 /* op1: 0 == array, 1 == class */
2910 /* val.a: (classinfo*) superclass */
2912 /* superclass is an interface:
2914 * return (sub != NULL) &&
2915 * (sub->vftbl->interfacetablelength > super->index) &&
2916 * (sub->vftbl->interfacetable[-super->index] != NULL);
2918 * superclass is a class:
2920 * return ((sub != NULL) && (0
2921 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2922 * super->vftbl->diffvall));
2926 classinfo *super = (classinfo*) iptr->val.a;
2928 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2929 codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
2931 var_to_reg_int(s1, src, REG_ITMP1);
2932 d = reg_of_var(iptr->dst, REG_ITMP3);
2934 M_MOV(s1, REG_ITMP1);
2938 if (iptr->op1) { /* class/interface */
2940 if (super->flags & ACC_INTERFACE) { /* interface */
2942 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2943 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
2944 M_LDATST(REG_ITMP2, REG_ITMP2, - super->index);
2946 M_ALD(REG_ITMP1, REG_ITMP1,
2947 OFFSET(vftbl, interfacetable[0]) -
2948 super->index * sizeof(methodptr*));
2952 M_IADD_IMM(REG_ZERO, 1, d);
2956 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2957 a = dseg_addaddress ((void*) super->vftbl);
2958 M_ALD(REG_ITMP2, REG_PV, a);
2959 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2960 codegen_threadcritstart((u1*) mcodeptr - mcodebase);
2962 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
2963 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
2964 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
2965 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2966 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
2968 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2969 M_CMPU(REG_ITMP1, REG_ITMP2);
2972 M_IADD_IMM(REG_ZERO, 1, d);
2976 panic ("internal error: no inlined array instanceof");
2978 store_reg_to_var_int(iptr->dst, d);
2981 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2983 /* op1: 0 == array, 1 == class */
2984 /* val.a: (classinfo*) superclass */
2986 /* superclass is an interface:
2988 * OK if ((sub == NULL) ||
2989 * (sub->vftbl->interfacetablelength > super->index) &&
2990 * (sub->vftbl->interfacetable[-super->index] != NULL));
2992 * superclass is a class:
2994 * OK if ((sub == NULL) || (0
2995 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2996 * super->vftbl->diffvall));
3000 classinfo *super = (classinfo*) iptr->val.a;
3002 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3003 codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
3005 d = reg_of_var(iptr->dst, REG_ITMP1);
3006 var_to_reg_int(s1, src, d);
3007 if (iptr->op1) { /* class/interface */
3009 if (super->flags & ACC_INTERFACE) { /* interface */
3011 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3012 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, interfacetablelength));
3013 M_LDATST(REG_ITMP3, REG_ITMP3, - super->index);
3015 codegen_addxcastrefs(mcodeptr);
3016 M_ALD(REG_ITMP3, REG_ITMP2,
3017 OFFSET(vftbl, interfacetable[0]) -
3018 super->index * sizeof(methodptr*));
3021 codegen_addxcastrefs(mcodeptr);
3024 M_BEQ(8 + (s1 == REG_ITMP1));
3025 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3026 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3027 codegen_threadcritstart((u1*) mcodeptr - mcodebase);
3029 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3030 a = dseg_addaddress ((void*) super->vftbl);
3031 M_ALD(REG_ITMP2, REG_PV, a);
3032 if (d != REG_ITMP1) {
3033 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl, baseval));
3034 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3035 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3036 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
3038 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
3041 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, baseval));
3042 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3043 M_ALD(REG_ITMP2, REG_PV, a);
3044 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3045 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3046 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
3049 M_CMPU(REG_ITMP3, REG_ITMP2);
3051 codegen_addxcastrefs(mcodeptr);
3055 panic ("internal error: no inlined array checkcast");
3058 store_reg_to_var_int(iptr->dst, d);
3061 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3063 var_to_reg_int(s1, src, REG_ITMP1);
3066 codegen_addxcheckarefs(mcodeptr);
3069 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3071 M_CMPI(REG_RESULT, 0);
3073 codegen_addxexceptionrefs(mcodeptr);
3076 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3077 /* op1 = dimension, val.a = array descriptor */
3079 /* check for negative sizes and copy sizes to stack if necessary */
3081 MCODECHECK((iptr->op1 << 1) + 64);
3083 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3084 var_to_reg_int(s2, src, REG_ITMP1);
3087 codegen_addxcheckarefs(mcodeptr);
3089 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3091 if (src->varkind != ARGVAR) {
3092 M_IST(s2, REG_SP, 4 * (s1 + INT_ARG_CNT + 6));
3096 /* a0 = dimension count */
3098 ICONST(argintregs[0], iptr->op1);
3100 /* a1 = arraydescriptor */
3102 a = dseg_addaddress(iptr->val.a);
3103 M_ALD(argintregs[1], REG_PV, a);
3105 /* a2 = pointer to dimensions = stack pointer */
3107 M_LDA(argintregs[2], REG_SP, (INT_ARG_CNT + 6)*4);
3109 a = dseg_addaddress((void*) (builtin_nmultianewarray));
3110 M_ALD(REG_PV, REG_PV, a);
3113 s1 = (int)((u1*) mcodeptr - mcodebase);
3116 M_LDA (REG_PV, REG_ITMP1, -s1);
3118 s4 ml = -s1, mh = 0;
3119 while (ml < -32768) {ml += 65536; mh--;}
3120 M_LDA(REG_PV, REG_ITMP1, ml);
3121 M_LDAH(REG_PV, REG_PV, mh);
3123 s1 = reg_of_var(iptr->dst, REG_RESULT);
3124 M_INTMOVE(REG_RESULT, s1);
3125 store_reg_to_var_int(iptr->dst, s1);
3129 default: error ("Unknown pseudo command: %d", iptr->opc);
3135 } /* for instruction */
3137 /* copy values to interface registers */
3139 src = bptr->outstack;
3140 len = bptr->outdepth;
3144 if ((src->varkind != STACKVAR)) {
3146 if (IS_FLT_DBL_TYPE(s2)) {
3147 var_to_reg_flt(s1, src, REG_FTMP1);
3148 if (!(interfaces[len][s2].flags & INMEMORY)) {
3149 M_FLTMOVE(s1,interfaces[len][s2].regoff);
3152 M_DST(s1, REG_SP, 4 * interfaces[len][s2].regoff);
3156 var_to_reg_int(s1, src, REG_ITMP1);
3157 if (!(interfaces[len][s2].flags & INMEMORY)) {
3158 M_TINTMOVE(s2,s1,interfaces[len][s2].regoff);
3161 M_IST(s1, REG_SP, 4 * interfaces[len][s2].regoff);
3162 if (IS_2_WORD_TYPE(s2))
3163 M_IST(secondregs[s1], REG_SP, 4 * interfaces[len][s2].regoff + 4);
3169 } /* if (bptr -> flags >= BBREACHED) */
3170 } /* for basic block */
3172 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3175 /* generate bound check stubs */
3177 s4 *xcodeptr = NULL;
3179 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3180 gen_resolvebranch((u1 *) mcodebase + xboundrefs->branchpos,
3181 xboundrefs->branchpos,
3182 (u1 *) mcodeptr - mcodebase);
3186 M_MOV(xboundrefs->reg, REG_ITMP1);
3187 M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos - 4);
3189 if (xcodeptr != NULL) {
3190 M_BR(xcodeptr - mcodeptr - 1);
3193 xcodeptr = mcodeptr;
3195 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3196 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3198 a = dseg_addaddress(string_java_lang_ArrayIndexOutOfBoundsException);
3199 M_ALD(argintregs[0], REG_PV, a);
3200 M_MOV(REG_ITMP1, argintregs[1]);
3202 a = dseg_addaddress(new_exception_int);
3203 M_ALD(REG_ITMP2, REG_PV, a);
3206 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3208 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3209 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3211 a = dseg_addaddress(asm_handle_exception);
3212 M_ALD(REG_ITMP3, REG_PV, a);
3219 /* generate negative array size check stubs */
3223 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3224 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3225 gen_resolvebranch((u1 *) mcodebase + xcheckarefs->branchpos,
3226 xcheckarefs->branchpos,
3227 (u1 *) xcodeptr - (u1 *) mcodebase - 4);
3231 gen_resolvebranch((u1 *) mcodebase + xcheckarefs->branchpos,
3232 xcheckarefs->branchpos,
3233 (u1 *) mcodeptr - mcodebase);
3237 M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos - 4);
3239 if (xcodeptr != NULL) {
3240 M_BR(xcodeptr - mcodeptr - 1);
3243 xcodeptr = mcodeptr;
3245 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3246 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3248 a = dseg_addaddress(string_java_lang_NegativeArraySizeException);
3249 M_ALD(argintregs[0], REG_PV, a);
3251 a = dseg_addaddress(new_exception);
3252 M_ALD(REG_ITMP2, REG_PV, a);
3255 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3257 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3258 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3260 a = dseg_addaddress(asm_handle_exception);
3261 M_ALD(REG_ITMP3, REG_PV, a);
3268 /* generate cast check stubs */
3272 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3273 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3274 gen_resolvebranch((u1 *) mcodebase + xcastrefs->branchpos,
3275 xcastrefs->branchpos,
3276 (u1 *) xcodeptr - (u1 *) mcodebase - 4);
3280 gen_resolvebranch((u1 *) mcodebase + xcastrefs->branchpos,
3281 xcastrefs->branchpos,
3282 (u1 *) mcodeptr - mcodebase);
3286 M_LDA(REG_ITMP2_XPC, REG_PV, xcastrefs->branchpos - 4);
3288 if (xcodeptr != NULL) {
3289 M_BR(xcodeptr - mcodeptr - 1);
3292 xcodeptr = mcodeptr;
3294 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3295 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3297 a = dseg_addaddress(string_java_lang_ClassCastException);
3298 M_ALD(argintregs[0], REG_PV, a);
3300 a = dseg_addaddress(new_exception);
3301 M_ALD(REG_ITMP2, REG_PV, a);
3304 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3306 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3307 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3309 a = dseg_addaddress(asm_handle_exception);
3310 M_ALD(REG_ITMP3, REG_PV, a);
3317 /* generate exception check stubs */
3321 for (; xexceptionrefs != NULL; xexceptionrefs = xexceptionrefs->next) {
3322 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3323 gen_resolvebranch((u1 *) mcodebase + xexceptionrefs->branchpos,
3324 xexceptionrefs->branchpos,
3325 (u1 *) xcodeptr - (u1 *) mcodebase - 4);
3329 gen_resolvebranch((u1 *) mcodebase + xexceptionrefs->branchpos,
3330 xexceptionrefs->branchpos,
3331 (u1 *) mcodeptr - mcodebase);
3335 M_LDA(REG_ITMP2_XPC, REG_PV, xexceptionrefs->branchpos - 4);
3337 if (xcodeptr != NULL) {
3338 M_BR(xcodeptr - mcodeptr - 1);
3341 xcodeptr = mcodeptr;
3343 /* XXX this cannot work - there is no link area */
3344 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3345 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3347 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3348 a = dseg_addaddress(builtin_get_exceptionptrptr);
3349 M_ALD(REG_ITMP2, REG_PV, a);
3352 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3354 a = dseg_addaddress(&_exceptionptr);
3355 M_ALD(REG_ITMP2, REG_PV, a);
3357 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);
3359 M_AST(REG_ITMP3, REG_ITMP2, 0);
3362 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3363 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3365 a = dseg_addaddress(asm_handle_exception);
3366 M_ALD(REG_ITMP3, REG_PV, a);
3372 /* generate null pointer check stubs */
3376 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3377 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3378 gen_resolvebranch((u1 *) mcodebase + xnullrefs->branchpos,
3379 xnullrefs->branchpos,
3380 (u1 *) xcodeptr - (u1 *) mcodebase - 4);
3384 gen_resolvebranch((u1 *) mcodebase + xnullrefs->branchpos,
3385 xnullrefs->branchpos,
3386 (u1 *) mcodeptr - mcodebase);
3390 M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
3392 if (xcodeptr != NULL) {
3393 M_BR(xcodeptr - mcodeptr - 1);
3396 xcodeptr = mcodeptr;
3398 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3399 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3401 a = dseg_addaddress(string_java_lang_NullPointerException);
3402 M_ALD(argintregs[0], REG_PV, a);
3404 a = dseg_addaddress(new_exception);
3405 M_ALD(REG_ITMP2, REG_PV, a);
3408 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3410 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3411 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3413 a = dseg_addaddress(asm_handle_exception);
3414 M_ALD(REG_ITMP3, REG_PV, a);
3421 codegen_finish((int)((u1*) mcodeptr - mcodebase));
3423 asm_cacheflush((void*) method->entrypoint, ((u1*) mcodeptr - mcodebase));
3427 /* function createcompilerstub *************************************************
3429 creates a stub routine which calls the compiler
3431 *******************************************************************************/
3433 #define COMPSTUBSIZE 6
3435 u1 *createcompilerstub (methodinfo *m)
3437 s4 *s = CNEW (s4, COMPSTUBSIZE); /* memory to hold the stub */
3438 s4 *mcodeptr = s; /* code generation pointer */
3440 M_LDA(2, REG_PV, 4*4);
3441 M_ALD(REG_PV, REG_PV, 5*4);
3445 s[4] = (s4) m; /* literals to be adressed */
3446 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3448 asm_cacheflush((void*) s, (char*) mcodeptr - (char*) s);
3451 count_cstub_len += COMPSTUBSIZE * 4;
3458 /* function removecompilerstub *************************************************
3460 deletes a compilerstub from memory (simply by freeing it)
3462 *******************************************************************************/
3464 void removecompilerstub(u1 *stub)
3466 CFREE (stub, COMPSTUBSIZE * 4);
3470 /* function: createnativestub **************************************************
3472 creates a stub routine which calls a native method
3474 *******************************************************************************/
3476 #define NATIVESTUBSIZE 200
3477 #define NATIVESTUBOFFSET 9
3479 u1 *createnativestub(functionptr f, methodinfo *m)
3481 s4 *s; /* memory to hold the stub */
3483 s4 *mcodeptr; /* code generation pointer */
3485 s4 stackframesize = 0; /* size of stackframe if needed */
3488 descriptor2types(m); /* set paramcount and paramtypes */
3490 s = CNEW(s4, NATIVESTUBSIZE);
3491 cs = s + NATIVESTUBOFFSET;
3494 *(cs-1) = (u4) f; /* address of native method */
3495 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3496 *(cs-2) = (u4) builtin_get_exceptionptrptr;
3498 *(cs-2) = (u4) (&_exceptionptr); /* address of exceptionptr */
3500 *(cs-3) = (u4) asm_handle_nat_exception; /* addr of asm exception handler */
3501 *(cs-4) = (u4) (&env); /* addr of jni_environement */
3502 *(cs-5) = (u4) builtin_trace_args;
3504 *(cs-7) = (u4) builtin_displaymethodstop;
3505 *(cs-8) = (u4) m->class;
3506 *(cs-9) = (u4) asm_check_clinit;
3509 M_AST(REG_ITMP1, REG_SP, 8); /* store return address */
3510 M_LDA(REG_SP, REG_SP, -64); /* build up stackframe */
3512 /* if function is static, check for initialized */
3514 if (m->flags & ACC_STATIC) {
3515 /* if class isn't yet initialized, do it */
3516 if (!m->class->initialized) {
3517 /* call helper function which patches this code */
3518 M_ALD(REG_ITMP1, REG_PV, -8 * 4); /* class */
3519 M_ALD(REG_PV, REG_PV, -9 * 4); /* asm_check_clinit */
3522 disp = -(s4) (mcodeptr - cs) * 4;
3524 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3534 /* M_MFLR(REG_ITMP3); */
3535 /* XXX must be a multiple of 16 */
3536 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
3538 /* M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3542 /* save all arguments into the reserved stack space */
3543 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3544 t = m->paramtypes[p];
3546 if (IS_INT_LNG_TYPE(t)) {
3547 /* overlapping u8's are on the stack */
3548 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
3549 s1 = argintregs[p + longargs + dblargs];
3551 if (!IS_2_WORD_TYPE(t)) {
3552 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3553 M_IST(s1, REG_SP, 24 + p * 8 + 4);
3556 M_IST(s1, REG_SP, 24 + p * 8);
3557 M_IST(secondregs[s1], REG_SP, 24 + p * 8 + 4);
3562 a = dseg_adds4(0xdeadbeef);
3563 M_ILD(REG_ITMP1, REG_PV, a);
3564 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3565 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
3569 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3570 s1 = argfltregs[fltargs + dblargs];
3572 if (!IS_2_WORD_TYPE(t)) {
3573 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3574 M_FST(s1, REG_SP, 24 + p * 8 + 4);
3578 M_DST(s1, REG_SP, 24 + p * 8);
3583 /* this should not happen */
3588 /* TODO: save remaining integer and flaot argument registers */
3590 /* load first 4 arguments into integer argument registers */
3591 for (p = 0; p < 8; p++) {
3593 M_ILD(d, REG_SP, 24 + p * 4);
3596 M_ALD(REG_ITMP1, REG_PV, -6 * 4);
3597 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
3598 M_ALD(REG_ITMP2, REG_PV, -5 * 4);
3606 /* restore arguments into the reserved stack space */
3607 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3608 t = m->paramtypes[p];
3610 if (IS_INT_LNG_TYPE(t)) {
3611 if ((p + longargs + dblargs) < INT_ARG_CNT) {
3612 s1 = argintregs[p + longargs + dblargs];
3614 if (!IS_2_WORD_TYPE(t)) {
3615 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
3618 M_ILD(s1, REG_SP, 24 + p * 8);
3619 M_ILD(secondregs[s1], REG_SP, 24 + p * 8 + 4);
3625 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3626 s1 = argfltregs[fltargs + dblargs];
3628 if (!IS_2_WORD_TYPE(t)) {
3629 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
3633 M_DLD(s1, REG_SP, 24 + p * 8);
3640 /* M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3642 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
3643 /* M_MTLR(REG_ITMP3); */
3646 /* save argument registers on stack -- if we have to */
3647 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) ||
3648 m->paramcount > (INT_ARG_CNT - 1)) {
3650 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3651 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3653 stackframesize = stackparamcnt + paramshiftcnt;
3655 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
3657 panic("nativestub");
3660 if (m->flags & ACC_STATIC) {
3661 M_MOV(argintregs[5], argintregs[7]);
3662 M_MOV(argintregs[4], argintregs[6]);
3663 M_MOV(argintregs[3], argintregs[5]);
3664 M_MOV(argintregs[2], argintregs[4]);
3665 M_MOV(argintregs[1], argintregs[3]);
3666 M_MOV(argintregs[0], argintregs[2]);
3668 /* put class into second argument register */
3669 M_ALD(argintregs[1], REG_PV, -8 * 4);
3672 M_MOV(argintregs[6], argintregs[7]);
3673 M_MOV(argintregs[5], argintregs[6]);
3674 M_MOV(argintregs[4], argintregs[5]);
3675 M_MOV(argintregs[3], argintregs[4]);
3676 M_MOV(argintregs[2], argintregs[3]);
3677 M_MOV(argintregs[1], argintregs[2]);
3678 M_MOV(argintregs[0], argintregs[1]);
3681 /* put env into first argument register */
3682 M_ALD(argintregs[0], REG_PV, -4 * 4);
3684 M_ALD(REG_PV, REG_PV, -1 * 4); /* load adress of native method */
3687 disp = -(s4) (mcodeptr - cs) * 4;
3689 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3691 /* remove stackframe if there is one */
3692 if (stackframesize) {
3693 M_LDA(REG_SP, REG_SP, stackframesize * 8);
3696 /* 20 instructions */
3699 M_LDA(REG_SP, REG_SP, -10 * 8);
3700 M_DST(REG_FRESULT, REG_SP, 48+0);
3701 M_IST(REG_RESULT, REG_SP, 48+8);
3702 M_AST(REG_ITMP3, REG_SP, 48+12);
3703 M_IST(REG_RESULT2, REG_SP, 48+16);
3705 /* keep this order */
3706 switch (m->returntype) {
3709 M_MOV(REG_RESULT, argintregs[2]);
3710 M_CLR(argintregs[1]);
3714 M_MOV(REG_RESULT2, argintregs[2]);
3715 M_MOV(REG_RESULT, argintregs[1]);
3718 M_ALD(argintregs[0], REG_PV, -6 * 4);
3720 M_FLTMOVE(REG_FRESULT, argfltregs[0]);
3721 M_FLTMOVE(REG_FRESULT, argfltregs[1]);
3722 M_ALD(REG_ITMP2, REG_PV, -7 * 4);/* builtin_displaymethodstop */
3725 M_DLD(REG_FRESULT, REG_SP, 48+0);
3726 M_ILD(REG_RESULT, REG_SP, 48+8);
3727 M_ALD(REG_ITMP3, REG_SP, 48+12);
3728 M_ILD(REG_RESULT2, REG_SP, 48+16);
3729 M_LDA(REG_SP, REG_SP, 10 * 8);
3733 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3734 if (IS_FLT_DBL_TYPE(m->returntype))
3735 if (IS_2_WORD_TYPE(m->returntype))
3736 M_DST(REG_FRESULT, REG_SP, 56);
3738 M_FST(REG_FRESULT, REG_SP, 56);
3740 M_IST(REG_RESULT, REG_SP, 56);
3741 if (IS_2_WORD_TYPE(m->returntype))
3742 M_IST(REG_RESULT2, REG_SP, 60);
3745 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* builtin_get_exceptionptrptr */
3748 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3750 M_LDA(REG_PV, REG_ITMP1, disp);
3751 M_MOV(REG_RESULT, REG_ITMP2);
3753 if (IS_FLT_DBL_TYPE(m->returntype))
3754 if (IS_2_WORD_TYPE(m->returntype))
3755 M_DLD(REG_FRESULT, REG_SP, 56);
3757 M_FLD(REG_FRESULT, REG_SP, 56);
3759 M_ILD(REG_RESULT, REG_SP, 56);
3760 if (IS_2_WORD_TYPE(m->returntype))
3761 M_ILD(REG_RESULT2, REG_SP, 60);
3764 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* get address of exceptionptr */
3766 M_ALD(REG_ITMP1, REG_ITMP2, 0); /* load exception into reg. itmp1 */
3768 M_BNE(4); /* if no exception then return */
3770 M_ALD(REG_ITMP1, REG_SP, 64 + 8); /* load return address */
3772 M_LDA(REG_SP, REG_SP, 64); /* remove stackframe */
3777 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
3779 M_ALD(REG_ITMP3, REG_SP, 64 + 8); /* load return address */
3781 M_LDA(REG_SP, REG_SP, 64); /* remove stackframe */
3783 M_LDA(REG_ITMP2, REG_ITMP1, -4); /* move fault address into reg. itmp2 */
3785 M_ALD(REG_ITMP3, REG_PV, -3 * 4); /* load asm exception handler address */
3790 dolog_plain("stubsize: %d (for %d params)\n", (int) (mcodeptr - (s4 *) s), m->paramcount);
3793 asm_cacheflush((void *) s, (char *) mcodeptr - (char *) s);
3796 count_nstub_len += NATIVESTUBSIZE * 4;
3799 return (u1*) (s + NATIVESTUBOFFSET);
3802 /* function: removenativestub **************************************************
3804 removes a previously created native-stub from memory
3806 *******************************************************************************/
3808 void removenativestub(u1 *stub)
3810 CFREE ((s4*) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 4);
3815 * These are local overrides for various environment variables in Emacs.
3816 * Please do not remove this and leave it at the end of the file, where
3817 * Emacs will automagically detect them.
3818 * ---------------------------------------------------------------------
3821 * indent-tabs-mode: t