1 /* src/vm/jit/mips/codegen.c - machine code generator for MIPS
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
30 Changes: Christian Thalinger
32 Contains the codegenerator for an MIPS (R4000 or higher) processor.
33 This module generates MIPS machine code for a sequence of
34 intermediate code commands (ICMDs).
36 $Id: codegen.c 2478 2005-05-13 14:19:50Z twisti $
47 #include "cacao/cacao.h"
48 #include "native/native.h"
49 #include "vm/builtin.h"
50 #include "vm/stringlocal.h"
51 #include "vm/jit/asmpart.h"
52 #include "vm/jit/jit.h"
54 #include "vm/jit/lsra.h"
57 #include "vm/jit/patcher.h"
58 #include "vm/jit/reg.h"
59 #include "vm/jit/mips/codegen.h"
60 #include "vm/jit/mips/arch.h"
61 #include "vm/jit/mips/types.h"
64 /* *****************************************************************************
66 Datatypes and Register Allocations:
67 -----------------------------------
69 On 64-bit-machines (like the MIPS) all operands are stored in the
70 registers in a 64-bit form, even when the correspondig JavaVM operands
71 only need 32 bits. This is done by a canonical representation:
73 32-bit integers are allways stored as sign-extended 64-bit values (this
74 approach is directly supported by the MIPS architecture and is very easy
77 32-bit-floats are stored in a 64-bit double precision register by simply
78 expanding the exponent and mantissa with zeroes. (also supported by the
84 The calling conventions and the layout of the stack is explained in detail
85 in the documention file: calling.doc
87 *******************************************************************************/
90 /* register descripton - array ************************************************/
92 /* #define REG_RES 0 reserved register for OS or code generator */
93 /* #define REG_RET 1 return value register */
94 /* #define REG_EXC 2 exception value register (only old jit) */
95 /* #define REG_SAV 3 (callee) saved register */
96 /* #define REG_TMP 4 scratch temporary register (caller saved) */
97 /* #define REG_ARG 5 argument register (caller saved) */
99 /* #define REG_END -1 last entry in tables */
101 static int nregdescint[] = {
102 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
103 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
104 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
105 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
108 /* for use of reserved registers, see comment above */
110 static int nregdescfloat[] = {
111 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
112 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
113 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
114 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
117 /* for use of reserved registers, see comment above */
120 /* Include independent code generation stuff -- include after register */
121 /* descriptions to avoid extern definitions. */
123 #include "vm/jit/codegen.inc"
124 #include "vm/jit/reg.inc"
126 #include "vm/jit/lsra.inc"
130 /* NullPointerException handlers and exception handling initialisation */
132 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
133 void thread_restartcriticalsection(ucontext_t *uc)
136 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[CTX_EPC])) != NULL)
137 uc->uc_mcontext.gregs[CTX_EPC] = (u8) critical;
141 /* NullPointerException signal handler for hardware null pointer check */
143 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
148 java_objectheader *xptr;
150 struct ucontext *_uc = (struct ucontext *) _p;
151 mcontext_t *sigctx = &_uc->uc_mcontext;
152 struct sigaction act;
154 instr = *((s4 *) (sigctx->gregs[CTX_EPC]));
155 faultaddr = sigctx->gregs[(instr >> 21) & 0x1f];
157 if (faultaddr == 0) {
158 /* Reset signal handler - necessary for SysV, does no harm for BSD */
160 act.sa_sigaction = catch_NullPointerException;
161 act.sa_flags = SA_SIGINFO;
162 sigaction(sig, &act, NULL);
165 sigaddset(&nsig, sig);
166 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
168 xptr = new_nullpointerexception();
170 sigctx->gregs[REG_ITMP1_XPTR] = (u8) xptr;
171 sigctx->gregs[REG_ITMP2_XPC] = sigctx->gregs[CTX_EPC];
172 sigctx->gregs[CTX_EPC] = (u8) asm_handle_exception;
175 faultaddr += (long) ((instr << 16) >> 16);
176 fprintf(stderr, "faulting address: 0x%lx at 0x%lx\n", (long) faultaddr, (long) sigctx->gregs[CTX_EPC]);
177 panic("Stack overflow");
184 void init_exceptions(void)
186 struct sigaction act;
188 /* The Boehm GC initialization blocks the SIGSEGV signal. So we do a
189 dummy allocation here to ensure that the GC is initialized.
191 heap_allocate(1, 0, NULL);
193 /* install signal handlers we need to convert to exceptions */
195 sigemptyset(&act.sa_mask);
198 act.sa_sigaction = catch_NullPointerException;
199 act.sa_flags = SA_SIGINFO;
202 sigaction(SIGSEGV, &act, NULL);
206 sigaction(SIGBUS, &act, NULL);
210 /* Turn off flush-to-zero */
213 n.fc_word = get_fpc_csr();
214 n.fc_struct.flush = 0;
215 set_fpc_csr(n.fc_word);
220 /* function gen_mcode **********************************************************
222 generates machine code
224 *******************************************************************************/
226 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
228 s4 len, s1, s2, s3, d;
242 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
244 /* space to save used callee saved registers */
246 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
247 savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
249 parentargs_base = rd->maxmemuse + savedregs_num;
251 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
253 if (checksync && (m->flags & ACC_SYNCHRONIZED))
258 /* adjust frame size for 16 byte alignment */
260 if (parentargs_base & 1)
263 /* create method header */
266 (void) dseg_addaddress(cd, m); /* Filler */
268 (void) dseg_addaddress(cd, m); /* MethodPointer */
269 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
271 #if defined(USE_THREADS)
273 /* IsSync contains the offset relative to the stack pointer for the
274 argument of monitor_exit used in the exception handler. Since the
275 offset could be zero and give a wrong meaning of the flag it is
279 if (checksync && (m->flags & ACC_SYNCHRONIZED))
280 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8); /* IsSync */
285 (void) dseg_adds4(cd, 0); /* IsSync */
287 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
288 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse);/* IntSave */
289 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse);/* FltSave */
290 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
292 /* create exception table */
294 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
295 dseg_addtarget(cd, ex->start);
296 dseg_addtarget(cd, ex->end);
297 dseg_addtarget(cd, ex->handler);
298 (void) dseg_addaddress(cd, ex->catchtype.cls);
301 /* initialize mcode variables */
303 mcodeptr = (s4 *) cd->mcodebase;
304 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
305 MCODECHECK(128 + m->paramcount);
307 /* create stack frame (if necessary) */
309 if (parentargs_base) {
310 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
313 /* save return address and used callee saved registers */
316 if (!m->isleafmethod) {
317 p--; M_LST(REG_RA, REG_SP, p * 8);
319 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
320 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
322 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
323 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
326 /* take arguments out of register or stack frame */
328 for (p = 0, l = 0; p < m->paramcount; p++) {
329 t = m->paramtypes[p];
330 var = &(rd->locals[l][t]);
332 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
336 if (IS_INT_LNG_TYPE(t)) { /* integer args */
337 if (p < INT_ARG_CNT) { /* register arguments */
338 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
339 M_INTMOVE(rd->argintregs[p], var->regoff);
340 } else { /* reg arg -> spilled */
341 M_LST(rd->argintregs[p], REG_SP, 8 * var->regoff);
344 } else { /* stack arguments */
345 pa = p - INT_ARG_CNT;
346 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
347 M_LLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
349 } else { /* stack arg -> spilled */
350 /* M_LLD(REG_ITMP1, REG_SP, 8 * (parentargs_base + pa)); */
351 /* M_LST(REG_ITMP1, REG_SP, 8 * var->regoff); */
352 var->regoff = parentargs_base + pa;
356 } else { /* floating args */
357 if (p < FLT_ARG_CNT) { /* register arguments */
358 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
359 M_TFLTMOVE(var->type, rd->argfltregs[p], var->regoff);
361 } else { /* reg arg -> spilled */
362 M_DST(rd->argfltregs[p], REG_SP, var->regoff * 8);
365 } else { /* stack arguments */
366 pa = p - FLT_ARG_CNT;
367 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
368 M_DLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
370 } else { /* stack-arg -> spilled */
371 /* M_DLD(REG_FTMP1, REG_SP, 8 * (parentargs_base + pa)); */
372 /* M_DST(REG_FTMP1, REG_SP, 8 * var->regoff); */
373 var->regoff = parentargs_base + pa;
379 /* call monitorenter function */
381 #if defined(USE_THREADS)
382 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
385 /* stack offset for monitor argument */
390 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
392 for (p = 0; p < INT_ARG_CNT; p++)
393 M_LST(rd->argintregs[p], REG_SP, p * 8);
395 for (p = 0; p < FLT_ARG_CNT; p++)
396 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
398 if (m->isleafmethod) {
399 for (p = 0; p < INT_TMP_CNT; p++)
400 M_LST(rd->tmpintregs[p], REG_SP, (INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
402 for (p = 0; p < FLT_TMP_CNT; p++)
403 M_DST(rd->tmpfltregs[p], REG_SP, (INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
406 s1 += INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT;
409 /* decide which monitor enter function to call */
411 if (m->flags & ACC_STATIC) {
412 p = dseg_addaddress(cd, m->class);
413 M_ALD(REG_ITMP1, REG_PV, p);
414 M_AST(REG_ITMP1, REG_SP, s1 * 8);
415 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
416 M_ALD(REG_ITMP3, REG_PV, p);
417 M_JSR(REG_RA, REG_ITMP3);
418 M_INTMOVE(REG_ITMP1, rd->argintregs[0]); /* branch delay */
419 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
420 M_LDA(REG_PV, REG_RA, disp);
423 M_BEQZ(rd->argintregs[0], 0);
424 codegen_addxnullrefs(cd, mcodeptr);
425 p = dseg_addaddress(cd, BUILTIN_monitorenter);
426 M_ALD(REG_ITMP3, REG_PV, p);
427 M_JSR(REG_RA, REG_ITMP3);
428 M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* br delay */
429 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
430 M_LDA(REG_PV, REG_RA, disp);
434 for (p = 0; p < INT_ARG_CNT; p++)
435 M_LLD(rd->argintregs[p], REG_SP, p * 8);
437 for (p = 0; p < FLT_ARG_CNT; p++)
438 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
441 if (m->isleafmethod) {
442 for (p = 0; p < INT_TMP_CNT; p++)
443 M_LLD(rd->tmpintregs[p], REG_SP, (INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
445 for (p = 0; p < FLT_TMP_CNT; p++)
446 M_DLD(rd->tmpfltregs[p], REG_SP, (INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
449 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
454 /* copy argument registers to stack and call trace function */
457 M_LDA(REG_SP, REG_SP, -(2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
458 M_LST(REG_RA, REG_SP, 1 * 8);
460 /* save integer argument registers */
462 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++)
463 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
465 /* save and copy float arguments into integer registers */
467 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
468 t = m->paramtypes[p];
470 if (IS_FLT_DBL_TYPE(t)) {
471 if (IS_2_WORD_TYPE(t)) {
472 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
473 M_LLD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
476 M_FST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
477 M_ILD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
481 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
485 /* save temporary registers for leaf methods */
487 if (m->isleafmethod) {
488 for (p = 0; p < INT_TMP_CNT; p++)
489 M_LST(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
491 for (p = 0; p < FLT_TMP_CNT; p++)
492 M_DST(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
495 p = dseg_addaddress(cd, m);
496 M_ALD(REG_ITMP1, REG_PV, p);
497 M_LST(REG_ITMP1, REG_SP, 0);
498 p = dseg_addaddress(cd, (void *) builtin_trace_args);
499 M_ALD(REG_ITMP3, REG_PV, p);
500 M_JSR(REG_RA, REG_ITMP3);
503 M_LLD(REG_RA, REG_SP, 1 * 8);
505 /* restore integer argument registers */
507 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++)
508 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
510 /* restore float argument registers */
512 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
513 t = m->paramtypes[p];
515 if (IS_FLT_DBL_TYPE(t)) {
516 if (IS_2_WORD_TYPE(t)) {
517 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
520 M_FLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
524 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
528 /* restore temporary registers for leaf methods */
530 if (m->isleafmethod) {
531 for (p = 0; p < INT_TMP_CNT; p++)
532 M_LLD(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
534 for (p = 0; p < FLT_TMP_CNT; p++)
535 M_DLD(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
538 M_LDA(REG_SP, REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
543 /* end of header generation */
545 /* walk through all basic blocks */
547 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
549 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
551 if (bptr->flags >= BBREACHED) {
553 /* branch resolving */
556 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
557 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
563 /* copy interface registers to their destination */
570 while (src != NULL) {
572 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
573 /* d = reg_of_var(m, src, REG_ITMP1); */
574 if (!(src->flags & INMEMORY))
578 M_INTMOVE(REG_ITMP1, d);
579 store_reg_to_var_int(src, d);
585 while (src != NULL) {
587 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
588 d = reg_of_var(rd, src, REG_ITMP1);
589 M_INTMOVE(REG_ITMP1, d);
590 store_reg_to_var_int(src, d);
593 d = reg_of_var(rd, src, REG_IFTMP);
594 if ((src->varkind != STACKVAR)) {
596 if (IS_FLT_DBL_TYPE(s2)) {
597 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
598 s1 = rd->interfaces[len][s2].regoff;
599 M_TFLTMOVE(s2, s1, d);
602 M_DLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
604 store_reg_to_var_flt(src, d);
607 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
608 s1 = rd->interfaces[len][s2].regoff;
612 M_LLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
614 store_reg_to_var_int(src, d);
623 /* walk through all instructions */
628 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
630 MCODECHECK(64); /* an instruction usually needs < 64 words */
634 case ICMD_NOP: /* ... ==> ... */
637 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
639 var_to_reg_int(s1, src, REG_ITMP1);
641 codegen_addxnullrefs(cd, mcodeptr);
645 /* constant operations ************************************************/
647 case ICMD_ICONST: /* ... ==> ..., constant */
648 /* op1 = 0, val.i = constant */
650 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
651 ICONST(d, iptr->val.i);
652 store_reg_to_var_int(iptr->dst, d);
655 case ICMD_LCONST: /* ... ==> ..., constant */
656 /* op1 = 0, val.l = constant */
658 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
659 LCONST(d, iptr->val.l);
660 store_reg_to_var_int(iptr->dst, d);
663 case ICMD_FCONST: /* ... ==> ..., constant */
664 /* op1 = 0, val.f = constant */
666 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
667 a = dseg_addfloat(cd, iptr->val.f);
669 store_reg_to_var_flt(iptr->dst, d);
672 case ICMD_DCONST: /* ... ==> ..., constant */
673 /* op1 = 0, val.d = constant */
675 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
676 a = dseg_adddouble(cd, iptr->val.d);
678 store_reg_to_var_flt (iptr->dst, d);
681 case ICMD_ACONST: /* ... ==> ..., constant */
682 /* op1 = 0, val.a = constant */
684 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
686 a = dseg_addaddress(cd, iptr->val.a);
689 M_INTMOVE(REG_ZERO, d);
691 store_reg_to_var_int(iptr->dst, d);
695 /* load/store operations **********************************************/
697 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
698 case ICMD_LLOAD: /* op1 = local variable */
701 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
702 if ((iptr->dst->varkind == LOCALVAR) &&
703 (iptr->dst->varnum == iptr->op1))
705 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
706 if (var->flags & INMEMORY) {
707 M_LLD(d, REG_SP, 8 * var->regoff);
709 M_INTMOVE(var->regoff,d);
711 store_reg_to_var_int(iptr->dst, d);
714 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
715 case ICMD_DLOAD: /* op1 = local variable */
717 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
718 if ((iptr->dst->varkind == LOCALVAR) &&
719 (iptr->dst->varnum == iptr->op1))
721 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
723 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
724 if (var->flags & INMEMORY) {
725 M_CCFLD(var->type, t2, d, REG_SP, 8 * var->regoff);
727 M_CCFLTMOVE(var->type, t2, var->regoff, d);
730 store_reg_to_var_flt(iptr->dst, d);
734 case ICMD_ISTORE: /* ..., value ==> ... */
735 case ICMD_LSTORE: /* op1 = local variable */
738 if ((src->varkind == LOCALVAR) &&
739 (src->varnum == iptr->op1))
741 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
742 if (var->flags & INMEMORY) {
743 var_to_reg_int(s1, src, REG_ITMP1);
744 M_LST(s1, REG_SP, 8 * var->regoff);
747 var_to_reg_int(s1, src, var->regoff);
748 M_INTMOVE(s1, var->regoff);
752 case ICMD_FSTORE: /* ..., value ==> ... */
753 case ICMD_DSTORE: /* op1 = local variable */
755 if ((src->varkind == LOCALVAR) &&
756 (src->varnum == iptr->op1))
758 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
760 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
761 if (var->flags & INMEMORY) {
762 var_to_reg_flt(s1, src, REG_FTMP1);
763 M_CCFST(t1, var->type, s1, REG_SP, 8 * var->regoff);
766 var_to_reg_flt(s1, src, var->regoff);
767 M_CCFLTMOVE(t1, var->type, s1, var->regoff);
773 /* pop/dup/swap operations ********************************************/
775 /* attention: double and longs are only one entry in CACAO ICMDs */
777 case ICMD_POP: /* ..., value ==> ... */
778 case ICMD_POP2: /* ..., value, value ==> ... */
781 case ICMD_DUP: /* ..., a ==> ..., a, a */
782 M_COPY(src, iptr->dst);
785 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
787 M_COPY(src, iptr->dst);
788 M_COPY(src->prev, iptr->dst->prev);
789 M_COPY(iptr->dst, iptr->dst->prev->prev);
792 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
794 M_COPY(src, iptr->dst);
795 M_COPY(src->prev, iptr->dst->prev);
796 M_COPY(src->prev->prev, iptr->dst->prev->prev);
797 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
800 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
802 M_COPY(src, iptr->dst);
803 M_COPY(src->prev, iptr->dst->prev);
806 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
808 M_COPY(src, iptr->dst);
809 M_COPY(src->prev, iptr->dst->prev);
810 M_COPY(src->prev->prev, iptr->dst->prev->prev);
811 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
812 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
815 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
817 M_COPY(src, iptr->dst);
818 M_COPY(src->prev, iptr->dst->prev);
819 M_COPY(src->prev->prev, iptr->dst->prev->prev);
820 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
821 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
822 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
825 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
827 M_COPY(src, iptr->dst->prev);
828 M_COPY(src->prev, iptr->dst);
832 /* integer operations *************************************************/
834 case ICMD_INEG: /* ..., value ==> ..., - value */
836 var_to_reg_int(s1, src, REG_ITMP1);
837 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
838 M_ISUB(REG_ZERO, s1, d);
839 store_reg_to_var_int(iptr->dst, d);
842 case ICMD_LNEG: /* ..., value ==> ..., - value */
844 var_to_reg_int(s1, src, REG_ITMP1);
845 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
846 M_LSUB(REG_ZERO, s1, d);
847 store_reg_to_var_int(iptr->dst, d);
850 case ICMD_I2L: /* ..., value ==> ..., value */
852 var_to_reg_int(s1, src, REG_ITMP1);
853 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
855 store_reg_to_var_int(iptr->dst, d);
858 case ICMD_L2I: /* ..., value ==> ..., value */
860 var_to_reg_int(s1, src, REG_ITMP1);
861 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
862 M_ISLL_IMM(s1, 0, d );
863 store_reg_to_var_int(iptr->dst, d);
866 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
868 var_to_reg_int(s1, src, REG_ITMP1);
869 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
870 M_LSLL_IMM(s1, 56, d);
871 M_LSRA_IMM( d, 56, d);
872 store_reg_to_var_int(iptr->dst, d);
875 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
877 var_to_reg_int(s1, src, REG_ITMP1);
878 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
880 store_reg_to_var_int(iptr->dst, d);
883 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
885 var_to_reg_int(s1, src, REG_ITMP1);
886 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
887 M_LSLL_IMM(s1, 48, d);
888 M_LSRA_IMM( d, 48, d);
889 store_reg_to_var_int(iptr->dst, d);
893 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
895 var_to_reg_int(s1, src->prev, REG_ITMP1);
896 var_to_reg_int(s2, src, REG_ITMP2);
897 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
899 store_reg_to_var_int(iptr->dst, d);
902 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
903 /* val.i = constant */
905 var_to_reg_int(s1, src, REG_ITMP1);
906 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
907 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
908 M_IADD_IMM(s1, iptr->val.i, d);
911 ICONST(REG_ITMP2, iptr->val.i);
912 M_IADD(s1, REG_ITMP2, d);
914 store_reg_to_var_int(iptr->dst, d);
917 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
919 var_to_reg_int(s1, src->prev, REG_ITMP1);
920 var_to_reg_int(s2, src, REG_ITMP2);
921 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
923 store_reg_to_var_int(iptr->dst, d);
926 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
927 /* val.l = constant */
929 var_to_reg_int(s1, src, REG_ITMP1);
930 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
931 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
932 M_LADD_IMM(s1, iptr->val.l, d);
935 LCONST(REG_ITMP2, iptr->val.l);
936 M_LADD(s1, REG_ITMP2, d);
938 store_reg_to_var_int(iptr->dst, d);
941 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
943 var_to_reg_int(s1, src->prev, REG_ITMP1);
944 var_to_reg_int(s2, src, REG_ITMP2);
945 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
947 store_reg_to_var_int(iptr->dst, d);
950 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
951 /* val.i = constant */
953 var_to_reg_int(s1, src, REG_ITMP1);
954 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
955 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
956 M_IADD_IMM(s1, -iptr->val.i, d);
959 ICONST(REG_ITMP2, iptr->val.i);
960 M_ISUB(s1, REG_ITMP2, d);
962 store_reg_to_var_int(iptr->dst, d);
965 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
967 var_to_reg_int(s1, src->prev, REG_ITMP1);
968 var_to_reg_int(s2, src, REG_ITMP2);
969 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
971 store_reg_to_var_int(iptr->dst, d);
974 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
975 /* val.l = constant */
977 var_to_reg_int(s1, src, REG_ITMP1);
978 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
979 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
980 M_LADD_IMM(s1, -iptr->val.l, d);
983 LCONST(REG_ITMP2, iptr->val.l);
984 M_LSUB(s1, REG_ITMP2, d);
986 store_reg_to_var_int(iptr->dst, d);
989 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
991 var_to_reg_int(s1, src->prev, REG_ITMP1);
992 var_to_reg_int(s2, src, REG_ITMP2);
993 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
998 store_reg_to_var_int(iptr->dst, d);
1001 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1002 /* val.i = constant */
1004 var_to_reg_int(s1, src, REG_ITMP1);
1005 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1006 ICONST(REG_ITMP2, iptr->val.i);
1007 M_IMUL(s1, REG_ITMP2);
1011 store_reg_to_var_int(iptr->dst, d);
1014 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1016 var_to_reg_int(s1, src->prev, REG_ITMP1);
1017 var_to_reg_int(s2, src, REG_ITMP2);
1018 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1023 store_reg_to_var_int(iptr->dst, d);
1026 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1027 /* val.l = constant */
1029 var_to_reg_int(s1, src, REG_ITMP1);
1030 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1031 LCONST(REG_ITMP2, iptr->val.l);
1032 M_LMUL(s1, REG_ITMP2);
1036 store_reg_to_var_int(iptr->dst, d);
1039 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1041 var_to_reg_int(s1, src->prev, REG_ITMP1);
1042 var_to_reg_int(s2, src, REG_ITMP2);
1043 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1048 store_reg_to_var_int(iptr->dst, d);
1051 case ICMD_IDIVCONST: /* ..., value ==> ..., value / constant */
1052 /* val.i = constant */
1054 var_to_reg_int(s1, src, REG_ITMP1);
1055 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1056 ICONST(REG_ITMP2, iptr->val.i);
1057 M_IDIV(s1, REG_ITMP2);
1061 store_reg_to_var_int(iptr->dst, d);
1064 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1066 var_to_reg_int(s1, src->prev, REG_ITMP1);
1067 var_to_reg_int(s2, src, REG_ITMP2);
1068 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1073 store_reg_to_var_int(iptr->dst, d);
1076 case ICMD_LDIVCONST: /* ..., value ==> ..., value / constant */
1077 /* val.l = constant */
1079 var_to_reg_int(s1, src, REG_ITMP1);
1080 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1081 LCONST(REG_ITMP2, iptr->val.l);
1082 M_LDIV(s1, REG_ITMP2);
1086 store_reg_to_var_int(iptr->dst, d);
1089 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1091 var_to_reg_int(s1, src->prev, REG_ITMP1);
1092 var_to_reg_int(s2, src, REG_ITMP2);
1093 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1098 store_reg_to_var_int(iptr->dst, d);
1101 case ICMD_IREMCONST: /* ..., value ==> ..., value % constant */
1102 /* val.i = constant */
1104 var_to_reg_int(s1, src, REG_ITMP1);
1105 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1106 ICONST(REG_ITMP2, iptr->val.i);
1107 M_IDIV(s1, REG_ITMP2);
1111 store_reg_to_var_int(iptr->dst, d);
1114 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1116 var_to_reg_int(s1, src->prev, REG_ITMP1);
1117 var_to_reg_int(s2, src, REG_ITMP2);
1118 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1123 store_reg_to_var_int(iptr->dst, d);
1126 case ICMD_LREMCONST: /* ..., value ==> ..., value % constant */
1127 /* val.l = constant */
1129 var_to_reg_int(s1, src, REG_ITMP1);
1130 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1131 LCONST(REG_ITMP2, iptr->val.l);
1132 M_LDIV(s1, REG_ITMP2);
1136 store_reg_to_var_int(iptr->dst, d);
1139 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1140 case ICMD_LDIVPOW2: /* val.i = constant */
1142 var_to_reg_int(s1, src, REG_ITMP1);
1143 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1144 M_LSRA_IMM(s1, 63, REG_ITMP2);
1145 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1146 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1147 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
1148 store_reg_to_var_int(iptr->dst, d);
1151 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1153 var_to_reg_int(s1, src->prev, REG_ITMP1);
1154 var_to_reg_int(s2, src, REG_ITMP2);
1155 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1157 store_reg_to_var_int(iptr->dst, d);
1160 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1161 /* val.i = constant */
1163 var_to_reg_int(s1, src, REG_ITMP1);
1164 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1165 M_ISLL_IMM(s1, iptr->val.i, d);
1166 store_reg_to_var_int(iptr->dst, d);
1169 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1171 var_to_reg_int(s1, src->prev, REG_ITMP1);
1172 var_to_reg_int(s2, src, REG_ITMP2);
1173 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1175 store_reg_to_var_int(iptr->dst, d);
1178 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1179 /* val.i = constant */
1181 var_to_reg_int(s1, src, REG_ITMP1);
1182 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1183 M_ISRA_IMM(s1, iptr->val.i, d);
1184 store_reg_to_var_int(iptr->dst, d);
1187 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1189 var_to_reg_int(s1, src->prev, REG_ITMP1);
1190 var_to_reg_int(s2, src, REG_ITMP2);
1191 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1193 store_reg_to_var_int(iptr->dst, d);
1196 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1197 /* val.i = constant */
1199 var_to_reg_int(s1, src, REG_ITMP1);
1200 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1201 M_ISRL_IMM(s1, iptr->val.i, d);
1202 store_reg_to_var_int(iptr->dst, d);
1205 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1207 var_to_reg_int(s1, src->prev, REG_ITMP1);
1208 var_to_reg_int(s2, src, REG_ITMP2);
1209 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1211 store_reg_to_var_int(iptr->dst, d);
1214 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1215 /* val.i = constant */
1217 var_to_reg_int(s1, src, REG_ITMP1);
1218 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1219 M_LSLL_IMM(s1, iptr->val.i, d);
1220 store_reg_to_var_int(iptr->dst, d);
1223 case ICMD_LSHR: /* ..., 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(rd, iptr->dst, REG_ITMP3);
1229 store_reg_to_var_int(iptr->dst, d);
1232 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1233 /* val.i = constant */
1235 var_to_reg_int(s1, src, REG_ITMP1);
1236 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1237 M_LSRA_IMM(s1, iptr->val.i, d);
1238 store_reg_to_var_int(iptr->dst, d);
1241 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1243 var_to_reg_int(s1, src->prev, REG_ITMP1);
1244 var_to_reg_int(s2, src, REG_ITMP2);
1245 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1247 store_reg_to_var_int(iptr->dst, d);
1250 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1251 /* val.i = constant */
1253 var_to_reg_int(s1, src, REG_ITMP1);
1254 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1255 M_LSRL_IMM(s1, iptr->val.i, d);
1256 store_reg_to_var_int(iptr->dst, d);
1259 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1262 var_to_reg_int(s1, src->prev, REG_ITMP1);
1263 var_to_reg_int(s2, src, REG_ITMP2);
1264 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1266 store_reg_to_var_int(iptr->dst, d);
1269 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1270 /* val.i = constant */
1272 var_to_reg_int(s1, src, REG_ITMP1);
1273 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1274 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1275 M_AND_IMM(s1, iptr->val.i, d);
1278 ICONST(REG_ITMP2, iptr->val.i);
1279 M_AND(s1, REG_ITMP2, d);
1281 store_reg_to_var_int(iptr->dst, d);
1284 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1285 /* val.i = constant */
1287 var_to_reg_int(s1, src, REG_ITMP1);
1288 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1290 M_MOV(s1, REG_ITMP1);
1293 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1294 M_AND_IMM(s1, iptr->val.i, d);
1297 M_ISUB(REG_ZERO, s1, d);
1298 M_AND_IMM(d, iptr->val.i, d);
1301 ICONST(REG_ITMP2, iptr->val.i);
1302 M_AND(s1, REG_ITMP2, d);
1305 M_ISUB(REG_ZERO, s1, d);
1306 M_AND(d, REG_ITMP2, d);
1308 M_ISUB(REG_ZERO, d, d);
1309 store_reg_to_var_int(iptr->dst, d);
1312 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1313 /* val.l = constant */
1315 var_to_reg_int(s1, src, REG_ITMP1);
1316 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1317 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1318 M_AND_IMM(s1, iptr->val.l, d);
1321 LCONST(REG_ITMP2, iptr->val.l);
1322 M_AND(s1, REG_ITMP2, d);
1324 store_reg_to_var_int(iptr->dst, d);
1327 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1328 /* val.l = constant */
1330 var_to_reg_int(s1, src, REG_ITMP1);
1331 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1333 M_MOV(s1, REG_ITMP1);
1336 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1337 M_AND_IMM(s1, iptr->val.l, d);
1340 M_LSUB(REG_ZERO, s1, d);
1341 M_AND_IMM(d, iptr->val.l, d);
1344 LCONST(REG_ITMP2, iptr->val.l);
1345 M_AND(s1, REG_ITMP2, d);
1348 M_LSUB(REG_ZERO, s1, d);
1349 M_AND(d, REG_ITMP2, d);
1351 M_LSUB(REG_ZERO, d, d);
1352 store_reg_to_var_int(iptr->dst, d);
1355 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1358 var_to_reg_int(s1, src->prev, REG_ITMP1);
1359 var_to_reg_int(s2, src, REG_ITMP2);
1360 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1362 store_reg_to_var_int(iptr->dst, d);
1365 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1366 /* val.i = constant */
1368 var_to_reg_int(s1, src, REG_ITMP1);
1369 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1370 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1371 M_OR_IMM(s1, iptr->val.i, d);
1374 ICONST(REG_ITMP2, iptr->val.i);
1375 M_OR(s1, REG_ITMP2, d);
1377 store_reg_to_var_int(iptr->dst, d);
1380 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1381 /* val.l = constant */
1383 var_to_reg_int(s1, src, REG_ITMP1);
1384 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1385 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1386 M_OR_IMM(s1, iptr->val.l, d);
1389 LCONST(REG_ITMP2, iptr->val.l);
1390 M_OR(s1, REG_ITMP2, d);
1392 store_reg_to_var_int(iptr->dst, d);
1395 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1398 var_to_reg_int(s1, src->prev, REG_ITMP1);
1399 var_to_reg_int(s2, src, REG_ITMP2);
1400 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1402 store_reg_to_var_int(iptr->dst, d);
1405 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1406 /* val.i = constant */
1408 var_to_reg_int(s1, src, REG_ITMP1);
1409 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1410 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1411 M_XOR_IMM(s1, iptr->val.i, d);
1414 ICONST(REG_ITMP2, iptr->val.i);
1415 M_XOR(s1, REG_ITMP2, d);
1417 store_reg_to_var_int(iptr->dst, d);
1420 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1421 /* val.l = constant */
1423 var_to_reg_int(s1, src, REG_ITMP1);
1424 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1425 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1426 M_XOR_IMM(s1, iptr->val.l, d);
1429 LCONST(REG_ITMP2, iptr->val.l);
1430 M_XOR(s1, REG_ITMP2, d);
1432 store_reg_to_var_int(iptr->dst, d);
1436 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1438 var_to_reg_int(s1, src->prev, REG_ITMP1);
1439 var_to_reg_int(s2, src, REG_ITMP2);
1440 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1441 M_CMPLT(s1, s2, REG_ITMP3);
1442 M_CMPLT(s2, s1, REG_ITMP1);
1443 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1444 store_reg_to_var_int(iptr->dst, d);
1448 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1449 /* op1 = variable, val.i = constant */
1451 var = &(rd->locals[iptr->op1][TYPE_INT]);
1452 if (var->flags & INMEMORY) {
1454 M_LLD(s1, REG_SP, 8 * var->regoff);
1458 M_IADD_IMM(s1, iptr->val.i, s1);
1459 if (var->flags & INMEMORY)
1460 M_LST(s1, REG_SP, 8 * var->regoff);
1464 /* floating operations ************************************************/
1466 case ICMD_FNEG: /* ..., value ==> ..., - value */
1468 var_to_reg_flt(s1, src, REG_FTMP1);
1469 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1471 store_reg_to_var_flt(iptr->dst, d);
1474 case ICMD_DNEG: /* ..., value ==> ..., - value */
1476 var_to_reg_flt(s1, src, REG_FTMP1);
1477 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1479 store_reg_to_var_flt(iptr->dst, d);
1482 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1484 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1485 var_to_reg_flt(s2, src, REG_FTMP2);
1486 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1488 store_reg_to_var_flt(iptr->dst, d);
1491 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1493 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1494 var_to_reg_flt(s2, src, REG_FTMP2);
1495 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1497 store_reg_to_var_flt(iptr->dst, d);
1500 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1502 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1503 var_to_reg_flt(s2, src, REG_FTMP2);
1504 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1506 store_reg_to_var_flt(iptr->dst, d);
1509 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1511 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1512 var_to_reg_flt(s2, src, REG_FTMP2);
1513 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1515 store_reg_to_var_flt(iptr->dst, d);
1518 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1520 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1521 var_to_reg_flt(s2, src, REG_FTMP2);
1522 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1524 store_reg_to_var_flt(iptr->dst, d);
1527 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1529 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1530 var_to_reg_flt(s2, src, REG_FTMP2);
1531 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1533 store_reg_to_var_flt(iptr->dst, d);
1536 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1538 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1539 var_to_reg_flt(s2, src, REG_FTMP2);
1540 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1542 store_reg_to_var_flt(iptr->dst, d);
1545 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1547 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1548 var_to_reg_flt(s2, src, REG_FTMP2);
1549 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1551 store_reg_to_var_flt(iptr->dst, d);
1554 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1557 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1558 var_to_reg_flt(s2, src, REG_FTMP2);
1559 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1560 M_FDIV(s1,s2, REG_FTMP3);
1561 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1562 M_CVTLF(REG_FTMP3, REG_FTMP3);
1563 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1564 M_FSUB(s1, REG_FTMP3, d);
1565 store_reg_to_var_flt(iptr->dst, d);
1568 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1570 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1571 var_to_reg_flt(s2, src, REG_FTMP2);
1572 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1573 M_DDIV(s1,s2, REG_FTMP3);
1574 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1575 M_CVTLD(REG_FTMP3, REG_FTMP3);
1576 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1577 M_DSUB(s1, REG_FTMP3, d);
1578 store_reg_to_var_flt(iptr->dst, d);
1581 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1583 var_to_reg_int(s1, src, REG_ITMP1);
1584 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1587 store_reg_to_var_flt(iptr->dst, d);
1590 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1592 var_to_reg_int(s1, src, REG_ITMP1);
1593 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1596 store_reg_to_var_flt(iptr->dst, d);
1599 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1601 var_to_reg_flt(s1, src, REG_FTMP1);
1602 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1603 M_TRUNCFI(s1, REG_FTMP1);
1604 M_MOVDI(REG_FTMP1, d);
1606 store_reg_to_var_int(iptr->dst, d);
1609 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1611 var_to_reg_flt(s1, src, REG_FTMP1);
1612 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1613 M_TRUNCDI(s1, REG_FTMP1);
1614 M_MOVDI(REG_FTMP1, d);
1616 store_reg_to_var_int(iptr->dst, d);
1619 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1621 var_to_reg_flt(s1, src, REG_FTMP1);
1622 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1623 M_TRUNCFL(s1, REG_FTMP1);
1624 M_MOVDL(REG_FTMP1, d);
1626 store_reg_to_var_int(iptr->dst, d);
1629 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1631 var_to_reg_flt(s1, src, REG_FTMP1);
1632 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1633 M_TRUNCDL(s1, REG_FTMP1);
1634 M_MOVDL(REG_FTMP1, d);
1636 store_reg_to_var_int(iptr->dst, d);
1639 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1641 var_to_reg_flt(s1, src, REG_FTMP1);
1642 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1644 store_reg_to_var_flt(iptr->dst, d);
1647 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1649 var_to_reg_flt(s1, src, REG_FTMP1);
1650 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1652 store_reg_to_var_flt(iptr->dst, d);
1655 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl 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(rd, iptr->dst, REG_ITMP3);
1662 M_LADD_IMM(REG_ZERO, 1, d);
1666 M_LSUB_IMM(REG_ZERO, 1, d);
1667 M_CMOVT(REG_ZERO, d);
1668 store_reg_to_var_int(iptr->dst, d);
1671 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1673 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1674 var_to_reg_flt(s2, src, REG_FTMP2);
1675 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1678 M_LADD_IMM(REG_ZERO, 1, d);
1682 M_LSUB_IMM(REG_ZERO, 1, d);
1683 M_CMOVT(REG_ZERO, d);
1684 store_reg_to_var_int(iptr->dst, d);
1687 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1689 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1690 var_to_reg_flt(s2, src, REG_FTMP2);
1691 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1694 M_LSUB_IMM(REG_ZERO, 1, d);
1698 M_LADD_IMM(REG_ZERO, 1, d);
1699 M_CMOVT(REG_ZERO, d);
1700 store_reg_to_var_int(iptr->dst, d);
1703 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1705 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1706 var_to_reg_flt(s2, src, REG_FTMP2);
1707 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1710 M_LSUB_IMM(REG_ZERO, 1, d);
1714 M_LADD_IMM(REG_ZERO, 1, d);
1715 M_CMOVT(REG_ZERO, d);
1716 store_reg_to_var_int(iptr->dst, d);
1720 /* memory operations **************************************************/
1722 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1724 var_to_reg_int(s1, src, REG_ITMP1);
1725 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1726 gen_nullptr_check(s1);
1727 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1728 store_reg_to_var_int(iptr->dst, d);
1731 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1733 var_to_reg_int(s1, src->prev, REG_ITMP1);
1734 var_to_reg_int(s2, src, REG_ITMP2);
1735 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1736 if (iptr->op1 == 0) {
1737 gen_nullptr_check(s1);
1740 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1741 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1742 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1743 store_reg_to_var_int(iptr->dst, d);
1746 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1748 var_to_reg_int(s1, src->prev, REG_ITMP1);
1749 var_to_reg_int(s2, src, REG_ITMP2);
1750 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1751 if (iptr->op1 == 0) {
1752 gen_nullptr_check(s1);
1755 M_ASLL_IMM(s2, 2, REG_ITMP2);
1756 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1757 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1758 store_reg_to_var_int(iptr->dst, d);
1761 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1763 var_to_reg_int(s1, src->prev, REG_ITMP1);
1764 var_to_reg_int(s2, src, REG_ITMP2);
1765 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1766 if (iptr->op1 == 0) {
1767 gen_nullptr_check(s1);
1770 M_ASLL_IMM(s2, 3, REG_ITMP2);
1771 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1772 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1773 store_reg_to_var_int(iptr->dst, d);
1776 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1778 var_to_reg_int(s1, src->prev, REG_ITMP1);
1779 var_to_reg_int(s2, src, REG_ITMP2);
1780 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1781 if (iptr->op1 == 0) {
1782 gen_nullptr_check(s1);
1785 M_ASLL_IMM(s2, 2, REG_ITMP2);
1786 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1787 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1788 store_reg_to_var_flt(iptr->dst, d);
1791 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1793 var_to_reg_int(s1, src->prev, REG_ITMP1);
1794 var_to_reg_int(s2, src, REG_ITMP2);
1795 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1796 if (iptr->op1 == 0) {
1797 gen_nullptr_check(s1);
1800 M_ASLL_IMM(s2, 3, REG_ITMP2);
1801 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1802 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1803 store_reg_to_var_flt(iptr->dst, d);
1806 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1808 var_to_reg_int(s1, src->prev, REG_ITMP1);
1809 var_to_reg_int(s2, src, REG_ITMP2);
1810 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1811 if (iptr->op1 == 0) {
1812 gen_nullptr_check(s1);
1815 M_AADD(s2, s1, REG_ITMP1);
1816 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1817 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1818 store_reg_to_var_int(iptr->dst, d);
1821 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1823 var_to_reg_int(s1, src->prev, REG_ITMP1);
1824 var_to_reg_int(s2, src, REG_ITMP2);
1825 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1826 if (iptr->op1 == 0) {
1827 gen_nullptr_check(s1);
1830 M_AADD(s2, s1, REG_ITMP1);
1831 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1832 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1833 store_reg_to_var_int(iptr->dst, d);
1836 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1838 var_to_reg_int(s1, src->prev, REG_ITMP1);
1839 var_to_reg_int(s2, src, REG_ITMP2);
1840 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1841 if (iptr->op1 == 0) {
1842 gen_nullptr_check(s1);
1845 M_AADD(s2, s1, REG_ITMP1);
1846 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1847 store_reg_to_var_int(iptr->dst, d);
1851 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1853 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1854 var_to_reg_int(s2, src->prev, REG_ITMP2);
1855 if (iptr->op1 == 0) {
1856 gen_nullptr_check(s1);
1859 var_to_reg_int(s3, src, REG_ITMP3);
1860 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1861 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1862 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1865 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1867 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1868 var_to_reg_int(s2, src->prev, REG_ITMP2);
1869 if (iptr->op1 == 0) {
1870 gen_nullptr_check(s1);
1873 var_to_reg_int(s3, src, REG_ITMP3);
1874 M_ASLL_IMM(s2, 2, REG_ITMP2);
1875 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1876 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1879 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1881 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1882 var_to_reg_int(s2, src->prev, REG_ITMP2);
1883 if (iptr->op1 == 0) {
1884 gen_nullptr_check(s1);
1887 var_to_reg_int(s3, src, REG_ITMP3);
1888 M_ASLL_IMM(s2, 3, REG_ITMP2);
1889 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1890 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1893 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1895 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1896 var_to_reg_int(s2, src->prev, REG_ITMP2);
1897 if (iptr->op1 == 0) {
1898 gen_nullptr_check(s1);
1901 var_to_reg_flt(s3, src, REG_FTMP3);
1902 M_ASLL_IMM(s2, 2, REG_ITMP2);
1903 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1904 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1907 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1909 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1910 var_to_reg_int(s2, src->prev, REG_ITMP2);
1911 if (iptr->op1 == 0) {
1912 gen_nullptr_check(s1);
1915 var_to_reg_flt(s3, src, REG_FTMP3);
1916 M_ASLL_IMM(s2, 3, REG_ITMP2);
1917 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1918 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1921 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1922 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1924 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1925 var_to_reg_int(s2, src->prev, REG_ITMP2);
1926 if (iptr->op1 == 0) {
1927 gen_nullptr_check(s1);
1930 var_to_reg_int(s3, src, REG_ITMP3);
1931 M_AADD(s2, s1, REG_ITMP1);
1932 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1933 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1936 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1938 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1939 var_to_reg_int(s2, src->prev, REG_ITMP2);
1940 if (iptr->op1 == 0) {
1941 gen_nullptr_check(s1);
1944 var_to_reg_int(s3, src, REG_ITMP3);
1945 M_AADD(s2, s1, REG_ITMP1);
1946 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1950 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1952 var_to_reg_int(s1, src->prev, REG_ITMP1);
1953 var_to_reg_int(s2, src, REG_ITMP2);
1954 if (iptr->op1 == 0) {
1955 gen_nullptr_check(s1);
1958 M_ASLL_IMM(s2, 2, REG_ITMP2);
1959 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1960 M_IST(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1963 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1965 var_to_reg_int(s1, src->prev, REG_ITMP1);
1966 var_to_reg_int(s2, src, REG_ITMP2);
1967 if (iptr->op1 == 0) {
1968 gen_nullptr_check(s1);
1971 M_ASLL_IMM(s2, 3, REG_ITMP2);
1972 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1973 M_LST(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1976 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1978 var_to_reg_int(s1, src->prev, REG_ITMP1);
1979 var_to_reg_int(s2, src, REG_ITMP2);
1980 if (iptr->op1 == 0) {
1981 gen_nullptr_check(s1);
1984 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1985 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1986 M_AST(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1989 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1991 var_to_reg_int(s1, src->prev, REG_ITMP1);
1992 var_to_reg_int(s2, src, REG_ITMP2);
1993 if (iptr->op1 == 0) {
1994 gen_nullptr_check(s1);
1997 M_AADD(s2, s1, REG_ITMP1);
1998 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2001 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2002 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2004 var_to_reg_int(s1, src->prev, REG_ITMP1);
2005 var_to_reg_int(s2, src, REG_ITMP2);
2006 if (iptr->op1 == 0) {
2007 gen_nullptr_check(s1);
2010 M_AADD(s2, s1, REG_ITMP1);
2011 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2012 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
2016 case ICMD_GETSTATIC: /* ... ==> ..., value */
2017 /* op1 = type, val.a = field address */
2020 codegen_addpatchref(cd, mcodeptr,
2021 PATCHER_get_putstatic,
2022 (unresolved_field *) iptr->target);
2024 if (showdisassemble) {
2031 fieldinfo *fi = iptr->val.a;
2033 if (!fi->class->initialized) {
2034 codegen_addpatchref(cd, mcodeptr,
2035 PATCHER_clinit, fi->class);
2037 if (showdisassemble) {
2042 a = (ptrint) &(fi->value);
2045 a = dseg_addaddress(cd, a);
2046 M_ALD(REG_ITMP1, REG_PV, a);
2047 switch (iptr->op1) {
2049 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2050 M_ILD(d, REG_ITMP1, 0);
2051 store_reg_to_var_int(iptr->dst, d);
2054 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2055 M_LLD(d, REG_ITMP1, 0);
2056 store_reg_to_var_int(iptr->dst, d);
2059 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2060 M_ALD(d, REG_ITMP1, 0);
2061 store_reg_to_var_int(iptr->dst, d);
2064 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2065 M_FLD(d, REG_ITMP1, 0);
2066 store_reg_to_var_flt(iptr->dst, d);
2069 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2070 M_DLD(d, REG_ITMP1, 0);
2071 store_reg_to_var_flt(iptr->dst, d);
2076 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2077 /* op1 = type, val.a = field address */
2080 codegen_addpatchref(cd, mcodeptr,
2081 PATCHER_get_putstatic,
2082 (unresolved_field *) iptr->target);
2084 if (showdisassemble) {
2091 fieldinfo *fi = iptr->val.a;
2093 if (!fi->class->initialized) {
2094 codegen_addpatchref(cd, mcodeptr,
2095 PATCHER_clinit, fi->class);
2097 if (showdisassemble) {
2102 a = (ptrint) &(fi->value);
2105 a = dseg_addaddress(cd, a);
2106 M_ALD(REG_ITMP1, REG_PV, a);
2107 switch (iptr->op1) {
2109 var_to_reg_int(s2, src, REG_ITMP2);
2110 M_IST(s2, REG_ITMP1, 0);
2113 var_to_reg_int(s2, src, REG_ITMP2);
2114 M_LST(s2, REG_ITMP1, 0);
2117 var_to_reg_int(s2, src, REG_ITMP2);
2118 M_AST(s2, REG_ITMP1, 0);
2121 var_to_reg_flt(s2, src, REG_FTMP2);
2122 M_FST(s2, REG_ITMP1, 0);
2125 var_to_reg_flt(s2, src, REG_FTMP2);
2126 M_DST(s2, REG_ITMP1, 0);
2131 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2132 /* val = value (in current instruction) */
2133 /* op1 = type, val.a = field address (in */
2134 /* following NOP) */
2136 if (!iptr[1].val.a) {
2137 codegen_addpatchref(cd, mcodeptr,
2138 PATCHER_get_putstatic,
2139 (unresolved_field *) iptr[1].target);
2141 if (showdisassemble) {
2148 fieldinfo *fi = iptr[1].val.a;
2150 if (!fi->class->initialized) {
2151 codegen_addpatchref(cd, mcodeptr,
2152 PATCHER_clinit, fi->class);
2154 if (showdisassemble) {
2159 a = (ptrint) &(fi->value);
2162 a = dseg_addaddress(cd, a);
2163 M_ALD(REG_ITMP1, REG_PV, a);
2164 switch (iptr->op1) {
2166 M_IST(REG_ZERO, REG_ITMP1, 0);
2169 M_LST(REG_ZERO, REG_ITMP1, 0);
2172 M_AST(REG_ZERO, REG_ITMP1, 0);
2175 M_FST(REG_ZERO, REG_ITMP1, 0);
2178 M_DST(REG_ZERO, REG_ITMP1, 0);
2184 case ICMD_GETFIELD: /* ... ==> ..., value */
2185 /* op1 = type, val.i = field offset */
2187 var_to_reg_int(s1, src, REG_ITMP1);
2188 gen_nullptr_check(s1);
2191 codegen_addpatchref(cd, mcodeptr,
2192 PATCHER_get_putfield,
2193 (unresolved_field *) iptr->target);
2195 if (showdisassemble) {
2202 a = ((fieldinfo *) (iptr->val.a))->offset;
2205 switch (iptr->op1) {
2207 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2209 store_reg_to_var_int(iptr->dst, d);
2212 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2214 store_reg_to_var_int(iptr->dst, d);
2217 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2219 store_reg_to_var_int(iptr->dst, d);
2222 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2224 store_reg_to_var_flt(iptr->dst, d);
2227 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2229 store_reg_to_var_flt(iptr->dst, d);
2232 /* XXX quick hack */
2236 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2237 /* op1 = type, val.a = field address */
2239 var_to_reg_int(s1, src->prev, REG_ITMP1);
2240 gen_nullptr_check(s1);
2242 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2243 var_to_reg_int(s2, src, REG_ITMP2);
2245 var_to_reg_flt(s2, src, REG_FTMP2);
2249 codegen_addpatchref(cd, mcodeptr,
2250 PATCHER_get_putfield,
2251 (unresolved_field *) iptr->target);
2253 if (showdisassemble) {
2260 a = ((fieldinfo *) (iptr->val.a))->offset;
2263 switch (iptr->op1) {
2280 /* XXX quick hack */
2284 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2285 /* val = value (in current instruction) */
2286 /* op1 = type, val.a = field address (in */
2287 /* following NOP) */
2289 var_to_reg_int(s1, src, REG_ITMP1);
2290 gen_nullptr_check(s1);
2292 if (!iptr[1].val.a) {
2293 codegen_addpatchref(cd, mcodeptr,
2294 PATCHER_get_putfield,
2295 (unresolved_field *) iptr[1].target);
2297 if (showdisassemble) {
2304 a = ((fieldinfo *) (iptr[1].val.a))->offset;
2307 switch (iptr[1].op1) {
2309 M_IST(REG_ZERO, s1, a);
2312 M_LST(REG_ZERO, s1, a);
2315 M_AST(REG_ZERO, s1, a);
2318 M_FST(REG_ZERO, s1, a);
2321 M_DST(REG_ZERO, s1, a);
2324 /* XXX quick hack */
2329 /* branch operations **************************************************/
2331 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2333 var_to_reg_int(s1, src, REG_ITMP1);
2334 M_INTMOVE(s1, REG_ITMP1_XPTR);
2335 a = dseg_addaddress(cd, asm_handle_exception);
2336 M_ALD(REG_ITMP2, REG_PV, a);
2337 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2339 M_NOP; /* nop ensures that XPC is less than the end */
2340 /* of basic block */
2344 case ICMD_GOTO: /* ... ==> ... */
2345 /* op1 = target JavaVM pc */
2347 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2352 case ICMD_JSR: /* ... ==> ... */
2353 /* op1 = target JavaVM pc */
2355 dseg_addtarget(cd, BlockPtrOfPC(iptr->op1));
2356 M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
2357 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2361 case ICMD_RET: /* ... ==> ... */
2362 /* op1 = local variable */
2363 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2364 if (var->flags & INMEMORY) {
2365 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2374 case ICMD_IFNULL: /* ..., value ==> ... */
2375 /* op1 = target JavaVM pc */
2377 var_to_reg_int(s1, src, REG_ITMP1);
2379 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2383 case ICMD_IFNONNULL: /* ..., value ==> ... */
2384 /* op1 = target JavaVM pc */
2386 var_to_reg_int(s1, src, REG_ITMP1);
2388 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2392 case ICMD_IFEQ: /* ..., value ==> ... */
2393 /* op1 = target JavaVM pc, val.i = constant */
2395 var_to_reg_int(s1, src, REG_ITMP1);
2396 if (iptr->val.i == 0) {
2400 ICONST(REG_ITMP2, iptr->val.i);
2401 M_BEQ(s1, REG_ITMP2, 0);
2403 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2407 case ICMD_IFLT: /* ..., value ==> ... */
2408 /* op1 = target JavaVM pc, val.i = constant */
2410 var_to_reg_int(s1, src, REG_ITMP1);
2411 if (iptr->val.i == 0) {
2415 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2416 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2419 ICONST(REG_ITMP2, iptr->val.i);
2420 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2422 M_BNEZ(REG_ITMP1, 0);
2424 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2428 case ICMD_IFLE: /* ..., value ==> ... */
2429 /* op1 = target JavaVM pc, val.i = constant */
2431 var_to_reg_int(s1, src, REG_ITMP1);
2432 if (iptr->val.i == 0) {
2436 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2437 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2438 M_BNEZ(REG_ITMP1, 0);
2441 ICONST(REG_ITMP2, iptr->val.i);
2442 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2443 M_BEQZ(REG_ITMP1, 0);
2446 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2450 case ICMD_IFNE: /* ..., value ==> ... */
2451 /* op1 = target JavaVM pc, val.i = constant */
2453 var_to_reg_int(s1, src, REG_ITMP1);
2454 if (iptr->val.i == 0) {
2458 ICONST(REG_ITMP2, iptr->val.i);
2459 M_BNE(s1, REG_ITMP2, 0);
2461 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2465 case ICMD_IFGT: /* ..., value ==> ... */
2466 /* op1 = target JavaVM pc, val.i = constant */
2468 var_to_reg_int(s1, src, REG_ITMP1);
2469 if (iptr->val.i == 0) {
2473 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2474 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2475 M_BEQZ(REG_ITMP1, 0);
2478 ICONST(REG_ITMP2, iptr->val.i);
2479 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2480 M_BNEZ(REG_ITMP1, 0);
2483 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2487 case ICMD_IFGE: /* ..., value ==> ... */
2488 /* op1 = target JavaVM pc, val.i = constant */
2490 var_to_reg_int(s1, src, REG_ITMP1);
2491 if (iptr->val.i == 0) {
2495 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2496 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2499 ICONST(REG_ITMP2, iptr->val.i);
2500 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2502 M_BEQZ(REG_ITMP1, 0);
2504 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2508 case ICMD_IF_LEQ: /* ..., value ==> ... */
2509 /* op1 = target JavaVM pc, val.l = constant */
2511 var_to_reg_int(s1, src, REG_ITMP1);
2512 if (iptr->val.l == 0) {
2516 LCONST(REG_ITMP2, iptr->val.l);
2517 M_BEQ(s1, REG_ITMP2, 0);
2519 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2523 case ICMD_IF_LLT: /* ..., value ==> ... */
2524 /* op1 = target JavaVM pc, val.l = constant */
2526 var_to_reg_int(s1, src, REG_ITMP1);
2527 if (iptr->val.l == 0) {
2531 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2532 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2535 LCONST(REG_ITMP2, iptr->val.l);
2536 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2538 M_BNEZ(REG_ITMP1, 0);
2540 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2544 case ICMD_IF_LLE: /* ..., value ==> ... */
2545 /* op1 = target JavaVM pc, val.l = constant */
2547 var_to_reg_int(s1, src, REG_ITMP1);
2548 if (iptr->val.l == 0) {
2552 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2553 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2554 M_BNEZ(REG_ITMP1, 0);
2557 LCONST(REG_ITMP2, iptr->val.l);
2558 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2559 M_BEQZ(REG_ITMP1, 0);
2562 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2566 case ICMD_IF_LNE: /* ..., value ==> ... */
2567 /* op1 = target JavaVM pc, val.l = constant */
2569 var_to_reg_int(s1, src, REG_ITMP1);
2570 if (iptr->val.l == 0) {
2574 LCONST(REG_ITMP2, iptr->val.l);
2575 M_BNE(s1, REG_ITMP2, 0);
2577 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2581 case ICMD_IF_LGT: /* ..., value ==> ... */
2582 /* op1 = target JavaVM pc, val.l = constant */
2584 var_to_reg_int(s1, src, REG_ITMP1);
2585 if (iptr->val.l == 0) {
2589 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2590 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2591 M_BEQZ(REG_ITMP1, 0);
2594 LCONST(REG_ITMP2, iptr->val.l);
2595 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2596 M_BNEZ(REG_ITMP1, 0);
2599 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2603 case ICMD_IF_LGE: /* ..., value ==> ... */
2604 /* op1 = target JavaVM pc, val.l = constant */
2606 var_to_reg_int(s1, src, REG_ITMP1);
2607 if (iptr->val.l == 0) {
2611 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2612 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2615 LCONST(REG_ITMP2, iptr->val.l);
2616 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2618 M_BEQZ(REG_ITMP1, 0);
2620 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2624 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2625 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2626 case ICMD_IF_ACMPEQ:
2628 var_to_reg_int(s1, src->prev, REG_ITMP1);
2629 var_to_reg_int(s2, src, REG_ITMP2);
2631 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2635 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2636 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2637 case ICMD_IF_ACMPNE:
2639 var_to_reg_int(s1, src->prev, REG_ITMP1);
2640 var_to_reg_int(s2, src, REG_ITMP2);
2642 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2646 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2647 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2649 var_to_reg_int(s1, src->prev, REG_ITMP1);
2650 var_to_reg_int(s2, src, REG_ITMP2);
2651 M_CMPLT(s1, s2, REG_ITMP1);
2652 M_BNEZ(REG_ITMP1, 0);
2653 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2657 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2658 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2660 var_to_reg_int(s1, src->prev, REG_ITMP1);
2661 var_to_reg_int(s2, src, REG_ITMP2);
2662 M_CMPGT(s1, s2, REG_ITMP1);
2663 M_BNEZ(REG_ITMP1, 0);
2664 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2668 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2669 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2671 var_to_reg_int(s1, src->prev, REG_ITMP1);
2672 var_to_reg_int(s2, src, REG_ITMP2);
2673 M_CMPGT(s1, s2, REG_ITMP1);
2674 M_BEQZ(REG_ITMP1, 0);
2675 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2679 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2680 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2682 var_to_reg_int(s1, src->prev, REG_ITMP1);
2683 var_to_reg_int(s2, src, REG_ITMP2);
2684 M_CMPLT(s1, s2, REG_ITMP1);
2685 M_BEQZ(REG_ITMP1, 0);
2686 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2690 #ifdef CONDITIONAL_LOADCONST
2691 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2693 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2696 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2697 /* val.i = constant */
2699 var_to_reg_int(s1, src, REG_ITMP1);
2700 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2702 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2703 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2704 M_CMPEQ(s1, REG_ZERO, d);
2705 store_reg_to_var_int(iptr->dst, d);
2708 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2709 M_CMPEQ(s1, REG_ZERO, d);
2711 store_reg_to_var_int(iptr->dst, d);
2715 M_MOV(s1, REG_ITMP1);
2718 ICONST(d, iptr[1].val.i);
2720 if ((s3 >= 0) && (s3 <= 255)) {
2721 M_CMOVEQ_IMM(s1, s3, d);
2724 ICONST(REG_ITMP2, s3);
2725 M_CMOVEQ(s1, REG_ITMP2, d);
2727 store_reg_to_var_int(iptr->dst, d);
2730 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2731 /* val.i = constant */
2733 var_to_reg_int(s1, src, REG_ITMP1);
2734 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2736 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2737 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2738 M_CMPEQ(s1, REG_ZERO, d);
2739 store_reg_to_var_int(iptr->dst, d);
2742 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2743 M_CMPEQ(s1, REG_ZERO, d);
2745 store_reg_to_var_int(iptr->dst, d);
2749 M_MOV(s1, REG_ITMP1);
2752 ICONST(d, iptr[1].val.i);
2754 if ((s3 >= 0) && (s3 <= 255)) {
2755 M_CMOVNE_IMM(s1, s3, d);
2758 ICONST(REG_ITMP2, s3);
2759 M_CMOVNE(s1, REG_ITMP2, d);
2761 store_reg_to_var_int(iptr->dst, d);
2764 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2765 /* val.i = constant */
2767 var_to_reg_int(s1, src, REG_ITMP1);
2768 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2770 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2771 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2772 M_CMPLT(s1, REG_ZERO, d);
2773 store_reg_to_var_int(iptr->dst, d);
2776 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2777 M_CMPLE(REG_ZERO, s1, d);
2778 store_reg_to_var_int(iptr->dst, d);
2782 M_MOV(s1, REG_ITMP1);
2785 ICONST(d, iptr[1].val.i);
2787 if ((s3 >= 0) && (s3 <= 255)) {
2788 M_CMOVLT_IMM(s1, s3, d);
2791 ICONST(REG_ITMP2, s3);
2792 M_CMOVLT(s1, REG_ITMP2, d);
2794 store_reg_to_var_int(iptr->dst, d);
2797 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2798 /* val.i = constant */
2800 var_to_reg_int(s1, src, REG_ITMP1);
2801 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2803 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2804 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2805 M_CMPLE(REG_ZERO, s1, d);
2806 store_reg_to_var_int(iptr->dst, d);
2809 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2810 M_CMPLT(s1, REG_ZERO, d);
2811 store_reg_to_var_int(iptr->dst, d);
2815 M_MOV(s1, REG_ITMP1);
2818 ICONST(d, iptr[1].val.i);
2820 if ((s3 >= 0) && (s3 <= 255)) {
2821 M_CMOVGE_IMM(s1, s3, d);
2824 ICONST(REG_ITMP2, s3);
2825 M_CMOVGE(s1, REG_ITMP2, d);
2827 store_reg_to_var_int(iptr->dst, d);
2830 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2831 /* val.i = constant */
2833 var_to_reg_int(s1, src, REG_ITMP1);
2834 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2836 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2837 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2838 M_CMPLT(REG_ZERO, s1, d);
2839 store_reg_to_var_int(iptr->dst, d);
2842 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2843 M_CMPLE(s1, REG_ZERO, d);
2844 store_reg_to_var_int(iptr->dst, d);
2848 M_MOV(s1, REG_ITMP1);
2851 ICONST(d, iptr[1].val.i);
2853 if ((s3 >= 0) && (s3 <= 255)) {
2854 M_CMOVGT_IMM(s1, s3, d);
2857 ICONST(REG_ITMP2, s3);
2858 M_CMOVGT(s1, REG_ITMP2, d);
2860 store_reg_to_var_int(iptr->dst, d);
2863 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2864 /* val.i = constant */
2866 var_to_reg_int(s1, src, REG_ITMP1);
2867 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2869 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2870 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2871 M_CMPLE(s1, REG_ZERO, d);
2872 store_reg_to_var_int(iptr->dst, d);
2875 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2876 M_CMPLT(REG_ZERO, s1, d);
2877 store_reg_to_var_int(iptr->dst, d);
2881 M_MOV(s1, REG_ITMP1);
2884 ICONST(d, iptr[1].val.i);
2886 if ((s3 >= 0) && (s3 <= 255)) {
2887 M_CMOVLE_IMM(s1, s3, d);
2890 ICONST(REG_ITMP2, s3);
2891 M_CMOVLE(s1, REG_ITMP2, d);
2893 store_reg_to_var_int(iptr->dst, d);
2898 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2901 var_to_reg_int(s1, src, REG_RESULT);
2902 M_INTMOVE(s1, REG_RESULT);
2904 #if defined(USE_THREADS)
2905 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2907 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2908 M_ALD(REG_ITMP3, REG_PV, a);
2909 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
2910 M_JSR(REG_RA, REG_ITMP3);
2911 M_LST(REG_RESULT, REG_SP, rd->maxmemuse * 8); /* delay slot */
2913 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2914 M_LDA(REG_PV, REG_RA, disp);
2915 M_LLD(REG_RESULT, REG_SP, rd->maxmemuse * 8);
2918 goto nowperformreturn;
2920 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2922 var_to_reg_flt(s1, src, REG_FRESULT);
2924 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2925 M_TFLTMOVE(t, s1, REG_FRESULT);
2928 #if defined(USE_THREADS)
2929 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2931 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2932 M_ALD(REG_ITMP3, REG_PV, a);
2933 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
2934 M_JSR(REG_RA, REG_ITMP3);
2935 M_DST(REG_FRESULT, REG_SP, rd->maxmemuse * 8); /* delay slot */
2937 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2938 M_LDA(REG_PV, REG_RA, disp);
2939 M_DLD(REG_FRESULT, REG_SP, rd->maxmemuse * 8);
2942 goto nowperformreturn;
2944 case ICMD_RETURN: /* ... ==> ... */
2946 #if defined(USE_THREADS)
2947 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2949 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2950 M_ALD(REG_ITMP3, REG_PV, a);
2951 M_JSR(REG_RA, REG_ITMP3);
2952 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8); /* delay slot */
2953 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2954 M_LDA(REG_PV, REG_RA, disp);
2962 p = parentargs_base;
2964 /* restore return address */
2966 if (!m->isleafmethod) {
2967 p--; M_LLD(REG_RA, REG_SP, 8 * p);
2970 /* restore saved registers */
2972 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2973 p--; M_LLD(rd->savintregs[i], REG_SP, 8 * p);
2975 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2976 p--; M_DLD(rd->savfltregs[i], REG_SP, 8 * p);
2979 /* call trace function */
2982 M_LDA (REG_SP, REG_SP, -24);
2983 M_LST(REG_RA, REG_SP, 0);
2984 M_LST(REG_RESULT, REG_SP, 8);
2985 M_DST(REG_FRESULT, REG_SP,16);
2986 a = dseg_addaddress(cd, m);
2987 M_ALD(rd->argintregs[0], REG_PV, a);
2988 M_MOV(REG_RESULT, rd->argintregs[1]);
2989 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2990 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
2991 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2992 M_ALD(REG_ITMP3, REG_PV, a);
2993 M_JSR (REG_RA, REG_ITMP3);
2995 M_DLD(REG_FRESULT, REG_SP,16);
2996 M_LLD(REG_RESULT, REG_SP, 8);
2997 M_LLD(REG_RA, REG_SP, 0);
2998 M_LDA (REG_SP, REG_SP, 24);
3003 /* deallocate stack */
3005 if (parentargs_base) {
3006 M_LDA(REG_SP, REG_SP, parentargs_base * 8);
3017 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3022 tptr = (void **) iptr->target;
3024 s4ptr = iptr->val.a;
3025 l = s4ptr[1]; /* low */
3026 i = s4ptr[2]; /* high */
3028 var_to_reg_int(s1, src, REG_ITMP1);
3030 {M_INTMOVE(s1, REG_ITMP1);}
3031 else if (l <= 32768) {
3032 M_IADD_IMM(s1, -l, REG_ITMP1);
3035 ICONST(REG_ITMP2, l);
3036 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3042 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
3043 M_BEQZ(REG_ITMP2, 0);
3044 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
3045 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
3047 /* build jump table top down and use address of lowest entry */
3049 /* s4ptr += 3 + i; */
3053 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
3054 dseg_addtarget(cd, (basicblock *) tptr[0]);
3059 /* length of dataseg after last dseg_addtarget is used by load */
3061 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
3062 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
3069 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3071 s4 i, /*l, */val, *s4ptr;
3074 tptr = (void **) iptr->target;
3076 s4ptr = iptr->val.a;
3077 /*l = s4ptr[0];*/ /* default */
3078 i = s4ptr[1]; /* count */
3080 MCODECHECK((i<<2)+8);
3081 var_to_reg_int(s1, src, REG_ITMP1);
3087 ICONST(REG_ITMP2, val);
3088 M_BEQ(s1, REG_ITMP2, 0);
3089 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
3094 tptr = (void **) iptr->target;
3095 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
3102 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3103 /* op1 = return type, val.a = function pointer*/
3107 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3108 /* op1 = return type, val.a = function pointer*/
3112 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3113 /* op1 = return type, val.a = function pointer*/
3117 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3118 /* op1 = arg count, val.a = method pointer */
3120 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3121 /* op1 = arg count, val.a = method pointer */
3123 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3124 /* op1 = arg count, val.a = method pointer */
3126 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3127 /* op1 = arg count, val.a = method pointer */
3134 MCODECHECK((s3 << 1) + 64);
3136 /* copy arguments to registers or stack location */
3138 for (; --s3 >= 0; src = src->prev) {
3139 if (src->varkind == ARGVAR)
3141 if (IS_INT_LNG_TYPE(src->type)) {
3142 if (s3 < INT_ARG_CNT) {
3143 s1 = rd->argintregs[s3];
3144 var_to_reg_int(d, src, s1);
3148 var_to_reg_int(d, src, REG_ITMP1);
3149 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3153 if (s3 < FLT_ARG_CNT) {
3154 s1 = rd->argfltregs[s3];
3155 var_to_reg_flt(d, src, s1);
3156 M_TFLTMOVE(src->type, d, s1);
3159 var_to_reg_flt(d, src, REG_FTMP1);
3160 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3166 switch (iptr->opc) {
3171 codegen_addpatchref(cd, mcodeptr,
3172 (functionptr) lm, iptr->target);
3174 if (showdisassemble) {
3184 a = dseg_addaddress(cd, a);
3185 d = iptr->op1; /* return type */
3187 M_ALD(REG_ITMP3, REG_PV, a); /* built-in-function pointer */
3188 M_JSR(REG_RA, REG_ITMP3);
3190 goto afteractualcall;
3192 case ICMD_INVOKESPECIAL:
3193 gen_nullptr_check(rd->argintregs[0]);
3194 M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr */
3197 case ICMD_INVOKESTATIC:
3199 unresolved_method *um = iptr->target;
3201 codegen_addpatchref(cd, mcodeptr,
3202 PATCHER_invokestatic_special, um);
3204 if (showdisassemble) {
3209 d = um->methodref->parseddesc.md->returntype.type;
3212 a = (ptrint) lm->stubroutine;
3213 d = lm->parseddesc->returntype.type;
3216 a = dseg_addaddress(cd, a);
3217 M_ALD(REG_PV, REG_PV, a); /* method pointer in pv */
3220 case ICMD_INVOKEVIRTUAL:
3221 gen_nullptr_check(rd->argintregs[0]);
3224 unresolved_method *um = iptr->target;
3226 codegen_addpatchref(cd, mcodeptr,
3227 PATCHER_invokevirtual, um);
3229 if (showdisassemble) {
3234 d = um->methodref->parseddesc.md->returntype.type;
3237 s1 = OFFSET(vftbl_t, table[0]) +
3238 sizeof(methodptr) * lm->vftblindex;
3239 d = lm->parseddesc->returntype.type;
3242 M_ALD(REG_METHODPTR, rd->argintregs[0],
3243 OFFSET(java_objectheader, vftbl));
3244 M_ALD(REG_PV, REG_METHODPTR, s1);
3247 case ICMD_INVOKEINTERFACE:
3248 gen_nullptr_check(rd->argintregs[0]);
3251 unresolved_method *um = iptr->target;
3253 codegen_addpatchref(cd, mcodeptr,
3254 PATCHER_invokeinterface, um);
3256 if (showdisassemble) {
3262 d = um->methodref->parseddesc.md->returntype.type;
3265 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3266 sizeof(methodptr*) * lm->class->index;
3268 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3270 d = lm->parseddesc->returntype.type;
3273 M_ALD(REG_METHODPTR, rd->argintregs[0],
3274 OFFSET(java_objectheader, vftbl));
3275 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3276 M_ALD(REG_PV, REG_METHODPTR, s2);
3280 M_JSR(REG_RA, REG_PV);
3287 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3288 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3290 s4 ml = -s1, mh = 0;
3291 while (ml < -32768) { ml += 65536; mh--; }
3293 M_IADD_IMM(REG_PV, ml, REG_PV);
3294 M_LADD(REG_PV, REG_RA, REG_PV);
3297 /* d contains return type */
3299 if (d != TYPE_VOID) {
3300 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3301 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3302 M_INTMOVE(REG_RESULT, s1);
3303 store_reg_to_var_int(iptr->dst, s1);
3306 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3307 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3308 store_reg_to_var_flt(iptr->dst, s1);
3315 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3316 /* op1: 0 == array, 1 == class */
3317 /* val.a: (classinfo*) superclass */
3319 /* superclass is an interface:
3321 * OK if ((sub == NULL) ||
3322 * (sub->vftbl->interfacetablelength > super->index) &&
3323 * (sub->vftbl->interfacetable[-super->index] != NULL));
3325 * superclass is a class:
3327 * OK if ((sub == NULL) || (0
3328 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3329 * super->vftbl->diffvall));
3334 vftbl_t *supervftbl;
3337 super = (classinfo *) iptr->val.a;
3344 superindex = super->index;
3345 supervftbl = super->vftbl;
3348 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3349 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3352 var_to_reg_int(s1, src, REG_ITMP1);
3354 /* calculate interface checkcast code size */
3358 s2 += (showdisassemble ? 2 : 0);
3360 /* calculate class checkcast code size */
3362 s3 = 10 /* 10 + (s1 == REG_ITMP1) */;
3364 s3 += (showdisassemble ? 2 : 0);
3366 /* if class is not resolved, check which code to call */
3369 M_BEQZ(s1, 5 + (showdisassemble ? 2 : 0) + s2 + 2 + s3);
3372 codegen_addpatchref(cd, mcodeptr,
3373 PATCHER_checkcast_instanceof_flags,
3374 (constant_classref *) iptr->target);
3376 if (showdisassemble) {
3380 a = dseg_adds4(cd, 0); /* super->flags */
3381 M_ILD(REG_ITMP2, REG_PV, a);
3382 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3383 M_BEQZ(REG_ITMP2, 1 + s2 + 2);
3387 /* interface checkcast code */
3389 if (!super || super->flags & ACC_INTERFACE) {
3395 codegen_addpatchref(cd, mcodeptr,
3396 PATCHER_checkcast_instanceof_interface,
3397 (constant_classref *) iptr->target);
3399 if (showdisassemble) {
3404 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3405 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3406 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3407 M_BLEZ(REG_ITMP3, 0);
3408 codegen_addxcastrefs(cd, mcodeptr);
3410 M_ALD(REG_ITMP3, REG_ITMP2,
3411 OFFSET(vftbl_t, interfacetable[0]) -
3412 superindex * sizeof(methodptr*));
3413 M_BEQZ(REG_ITMP3, 0);
3414 codegen_addxcastrefs(cd, mcodeptr);
3423 /* class checkcast code */
3425 if (!super || !(super->flags & ACC_INTERFACE)) {
3431 codegen_addpatchref(cd, mcodeptr,
3432 PATCHER_checkcast_instanceof_class,
3433 (constant_classref *) iptr->target);
3435 if (showdisassemble) {
3440 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3441 a = dseg_addaddress(cd, (void *) supervftbl);
3442 M_ALD(REG_ITMP3, REG_PV, a);
3443 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3444 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3446 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3447 /* if (s1 != REG_ITMP1) { */
3448 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3449 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3450 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3451 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3453 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3455 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3456 M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3457 M_ALD(REG_ITMP3, REG_PV, a);
3458 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3459 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3460 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3463 M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3464 M_BNEZ(REG_ITMP3, 0);
3465 codegen_addxcastrefs(cd, mcodeptr);
3468 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3470 store_reg_to_var_int(iptr->dst, d);
3474 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3475 /* op1: 0 == array, 1 == class */
3476 /* val.a: (classinfo*) superclass */
3478 /* superclass is an interface:
3480 * return (sub != NULL) &&
3481 * (sub->vftbl->interfacetablelength > super->index) &&
3482 * (sub->vftbl->interfacetable[-super->index] != NULL);
3484 * superclass is a class:
3486 * return ((sub != NULL) && (0
3487 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3488 * super->vftbl->diffvall));
3493 vftbl_t *supervftbl;
3496 super = (classinfo *) iptr->val.a;
3503 superindex = super->index;
3504 supervftbl = super->vftbl;
3507 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3508 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3511 var_to_reg_int(s1, src, REG_ITMP1);
3512 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3514 M_MOV(s1, REG_ITMP1);
3518 /* calculate interface instanceof code size */
3522 s2 += (showdisassemble ? 2 : 0);
3524 /* calculate class instanceof code size */
3528 s3 += (showdisassemble ? 2 : 0);
3532 /* if class is not resolved, check which code to call */
3535 M_BEQZ(s1, 5 + (showdisassemble ? 2 : 0) + s2 + 2 + s3);
3538 codegen_addpatchref(cd, mcodeptr,
3539 PATCHER_checkcast_instanceof_flags,
3540 (constant_classref *) iptr->target);
3542 if (showdisassemble) {
3546 a = dseg_adds4(cd, 0); /* super->flags */
3547 M_ILD(REG_ITMP3, REG_PV, a);
3548 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
3549 M_BEQZ(REG_ITMP3, 1 + s2 + 2);
3553 /* interface instanceof code */
3555 if (!super || (super->flags & ACC_INTERFACE)) {
3561 codegen_addpatchref(cd, mcodeptr,
3562 PATCHER_checkcast_instanceof_interface,
3563 (constant_classref *) iptr->target);
3565 if (showdisassemble) {
3570 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3571 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3572 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3573 M_BLEZ(REG_ITMP3, 3);
3575 M_ALD(REG_ITMP1, REG_ITMP1,
3576 OFFSET(vftbl_t, interfacetable[0]) -
3577 superindex * sizeof(methodptr*));
3578 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3586 /* class instanceof code */
3588 if (!super || !(super->flags & ACC_INTERFACE)) {
3594 codegen_addpatchref(cd, mcodeptr,
3595 PATCHER_checkcast_instanceof_class,
3596 (constant_classref *) iptr->target);
3598 if (showdisassemble) {
3603 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3604 a = dseg_addaddress(cd, supervftbl);
3605 M_ALD(REG_ITMP2, REG_PV, a);
3606 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3607 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3609 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3610 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3611 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3612 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3613 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3615 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3616 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3619 store_reg_to_var_int(iptr->dst, d);
3623 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3625 var_to_reg_int(s1, src, REG_ITMP1);
3627 codegen_addxcheckarefs(cd, mcodeptr);
3631 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3633 M_BEQZ(REG_RESULT, 0);
3634 codegen_addxexceptionrefs(cd, mcodeptr);
3638 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3639 /* op1 = dimension, val.a = array descriptor */
3641 /* check for negative sizes and copy sizes to stack if necessary */
3643 MCODECHECK((iptr->op1 << 1) + 64);
3645 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3646 var_to_reg_int(s2, src, REG_ITMP1);
3648 codegen_addxcheckarefs(cd, mcodeptr);
3651 /* copy SAVEDVAR sizes to stack */
3653 if (src->varkind != ARGVAR) {
3654 M_LST(s2, REG_SP, s1 * 8);
3658 /* is patcher function set? */
3661 codegen_addpatchref(cd, mcodeptr,
3662 (functionptr) iptr->target, iptr->val.a);
3664 if (showdisassemble) {
3671 a = (ptrint) iptr->val.a;
3674 /* a0 = dimension count */
3676 ICONST(rd->argintregs[0], iptr->op1);
3678 /* a1 = arraydescriptor */
3680 a = dseg_addaddress(cd, a);
3681 M_ALD(rd->argintregs[1], REG_PV, a);
3683 /* a2 = pointer to dimensions = stack pointer */
3685 M_INTMOVE(REG_SP, rd->argintregs[2]);
3687 a = dseg_addaddress(cd, BUILTIN_multianewarray);
3688 M_ALD(REG_ITMP3, REG_PV, a);
3689 M_JSR(REG_RA, REG_ITMP3);
3691 s1 = (s4)((u1 *) mcodeptr - cd->mcodebase);
3693 M_LDA (REG_PV, REG_RA, -s1);
3697 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3698 M_INTMOVE(REG_RESULT, s1);
3699 store_reg_to_var_int(iptr->dst, s1);
3703 throw_cacao_exception_exit(string_java_lang_InternalError,
3704 "Unknown ICMD %d", iptr->opc);
3707 } /* for instruction */
3709 /* copy values to interface registers */
3711 src = bptr->outstack;
3712 len = bptr->outdepth;
3719 if ((src->varkind != STACKVAR)) {
3721 if (IS_FLT_DBL_TYPE(s2)) {
3722 var_to_reg_flt(s1, src, REG_FTMP1);
3723 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3724 M_TFLTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3727 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3731 var_to_reg_int(s1, src, REG_ITMP1);
3732 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3733 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3736 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3742 } /* if (bptr -> flags >= BBREACHED) */
3743 } /* for basic block */
3746 /* generate bound check stubs */
3748 s4 *xcodeptr = NULL;
3751 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3752 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3754 (u1 *) mcodeptr - cd->mcodebase);
3758 M_MOV(bref->reg, REG_ITMP1);
3759 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3761 if (xcodeptr != NULL) {
3762 M_BR(xcodeptr - mcodeptr);
3766 xcodeptr = mcodeptr;
3768 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3769 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3771 M_MOV(REG_ITMP1, rd->argintregs[0]);
3772 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3773 M_ALD(REG_ITMP3, REG_PV, a);
3774 M_JSR(REG_RA, REG_ITMP3);
3776 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3778 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3779 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3781 a = dseg_addaddress(cd, asm_handle_exception);
3782 M_ALD(REG_ITMP3, REG_PV, a);
3788 /* generate negative array size check stubs */
3792 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3793 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3794 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3796 (u1 *) xcodeptr - cd->mcodebase - 4);
3800 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3802 (u1 *) mcodeptr - cd->mcodebase);
3806 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3808 if (xcodeptr != NULL) {
3809 M_BR(xcodeptr - mcodeptr);
3813 xcodeptr = mcodeptr;
3815 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3816 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3818 a = dseg_addaddress(cd, new_negativearraysizeexception);
3819 M_ALD(REG_ITMP3, REG_PV, a);
3820 M_JSR(REG_RA, REG_ITMP3);
3822 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3824 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3825 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3827 a = dseg_addaddress(cd, asm_handle_exception);
3828 M_ALD(REG_ITMP3, REG_PV, a);
3834 /* generate cast check stubs */
3838 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3839 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3840 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3842 (u1 *) xcodeptr - cd->mcodebase - 4);
3846 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3848 (u1 *) mcodeptr - cd->mcodebase);
3852 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3854 if (xcodeptr != NULL) {
3855 M_BR(xcodeptr - mcodeptr);
3859 xcodeptr = mcodeptr;
3861 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3862 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3864 a = dseg_addaddress(cd, new_classcastexception);
3865 M_ALD(REG_ITMP3, REG_PV, a);
3866 M_JSR(REG_RA, REG_ITMP3);
3868 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3870 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3871 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3873 a = dseg_addaddress(cd, asm_handle_exception);
3874 M_ALD(REG_ITMP3, REG_PV, a);
3880 /* generate exception check stubs */
3884 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3885 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3886 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3888 (u1 *) xcodeptr - cd->mcodebase - 4);
3892 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3894 (u1 *) mcodeptr - cd->mcodebase);
3898 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3900 if (xcodeptr != NULL) {
3901 M_BR(xcodeptr - mcodeptr);
3905 xcodeptr = mcodeptr;
3907 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3908 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3909 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3911 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3912 M_ALD(REG_ITMP3, REG_PV, a);
3913 M_JSR(REG_RA, REG_ITMP3);
3916 /* get the exceptionptr from the ptrprt and clear it */
3917 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3918 M_AST(REG_ZERO, REG_RESULT, 0);
3920 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3921 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3923 a = dseg_addaddress(cd, &_exceptionptr);
3924 M_ALD(REG_ITMP3, REG_PV, a);
3925 M_ALD(REG_ITMP1_XPTR, REG_ITMP3, 0);
3926 M_AST(REG_ZERO, REG_ITMP3, 0);
3929 a = dseg_addaddress(cd, asm_handle_exception);
3930 M_ALD(REG_ITMP3, REG_PV, a);
3936 /* generate null pointer check stubs */
3940 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3941 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3942 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3944 (u1 *) xcodeptr - cd->mcodebase - 4);
3948 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3950 (u1 *) mcodeptr - cd->mcodebase);
3954 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3956 if (xcodeptr != NULL) {
3957 M_BR(xcodeptr - mcodeptr);
3961 xcodeptr = mcodeptr;
3963 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3964 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3966 a = dseg_addaddress(cd, new_nullpointerexception);
3967 M_ALD(REG_ITMP3, REG_PV, a);
3968 M_JSR(REG_RA, REG_ITMP3);
3970 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3972 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3973 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3975 a = dseg_addaddress(cd, asm_handle_exception);
3976 M_ALD(REG_ITMP3, REG_PV, a);
3983 /* generate put/getstatic stub call code */
3990 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3991 /* check code segment size */
3993 MCODECHECK(22 + 4 + 1);
3995 /* Get machine code which is patched back in later. The call is */
3996 /* 2 instruction words long. */
3998 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4000 /* We need to split this, because an unaligned 8 byte read causes */
4003 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
4005 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4006 /* create a virtual java_objectheader */
4008 /* align data structure to 8-byte */
4012 *((ptrint *) (mcodeptr + 0)) = 0; /* vftbl */
4013 *((ptrint *) (mcodeptr + 2)) = (ptrint) get_dummyLR(); /* monitorPtr */
4015 mcodeptr += 2 * 2; /* mcodeptr is a `u4*' pointer */
4018 /* patch in the call to call the following code (done at compile */
4021 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4022 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4024 M_BRS(tmpmcodeptr - (xcodeptr + 1));
4025 M_MOV(REG_RA, REG_ITMP3); /* branch delay slot */
4027 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4029 /* create stack frame */
4031 M_LSUB_IMM(REG_SP, 5 * 8, REG_SP);
4033 /* move return address onto stack */
4035 M_AST(REG_RA, REG_SP, 4 * 8);
4036 M_MOV(REG_ITMP3, REG_RA); /* restore return address */
4038 /* move pointer to java_objectheader onto stack */
4040 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4041 M_MOV(REG_RA, REG_ITMP3); /* save return address */
4044 M_LSUB_IMM(REG_RA, 6 * 4 + 2 * 8, REG_RA);
4045 M_AST(REG_RA, REG_SP, 3 * 8);
4046 M_MOV(REG_ITMP3, REG_RA); /* restore return address */
4048 M_AST(REG_ZERO, REG_SP, 3 * 8);
4051 /* move machine code onto stack */
4053 a = dseg_adds8(cd, mcode);
4054 M_LLD(REG_ITMP3, REG_PV, a);
4055 M_LST(REG_ITMP3, REG_SP, 2 * 8);
4057 /* move class/method/field reference onto stack */
4059 a = dseg_addaddress(cd, pref->ref);
4060 M_ALD(REG_ITMP3, REG_PV, a);
4061 M_AST(REG_ITMP3, REG_SP, 1 * 8);
4063 /* move patcher function pointer onto stack */
4065 a = dseg_addaddress(cd, pref->patcher);
4066 M_ALD(REG_ITMP3, REG_PV, a);
4067 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4069 a = dseg_addaddress(cd, asm_wrapper_patcher);
4070 M_ALD(REG_ITMP3, REG_PV, a);
4077 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4079 docacheflush((void*) m->entrypoint, ((u1*) mcodeptr - cd->mcodebase));
4083 /* createcompilerstub **********************************************************
4085 Creates a stub routine which calls the compiler.
4087 *******************************************************************************/
4089 #define COMPSTUB_SIZE 4
4091 u1 *createcompilerstub(methodinfo *m)
4093 u8 *s = CNEW(u8, COMPSTUB_SIZE); /* memory to hold the stub */
4094 s4 *mcodeptr = (s4 *) s; /* code generation pointer */
4096 /* code for the stub */
4097 M_ALD(REG_PV, REG_PV, 24); /* load pointer to the compiler */
4099 M_JSR(REG_ITMP1, REG_PV); /* jump to the compiler, return address
4100 in itmp1 is used as method pointer */
4103 s[2] = (u8) m; /* literals to be adressed */
4104 s[3] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
4106 (void) docacheflush((void*) s, (char*) mcodeptr - (char*) s);
4108 #if defined(STATISTICS)
4110 count_cstub_len += COMPSTUB_SIZE * 8;
4117 /* function removecompilerstub *************************************************
4119 deletes a compilerstub from memory (simply by freeing it)
4121 *******************************************************************************/
4123 void removecompilerstub(u1 *stub)
4125 CFREE(stub, COMPSTUB_SIZE * 8);
4129 /* function: createnativestub **************************************************
4131 creates a stub routine which calls a native method
4133 *******************************************************************************/
4135 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4136 #define NATIVESTUB_STACK 2
4137 #define NATIVESTUB_THREAD_EXTRA 5
4139 #define NATIVESTUB_STACK 1
4140 #define NATIVESTUB_THREAD_EXTRA 1
4143 #define NATIVESTUB_SIZE (54 + 4 + NATIVESTUB_THREAD_EXTRA - 1)
4144 #define NATIVESTUB_STATIC_SIZE (18 + 4 + 1)
4145 #define NATIVESTUB_VERBOSE_SIZE (50 + 17)
4146 #define NATIVESTUB_OFFSET 11
4149 u1 *createnativestub(functionptr f, methodinfo *m)
4151 u8 *s; /* memory to hold the stub */
4153 s4 *mcodeptr; /* code generation pointer */
4154 s4 stackframesize = 0; /* size of stackframe if needed */
4159 t_inlining_globals *id;
4162 /* mark start of dump memory area */
4164 dumpsize = dump_size();
4166 /* setup registers before using it */
4168 cd = DNEW(codegendata);
4169 rd = DNEW(registerdata);
4170 id = DNEW(t_inlining_globals);
4172 inlining_setup(m, id);
4173 reg_setup(m, rd, id);
4175 method_descriptor2types(m); /* set paramcount and paramtypes */
4177 stubsize = NATIVESTUB_SIZE; /* calculate nativestub size */
4179 if ((m->flags & ACC_STATIC) && !m->class->initialized)
4180 stubsize += NATIVESTUB_STATIC_SIZE;
4183 stubsize += NATIVESTUB_VERBOSE_SIZE;
4185 s = CNEW(u8, stubsize); /* memory to hold the stub */
4186 cs = s + NATIVESTUB_OFFSET;
4187 mcodeptr = (s4 *) (cs); /* code generation pointer */
4189 /* set some required varibles which are normally set by codegen_setup */
4190 cd->mcodebase = (u1 *) mcodeptr;
4191 cd->patchrefs = NULL;
4193 *(cs-1) = (u8) f; /* address of native method */
4194 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4195 *(cs-2) = (u8) &builtin_get_exceptionptrptr;
4197 *(cs-2) = (u8) (&_exceptionptr); /* address of exceptionptr */
4199 *(cs-3) = (u8) asm_handle_nat_exception;/* addr of asm exception handler */
4200 *(cs-4) = (u8) (&env); /* addr of jni_environement */
4201 *(cs-5) = (u8) builtin_trace_args;
4203 *(cs-7) = (u8) builtin_displaymethodstop;
4204 *(cs-8) = (u8) m->class;
4205 *(cs-9) = (u8) asm_wrapper_patcher;
4206 *(cs-10) = (u8) NULL; /* filled with machine code */
4207 *(cs-11) = (u8) PATCHER_clinit;
4209 M_LDA(REG_SP, REG_SP, -NATIVESTUB_STACK * 8); /* build up stackframe */
4210 M_LST(REG_RA, REG_SP, 0); /* store return address */
4212 /* if function is static, check for initialized */
4214 if ((m->flags & ACC_STATIC) && !m->class->initialized) {
4215 codegen_addpatchref(cd, mcodeptr, NULL, NULL);
4218 /* max. 50 instructions */
4224 M_LDA(REG_SP, REG_SP, -(18 * 8));
4225 M_AST(REG_RA, REG_SP, 1 * 8);
4227 /* save integer argument registers */
4228 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
4229 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
4232 /* save and copy float arguments into integer registers */
4233 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
4234 t = m->paramtypes[p];
4236 if (IS_FLT_DBL_TYPE(t)) {
4237 if (IS_2_WORD_TYPE(t)) {
4238 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
4239 M_LLD(rd->argintregs[p], REG_SP, (10 + p) * 8);
4242 M_FST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
4243 M_ILD(rd->argintregs[p], REG_SP, (10 + p) * 8);
4247 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
4251 M_ALD(REG_ITMP1, REG_PV, -6 * 8); /* method address */
4252 M_AST(REG_ITMP1, REG_SP, 0);
4253 M_ALD(REG_ITMP3, REG_PV, -5 * 8); /* builtin_trace_args */
4254 M_JSR(REG_RA, REG_ITMP3);
4256 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4257 M_LDA(REG_PV, REG_RA, disp);
4259 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
4260 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
4263 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
4264 t = m->paramtypes[p];
4266 if (IS_FLT_DBL_TYPE(t)) {
4267 if (IS_2_WORD_TYPE(t)) {
4268 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
4271 M_FLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
4275 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
4279 M_ALD(REG_RA, REG_SP, 1 * 8);
4280 M_LDA(REG_SP, REG_SP, 18 * 8);
4283 /* save argument registers on stack -- if we have to */
4285 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
4287 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
4288 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
4290 stackframesize = stackparamcnt + paramshiftcnt;
4292 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
4294 /* copy stack arguments into new stack frame -- if any */
4295 for (i = 0; i < stackparamcnt; i++) {
4296 M_LLD(REG_ITMP1, REG_SP, (stackparamcnt + 1 + i) * 8);
4297 M_LST(REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
4300 if (m->flags & ACC_STATIC) {
4301 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4302 M_DST(rd->argfltregs[5], REG_SP, 1 * 8);
4304 M_LST(rd->argintregs[5], REG_SP, 1 * 8);
4307 if (IS_FLT_DBL_TYPE(m->paramtypes[4])) {
4308 M_DST(rd->argfltregs[4], REG_SP, 0 * 8);
4310 M_LST(rd->argintregs[4], REG_SP, 0 * 8);
4314 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
4315 M_DST(rd->argfltregs[5], REG_SP, 0 * 8);
4317 M_LST(rd->argintregs[5], REG_SP, 0 * 8);
4322 if (m->flags & ACC_STATIC) {
4323 M_MOV(rd->argintregs[5], rd->argintregs[7]);
4325 M_DMFC1(REG_ITMP1, rd->argfltregs[5]);
4326 M_DMTC1(REG_ITMP1, rd->argfltregs[7]);
4328 M_MOV(rd->argintregs[4], rd->argintregs[6]);
4330 M_DMFC1(REG_ITMP1, rd->argfltregs[4]);
4331 M_DMTC1(REG_ITMP1, rd->argfltregs[6]);
4333 M_MOV(rd->argintregs[3], rd->argintregs[5]);
4334 M_DMFC1(REG_ITMP1, rd->argfltregs[3]);
4336 M_MOV(rd->argintregs[2], rd->argintregs[4]);
4337 M_DMTC1(REG_ITMP1, rd->argfltregs[5]);
4339 M_MOV(rd->argintregs[1], rd->argintregs[3]);
4340 M_DMFC1(REG_ITMP1, rd->argfltregs[2]);
4342 M_MOV(rd->argintregs[0], rd->argintregs[2]);
4343 M_DMTC1(REG_ITMP1, rd->argfltregs[4]);
4345 M_DMFC1(REG_ITMP1, rd->argfltregs[1]);
4346 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4348 M_DMFC1(REG_ITMP1, rd->argfltregs[0]);
4349 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4351 M_ALD(rd->argintregs[1], REG_PV, -8 * 8);
4354 M_MOV(rd->argintregs[6], rd->argintregs[7]);
4356 M_DMFC1(REG_ITMP1, rd->argfltregs[6]);
4357 M_DMTC1(REG_ITMP1, rd->argfltregs[7]);
4359 M_MOV(rd->argintregs[5], rd->argintregs[6]);
4361 M_DMFC1(REG_ITMP1, rd->argfltregs[5]);
4362 M_DMTC1(REG_ITMP1, rd->argfltregs[6]);
4364 M_MOV(rd->argintregs[4], rd->argintregs[5]);
4365 M_DMFC1(REG_ITMP1, rd->argfltregs[4]);
4367 M_MOV(rd->argintregs[3], rd->argintregs[4]);
4368 M_DMTC1(REG_ITMP1, rd->argfltregs[5]);
4370 M_MOV(rd->argintregs[2], rd->argintregs[3]);
4371 M_DMFC1(REG_ITMP1, rd->argfltregs[3]);
4373 M_MOV(rd->argintregs[1], rd->argintregs[2]);
4374 M_DMTC1(REG_ITMP1, rd->argfltregs[4]);
4376 M_MOV(rd->argintregs[0], rd->argintregs[1]);
4377 M_DMFC1(REG_ITMP1, rd->argfltregs[2]);
4379 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4381 M_DMFC1(REG_ITMP1, rd->argfltregs[1]);
4382 M_DMFC1(REG_ITMP2, rd->argfltregs[0]);
4384 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4385 M_DMTC1(REG_ITMP2, rd->argfltregs[1]);
4388 M_ALD(rd->argintregs[0], REG_PV, -4 * 8); /* jni environement */
4389 M_ALD(REG_ITMP3, REG_PV, -1 * 8); /* load adress of native method */
4390 M_JSR(REG_RA, REG_ITMP3); /* call native method */
4391 M_NOP; /* delay slot */
4393 /* remove stackframe if there is one */
4394 if (stackframesize) {
4395 M_LDA(REG_SP, REG_SP, stackframesize * 8);
4398 /* 17 instructions */
4400 M_LDA(REG_SP, REG_SP, -(3 * 8));
4401 M_AST(REG_RA, REG_SP, 0 * 8);
4402 M_LST(REG_RESULT, REG_SP, 1 * 8);
4403 M_DST(REG_FRESULT, REG_SP, 2 * 8);
4404 M_ALD(rd->argintregs[0], REG_PV, -6 * 8);
4405 M_MOV(REG_RESULT, rd->argintregs[1]);
4406 M_DMFC1(REG_ITMP1, REG_FRESULT);
4407 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4408 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4409 M_ALD(REG_ITMP3, REG_PV, -7 * 8);/* builtin_displaymethodstop */
4410 M_JSR(REG_RA, REG_ITMP3);
4412 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
4413 M_LDA(REG_PV, REG_RA, disp);
4414 M_ALD(REG_RA, REG_SP, 0 * 8);
4415 M_LLD(REG_RESULT, REG_SP, 1 * 8);
4416 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
4417 M_LDA(REG_SP, REG_SP, 3 * 8);
4420 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4421 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* builtin_get_exceptionptrptr */
4422 M_JSR(REG_RA, REG_ITMP3);
4425 if (IS_FLT_DBL_TYPE(m->returntype)) {
4426 M_DST(REG_FRESULT, REG_SP, 1 * 8);
4429 M_AST(REG_RESULT, REG_SP, 1 * 8);
4432 M_MOV(REG_RESULT, REG_ITMP3);
4434 if (IS_FLT_DBL_TYPE(m->returntype)) {
4435 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
4438 M_ALD(REG_RESULT, REG_SP, 1 * 8);
4441 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* get address of exceptionptr */
4444 M_LLD(REG_RA, REG_SP, 0); /* load return address */
4445 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4447 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
4448 M_LDA(REG_SP, REG_SP, NATIVESTUB_STACK * 8);/*remove stackframe, delay slot*/
4450 M_RET(REG_RA); /* return to caller */
4451 M_NOP; /* delay slot */
4453 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4454 M_ALD(REG_ITMP3, REG_PV, -3 * 8); /* load asm exception handler address */
4456 M_JMP(REG_ITMP3); /* jump to asm exception handler */
4457 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4460 /* generate static stub call code */
4467 /* there can only be one clinit ref entry */
4468 pref = cd->patchrefs;
4471 /* Get machine code which is patched back in later. The call is */
4472 /* 2 instruction words long. */
4474 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4476 /* We need to split this, because an unaligned 8 byte read causes */
4479 *(cs-10) = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
4481 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4482 /* create a virtual java_objectheader */
4484 /* align data structure to 8-byte */
4488 *((ptrint *) (mcodeptr + 0)) = 0; /* vftbl */
4489 *((ptrint *) (mcodeptr + 2)) = (ptrint) get_dummyLR(); /* monitorPtr */
4491 mcodeptr += 2 * 2; /* mcodeptr is a `u4*' pointer */
4494 /* patch in the call to call the following code (done at compile */
4497 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4498 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4500 M_BRS(tmpmcodeptr - (xcodeptr + 1));
4501 M_MOV(REG_RA, REG_ITMP3); /* branch delay slot */
4503 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4505 /* create stack frame */
4507 M_LSUB_IMM(REG_SP, 5 * 8, REG_SP);
4509 /* move return address onto stack */
4511 M_AST(REG_RA, REG_SP, 4 * 8);
4512 M_MOV(REG_ITMP3, REG_RA); /* restore return address */
4514 /* move pointer to java_objectheader onto stack */
4516 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4517 M_MOV(REG_RA, REG_ITMP3); /* save return address */
4520 M_LSUB_IMM(REG_RA, 6 * 4 + 2 * 8, REG_RA);
4521 M_AST(REG_RA, REG_SP, 3 * 8);
4522 M_MOV(REG_ITMP3, REG_RA); /* restore return address */
4524 M_AST(REG_ZERO, REG_SP, 3 * 8);
4527 /* move machine code onto stack */
4529 M_LLD(REG_ITMP3, REG_PV, -10 * 8); /* machine code */
4530 M_LST(REG_ITMP3, REG_SP, 2 * 8);
4532 /* move class reference onto stack */
4534 M_ALD(REG_ITMP3, REG_PV, -8 * 8); /* class */
4535 M_AST(REG_ITMP3, REG_SP, 1 * 8);
4537 /* move patcher function pointer onto stack */
4539 M_ALD(REG_ITMP3, REG_PV, -11 * 8); /* patcher function */
4540 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4542 M_ALD(REG_ITMP3, REG_PV, -9 * 8); /* asm_wrapper_patcher */
4548 (void) docacheflush((void*) cs, (char*) mcodeptr - (char*) cs);
4550 /* Check if the stub size is big enough to hold the whole stub generated. */
4551 /* If not, this can lead into unpredictable crashes, because of heap */
4554 if ((s4) ((ptrint) mcodeptr - (ptrint) s) > stubsize * sizeof(u8)) {
4555 throw_cacao_exception_exit(string_java_lang_InternalError,
4556 "Native stub size %d is to small for current stub size %d",
4557 stubsize, (s4) ((ptrint) mcodeptr - (ptrint) s));
4560 #if defined(STATISTICS)
4562 count_nstub_len += NATIVESTUB_SIZE * 8;
4565 /* release dump area */
4567 dump_release(dumpsize);
4569 return (u1 *) (s + NATIVESTUB_OFFSET);
4573 /* function: removenativestub **************************************************
4575 removes a previously created native-stub from memory
4577 *******************************************************************************/
4579 void removenativestub(u1 *stub)
4581 CFREE((u8 *) stub - NATIVESTUB_OFFSET, NATIVESTUB_SIZE * 8);
4585 void docacheflush(u1 *p, long bytelen)
4587 u1 *e = p + bytelen;
4588 long psize = sysconf(_SC_PAGESIZE);
4589 p -= (long) p & (psize - 1);
4590 e += psize - ((((long) e - 1) & (psize - 1)) + 1);
4592 mprotect(p, bytelen, PROT_READ | PROT_WRITE | PROT_EXEC);
4597 * These are local overrides for various environment variables in Emacs.
4598 * Please do not remove this and leave it at the end of the file, where
4599 * Emacs will automagically detect them.
4600 * ---------------------------------------------------------------------
4603 * indent-tabs-mode: t