1 /* jit/i386/codegen.c - machine code generator for i386
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 Institut f. Computersprachen, TU Wien
5 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6 S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
9 This file is part of CACAO.
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2, or (at
14 your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Andreas Krall
31 $Id: codegen.c 1608 2004-11-29 10:24:31Z twisti $
39 #include <sys/ucontext.h>
47 #include "exceptions.h"
53 #include "jit/parse.h"
55 #include "jit/i386/codegen.h"
56 #include "jit/i386/emitfuncs.h"
58 /* register descripton - array ************************************************/
60 /* #define REG_RES 0 reserved register for OS or code generator */
61 /* #define REG_RET 1 return value register */
62 /* #define REG_EXC 2 exception value register (only old jit) */
63 /* #define REG_SAV 3 (callee) saved register */
64 /* #define REG_TMP 4 scratch temporary register (caller saved) */
65 /* #define REG_ARG 5 argument register (caller saved) */
67 /* #define REG_END -1 last entry in tables */
69 static int nregdescint[] = {
70 REG_RET, REG_RES, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV,
75 static int nregdescfloat[] = {
76 /* rounding problems with callee saved registers */
77 /* REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_RES, REG_RES, */
78 /* REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, */
79 REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
84 /*******************************************************************************
86 include independent code generation stuff -- include after register
87 descriptions to avoid extern definitions
89 *******************************************************************************/
91 #include "jit/codegen.inc"
92 #include "jit/reg.inc"
93 #include "jit/lsra.inc"
95 void codegen_stubcalled() {
96 log_text("Stub has been called");
99 void codegen_general_stubcalled() {
100 log_text("general exception stub has been called");
104 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
105 void thread_restartcriticalsection(ucontext_t *uc)
108 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL)
109 uc->uc_mcontext.gregs[REG_EIP] = (u4) critical;
114 #define PREPARE_NATIVE_STACKINFO \
115 i386_push_reg(cd, REG_ITMP1); /*save itmp1, needed by some stubs */ \
116 i386_alu_imm_reg(cd, I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \
117 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1); \
118 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/ \
119 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \
120 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/ \
121 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/ \
122 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \
123 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */ \
124 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \
125 i386_mov_membase_reg(cd, REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \
126 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
129 #define REMOVE_NATIVE_STACKINFO \
130 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2); \
131 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3); \
132 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0); \
133 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
136 /* NullPointerException signal handler for hardware null pointer check */
138 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
141 /* long faultaddr; */
143 struct ucontext *_uc = (struct ucontext *) _p;
144 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
145 struct sigaction act;
147 /* Reset signal handler - necessary for SysV, does no harm for BSD */
149 /* instr = *((int*)(sigctx->eip)); */
150 /* faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f]; */
152 /* fprintf(stderr, "null=%d %p addr=%p\n", sig, sigctx, sigctx->eip);*/
154 /* if (faultaddr == 0) { */
155 /* signal(sig, (void *) catch_NullPointerException); */
156 act.sa_sigaction = (functionptr) catch_NullPointerException;
157 act.sa_flags = SA_SIGINFO;
158 sigaction(sig, &act, NULL); /* reinstall handler */
161 sigaddset(&nsig, sig);
162 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
164 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
165 sigctx->eax = (u4) string_java_lang_NullPointerException;
166 sigctx->eip = (u4) asm_throw_and_handle_exception;
171 /* faultaddr += (long) ((instr << 16) >> 16); */
172 /* fprintf(stderr, "faulting address: 0x%08x\n", faultaddr); */
173 /* panic("Stack overflow"); */
178 /* ArithmeticException signal handler for hardware divide by zero check */
180 void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p)
184 /* void **_p = (void **) &sig; */
185 /* struct sigcontext *sigctx = (struct sigcontext *) ++_p; */
186 struct ucontext *_uc = (struct ucontext *) _p;
187 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
188 struct sigaction act;
190 /* Reset signal handler - necessary for SysV, does no harm for BSD */
192 /* signal(sig, (void *) catch_ArithmeticException); */
193 act.sa_sigaction = (functionptr) catch_ArithmeticException;
194 act.sa_flags = SA_SIGINFO;
195 sigaction(sig, &act, NULL); /* reinstall handler */
198 sigaddset(&nsig, sig);
199 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
201 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
202 sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
208 void init_exceptions(void)
210 struct sigaction act;
212 /* install signal handlers we need to convert to exceptions */
213 sigemptyset(&act.sa_mask);
217 /* signal(SIGSEGV, (void *) catch_NullPointerException); */
218 act.sa_sigaction = (functionptr) catch_NullPointerException;
219 act.sa_flags = SA_SIGINFO;
220 sigaction(SIGSEGV, &act, NULL);
224 /* signal(SIGBUS, (void *) catch_NullPointerException); */
225 act.sa_sigaction = (functionptr) catch_NullPointerException;
226 act.sa_flags = SA_SIGINFO;
227 sigaction(SIGBUS, &act, NULL);
231 /* signal(SIGFPE, (void *) catch_ArithmeticException); */
232 act.sa_sigaction = (functionptr) catch_ArithmeticException;
233 act.sa_flags = SA_SIGINFO;
234 sigaction(SIGFPE, &act, NULL);
238 /* function codegen ************************************************************
240 generates machine code
242 *******************************************************************************/
244 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
246 s4 len, s1, s2, s3, d;
254 s4 fpu_st_offset = 0;
260 s4 savedregs_num = 0;
262 /* space to save used callee saved registers */
264 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
265 savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
267 parentargs_base = rd->maxmemuse + savedregs_num;
270 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
272 if (checksync && (m->flags & ACC_SYNCHRONIZED))
277 /* create method header */
279 (void) dseg_addaddress(cd, m); /* MethodPointer */
280 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
282 #if defined(USE_THREADS)
284 /* IsSync contains the offset relative to the stack pointer for the
285 argument of monitor_exit used in the exception handler. Since the
286 offset could be zero and give a wrong meaning of the flag it is
290 if (checksync && (m->flags & ACC_SYNCHRONIZED))
291 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8); /* IsSync */
296 (void) dseg_adds4(cd, 0); /* IsSync */
298 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
299 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
300 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
302 /* adds a reference for the length of the line number counter. We don't
303 know the size yet, since we evaluate the information during code
304 generation, to save one additional iteration over the whole
305 instructions. During code optimization the position could have changed
306 to the information gotten from the class file */
307 (void) dseg_addlinenumbertablesize(cd);
309 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
311 /* create exception table */
313 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
314 dseg_addtarget(cd, ex->start);
315 dseg_addtarget(cd, ex->end);
316 dseg_addtarget(cd, ex->handler);
317 (void) dseg_addaddress(cd, ex->catchtype);
321 /* initialize mcode variables */
323 cd->mcodeptr = cd->mcodebase;
324 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
325 MCODECHECK(128 + m->paramcount);
327 /* create stack frame (if necessary) */
329 if (parentargs_base) {
330 i386_alu_imm_reg(cd, I386_SUB, parentargs_base * 8, REG_SP);
333 /* save return address and used callee saved registers */
336 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
337 p--; i386_mov_reg_membase(cd, rd->savintregs[i], REG_SP, p * 8);
339 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
340 p--; i386_fld_reg(cd, rd->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 8);
343 /* save monitorenter argument */
345 #if defined(USE_THREADS)
346 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
347 s4 func_enter = (m->flags & ACC_STATIC) ?
348 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
350 if (m->flags & ACC_STATIC) {
351 i386_mov_imm_reg(cd, (s4) m->class, REG_ITMP1);
352 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
355 i386_mov_membase_reg(cd, REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
356 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
359 /* call monitorenter function */
361 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
362 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
363 i386_mov_imm_reg(cd, func_enter, REG_ITMP1);
364 i386_call_reg(cd, REG_ITMP1);
365 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
369 /* copy argument registers to stack and call trace function with pointer
370 to arguments on stack.
374 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
376 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
377 t = m->paramtypes[p];
379 if (IS_INT_LNG_TYPE(t)) {
380 if (IS_2_WORD_TYPE(t)) {
381 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
382 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
383 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
384 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
386 /* } else if (t == TYPE_ADR) { */
388 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
389 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
390 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
391 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
394 /* i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
396 /* i386_mov_reg_membase(cd, EAX, REG_SP, p * 8); */
397 /* i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4); */
401 if (!IS_2_WORD_TYPE(t)) {
402 i386_flds_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
403 i386_fstps_membase(cd, REG_SP, p * 8);
404 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
405 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
408 i386_fldl_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
409 i386_fstpl_membase(cd, REG_SP, p * 8);
414 /* fill up the remaining arguments */
415 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
416 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
417 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
418 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
421 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
422 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
423 i386_call_reg(cd, REG_ITMP1);
425 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
428 /* take arguments out of register or stack frame */
430 for (p = 0, l = 0; p < m->paramcount; p++) {
431 t = m->paramtypes[p];
432 var = &(rd->locals[l][t]);
434 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
438 if (IS_INT_LNG_TYPE(t)) { /* integer args */
439 if (p < rd->intreg_argnum) { /* register arguments */
440 panic("integer register argument");
441 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
442 /* M_INTMOVE (argintregs[p], r); */
444 } else { /* reg arg -> spilled */
445 /* M_LST (argintregs[p], REG_SP, 8 * r); */
447 } else { /* stack arguments */
448 pa = p - rd->intreg_argnum;
449 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
450 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, var->regoff); /* + 4 for return address */
451 } else { /* stack arg -> spilled */
452 if (!IS_2_WORD_TYPE(t)) {
453 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
454 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
457 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
458 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
459 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1); /* + 4 for return address */
460 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8 + 4);
465 } else { /* floating args */
466 if (p < rd->fltreg_argnum) { /* register arguments */
467 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
468 panic("There are no float argument registers!");
470 } else { /* reg arg -> spilled */
471 panic("There are no float argument registers!");
474 } else { /* stack arguments */
475 pa = p - rd->fltreg_argnum;
476 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
478 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
480 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
484 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
486 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
490 } else { /* stack-arg -> spilled */
491 /* i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
492 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r * 8); */
494 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
495 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
498 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
499 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
508 /* end of header generation */
510 /* walk through all basic blocks */
511 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
513 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
515 if (bptr->flags >= BBREACHED) {
517 /* branch resolving */
520 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
521 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
526 /* copy interface registers to their destination */
533 while (src != NULL) {
535 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
536 if (!IS_2_WORD_TYPE(src->type)) {
537 if (bptr->type == BBTYPE_SBR) {
538 /* d = reg_of_var(m, src, REG_ITMP1); */
539 if (!(src->flags & INMEMORY))
544 store_reg_to_var_int(src, d);
545 } else if (bptr->type == BBTYPE_EXH) {
546 /* d = reg_of_var(m, src, REG_ITMP1); */
547 if (!(src->flags & INMEMORY))
551 M_INTMOVE(REG_ITMP1, d);
552 store_reg_to_var_int(src, d);
556 panic("copy interface registers(EXH, SBR): longs have to me in memory (begin 1)");
562 while (src != NULL) {
564 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
565 if (!IS_2_WORD_TYPE(src->type)) {
566 if (bptr->type == BBTYPE_SBR) {
567 d = reg_of_var(rd, src, REG_ITMP1);
569 store_reg_to_var_int(src, d);
570 } else if (bptr->type == BBTYPE_EXH) {
571 d = reg_of_var(rd, src, REG_ITMP1);
572 M_INTMOVE(REG_ITMP1, d);
573 store_reg_to_var_int(src, d);
577 panic("copy interface registers: longs have to me in memory (begin 1)");
581 d = reg_of_var(rd, src, REG_ITMP1);
582 if ((src->varkind != STACKVAR)) {
584 if (IS_FLT_DBL_TYPE(s2)) {
585 s1 = rd->interfaces[len][s2].regoff;
586 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
590 if (s2 == TYPE_FLT) {
591 i386_flds_membase(cd, REG_SP, s1 * 8);
594 i386_fldl_membase(cd, REG_SP, s1 * 8);
597 store_reg_to_var_flt(src, d);
600 s1 = rd->interfaces[len][s2].regoff;
601 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
602 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
606 i386_mov_membase_reg(cd, REG_SP, s1 * 8, d);
608 store_reg_to_var_int(src, d);
611 if (rd->interfaces[len][s2].flags & INMEMORY) {
612 M_LNGMEMMOVE(s1, src->regoff);
615 panic("copy interface registers: longs have to be in memory (begin 2)");
625 /* walk through all instructions */
630 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
631 if (iptr->line != currentline) {
632 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
633 currentline = iptr->line;
636 MCODECHECK(64); /* an instruction usually needs < 64 words */
639 case ICMD_NOP: /* ... ==> ... */
642 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
643 if (src->flags & INMEMORY) {
644 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
647 i386_test_reg_reg(cd, src->regoff, src->regoff);
649 i386_jcc(cd, I386_CC_E, 0);
650 codegen_addxnullrefs(cd, cd->mcodeptr);
653 /* constant operations ************************************************/
655 case ICMD_ICONST: /* ... ==> ..., constant */
656 /* op1 = 0, val.i = constant */
658 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
659 if (iptr->dst->flags & INMEMORY) {
660 i386_mov_imm_membase(cd, iptr->val.i, REG_SP, iptr->dst->regoff * 8);
663 if (iptr->val.i == 0) {
664 i386_alu_reg_reg(cd, I386_XOR, d, d);
667 i386_mov_imm_reg(cd, iptr->val.i, d);
672 case ICMD_LCONST: /* ... ==> ..., constant */
673 /* op1 = 0, val.l = constant */
675 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
676 if (iptr->dst->flags & INMEMORY) {
677 i386_mov_imm_membase(cd, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
678 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
681 panic("LCONST: longs have to be in memory");
685 case ICMD_FCONST: /* ... ==> ..., constant */
686 /* op1 = 0, val.f = constant */
688 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
689 if (iptr->val.f == 0.0) {
694 if (iptr->val.i == 0x80000000) {
698 } else if (iptr->val.f == 1.0) {
702 } else if (iptr->val.f == 2.0) {
709 a = dseg_addfloat(cd, iptr->val.f);
710 i386_mov_imm_reg(cd, 0, REG_ITMP1);
711 dseg_adddata(cd, cd->mcodeptr);
712 i386_flds_membase(cd, REG_ITMP1, a);
715 store_reg_to_var_flt(iptr->dst, d);
718 case ICMD_DCONST: /* ... ==> ..., constant */
719 /* op1 = 0, val.d = constant */
721 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
722 if (iptr->val.d == 0.0) {
727 if (iptr->val.l == 0x8000000000000000LL) {
731 } else if (iptr->val.d == 1.0) {
735 } else if (iptr->val.d == 2.0) {
742 a = dseg_adddouble(cd, iptr->val.d);
743 i386_mov_imm_reg(cd, 0, REG_ITMP1);
744 dseg_adddata(cd, cd->mcodeptr);
745 i386_fldl_membase(cd, REG_ITMP1, a);
748 store_reg_to_var_flt(iptr->dst, d);
751 case ICMD_ACONST: /* ... ==> ..., constant */
752 /* op1 = 0, val.a = constant */
754 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
755 if (iptr->dst->flags & INMEMORY) {
756 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
759 if ((s4) iptr->val.a == 0) {
760 i386_alu_reg_reg(cd, I386_XOR, d, d);
763 i386_mov_imm_reg(cd, (s4) iptr->val.a, d);
769 /* load/store operations **********************************************/
771 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
772 case ICMD_ALOAD: /* op1 = local variable */
774 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
775 if ((iptr->dst->varkind == LOCALVAR) &&
776 (iptr->dst->varnum == iptr->op1)) {
779 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
780 if (iptr->dst->flags & INMEMORY) {
781 if (var->flags & INMEMORY) {
782 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, REG_ITMP1);
783 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
786 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
790 if (var->flags & INMEMORY) {
791 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, iptr->dst->regoff);
794 M_INTMOVE(var->regoff, iptr->dst->regoff);
799 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
800 /* op1 = local variable */
802 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
803 if ((iptr->dst->varkind == LOCALVAR) &&
804 (iptr->dst->varnum == iptr->op1)) {
807 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
808 if (iptr->dst->flags & INMEMORY) {
809 if (var->flags & INMEMORY) {
810 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
813 panic("LLOAD: longs have to be in memory");
817 panic("LLOAD: longs have to be in memory");
821 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
822 /* op1 = local variable */
824 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
825 if ((iptr->dst->varkind == LOCALVAR) &&
826 (iptr->dst->varnum == iptr->op1)) {
829 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
830 if (var->flags & INMEMORY) {
831 i386_flds_membase(cd, REG_SP, var->regoff * 8);
834 i386_fld_reg(cd, var->regoff + fpu_st_offset);
837 store_reg_to_var_flt(iptr->dst, d);
840 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
841 /* op1 = local variable */
843 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
844 if ((iptr->dst->varkind == LOCALVAR) &&
845 (iptr->dst->varnum == iptr->op1)) {
848 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
849 if (var->flags & INMEMORY) {
850 i386_fldl_membase(cd, REG_SP, var->regoff * 8);
853 i386_fld_reg(cd, var->regoff + fpu_st_offset);
856 store_reg_to_var_flt(iptr->dst, d);
859 case ICMD_ISTORE: /* ..., value ==> ... */
860 case ICMD_ASTORE: /* op1 = local variable */
862 if ((src->varkind == LOCALVAR) &&
863 (src->varnum == iptr->op1)) {
866 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
867 if (var->flags & INMEMORY) {
868 if (src->flags & INMEMORY) {
869 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
870 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
873 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 8);
877 var_to_reg_int(s1, src, var->regoff);
878 M_INTMOVE(s1, var->regoff);
882 case ICMD_LSTORE: /* ..., value ==> ... */
883 /* op1 = local variable */
885 if ((src->varkind == LOCALVAR) &&
886 (src->varnum == iptr->op1)) {
889 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
890 if (var->flags & INMEMORY) {
891 if (src->flags & INMEMORY) {
892 M_LNGMEMMOVE(src->regoff, var->regoff);
895 panic("LSTORE: longs have to be in memory");
899 panic("LSTORE: longs have to be in memory");
903 case ICMD_FSTORE: /* ..., value ==> ... */
904 /* op1 = local variable */
906 if ((src->varkind == LOCALVAR) &&
907 (src->varnum == iptr->op1)) {
910 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
911 if (var->flags & INMEMORY) {
912 var_to_reg_flt(s1, src, REG_FTMP1);
913 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
916 var_to_reg_flt(s1, src, var->regoff);
917 /* M_FLTMOVE(s1, var->regoff); */
918 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
923 case ICMD_DSTORE: /* ..., value ==> ... */
924 /* op1 = local variable */
926 if ((src->varkind == LOCALVAR) &&
927 (src->varnum == iptr->op1)) {
930 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
931 if (var->flags & INMEMORY) {
932 var_to_reg_flt(s1, src, REG_FTMP1);
933 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
936 var_to_reg_flt(s1, src, var->regoff);
937 /* M_FLTMOVE(s1, var->regoff); */
938 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
944 /* pop/dup/swap operations ********************************************/
946 /* attention: double and longs are only one entry in CACAO ICMDs */
948 case ICMD_POP: /* ..., value ==> ... */
949 case ICMD_POP2: /* ..., value, value ==> ... */
952 case ICMD_DUP: /* ..., a ==> ..., a, a */
953 M_COPY(src, iptr->dst);
956 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
958 M_COPY(src, iptr->dst);
959 M_COPY(src->prev, iptr->dst->prev);
962 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
964 M_COPY(src, iptr->dst);
965 M_COPY(src->prev, iptr->dst->prev);
966 M_COPY(iptr->dst, iptr->dst->prev->prev);
969 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
971 M_COPY(src, iptr->dst);
972 M_COPY(src->prev, iptr->dst->prev);
973 M_COPY(src->prev->prev, iptr->dst->prev->prev);
974 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
977 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
979 M_COPY(src, iptr->dst);
980 M_COPY(src->prev, iptr->dst->prev);
981 M_COPY(src->prev->prev, iptr->dst->prev->prev);
982 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
983 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev);
986 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
988 M_COPY(src, iptr->dst);
989 M_COPY(src->prev, iptr->dst->prev);
990 M_COPY(src->prev->prev, iptr->dst->prev->prev);
991 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
992 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
993 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
996 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
998 M_COPY(src, iptr->dst->prev);
999 M_COPY(src->prev, iptr->dst);
1003 /* integer operations *************************************************/
1005 case ICMD_INEG: /* ..., value ==> ..., - value */
1007 d = reg_of_var(rd, iptr->dst, REG_NULL);
1008 if (iptr->dst->flags & INMEMORY) {
1009 if (src->flags & INMEMORY) {
1010 if (src->regoff == iptr->dst->regoff) {
1011 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1014 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1015 i386_neg_reg(cd, REG_ITMP1);
1016 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1020 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1021 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1025 if (src->flags & INMEMORY) {
1026 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1027 i386_neg_reg(cd, iptr->dst->regoff);
1030 M_INTMOVE(src->regoff, iptr->dst->regoff);
1031 i386_neg_reg(cd, iptr->dst->regoff);
1036 case ICMD_LNEG: /* ..., value ==> ..., - value */
1038 d = reg_of_var(rd, iptr->dst, REG_NULL);
1039 if (iptr->dst->flags & INMEMORY) {
1040 if (src->flags & INMEMORY) {
1041 if (src->regoff == iptr->dst->regoff) {
1042 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1043 i386_alu_imm_membase(cd, I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1044 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8 + 4);
1047 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1048 i386_neg_reg(cd, REG_ITMP1);
1049 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1050 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1051 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP1);
1052 i386_neg_reg(cd, REG_ITMP1);
1053 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1059 case ICMD_I2L: /* ..., value ==> ..., value */
1061 d = reg_of_var(rd, iptr->dst, REG_NULL);
1062 if (iptr->dst->flags & INMEMORY) {
1063 if (src->flags & INMEMORY) {
1064 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, EAX);
1066 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1067 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1070 M_INTMOVE(src->regoff, EAX);
1072 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1073 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1078 case ICMD_L2I: /* ..., value ==> ..., value */
1080 d = reg_of_var(rd, iptr->dst, REG_NULL);
1081 if (iptr->dst->flags & INMEMORY) {
1082 if (src->flags & INMEMORY) {
1083 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1084 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1088 if (src->flags & INMEMORY) {
1089 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1094 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1096 d = reg_of_var(rd, iptr->dst, REG_NULL);
1097 if (iptr->dst->flags & INMEMORY) {
1098 if (src->flags & INMEMORY) {
1099 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1100 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1101 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1102 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1105 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1106 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1107 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1111 if (src->flags & INMEMORY) {
1112 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1113 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1114 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1117 M_INTMOVE(src->regoff, iptr->dst->regoff);
1118 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1119 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1124 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1126 d = reg_of_var(rd, iptr->dst, REG_NULL);
1127 if (iptr->dst->flags & INMEMORY) {
1128 if (src->flags & INMEMORY) {
1129 if (src->regoff == iptr->dst->regoff) {
1130 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1133 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1134 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, REG_ITMP1);
1135 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1139 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1140 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1144 if (src->flags & INMEMORY) {
1145 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1146 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1149 M_INTMOVE(src->regoff, iptr->dst->regoff);
1150 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1155 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1157 d = reg_of_var(rd, iptr->dst, REG_NULL);
1158 if (iptr->dst->flags & INMEMORY) {
1159 if (src->flags & INMEMORY) {
1160 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1161 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1162 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1163 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1166 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1167 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1168 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1172 if (src->flags & INMEMORY) {
1173 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1174 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1175 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1178 M_INTMOVE(src->regoff, iptr->dst->regoff);
1179 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1180 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1186 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1188 d = reg_of_var(rd, iptr->dst, REG_NULL);
1189 i386_emit_ialu(cd, I386_ADD, src, iptr);
1192 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1193 /* val.i = constant */
1195 d = reg_of_var(rd, iptr->dst, REG_NULL);
1196 i386_emit_ialuconst(cd, I386_ADD, src, iptr);
1199 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1201 d = reg_of_var(rd, iptr->dst, REG_NULL);
1202 if (iptr->dst->flags & INMEMORY) {
1203 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1204 if (src->regoff == iptr->dst->regoff) {
1205 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1206 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1207 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1208 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1210 } else if (src->prev->regoff == iptr->dst->regoff) {
1211 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1212 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1213 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1214 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1217 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1218 i386_alu_membase_reg(cd, I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1219 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1220 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1221 i386_alu_membase_reg(cd, I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1222 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1229 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1230 /* val.l = constant */
1232 d = reg_of_var(rd, iptr->dst, REG_NULL);
1233 if (iptr->dst->flags & INMEMORY) {
1234 if (src->flags & INMEMORY) {
1235 if (src->regoff == iptr->dst->regoff) {
1236 i386_alu_imm_membase(cd, I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1237 i386_alu_imm_membase(cd, I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1240 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1241 i386_alu_imm_reg(cd, I386_ADD, iptr->val.l, REG_ITMP1);
1242 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1243 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1244 i386_alu_imm_reg(cd, I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1245 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1251 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1253 d = reg_of_var(rd, iptr->dst, REG_NULL);
1254 if (iptr->dst->flags & INMEMORY) {
1255 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1256 if (src->prev->regoff == iptr->dst->regoff) {
1257 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1258 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1261 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1262 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1263 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1266 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1267 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1268 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1269 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1271 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1272 if (src->prev->regoff == iptr->dst->regoff) {
1273 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1276 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1277 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1278 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1282 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1283 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1287 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1288 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1289 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1291 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1292 M_INTMOVE(src->prev->regoff, d);
1293 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1295 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1296 /* workaround for reg alloc */
1297 if (src->regoff == iptr->dst->regoff) {
1298 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1299 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1300 M_INTMOVE(REG_ITMP1, d);
1303 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1304 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1308 /* workaround for reg alloc */
1309 if (src->regoff == iptr->dst->regoff) {
1310 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1311 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1312 M_INTMOVE(REG_ITMP1, d);
1315 M_INTMOVE(src->prev->regoff, d);
1316 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1322 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1323 /* val.i = constant */
1325 d = reg_of_var(rd, iptr->dst, REG_NULL);
1326 i386_emit_ialuconst(cd, I386_SUB, src, iptr);
1329 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1331 d = reg_of_var(rd, iptr->dst, REG_NULL);
1332 if (iptr->dst->flags & INMEMORY) {
1333 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1334 if (src->prev->regoff == iptr->dst->regoff) {
1335 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1336 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1337 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1338 i386_alu_reg_membase(cd, I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1341 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1342 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1343 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1344 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1345 i386_alu_membase_reg(cd, I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1346 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1352 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1353 /* val.l = constant */
1355 d = reg_of_var(rd, iptr->dst, REG_NULL);
1356 if (iptr->dst->flags & INMEMORY) {
1357 if (src->flags & INMEMORY) {
1358 if (src->regoff == iptr->dst->regoff) {
1359 i386_alu_imm_membase(cd, I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1360 i386_alu_imm_membase(cd, I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1363 /* TODO: could be size optimized with lea -- see gcc output */
1364 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1365 i386_alu_imm_reg(cd, I386_SUB, iptr->val.l, REG_ITMP1);
1366 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1367 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1368 i386_alu_imm_reg(cd, I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1369 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1375 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1377 d = reg_of_var(rd, iptr->dst, REG_NULL);
1378 if (iptr->dst->flags & INMEMORY) {
1379 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1380 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1381 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1382 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1384 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1385 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1386 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1387 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1389 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1390 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1391 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1392 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1395 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1396 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1397 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1401 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1402 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1403 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1405 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1406 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1407 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1409 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1410 M_INTMOVE(src->regoff, iptr->dst->regoff);
1411 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1414 if (src->regoff == iptr->dst->regoff) {
1415 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1418 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1419 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1425 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1426 /* val.i = constant */
1428 d = reg_of_var(rd, iptr->dst, REG_NULL);
1429 if (iptr->dst->flags & INMEMORY) {
1430 if (src->flags & INMEMORY) {
1431 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1432 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1435 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1436 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1440 if (src->flags & INMEMORY) {
1441 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1444 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1449 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1451 d = reg_of_var(rd, iptr->dst, REG_NULL);
1452 if (iptr->dst->flags & INMEMORY) {
1453 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1454 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX); /* mem -> EAX */
1455 /* optimize move EAX -> REG_ITMP3 is slower??? */
1456 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1457 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1459 /* TODO: optimize move EAX -> REG_ITMP3 */
1460 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); /* mem -> ITMP3 */
1461 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1462 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1464 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP2); /* mem -> ITMP3 */
1465 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1467 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1468 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1469 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1474 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1475 /* val.l = constant */
1477 d = reg_of_var(rd, iptr->dst, REG_NULL);
1478 if (iptr->dst->flags & INMEMORY) {
1479 if (src->flags & INMEMORY) {
1480 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1481 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1482 /* TODO: optimize move EAX -> REG_ITMP3 */
1483 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1484 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1486 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1487 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1488 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1490 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1491 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1492 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1497 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1499 d = reg_of_var(rd, iptr->dst, REG_NULL);
1500 var_to_reg_int(s1, src, REG_ITMP2);
1502 if (src->prev->flags & INMEMORY) {
1503 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1506 M_INTMOVE(src->prev->regoff, EAX);
1509 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1510 i386_jcc(cd, I386_CC_NE, 3 + 6);
1511 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1512 i386_jcc(cd, I386_CC_E, 1 + 2);
1515 i386_idiv_reg(cd, s1);
1517 if (iptr->dst->flags & INMEMORY) {
1518 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1521 M_INTMOVE(EAX, iptr->dst->regoff);
1525 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1527 d = reg_of_var(rd, iptr->dst, REG_NULL);
1528 var_to_reg_int(s1, src, REG_ITMP2);
1530 if (src->prev->flags & INMEMORY) {
1531 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1534 M_INTMOVE(src->prev->regoff, EAX);
1537 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1538 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1539 i386_alu_reg_reg(cd, I386_XOR, EDX, EDX);
1540 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1541 i386_jcc(cd, I386_CC_E, 1 + 2);
1544 i386_idiv_reg(cd, s1);
1546 if (iptr->dst->flags & INMEMORY) {
1547 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8);
1550 M_INTMOVE(EDX, iptr->dst->regoff);
1554 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1555 /* val.i = constant */
1557 /* TODO: optimize for `/ 2' */
1558 var_to_reg_int(s1, src, REG_ITMP1);
1559 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1562 i386_test_reg_reg(cd, d, d);
1564 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1565 i386_jcc(cd, I386_CC_NS, a);
1566 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, d);
1568 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1569 store_reg_to_var_int(iptr->dst, d);
1572 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1573 /* val.i = constant */
1575 d = reg_of_var(rd, iptr->dst, REG_NULL);
1576 if (iptr->dst->flags & INMEMORY) {
1577 if (src->flags & INMEMORY) {
1579 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1581 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1582 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1584 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1585 i386_jcc(cd, I386_CC_NS, a);
1586 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1587 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1588 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1589 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1591 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1592 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1597 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1598 /* val.i = constant */
1600 var_to_reg_int(s1, src, REG_ITMP1);
1601 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1603 M_INTMOVE(s1, REG_ITMP1);
1610 CALCIMMEDIATEBYTES(a, iptr->val.i);
1613 /* TODO: optimize */
1615 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1616 i386_test_reg_reg(cd, s1, s1);
1617 i386_jcc(cd, I386_CC_GE, a);
1618 i386_mov_reg_reg(cd, s1, d);
1619 i386_neg_reg(cd, d);
1620 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1621 i386_neg_reg(cd, d);
1623 /* M_INTMOVE(s1, EAX); */
1624 /* i386_cltd(cd); */
1625 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1626 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1627 /* i386_alu_reg_reg(cd, I386_AND, iptr->val.i, EAX); */
1628 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1629 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1630 /* M_INTMOVE(EAX, d); */
1632 /* i386_alu_reg_reg(cd, I386_XOR, d, d); */
1633 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1634 /* i386_shrd_reg_reg(cd, s1, d); */
1635 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1637 store_reg_to_var_int(iptr->dst, d);
1640 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1641 /* val.l = constant */
1643 d = reg_of_var(rd, iptr->dst, REG_NULL);
1644 if (iptr->dst->flags & INMEMORY) {
1645 if (src->flags & INMEMORY) {
1646 /* Intel algorithm -- does not work, because constant is wrong */
1647 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1); */
1648 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1650 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1651 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1652 /* i386_jcc(cd, I386_CC_NS, offset); */
1653 /* i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1654 /* i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP3); */
1656 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1657 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1658 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1660 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1662 /* i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1); */
1663 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1664 /* i386_alu_reg_reg(cd, I386_SBB, REG_ITMP3, REG_ITMP2); */
1666 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1667 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1669 /* Alpha algorithm */
1671 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1673 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1679 /* TODO: hmm, don't know if this is always correct */
1681 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1683 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1689 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1690 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1692 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1693 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1694 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1695 i386_jcc(cd, I386_CC_GE, a);
1697 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1698 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1700 i386_neg_reg(cd, REG_ITMP1);
1701 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1702 i386_neg_reg(cd, REG_ITMP2);
1704 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1705 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1707 i386_neg_reg(cd, REG_ITMP1);
1708 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1709 i386_neg_reg(cd, REG_ITMP2);
1711 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1712 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1717 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1719 d = reg_of_var(rd, iptr->dst, REG_NULL);
1720 i386_emit_ishift(cd, I386_SHL, src, iptr);
1723 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1724 /* val.i = constant */
1726 d = reg_of_var(rd, iptr->dst, REG_NULL);
1727 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1730 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1732 d = reg_of_var(rd, iptr->dst, REG_NULL);
1733 i386_emit_ishift(cd, I386_SAR, src, iptr);
1736 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1737 /* val.i = constant */
1739 d = reg_of_var(rd, iptr->dst, REG_NULL);
1740 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1743 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1745 d = reg_of_var(rd, iptr->dst, REG_NULL);
1746 i386_emit_ishift(cd, I386_SHR, src, iptr);
1749 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1750 /* val.i = constant */
1752 d = reg_of_var(rd, iptr->dst, REG_NULL);
1753 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1756 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1758 d = reg_of_var(rd, iptr->dst, REG_NULL);
1759 if (iptr->dst->flags & INMEMORY ){
1760 if (src->prev->flags & INMEMORY) {
1761 /* if (src->prev->regoff == iptr->dst->regoff) { */
1762 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1764 /* if (src->flags & INMEMORY) { */
1765 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1767 /* M_INTMOVE(src->regoff, ECX); */
1770 /* i386_test_imm_reg(cd, 32, ECX); */
1771 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1772 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1773 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1); */
1775 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1776 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1779 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1780 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1782 if (src->flags & INMEMORY) {
1783 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1785 M_INTMOVE(src->regoff, ECX);
1788 i386_test_imm_reg(cd, 32, ECX);
1789 i386_jcc(cd, I386_CC_E, 2 + 2);
1790 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1791 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1793 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1794 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1795 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1796 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1802 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1803 /* val.i = constant */
1805 d = reg_of_var(rd, iptr->dst, REG_NULL);
1806 if (iptr->dst->flags & INMEMORY ) {
1807 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1808 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1810 if (iptr->val.i & 0x20) {
1811 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1812 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1813 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1816 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1817 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1820 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1821 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1825 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1827 d = reg_of_var(rd, iptr->dst, REG_NULL);
1828 if (iptr->dst->flags & INMEMORY ){
1829 if (src->prev->flags & INMEMORY) {
1830 /* if (src->prev->regoff == iptr->dst->regoff) { */
1831 /* TODO: optimize */
1832 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1833 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1835 /* if (src->flags & INMEMORY) { */
1836 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1838 /* M_INTMOVE(src->regoff, ECX); */
1841 /* i386_test_imm_reg(cd, 32, ECX); */
1842 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1843 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1844 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1846 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1847 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1848 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1849 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1852 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1853 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1855 if (src->flags & INMEMORY) {
1856 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1858 M_INTMOVE(src->regoff, ECX);
1861 i386_test_imm_reg(cd, 32, ECX);
1862 i386_jcc(cd, I386_CC_E, 2 + 3);
1863 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1864 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1866 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1867 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1868 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1869 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1875 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1876 /* val.i = constant */
1878 d = reg_of_var(rd, iptr->dst, REG_NULL);
1879 if (iptr->dst->flags & INMEMORY ) {
1880 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1881 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1883 if (iptr->val.i & 0x20) {
1884 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1885 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
1886 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1889 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1890 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1893 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1894 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1898 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1900 d = reg_of_var(rd, iptr->dst, REG_NULL);
1901 if (iptr->dst->flags & INMEMORY ){
1902 if (src->prev->flags & INMEMORY) {
1903 /* if (src->prev->regoff == iptr->dst->regoff) { */
1904 /* TODO: optimize */
1905 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1906 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1908 /* if (src->flags & INMEMORY) { */
1909 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1911 /* M_INTMOVE(src->regoff, ECX); */
1914 /* i386_test_imm_reg(cd, 32, ECX); */
1915 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1916 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1917 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2); */
1919 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1920 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
1921 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1922 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1925 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1926 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1928 if (src->flags & INMEMORY) {
1929 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1931 M_INTMOVE(src->regoff, ECX);
1934 i386_test_imm_reg(cd, 32, ECX);
1935 i386_jcc(cd, I386_CC_E, 2 + 2);
1936 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1937 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP3, REG_ITMP3);
1939 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1940 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
1941 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1942 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1948 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1949 /* val.l = constant */
1951 d = reg_of_var(rd, iptr->dst, REG_NULL);
1952 if (iptr->dst->flags & INMEMORY ) {
1953 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1954 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1956 if (iptr->val.i & 0x20) {
1957 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1958 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
1959 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1962 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1963 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
1966 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1967 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1971 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1973 d = reg_of_var(rd, iptr->dst, REG_NULL);
1974 i386_emit_ialu(cd, I386_AND, src, iptr);
1977 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1978 /* val.i = constant */
1980 d = reg_of_var(rd, iptr->dst, REG_NULL);
1981 i386_emit_ialuconst(cd, I386_AND, src, iptr);
1984 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1986 d = reg_of_var(rd, iptr->dst, REG_NULL);
1987 i386_emit_lalu(cd, I386_AND, src, iptr);
1990 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1991 /* val.l = constant */
1993 d = reg_of_var(rd, iptr->dst, REG_NULL);
1994 i386_emit_laluconst(cd, I386_AND, src, iptr);
1997 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1999 d = reg_of_var(rd, iptr->dst, REG_NULL);
2000 i386_emit_ialu(cd, I386_OR, src, iptr);
2003 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2004 /* val.i = constant */
2006 d = reg_of_var(rd, iptr->dst, REG_NULL);
2007 i386_emit_ialuconst(cd, I386_OR, src, iptr);
2010 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2012 d = reg_of_var(rd, iptr->dst, REG_NULL);
2013 i386_emit_lalu(cd, I386_OR, src, iptr);
2016 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2017 /* val.l = constant */
2019 d = reg_of_var(rd, iptr->dst, REG_NULL);
2020 i386_emit_laluconst(cd, I386_OR, src, iptr);
2023 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2025 d = reg_of_var(rd, iptr->dst, REG_NULL);
2026 i386_emit_ialu(cd, I386_XOR, src, iptr);
2029 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2030 /* val.i = constant */
2032 d = reg_of_var(rd, iptr->dst, REG_NULL);
2033 i386_emit_ialuconst(cd, I386_XOR, src, iptr);
2036 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2038 d = reg_of_var(rd, iptr->dst, REG_NULL);
2039 i386_emit_lalu(cd, I386_XOR, src, iptr);
2042 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2043 /* val.l = constant */
2045 d = reg_of_var(rd, iptr->dst, REG_NULL);
2046 i386_emit_laluconst(cd, I386_XOR, src, iptr);
2049 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2050 /* op1 = variable, val.i = constant */
2052 var = &(rd->locals[iptr->op1][TYPE_INT]);
2053 if (var->flags & INMEMORY) {
2054 i386_alu_imm_membase(cd, I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2057 /* `inc reg' is slower on p4's (regarding to ia32 */
2058 /* optimization reference manual and benchmarks) and as fast */
2060 i386_alu_imm_reg(cd, I386_ADD, iptr->val.i, var->regoff);
2065 /* floating operations ************************************************/
2067 #define ROUND_TO_SINGLE \
2068 i386_fstps_membase(cd, REG_SP, -8); \
2069 i386_flds_membase(cd, REG_SP, -8);
2071 #define ROUND_TO_DOUBLE \
2072 i386_fstpl_membase(cd, REG_SP, -8); \
2073 i386_fldl_membase(cd, REG_SP, -8);
2075 #define FPU_SET_24BIT_MODE \
2076 if (!fpu_in_24bit_mode) { \
2077 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2078 fpu_in_24bit_mode = 1; \
2081 #define FPU_SET_53BIT_MODE \
2082 if (fpu_in_24bit_mode) { \
2083 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2084 fpu_in_24bit_mode = 0; \
2087 #define ROUND_TO_SINGLE
2088 #define ROUND_TO_DOUBLE
2089 #define FPU_SET_24BIT_MODE
2090 #define FPU_SET_53BIT_MODE
2092 case ICMD_FNEG: /* ..., value ==> ..., - value */
2095 var_to_reg_flt(s1, src, REG_FTMP1);
2096 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2098 store_reg_to_var_flt(iptr->dst, d);
2101 case ICMD_DNEG: /* ..., value ==> ..., - value */
2104 var_to_reg_flt(s1, src, REG_FTMP1);
2105 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2107 store_reg_to_var_flt(iptr->dst, d);
2110 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2113 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2114 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2115 var_to_reg_flt(s2, src, REG_FTMP2);
2118 store_reg_to_var_flt(iptr->dst, d);
2121 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2124 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2125 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2126 var_to_reg_flt(s2, src, REG_FTMP2);
2129 store_reg_to_var_flt(iptr->dst, d);
2132 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2135 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2136 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2137 var_to_reg_flt(s2, src, REG_FTMP2);
2140 store_reg_to_var_flt(iptr->dst, d);
2143 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2146 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2147 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2148 var_to_reg_flt(s2, src, REG_FTMP2);
2151 store_reg_to_var_flt(iptr->dst, d);
2154 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2157 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2158 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2159 var_to_reg_flt(s2, src, REG_FTMP2);
2163 store_reg_to_var_flt(iptr->dst, d);
2166 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2169 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2170 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2172 /* i386_fldt_mem(cd, subnormal_bias1); */
2173 /* i386_fmulp(cd); */
2175 var_to_reg_flt(s2, src, REG_FTMP2);
2180 /* i386_fldt_mem(cd, subnormal_bias2); */
2181 /* i386_fmulp(cd); */
2183 store_reg_to_var_flt(iptr->dst, d);
2186 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2189 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2190 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2191 var_to_reg_flt(s2, src, REG_FTMP2);
2195 store_reg_to_var_flt(iptr->dst, d);
2198 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2201 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2202 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2204 /* i386_fldt_mem(cd, subnormal_bias1); */
2205 /* i386_fmulp(cd); */
2207 var_to_reg_flt(s2, src, REG_FTMP2);
2212 /* i386_fldt_mem(cd, subnormal_bias2); */
2213 /* i386_fmulp(cd); */
2215 store_reg_to_var_flt(iptr->dst, d);
2218 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2221 /* exchanged to skip fxch */
2222 var_to_reg_flt(s2, src, REG_FTMP2);
2223 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2224 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2225 /* i386_fxch(cd); */
2230 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2231 store_reg_to_var_flt(iptr->dst, d);
2232 i386_ffree_reg(cd, 0);
2237 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2240 /* exchanged to skip fxch */
2241 var_to_reg_flt(s2, src, REG_FTMP2);
2242 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2243 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2244 /* i386_fxch(cd); */
2249 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2250 store_reg_to_var_flt(iptr->dst, d);
2251 i386_ffree_reg(cd, 0);
2256 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2257 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2259 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2260 if (src->flags & INMEMORY) {
2261 i386_fildl_membase(cd, REG_SP, src->regoff * 8);
2265 a = dseg_adds4(cd, 0);
2266 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2267 dseg_adddata(cd, cd->mcodeptr);
2268 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, a);
2269 i386_fildl_membase(cd, REG_ITMP1, a);
2272 store_reg_to_var_flt(iptr->dst, d);
2275 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2276 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2278 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2279 if (src->flags & INMEMORY) {
2280 i386_fildll_membase(cd, REG_SP, src->regoff * 8);
2284 panic("L2F: longs have to be in memory");
2286 store_reg_to_var_flt(iptr->dst, d);
2289 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2291 var_to_reg_flt(s1, src, REG_FTMP1);
2292 d = reg_of_var(rd, iptr->dst, REG_NULL);
2294 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2295 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2296 dseg_adddata(cd, cd->mcodeptr);
2297 i386_fldcw_membase(cd, REG_ITMP1, a);
2299 if (iptr->dst->flags & INMEMORY) {
2300 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2303 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2304 i386_fldcw_membase(cd, REG_ITMP1, a);
2306 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2309 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2311 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2314 a = dseg_adds4(cd, 0);
2315 i386_fistpl_membase(cd, REG_ITMP1, a);
2317 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2319 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2320 i386_fldcw_membase(cd, REG_ITMP1, a);
2322 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2325 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2326 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2329 i386_jcc(cd, I386_CC_NE, a);
2331 /* XXX: change this when we use registers */
2332 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2333 i386_mov_imm_reg(cd, (s4) asm_builtin_f2i, REG_ITMP1);
2334 i386_call_reg(cd, REG_ITMP1);
2336 if (iptr->dst->flags & INMEMORY) {
2337 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2340 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2344 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2346 var_to_reg_flt(s1, src, REG_FTMP1);
2347 d = reg_of_var(rd, iptr->dst, REG_NULL);
2349 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2350 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2351 dseg_adddata(cd, cd->mcodeptr);
2352 i386_fldcw_membase(cd, REG_ITMP1, a);
2354 if (iptr->dst->flags & INMEMORY) {
2355 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2358 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2359 i386_fldcw_membase(cd, REG_ITMP1, a);
2361 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2364 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2366 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2369 a = dseg_adds4(cd, 0);
2370 i386_fistpl_membase(cd, REG_ITMP1, a);
2372 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2374 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2375 i386_fldcw_membase(cd, REG_ITMP1, a);
2377 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2380 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2381 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2384 i386_jcc(cd, I386_CC_NE, a);
2386 /* XXX: change this when we use registers */
2387 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2388 i386_mov_imm_reg(cd, (s4) asm_builtin_d2i, REG_ITMP1);
2389 i386_call_reg(cd, REG_ITMP1);
2391 if (iptr->dst->flags & INMEMORY) {
2392 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2394 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2398 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2400 var_to_reg_flt(s1, src, REG_FTMP1);
2401 d = reg_of_var(rd, iptr->dst, REG_NULL);
2403 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2404 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2405 dseg_adddata(cd, cd->mcodeptr);
2406 i386_fldcw_membase(cd, REG_ITMP1, a);
2408 if (iptr->dst->flags & INMEMORY) {
2409 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2412 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2413 i386_fldcw_membase(cd, REG_ITMP1, a);
2415 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2418 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2420 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2423 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2425 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2427 i386_jcc(cd, I386_CC_NE, a);
2429 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2432 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2434 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2436 i386_jcc(cd, I386_CC_NE, a);
2438 /* XXX: change this when we use registers */
2439 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2440 i386_mov_imm_reg(cd, (s4) asm_builtin_f2l, REG_ITMP1);
2441 i386_call_reg(cd, REG_ITMP1);
2442 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2443 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2446 panic("F2L: longs have to be in memory");
2450 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2452 var_to_reg_flt(s1, src, REG_FTMP1);
2453 d = reg_of_var(rd, iptr->dst, REG_NULL);
2455 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2456 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2457 dseg_adddata(cd, cd->mcodeptr);
2458 i386_fldcw_membase(cd, REG_ITMP1, a);
2460 if (iptr->dst->flags & INMEMORY) {
2461 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2464 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2465 i386_fldcw_membase(cd, REG_ITMP1, a);
2467 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2470 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2472 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2475 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2477 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2479 i386_jcc(cd, I386_CC_NE, a);
2481 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2484 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2486 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2488 i386_jcc(cd, I386_CC_NE, a);
2490 /* XXX: change this when we use registers */
2491 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2492 i386_mov_imm_reg(cd, (s4) asm_builtin_d2l, REG_ITMP1);
2493 i386_call_reg(cd, REG_ITMP1);
2494 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2495 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2498 panic("D2L: longs have to be in memory");
2502 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2504 var_to_reg_flt(s1, src, REG_FTMP1);
2505 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2507 store_reg_to_var_flt(iptr->dst, d);
2510 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2512 var_to_reg_flt(s1, src, REG_FTMP1);
2513 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2515 store_reg_to_var_flt(iptr->dst, d);
2518 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2521 /* exchanged to skip fxch */
2522 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2523 var_to_reg_flt(s1, src, REG_FTMP2);
2524 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2525 /* i386_fxch(cd); */
2529 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2530 i386_jcc(cd, I386_CC_E, 6);
2531 i386_alu_imm_reg(cd, I386_AND, 0x000000ff, EAX);
2533 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2534 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2535 i386_jcc(cd, I386_CC_B, 3 + 5);
2536 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2537 i386_jmp_imm(cd, 3);
2538 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2539 store_reg_to_var_int(iptr->dst, d);
2542 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2545 /* exchanged to skip fxch */
2546 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2547 var_to_reg_flt(s1, src, REG_FTMP2);
2548 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2549 /* i386_fxch(cd); */
2553 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2554 i386_jcc(cd, I386_CC_E, 3);
2555 i386_movb_imm_reg(cd, 1, I386_AH);
2557 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2558 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2559 i386_jcc(cd, I386_CC_B, 3 + 5);
2560 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2561 i386_jmp_imm(cd, 3);
2562 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2563 store_reg_to_var_int(iptr->dst, d);
2567 /* memory operations **************************************************/
2569 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2571 var_to_reg_int(s1, src, REG_ITMP1);
2572 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2573 gen_nullptr_check(s1);
2574 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2575 store_reg_to_var_int(iptr->dst, d);
2578 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2580 var_to_reg_int(s1, src->prev, REG_ITMP1);
2581 var_to_reg_int(s2, src, REG_ITMP2);
2582 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2583 if (iptr->op1 == 0) {
2584 gen_nullptr_check(s1);
2587 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2588 store_reg_to_var_int(iptr->dst, d);
2591 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2593 var_to_reg_int(s1, src->prev, REG_ITMP1);
2594 var_to_reg_int(s2, src, REG_ITMP2);
2595 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2596 if (iptr->op1 == 0) {
2597 gen_nullptr_check(s1);
2601 if (iptr->dst->flags & INMEMORY) {
2602 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2603 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2604 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2605 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2609 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2611 var_to_reg_int(s1, src->prev, REG_ITMP1);
2612 var_to_reg_int(s2, src, REG_ITMP2);
2613 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2614 if (iptr->op1 == 0) {
2615 gen_nullptr_check(s1);
2618 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2619 store_reg_to_var_int(iptr->dst, d);
2622 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2624 var_to_reg_int(s1, src->prev, REG_ITMP1);
2625 var_to_reg_int(s2, src, REG_ITMP2);
2626 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2627 if (iptr->op1 == 0) {
2628 gen_nullptr_check(s1);
2631 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2633 store_reg_to_var_flt(iptr->dst, d);
2636 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2638 var_to_reg_int(s1, src->prev, REG_ITMP1);
2639 var_to_reg_int(s2, src, REG_ITMP2);
2640 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2641 if (iptr->op1 == 0) {
2642 gen_nullptr_check(s1);
2645 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2647 store_reg_to_var_flt(iptr->dst, d);
2650 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2652 var_to_reg_int(s1, src->prev, REG_ITMP1);
2653 var_to_reg_int(s2, src, REG_ITMP2);
2654 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2655 if (iptr->op1 == 0) {
2656 gen_nullptr_check(s1);
2659 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2660 store_reg_to_var_int(iptr->dst, d);
2663 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2665 var_to_reg_int(s1, src->prev, REG_ITMP1);
2666 var_to_reg_int(s2, src, REG_ITMP2);
2667 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2668 if (iptr->op1 == 0) {
2669 gen_nullptr_check(s1);
2672 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2673 store_reg_to_var_int(iptr->dst, d);
2676 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2678 var_to_reg_int(s1, src->prev, REG_ITMP1);
2679 var_to_reg_int(s2, src, REG_ITMP2);
2680 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2681 if (iptr->op1 == 0) {
2682 gen_nullptr_check(s1);
2685 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2686 store_reg_to_var_int(iptr->dst, d);
2690 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2692 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2693 var_to_reg_int(s2, src->prev, REG_ITMP2);
2694 if (iptr->op1 == 0) {
2695 gen_nullptr_check(s1);
2698 var_to_reg_int(s3, src, REG_ITMP3);
2699 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2702 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2704 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2705 var_to_reg_int(s2, src->prev, REG_ITMP2);
2706 if (iptr->op1 == 0) {
2707 gen_nullptr_check(s1);
2711 if (src->flags & INMEMORY) {
2712 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
2713 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2714 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2715 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2719 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2721 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2722 var_to_reg_int(s2, src->prev, REG_ITMP2);
2723 if (iptr->op1 == 0) {
2724 gen_nullptr_check(s1);
2727 var_to_reg_int(s3, src, REG_ITMP3);
2728 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2731 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2733 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2734 var_to_reg_int(s2, src->prev, REG_ITMP2);
2735 if (iptr->op1 == 0) {
2736 gen_nullptr_check(s1);
2739 var_to_reg_flt(s3, src, REG_FTMP1);
2740 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2744 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2746 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2747 var_to_reg_int(s2, src->prev, REG_ITMP2);
2748 if (iptr->op1 == 0) {
2749 gen_nullptr_check(s1);
2752 var_to_reg_flt(s3, src, REG_FTMP1);
2753 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2757 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2759 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2760 var_to_reg_int(s2, src->prev, REG_ITMP2);
2761 if (iptr->op1 == 0) {
2762 gen_nullptr_check(s1);
2765 var_to_reg_int(s3, src, REG_ITMP3);
2766 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2769 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2771 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2772 var_to_reg_int(s2, src->prev, REG_ITMP2);
2773 if (iptr->op1 == 0) {
2774 gen_nullptr_check(s1);
2777 var_to_reg_int(s3, src, REG_ITMP3);
2778 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2781 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2783 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2784 var_to_reg_int(s2, src->prev, REG_ITMP2);
2785 if (iptr->op1 == 0) {
2786 gen_nullptr_check(s1);
2789 var_to_reg_int(s3, src, REG_ITMP3);
2790 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2791 M_INTMOVE(s3, REG_ITMP3);
2794 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2797 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2799 var_to_reg_int(s1, src->prev, REG_ITMP1);
2800 var_to_reg_int(s2, src, REG_ITMP2);
2801 if (iptr->op1 == 0) {
2802 gen_nullptr_check(s1);
2805 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2808 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2810 var_to_reg_int(s1, src->prev, REG_ITMP1);
2811 var_to_reg_int(s2, src, REG_ITMP2);
2812 if (iptr->op1 == 0) {
2813 gen_nullptr_check(s1);
2817 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2818 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2821 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2823 var_to_reg_int(s1, src->prev, REG_ITMP1);
2824 var_to_reg_int(s2, src, REG_ITMP2);
2825 if (iptr->op1 == 0) {
2826 gen_nullptr_check(s1);
2829 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2832 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2834 var_to_reg_int(s1, src->prev, REG_ITMP1);
2835 var_to_reg_int(s2, src, REG_ITMP2);
2836 if (iptr->op1 == 0) {
2837 gen_nullptr_check(s1);
2840 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2843 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2845 var_to_reg_int(s1, src->prev, REG_ITMP1);
2846 var_to_reg_int(s2, src, REG_ITMP2);
2847 if (iptr->op1 == 0) {
2848 gen_nullptr_check(s1);
2851 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2854 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2856 var_to_reg_int(s1, src->prev, REG_ITMP1);
2857 var_to_reg_int(s2, src, REG_ITMP2);
2858 if (iptr->op1 == 0) {
2859 gen_nullptr_check(s1);
2862 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2866 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2867 /* op1 = type, val.a = field address */
2869 /* If the static fields' class is not yet initialized, we do it */
2870 /* now. The call code is generated later. */
2871 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2872 codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
2874 /* This is just for debugging purposes. Is very difficult to */
2875 /* read patched code. Here we patch the following 5 nop's */
2876 /* so that the real code keeps untouched. */
2877 if (showdisassemble) {
2886 a = (u4) &(((fieldinfo *) iptr->val.a)->value);
2887 switch (iptr->op1) {
2890 var_to_reg_int(s2, src, REG_ITMP1);
2891 i386_mov_reg_mem(cd, s2, a);
2894 if (src->flags & INMEMORY) {
2895 /* Using both REG_ITMP1 and REG_ITMP2 is faster than only */
2896 /* using REG_ITMP1 alternating. */
2898 i386_mov_membase_reg(cd, REG_SP, s2 * 8, REG_ITMP1);
2899 i386_mov_membase_reg(cd, REG_SP, s2 * 8 + 4, REG_ITMP2);
2900 i386_mov_reg_mem(cd, REG_ITMP1, a);
2901 i386_mov_reg_mem(cd, REG_ITMP2, a + 4);
2903 panic("PUTSTATIC: longs have to be in memory");
2907 var_to_reg_flt(s2, src, REG_FTMP1);
2908 i386_fstps_mem(cd, a);
2912 var_to_reg_flt(s2, src, REG_FTMP1);
2913 i386_fstpl_mem(cd, a);
2917 throw_cacao_exception_exit(string_java_lang_InternalError,
2918 "Unknown PUTSTATIC operand type %d",
2923 case ICMD_GETSTATIC: /* ... ==> ..., value */
2924 /* op1 = type, val.a = field address */
2926 /* If the static fields' class is not yet initialized, we do it */
2927 /* now. The call code is generated later. */
2928 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2929 codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
2931 /* This is just for debugging purposes. Is very difficult to */
2932 /* read patched code. Here we patch the following 5 nop's */
2933 /* so that the real code keeps untouched. */
2934 if (showdisassemble) {
2943 a = (u4) &(((fieldinfo *) iptr->val.a)->value);
2944 switch (iptr->op1) {
2947 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2948 i386_mov_mem_reg(cd, a, d);
2949 store_reg_to_var_int(iptr->dst, d);
2952 d = reg_of_var(rd, iptr->dst, REG_NULL);
2953 if (iptr->dst->flags & INMEMORY) {
2954 /* Using both REG_ITMP1 and REG_ITMP2 is faster than only */
2955 /* using REG_ITMP1 alternating. */
2956 i386_mov_mem_reg(cd, a, REG_ITMP1);
2957 i386_mov_mem_reg(cd, a + 4, REG_ITMP2);
2958 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2959 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2961 panic("GETSTATIC: longs have to be in memory");
2965 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2966 i386_flds_mem(cd, a);
2968 store_reg_to_var_flt(iptr->dst, d);
2971 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2972 i386_fldl_mem(cd, a);
2974 store_reg_to_var_flt(iptr->dst, d);
2977 throw_cacao_exception_exit(string_java_lang_InternalError,
2978 "Unknown GETSTATIC operand type %d",
2983 case ICMD_PUTFIELD: /* ..., value ==> ... */
2984 /* op1 = type, val.i = field offset */
2986 a = ((fieldinfo *) (iptr->val.a))->offset;
2987 switch (iptr->op1) {
2990 var_to_reg_int(s1, src->prev, REG_ITMP1);
2991 var_to_reg_int(s2, src, REG_ITMP2);
2992 gen_nullptr_check(s1);
2993 i386_mov_reg_membase(cd, s2, s1, a);
2996 var_to_reg_int(s1, src->prev, REG_ITMP1);
2997 gen_nullptr_check(s1);
2998 if (src->flags & INMEMORY) {
2999 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);
3000 i386_mov_reg_membase(cd, REG_ITMP2, s1, a);
3001 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3002 i386_mov_reg_membase(cd, REG_ITMP2, s1, a + 4);
3004 panic("PUTFIELD: longs have to be in memory");
3008 var_to_reg_int(s1, src->prev, REG_ITMP1);
3009 var_to_reg_flt(s2, src, REG_FTMP1);
3010 gen_nullptr_check(s1);
3011 i386_fstps_membase(cd, s1, a);
3015 var_to_reg_int(s1, src->prev, REG_ITMP1);
3016 var_to_reg_flt(s2, src, REG_FTMP1);
3017 gen_nullptr_check(s1);
3018 i386_fstpl_membase(cd, s1, a);
3022 throw_cacao_exception_exit(string_java_lang_InternalError,
3023 "Unknown PUTFIELD operand type %d",
3028 case ICMD_GETFIELD: /* ... ==> ..., value */
3029 /* op1 = type, val.i = field offset */
3031 a = ((fieldinfo *) (iptr->val.a))->offset;
3032 switch (iptr->op1) {
3035 var_to_reg_int(s1, src, REG_ITMP1);
3036 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3037 gen_nullptr_check(s1);
3038 i386_mov_membase_reg(cd, s1, a, d);
3039 store_reg_to_var_int(iptr->dst, d);
3042 var_to_reg_int(s1, src, REG_ITMP1);
3043 d = reg_of_var(rd, iptr->dst, REG_NULL);
3044 gen_nullptr_check(s1);
3045 i386_mov_membase_reg(cd, s1, a, REG_ITMP2);
3046 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
3047 i386_mov_membase_reg(cd, s1, a + 4, REG_ITMP2);
3048 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
3051 var_to_reg_int(s1, src, REG_ITMP1);
3052 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3053 gen_nullptr_check(s1);
3054 i386_flds_membase(cd, s1, a);
3056 store_reg_to_var_flt(iptr->dst, d);
3059 var_to_reg_int(s1, src, REG_ITMP1);
3060 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3061 gen_nullptr_check(s1);
3062 i386_fldl_membase(cd, s1, a);
3064 store_reg_to_var_flt(iptr->dst, d);
3067 throw_cacao_exception_exit(string_java_lang_InternalError,
3068 "Unknown GETFIELD operand type %d",
3074 /* branch operations **************************************************/
3076 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3078 var_to_reg_int(s1, src, REG_ITMP1);
3079 M_INTMOVE(s1, REG_ITMP1_XPTR);
3081 i386_call_imm(cd, 0); /* passing exception pointer */
3082 i386_pop_reg(cd, REG_ITMP2_XPC);
3084 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
3085 i386_jmp_reg(cd, REG_ITMP3);
3089 case ICMD_GOTO: /* ... ==> ... */
3090 /* op1 = target JavaVM pc */
3092 i386_jmp_imm(cd, 0);
3093 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3097 case ICMD_JSR: /* ... ==> ... */
3098 /* op1 = target JavaVM pc */
3100 i386_call_imm(cd, 0);
3101 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3104 case ICMD_RET: /* ... ==> ... */
3105 /* op1 = local variable */
3107 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3108 var_to_reg_int(s1, var, REG_ITMP1);
3109 i386_jmp_reg(cd, s1);
3112 case ICMD_IFNULL: /* ..., value ==> ... */
3113 /* op1 = target JavaVM pc */
3115 if (src->flags & INMEMORY) {
3116 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3119 i386_test_reg_reg(cd, src->regoff, src->regoff);
3121 i386_jcc(cd, I386_CC_E, 0);
3122 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3125 case ICMD_IFNONNULL: /* ..., value ==> ... */
3126 /* op1 = target JavaVM pc */
3128 if (src->flags & INMEMORY) {
3129 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3132 i386_test_reg_reg(cd, src->regoff, src->regoff);
3134 i386_jcc(cd, I386_CC_NE, 0);
3135 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3138 case ICMD_IFEQ: /* ..., value ==> ... */
3139 /* op1 = target JavaVM pc, val.i = constant */
3141 if (src->flags & INMEMORY) {
3142 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3145 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3147 i386_jcc(cd, I386_CC_E, 0);
3148 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3151 case ICMD_IFLT: /* ..., value ==> ... */
3152 /* op1 = target JavaVM pc, val.i = constant */
3154 if (src->flags & INMEMORY) {
3155 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3158 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3160 i386_jcc(cd, I386_CC_L, 0);
3161 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3164 case ICMD_IFLE: /* ..., value ==> ... */
3165 /* op1 = target JavaVM pc, val.i = constant */
3167 if (src->flags & INMEMORY) {
3168 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3171 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3173 i386_jcc(cd, I386_CC_LE, 0);
3174 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3177 case ICMD_IFNE: /* ..., value ==> ... */
3178 /* op1 = target JavaVM pc, val.i = constant */
3180 if (src->flags & INMEMORY) {
3181 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3184 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3186 i386_jcc(cd, I386_CC_NE, 0);
3187 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3190 case ICMD_IFGT: /* ..., value ==> ... */
3191 /* op1 = target JavaVM pc, val.i = constant */
3193 if (src->flags & INMEMORY) {
3194 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3197 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3199 i386_jcc(cd, I386_CC_G, 0);
3200 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3203 case ICMD_IFGE: /* ..., value ==> ... */
3204 /* op1 = target JavaVM pc, val.i = constant */
3206 if (src->flags & INMEMORY) {
3207 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3210 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3212 i386_jcc(cd, I386_CC_GE, 0);
3213 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3216 case ICMD_IF_LEQ: /* ..., value ==> ... */
3217 /* op1 = target JavaVM pc, val.l = constant */
3219 if (src->flags & INMEMORY) {
3220 if (iptr->val.l == 0) {
3221 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3222 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3225 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3226 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3227 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3228 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l, REG_ITMP1);
3229 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3232 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3233 i386_jcc(cd, I386_CC_E, 0);
3234 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3237 case ICMD_IF_LLT: /* ..., value ==> ... */
3238 /* op1 = target JavaVM pc, val.l = constant */
3240 if (src->flags & INMEMORY) {
3241 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3242 i386_jcc(cd, I386_CC_L, 0);
3243 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3246 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3247 CALCIMMEDIATEBYTES(a, iptr->val.l);
3249 i386_jcc(cd, I386_CC_G, a);
3251 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3252 i386_jcc(cd, I386_CC_B, 0);
3253 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3257 case ICMD_IF_LLE: /* ..., value ==> ... */
3258 /* op1 = target JavaVM pc, val.l = constant */
3260 if (src->flags & INMEMORY) {
3261 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3262 i386_jcc(cd, I386_CC_L, 0);
3263 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3266 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3267 CALCIMMEDIATEBYTES(a, iptr->val.l);
3269 i386_jcc(cd, I386_CC_G, a);
3271 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3272 i386_jcc(cd, I386_CC_BE, 0);
3273 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3277 case ICMD_IF_LNE: /* ..., value ==> ... */
3278 /* op1 = target JavaVM pc, val.l = constant */
3280 if (src->flags & INMEMORY) {
3281 if (iptr->val.l == 0) {
3282 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3283 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3286 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3287 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3288 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3289 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3290 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3293 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3294 i386_jcc(cd, I386_CC_NE, 0);
3295 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3298 case ICMD_IF_LGT: /* ..., value ==> ... */
3299 /* op1 = target JavaVM pc, val.l = constant */
3301 if (src->flags & INMEMORY) {
3302 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3303 i386_jcc(cd, I386_CC_G, 0);
3304 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3307 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3308 CALCIMMEDIATEBYTES(a, iptr->val.l);
3310 i386_jcc(cd, I386_CC_L, a);
3312 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3313 i386_jcc(cd, I386_CC_A, 0);
3314 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3318 case ICMD_IF_LGE: /* ..., value ==> ... */
3319 /* op1 = target JavaVM pc, val.l = constant */
3321 if (src->flags & INMEMORY) {
3322 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3323 i386_jcc(cd, I386_CC_G, 0);
3324 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3327 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3328 CALCIMMEDIATEBYTES(a, iptr->val.l);
3330 i386_jcc(cd, I386_CC_L, a);
3332 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3333 i386_jcc(cd, I386_CC_AE, 0);
3334 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3338 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3339 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3341 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3342 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3343 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3345 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3346 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3348 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3349 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3352 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3354 i386_jcc(cd, I386_CC_E, 0);
3355 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3358 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3359 /* op1 = target JavaVM pc */
3361 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3362 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3363 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3364 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3365 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3366 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3367 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3369 i386_jcc(cd, I386_CC_E, 0);
3370 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3373 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3374 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3376 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3377 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3378 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3380 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3381 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3383 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3384 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3387 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3389 i386_jcc(cd, I386_CC_NE, 0);
3390 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3393 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3394 /* op1 = target JavaVM pc */
3396 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3397 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3398 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3399 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3400 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3401 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3402 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3404 i386_jcc(cd, I386_CC_NE, 0);
3405 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3408 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3409 /* op1 = target JavaVM pc */
3411 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3412 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3413 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3415 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3416 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3418 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3419 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3422 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3424 i386_jcc(cd, I386_CC_L, 0);
3425 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3428 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3429 /* op1 = target JavaVM pc */
3431 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3432 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3433 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3434 i386_jcc(cd, I386_CC_L, 0);
3435 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3438 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3439 CALCOFFSETBYTES(a, REG_SP, src->regoff);
3441 i386_jcc(cd, I386_CC_G, a);
3443 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3444 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3445 i386_jcc(cd, I386_CC_B, 0);
3446 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3450 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3451 /* op1 = target JavaVM pc */
3453 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3454 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3455 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3457 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3458 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3460 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3461 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3464 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3466 i386_jcc(cd, I386_CC_G, 0);
3467 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3470 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3471 /* op1 = target JavaVM pc */
3473 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3474 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3475 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3476 i386_jcc(cd, I386_CC_G, 0);
3477 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3480 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3481 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3483 i386_jcc(cd, I386_CC_L, a);
3485 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3486 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3487 i386_jcc(cd, I386_CC_A, 0);
3488 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3492 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3493 /* op1 = target JavaVM pc */
3495 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3496 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3497 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3499 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3500 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3502 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3503 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3506 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3508 i386_jcc(cd, I386_CC_LE, 0);
3509 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3512 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3513 /* op1 = target JavaVM pc */
3515 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3516 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3517 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3518 i386_jcc(cd, I386_CC_L, 0);
3519 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3522 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3523 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3525 i386_jcc(cd, I386_CC_G, a);
3527 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3528 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3529 i386_jcc(cd, I386_CC_BE, 0);
3530 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3534 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3535 /* op1 = target JavaVM pc */
3537 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3538 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3539 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3541 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3542 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3544 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3545 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3548 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3550 i386_jcc(cd, I386_CC_GE, 0);
3551 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3554 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3555 /* op1 = target JavaVM pc */
3557 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3558 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3559 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3560 i386_jcc(cd, I386_CC_G, 0);
3561 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3564 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3565 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3567 i386_jcc(cd, I386_CC_L, a);
3569 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3570 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3571 i386_jcc(cd, I386_CC_AE, 0);
3572 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3576 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3578 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3581 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3582 /* val.i = constant */
3584 d = reg_of_var(rd, iptr->dst, REG_NULL);
3585 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
3588 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3589 /* val.i = constant */
3591 d = reg_of_var(rd, iptr->dst, REG_NULL);
3592 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
3595 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3596 /* val.i = constant */
3598 d = reg_of_var(rd, iptr->dst, REG_NULL);
3599 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
3602 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3603 /* val.i = constant */
3605 d = reg_of_var(rd, iptr->dst, REG_NULL);
3606 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
3609 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3610 /* val.i = constant */
3612 d = reg_of_var(rd, iptr->dst, REG_NULL);
3613 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
3616 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3617 /* val.i = constant */
3619 d = reg_of_var(rd, iptr->dst, REG_NULL);
3620 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
3624 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3627 var_to_reg_int(s1, src, REG_RESULT);
3628 M_INTMOVE(s1, REG_RESULT);
3630 goto nowperformreturn;
3632 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3634 if (src->flags & INMEMORY) {
3635 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_RESULT);
3636 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3639 panic("LRETURN: longs have to be in memory");
3642 goto nowperformreturn;
3644 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3645 case ICMD_DRETURN: /* ..., retvalue ==> ... */
3647 var_to_reg_flt(s1, src, REG_FRESULT);
3648 /* this may be an early return -- keep the offset correct for the
3652 goto nowperformreturn;
3654 case ICMD_RETURN: /* ... ==> ... */
3660 p = parentargs_base;
3662 /* call trace function */
3664 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3666 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3668 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3669 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3671 i386_fstl_membase(cd, REG_SP, 4 + 8);
3672 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3674 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3675 i386_call_reg(cd, REG_ITMP1);
3677 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3678 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3680 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3683 #if defined(USE_THREADS)
3684 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3685 i386_mov_membase_reg(cd, REG_SP, 8 * rd->maxmemuse, REG_ITMP2);
3687 /* we need to save the proper return value */
3688 switch (iptr->opc) {
3691 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
3695 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
3696 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, rd->maxmemuse * 8 + 4);
3700 i386_fsts_membase(cd, REG_SP, rd->maxmemuse * 8);
3704 i386_fstl_membase(cd, REG_SP, rd->maxmemuse * 8);
3708 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
3709 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, 0);
3710 i386_mov_imm_reg(cd, (s4) builtin_monitorexit, REG_ITMP1);
3711 i386_call_reg(cd, REG_ITMP1);
3712 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
3714 /* and now restore the proper return value */
3715 switch (iptr->opc) {
3718 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
3722 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
3723 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8 + 4, REG_RESULT2);
3727 i386_flds_membase(cd, REG_SP, rd->maxmemuse * 8);
3731 i386_fldl_membase(cd, REG_SP, rd->maxmemuse * 8);
3737 /* restore saved registers */
3738 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
3740 i386_mov_membase_reg(cd, REG_SP, p * 8, rd->savintregs[i]);
3742 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
3744 i386_fldl_membase(cd, REG_SP, p * 8);
3746 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3747 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
3749 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
3754 /* deallocate stack */
3755 if (parentargs_base) {
3756 i386_alu_imm_reg(cd, I386_ADD, parentargs_base * 8, REG_SP);
3765 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3770 tptr = (void **) iptr->target;
3772 s4ptr = iptr->val.a;
3773 l = s4ptr[1]; /* low */
3774 i = s4ptr[2]; /* high */
3776 var_to_reg_int(s1, src, REG_ITMP1);
3777 M_INTMOVE(s1, REG_ITMP1);
3779 i386_alu_imm_reg(cd, I386_SUB, l, REG_ITMP1);
3785 i386_alu_imm_reg(cd, I386_CMP, i - 1, REG_ITMP1);
3786 i386_jcc(cd, I386_CC_A, 0);
3788 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
3789 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3791 /* build jump table top down and use address of lowest entry */
3793 /* s4ptr += 3 + i; */
3797 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
3798 dseg_addtarget(cd, (basicblock *) tptr[0]);
3802 /* length of dataseg after last dseg_addtarget is used by load */
3804 i386_mov_imm_reg(cd, 0, REG_ITMP2);
3805 dseg_adddata(cd, cd->mcodeptr);
3806 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3807 i386_jmp_reg(cd, REG_ITMP1);
3813 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3815 s4 i, l, val, *s4ptr;
3818 tptr = (void **) iptr->target;
3820 s4ptr = iptr->val.a;
3821 l = s4ptr[0]; /* default */
3822 i = s4ptr[1]; /* count */
3824 MCODECHECK((i<<2)+8);
3825 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3831 i386_alu_imm_reg(cd, I386_CMP, val, s1);
3832 i386_jcc(cd, I386_CC_E, 0);
3833 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), cd->mcodeptr); */
3834 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3837 i386_jmp_imm(cd, 0);
3838 /* codegen_addreference(cd, BlockPtrOfPC(l), cd->mcodeptr); */
3840 tptr = (void **) iptr->target;
3841 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3848 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3849 /* op1 = return type, val.a = function pointer*/
3853 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3854 /* op1 = return type, val.a = function pointer*/
3858 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3859 /* op1 = return type, val.a = function pointer*/
3863 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3864 /* op1 = arg count, val.a = method pointer */
3866 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3867 /* op1 = arg count, val.a = method pointer */
3869 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3870 /* op1 = arg count, val.a = method pointer */
3872 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3873 /* op1 = arg count, val.a = method pointer */
3880 MCODECHECK((s3 << 1) + 64);
3882 /* copy arguments to registers or stack location */
3884 for (; --s3 >= 0; src = src->prev) {
3885 if (src->varkind == ARGVAR) {
3889 if (IS_INT_LNG_TYPE(src->type)) {
3890 if (s3 < rd->intreg_argnum) {
3891 panic("No integer argument registers available!");
3894 if (!IS_2_WORD_TYPE(src->type)) {
3895 if (src->flags & INMEMORY) {
3896 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3897 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s3 * 8);
3900 i386_mov_reg_membase(cd, src->regoff, REG_SP, s3 * 8);
3904 if (src->flags & INMEMORY) {
3905 M_LNGMEMMOVE(src->regoff, s3);
3908 panic("copy arguments: longs have to be in memory");
3914 if (s3 < rd->fltreg_argnum) {
3915 panic("No float argument registers available!");
3918 var_to_reg_flt(d, src, REG_FTMP1);
3919 if (src->type == TYPE_FLT) {
3920 i386_fstps_membase(cd, REG_SP, s3 * 8);
3923 i386_fstpl_membase(cd, REG_SP, s3 * 8);
3930 switch (iptr->opc) {
3937 i386_mov_imm_reg(cd, a, REG_ITMP1);
3938 i386_call_reg(cd, REG_ITMP1);
3941 case ICMD_INVOKESTATIC:
3942 a = (u4) lm->stubroutine;
3945 i386_mov_imm_reg(cd, a, REG_ITMP2);
3946 i386_call_reg(cd, REG_ITMP2);
3949 case ICMD_INVOKESPECIAL:
3950 a = (u4) lm->stubroutine;
3953 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3954 gen_nullptr_check(REG_ITMP1);
3955 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
3957 i386_mov_imm_reg(cd, a, REG_ITMP2);
3958 i386_call_reg(cd, REG_ITMP2);
3961 case ICMD_INVOKEVIRTUAL:
3964 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3965 gen_nullptr_check(REG_ITMP1);
3966 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
3967 i386_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
3969 i386_call_reg(cd, REG_ITMP1);
3972 case ICMD_INVOKEINTERFACE:
3975 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3976 gen_nullptr_check(REG_ITMP1);
3977 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3978 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * lm->class->index, REG_ITMP2);
3979 i386_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - lm->class->methods), REG_ITMP1);
3981 i386_call_reg(cd, REG_ITMP1);
3985 /* d contains return type */
3987 if (d != TYPE_VOID) {
3988 d = reg_of_var(rd, iptr->dst, REG_NULL);
3990 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3991 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3992 if (iptr->dst->flags & INMEMORY) {
3993 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3994 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
3997 panic("RETURN: longs have to be in memory");
4001 if (iptr->dst->flags & INMEMORY) {
4002 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
4005 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
4010 /* fld from called function -- has other fpu_st_offset counter */
4012 store_reg_to_var_flt(iptr->dst, d);
4019 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
4021 /* op1: 0 == array, 1 == class */
4022 /* val.a: (classinfo*) superclass */
4024 /* superclass is an interface:
4026 * return (sub != NULL) &&
4027 * (sub->vftbl->interfacetablelength > super->index) &&
4028 * (sub->vftbl->interfacetable[-super->index] != NULL);
4030 * superclass is a class:
4032 * return ((sub != NULL) && (0
4033 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4034 * super->vftbl->diffvall));
4038 classinfo *super = (classinfo*) iptr->val.a;
4040 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4041 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4043 var_to_reg_int(s1, src, REG_ITMP1);
4044 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4046 M_INTMOVE(s1, REG_ITMP1);
4049 i386_alu_reg_reg(cd, I386_XOR, d, d);
4050 if (iptr->op1) { /* class/interface */
4051 if (super->flags & ACC_INTERFACE) { /* interface */
4052 i386_test_reg_reg(cd, s1, s1);
4054 /* TODO: clean up this calculation */
4056 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4059 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4062 /* CALCOFFSETBYTES(a, super->index); */
4063 CALCIMMEDIATEBYTES(a, super->index);
4069 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4076 i386_jcc(cd, I386_CC_E, a);
4078 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4079 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4080 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4082 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4084 /* TODO: clean up this calculation */
4087 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4094 i386_jcc(cd, I386_CC_LE, a);
4095 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4097 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP1);
4098 /* i386_setcc_reg(cd, I386_CC_A, d); */
4099 /* i386_jcc(cd, I386_CC_BE, 5); */
4100 i386_jcc(cd, I386_CC_E, 5);
4101 i386_mov_imm_reg(cd, 1, d);
4104 } else { /* class */
4105 i386_test_reg_reg(cd, s1, s1);
4107 /* TODO: clean up this calculation */
4109 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4112 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4114 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4117 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4127 i386_jcc(cd, I386_CC_E, a);
4129 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4130 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4131 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4132 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4134 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4135 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4136 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4137 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4138 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4140 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4141 i386_alu_reg_reg(cd, I386_XOR, d, d);
4143 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4144 i386_jcc(cd, I386_CC_A, 5);
4145 i386_mov_imm_reg(cd, 1, d);
4149 panic ("internal error: no inlined array instanceof");
4151 store_reg_to_var_int(iptr->dst, d);
4154 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4156 /* op1: 0 == array, 1 == class */
4157 /* val.a: (classinfo*) superclass */
4159 /* superclass is an interface:
4161 * OK if ((sub == NULL) ||
4162 * (sub->vftbl->interfacetablelength > super->index) &&
4163 * (sub->vftbl->interfacetable[-super->index] != NULL));
4165 * superclass is a class:
4167 * OK if ((sub == NULL) || (0
4168 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4169 * super->vftbl->diffvall));
4173 classinfo *super = (classinfo*) iptr->val.a;
4175 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4176 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4178 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4179 var_to_reg_int(s1, src, d);
4180 if (iptr->op1) { /* class/interface */
4181 if (super->flags & ACC_INTERFACE) { /* interface */
4182 i386_test_reg_reg(cd, s1, s1);
4184 /* TODO: clean up this calculation */
4186 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4189 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4192 /* CALCOFFSETBYTES(a, super->index); */
4193 CALCIMMEDIATEBYTES(a, super->index);
4199 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4204 i386_jcc(cd, I386_CC_E, a);
4206 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4207 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4208 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4210 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4211 i386_jcc(cd, I386_CC_LE, 0);
4212 codegen_addxcastrefs(cd, cd->mcodeptr);
4213 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
4215 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4216 i386_jcc(cd, I386_CC_E, 0);
4217 codegen_addxcastrefs(cd, cd->mcodeptr);
4219 } else { /* class */
4220 i386_test_reg_reg(cd, s1, s1);
4222 /* TODO: clean up this calculation */
4224 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4229 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4231 if (d != REG_ITMP3) {
4233 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4236 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4242 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4249 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4256 i386_jcc(cd, I386_CC_E, a);
4258 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4259 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4260 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4261 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4263 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4264 if (d != REG_ITMP3) {
4265 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4266 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4267 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4268 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4270 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4273 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
4274 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1);
4275 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4276 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4277 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4278 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4282 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4283 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
4284 codegen_addxcastrefs(cd, cd->mcodeptr);
4288 panic ("internal error: no inlined array checkcast");
4291 store_reg_to_var_int(iptr->dst, d);
4294 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4296 if (src->flags & INMEMORY) {
4297 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4300 i386_test_reg_reg(cd, src->regoff, src->regoff);
4302 i386_jcc(cd, I386_CC_L, 0);
4303 codegen_addxcheckarefs(cd, cd->mcodeptr);
4306 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4308 i386_test_reg_reg(cd, REG_RESULT, REG_RESULT);
4309 i386_jcc(cd, I386_CC_E, 0);
4310 codegen_addxexceptionrefs(cd, cd->mcodeptr);
4313 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4314 /* op1 = dimension, val.a = array descriptor */
4316 /* check for negative sizes and copy sizes to stack if necessary */
4318 MCODECHECK((iptr->op1 << 1) + 64);
4320 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4321 if (src->flags & INMEMORY) {
4322 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4325 i386_test_reg_reg(cd, src->regoff, src->regoff);
4327 i386_jcc(cd, I386_CC_L, 0);
4328 codegen_addxcheckarefs(cd, cd->mcodeptr);
4331 * copy sizes to new stack location, be cause native function
4332 * builtin_nmultianewarray access them as (int *)
4334 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
4335 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);
4337 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
4339 if (src->varkind != ARGVAR) {
4340 if (src->flags & INMEMORY) {
4341 i386_mov_membase_reg(cd, REG_SP, (src->regoff + INT_ARG_CNT) * 8, REG_ITMP1);
4342 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, (s1 + INT_ARG_CNT) * 8);
4345 i386_mov_reg_membase(cd, src->regoff, REG_SP, (s1 + INT_ARG_CNT) * 8);
4349 i386_alu_imm_reg(cd, I386_SUB, iptr->op1 * 4, REG_SP);
4351 /* a0 = dimension count */
4353 /* save stack pointer */
4354 M_INTMOVE(REG_SP, REG_ITMP1);
4356 i386_alu_imm_reg(cd, I386_SUB, 12, REG_SP);
4357 i386_mov_imm_membase(cd, iptr->op1, REG_SP, 0);
4359 /* a1 = arraydescriptor */
4361 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, 4);
4363 /* a2 = pointer to dimensions = stack pointer */
4365 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 8);
4367 i386_mov_imm_reg(cd, (s4) (builtin_nmultianewarray), REG_ITMP1);
4368 i386_call_reg(cd, REG_ITMP1);
4369 i386_alu_imm_reg(cd, I386_ADD, 12 + iptr->op1 * 4, REG_SP);
4371 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
4372 M_INTMOVE(REG_RESULT, s1);
4373 store_reg_to_var_int(iptr->dst, s1);
4376 case ICMD_INLINE_START:
4377 case ICMD_INLINE_END:
4380 error ("Unknown pseudo command: %d", iptr->opc);
4383 } /* for instruction */
4385 /* copy values to interface registers */
4387 src = bptr->outstack;
4388 len = bptr->outdepth;
4393 if ((src->varkind != STACKVAR)) {
4395 if (IS_FLT_DBL_TYPE(s2)) {
4396 var_to_reg_flt(s1, src, REG_FTMP1);
4397 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4398 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
4401 panic("double store");
4402 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4406 var_to_reg_int(s1, src, REG_ITMP1);
4407 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
4408 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4409 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
4412 i386_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
4416 if (rd->interfaces[len][s2].flags & INMEMORY) {
4417 M_LNGMEMMOVE(s1, rd->interfaces[len][s2].regoff);
4420 panic("copy interface registers: longs have to be in memory (end)");
4427 } /* if (bptr -> flags >= BBREACHED) */
4428 } /* for basic block */
4430 codegen_createlinenumbertable(cd);
4434 /* generate bound check stubs */
4436 u1 *xcodeptr = NULL;
4439 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
4440 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4442 cd->mcodeptr - cd->mcodebase);
4446 /* move index register into REG_ITMP1 */
4447 i386_mov_reg_reg(cd, bref->reg, REG_ITMP1); /* 2 bytes */
4449 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4450 dseg_adddata(cd, cd->mcodeptr);
4451 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3); /* 5 bytes */
4452 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4454 if (xcodeptr != NULL) {
4455 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4458 xcodeptr = cd->mcodeptr;
4460 i386_push_reg(cd, REG_ITMP2_XPC);
4462 PREPARE_NATIVE_STACKINFO;
4464 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4465 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 4);
4466 i386_mov_imm_reg(cd, (u4) new_arrayindexoutofboundsexception, REG_ITMP1);
4467 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4468 i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4470 REMOVE_NATIVE_STACKINFO;
4472 i386_pop_reg(cd, REG_ITMP2_XPC);
4474 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4475 i386_jmp_reg(cd, REG_ITMP3);
4479 /* generate negative array size check stubs */
4483 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
4484 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4485 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4487 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4491 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4493 cd->mcodeptr - cd->mcodebase);
4497 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4498 dseg_adddata(cd, cd->mcodeptr);
4499 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4500 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4502 if (xcodeptr != NULL) {
4503 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4506 xcodeptr = cd->mcodeptr;
4508 i386_push_reg(cd, REG_ITMP2_XPC);
4510 PREPARE_NATIVE_STACKINFO;
4512 i386_mov_imm_reg(cd, (u4) new_negativearraysizeexception, REG_ITMP1);
4513 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4514 /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4517 REMOVE_NATIVE_STACKINFO;
4519 i386_pop_reg(cd, REG_ITMP2_XPC);
4521 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4522 i386_jmp_reg(cd, REG_ITMP3);
4526 /* generate cast check stubs */
4530 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
4531 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4532 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4534 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4538 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4540 cd->mcodeptr - cd->mcodebase);
4544 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4545 dseg_adddata(cd, cd->mcodeptr);
4546 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4547 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4549 if (xcodeptr != NULL) {
4550 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4553 xcodeptr = cd->mcodeptr;
4555 i386_push_reg(cd, REG_ITMP2_XPC);
4557 PREPARE_NATIVE_STACKINFO;
4559 i386_mov_imm_reg(cd, (u4) new_classcastexception, REG_ITMP1);
4560 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4561 /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4564 REMOVE_NATIVE_STACKINFO;
4566 i386_pop_reg(cd, REG_ITMP2_XPC);
4568 i386_mov_imm_reg(cd, (u4) asm_handle_exception, REG_ITMP3);
4569 i386_jmp_reg(cd, REG_ITMP3);
4573 /* generate divide by zero check stubs */
4577 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
4578 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4579 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4581 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4585 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4587 cd->mcodeptr - cd->mcodebase);
4591 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4592 dseg_adddata(cd, cd->mcodeptr);
4593 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4594 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4596 if (xcodeptr != NULL) {
4597 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4600 xcodeptr = cd->mcodeptr;
4602 i386_push_reg(cd, REG_ITMP2_XPC);
4604 PREPARE_NATIVE_STACKINFO;
4606 i386_mov_imm_reg(cd, (u4) new_arithmeticexception, REG_ITMP1);
4607 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4609 REMOVE_NATIVE_STACKINFO;
4611 i386_pop_reg(cd, REG_ITMP2_XPC);
4613 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4614 i386_jmp_reg(cd, REG_ITMP3);
4618 /* generate exception check stubs */
4622 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
4623 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4624 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4626 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4630 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4632 cd->mcodeptr - cd->mcodebase);
4636 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4637 dseg_adddata(cd, cd->mcodeptr);
4638 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4639 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4641 if (xcodeptr != NULL) {
4642 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4645 xcodeptr = cd->mcodeptr;
4647 i386_push_reg(cd, REG_ITMP2_XPC);
4649 PREPARE_NATIVE_STACKINFO;
4651 i386_mov_imm_reg(cd, (s4) codegen_general_stubcalled, REG_ITMP1);
4652 i386_call_reg(cd, REG_ITMP1);
4654 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4655 i386_mov_imm_reg(cd, (s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4656 i386_call_reg(cd, REG_ITMP1);
4657 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP3);
4658 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
4659 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1_XPTR);
4661 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP3);
4662 i386_mov_membase_reg(cd, REG_ITMP3, 0, REG_ITMP1_XPTR);
4663 i386_mov_imm_membase(cd, 0, REG_ITMP3, 0);
4665 i386_push_imm(cd, 0);
4666 i386_push_reg(cd, REG_ITMP1_XPTR);
4668 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4669 java stack at this point*/
4670 i386_mov_membase_reg(cd, REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4671 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, class), REG_ITMP1);
4672 i386_push_imm(cd, (u4) utf_fillInStackTrace_desc);
4673 i386_push_imm(cd, (u4) utf_fillInStackTrace_name);
4674 i386_push_reg(cd, REG_ITMP1);
4675 i386_mov_imm_reg(cd, (s4) class_resolvemethod, REG_ITMP3);
4676 i386_call_reg(cd, REG_ITMP3);
4677 /*cleanup parameters of class_resolvemethod*/
4678 i386_alu_imm_reg(cd, I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4679 /*prepare call to asm_calljavafunction2 */
4680 i386_push_imm(cd, 0);
4681 i386_push_imm(cd, TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
4682 i386_push_reg(cd, REG_SP);
4683 i386_push_imm(cd, sizeof(jni_callblock));
4684 i386_push_imm(cd, 1);
4685 i386_push_reg(cd, REG_RESULT);
4687 i386_mov_imm_reg(cd, (s4) asm_calljavafunction2, REG_ITMP3);
4688 i386_call_reg(cd, REG_ITMP3);
4690 /* check exceptionptr + fail (JOWENN)*/
4692 i386_alu_imm_reg(cd, I386_ADD,6*4,REG_SP);
4694 i386_pop_reg(cd, REG_ITMP1_XPTR);
4695 i386_pop_reg(cd, REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4697 REMOVE_NATIVE_STACKINFO;
4699 i386_pop_reg(cd, REG_ITMP2_XPC);
4701 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4702 i386_jmp_reg(cd, REG_ITMP3);
4706 /* generate null pointer check stubs */
4710 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
4711 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4712 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4714 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4718 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4720 cd->mcodeptr - cd->mcodebase);
4724 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4725 dseg_adddata(cd, cd->mcodeptr);
4726 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4727 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4729 if (xcodeptr != NULL) {
4730 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4733 xcodeptr = cd->mcodeptr;
4735 i386_push_reg(cd, REG_ITMP2_XPC);
4737 PREPARE_NATIVE_STACKINFO;
4740 /* create native call block*/
4741 i386_alu_imm_reg(cd, I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4744 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1);
4745 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/
4747 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4748 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
4749 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
4750 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
4751 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4752 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */
4753 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4756 i386_mov_imm_reg(cd, (u4) new_nullpointerexception, REG_ITMP1);
4757 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4759 REMOVE_NATIVE_STACKINFO;
4762 /* restore native call stack */
4763 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2);
4764 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3);
4765 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0);
4766 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
4769 i386_pop_reg(cd, REG_ITMP2_XPC);
4771 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4772 i386_jmp_reg(cd, REG_ITMP3);
4776 /* generate put/getstatic stub call code */
4784 tmpcd = DNEW(codegendata);
4786 for (cref = cd->clinitrefs; cref != NULL; cref = cref->next) {
4787 /* Get machine code which is patched back in later. A */
4788 /* `call rel32' is 5 bytes long. */
4789 xcodeptr = cd->mcodebase + cref->branchpos;
4791 mcode = *((u4 *) (xcodeptr + 1));
4795 /* patch in `call rel32' to call the following code */
4796 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
4797 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
4799 /* Save current stack pointer into a temporary register. */
4800 i386_mov_reg_reg(cd, REG_SP, REG_ITMP1);
4802 /* Push machine code bytes to patch onto the stack. */
4803 i386_push_imm(cd, (u4) xmcode);
4804 i386_push_imm(cd, (u4) mcode);
4806 i386_push_imm(cd, (u4) cref->class);
4808 /* Push previously saved stack pointer onto stack. */
4809 i386_push_reg(cd, REG_ITMP1);
4811 i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP1);
4812 i386_jmp_reg(cd, REG_ITMP1);
4817 codegen_finish(m, cd, (u4) (cd->mcodeptr - cd->mcodebase));
4821 /* function createcompilerstub *************************************************
4823 creates a stub routine which calls the compiler
4825 *******************************************************************************/
4827 #define COMPSTUBSIZE 12
4829 u1 *createcompilerstub(methodinfo *m)
4831 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
4835 /* mark start of dump memory area */
4837 dumpsize = dump_size();
4839 cd = DNEW(codegendata);
4842 /* code for the stub */
4843 i386_mov_imm_reg(cd, (u4) m, REG_ITMP1);/* pass method pointer to compiler*/
4845 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
4846 i386_mov_imm_reg(cd, (u4) asm_call_jit_compiler, REG_ITMP3);
4847 i386_jmp_reg(cd, REG_ITMP3); /* jump to compiler */
4849 #if defined(STATISTICS)
4851 count_cstub_len += COMPSTUBSIZE;
4854 /* release dump area */
4856 dump_release(dumpsize);
4862 /* function removecompilerstub *************************************************
4864 deletes a compilerstub from memory (simply by freeing it)
4866 *******************************************************************************/
4868 void removecompilerstub(u1 *stub)
4870 CFREE(stub, COMPSTUBSIZE);
4874 /* function: createnativestub **************************************************
4876 creates a stub routine which calls a native method
4878 *******************************************************************************/
4880 #define NATIVESTUBSIZE 370 + 36
4883 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4884 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4887 void i386_native_stub_debug(void **p) {
4888 printf("Pos on stack: %p\n",p);
4889 printf("Return adress should be: %p\n",*p);
4892 void i386_native_stub_debug2(void **p) {
4893 printf("Pos on stack: %p\n",p);
4894 printf("Return for lookup is: %p\n",*p);
4897 void traverseStackInfo() {
4898 void **p=builtin_asm_get_stackframeinfo();
4902 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4903 m=*((methodinfo**)((*p)+8));
4904 utf_display(m->name);
4913 u1 *createnativestub(functionptr f, methodinfo *m)
4915 u1 *s = CNEW(u1, NATIVESTUBSIZE); /* memory to hold the stub */
4918 t_inlining_globals *id;
4924 int stackframesize = 4+12; /* initial 4 bytes is space for jni env,
4925 + 4 byte thread pointer + 4 byte previous pointer + method info*/
4926 int stackframeoffset = 4;
4930 void** callAddrPatchPos=0;
4932 void** jmpInstrPatchPos=0;
4934 /* mark start of dump memory area */
4936 dumpsize = dump_size();
4938 /* allocate required dump memory */
4940 cd = DNEW(codegendata);
4941 rd = DNEW(registerdata);
4942 id = DNEW(t_inlining_globals);
4944 /* setup registers before using it */
4946 inlining_setup(m, id);
4947 reg_setup(m, rd, id);
4949 /* set some required varibles which are normally set by codegen_setup */
4952 cd->clinitrefs = NULL;
4954 if (m->flags & ACC_STATIC) {
4955 stackframesize += 4;
4956 stackframeoffset += 4;
4959 descriptor2types(m); /* set paramcount and paramtypes */
4962 /* i386_push_reg(cd, REG_SP);
4963 i386_mov_imm_reg(cd, (s4) i386_native_stub_debug, REG_ITMP1);
4964 i386_call_reg(cd, REG_ITMP1);
4965 i386_pop_reg(cd, REG_ITMP1);*/
4968 /* if function is static, check for initialized */
4970 if (m->flags & ACC_STATIC) {
4971 /* if class isn't yet initialized, do it */
4972 if (!m->class->initialized) {
4973 s4 *header = (s4 *) s;
4974 *header = 0;/*extablesize*/
4976 *header = 0;/*line number table start*/
4978 *header = 0;/*line number table size*/
4980 *header = 0;/*fltsave*/
4982 *header = 0;/*intsave*/
4984 *header = 0;/*isleaf*/
4986 *header = 0;/*issync*/
4988 *header = 0;/*framesize*/
4990 *header = (u4) m;/*methodpointer*/
4999 codegen_addclinitref(cd, cd->mcodeptr, m->class);
5004 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
5006 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
5007 t = m->paramtypes[p];
5008 if (IS_INT_LNG_TYPE(t)) {
5009 if (IS_2_WORD_TYPE(t)) {
5010 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
5011 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
5012 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5013 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5015 } else if (t == TYPE_ADR) {
5016 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
5017 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
5018 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5019 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5022 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
5024 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
5025 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
5029 if (!IS_2_WORD_TYPE(t)) {
5030 i386_flds_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
5031 i386_fstps_membase(cd, REG_SP, p * 8);
5032 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
5033 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5036 i386_fldl_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
5037 i386_fstpl_membase(cd, REG_SP, p * 8);
5042 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
5043 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
5044 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5045 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
5048 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
5050 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
5051 i386_call_reg(cd, REG_ITMP1);
5053 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
5057 * mark the whole fpu stack as free for native functions
5058 * (only for saved register count == 0)
5060 i386_ffree_reg(cd, 0);
5061 i386_ffree_reg(cd, 1);
5062 i386_ffree_reg(cd, 2);
5063 i386_ffree_reg(cd, 3);
5064 i386_ffree_reg(cd, 4);
5065 i386_ffree_reg(cd, 5);
5066 i386_ffree_reg(cd, 6);
5067 i386_ffree_reg(cd, 7);
5069 /* calculate stackframe size for native function */
5070 tptr = m->paramtypes;
5071 for (i = 0; i < m->paramcount; i++) {
5076 stackframesize += 4;
5081 stackframesize += 8;
5085 panic("unknown parameter type in native function");
5089 i386_alu_imm_reg(cd, I386_SUB, stackframesize, REG_SP);
5091 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
5092 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
5093 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
5094 i386_call_reg(cd, REG_ITMP1);
5095 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
5096 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2);
5097 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
5098 i386_mov_reg_reg(cd, REG_SP,REG_ITMP2);
5099 i386_alu_imm_reg(cd, I386_ADD,stackframesize-12,REG_ITMP2);
5100 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0);
5103 /* i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
5104 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
5105 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-12);*/
5107 /* CREATE DYNAMIC STACK INFO -- END*/
5109 /* RESOLVE NATIVE METHOD -- BEGIN*/
5110 #ifndef STATIC_CLASSPATH
5112 log_text("Dynamic classpath: preparing for delayed native function resolving");
5114 jmpInstrPos=cd->mcodeptr-4;
5116 i386_mov_imm_reg(cd,jmpInstrPos,REG_ITMP1);
5117 i386_push_reg(cd,REG_ITMP1);
5119 i386_mov_imm_reg(cd,0,REG_ITMP1);
5120 jmpInstrPatchPos=cd->mcodeptr-4;
5121 i386_push_reg(cd,REG_ITMP1);
5122 /*position of call address to patch*/
5123 i386_mov_imm_reg(cd,0,REG_ITMP1);
5124 callAddrPatchPos=(cd->mcodeptr-4);
5125 i386_push_reg(cd,REG_ITMP1);
5126 /*method info structure*/
5127 i386_mov_imm_reg(cd,(s4) m, REG_ITMP1);
5128 i386_push_reg(cd,REG_ITMP1);
5129 /*call resolve functions*/
5130 i386_mov_imm_reg(cd, (s4)codegen_resolve_native,REG_ITMP1);
5131 i386_call_reg(cd,REG_ITMP1);
5133 i386_pop_reg(cd,REG_ITMP1);
5134 i386_pop_reg(cd,REG_ITMP1);
5135 i386_pop_reg(cd,REG_ITMP1);
5136 i386_pop_reg(cd,REG_ITMP1);
5137 /*fix jmp offset replacement*/
5138 (*jmpInstrPatchPos)=cd->mcodeptr-jmpInstrPos-4;
5139 } else log_text("Dynamic classpath: immediate native function resolution possible");
5141 /* RESOLVE NATIVE METHOD -- END*/
5145 tptr = m->paramtypes;
5146 for (i = 0; i < m->paramcount; i++) {
5151 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5152 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5153 stackframeoffset += 4;
5158 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5159 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5160 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5161 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, stackframeoffset + 4);
5162 stackframeoffset += 8;
5166 panic("unknown parameter type in native function");
5170 if (m->flags & ACC_STATIC) {
5171 /* put class into second argument */
5172 i386_mov_imm_membase(cd, (s4) m->class, REG_SP, 4);
5175 /* put env into first argument */
5176 i386_mov_imm_membase(cd, (s4) &env, REG_SP, 0);
5178 i386_mov_imm_reg(cd, (s4) f, REG_ITMP1);
5179 #ifndef STATIC_CLASSPATH
5181 (*callAddrPatchPos)=(cd->mcodeptr-4);
5183 i386_call_reg(cd, REG_ITMP1);
5185 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5186 i386_push_reg(cd, REG_RESULT2);
5187 i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
5188 i386_mov_membase_reg(cd, REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
5189 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT2,0);
5190 i386_pop_reg(cd, REG_RESULT2);
5191 /*REMOVE DYNAMIC STACK INFO -END */
5193 i386_alu_imm_reg(cd, I386_ADD, stackframesize, REG_SP);
5197 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5199 i386_mov_imm_membase(cd, (u4) m, REG_SP, 0);
5201 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
5202 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
5204 i386_fstl_membase(cd, REG_SP, 4 + 8);
5205 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5207 i386_mov_imm_reg(cd, (u4) builtin_displaymethodstop, REG_ITMP1);
5208 i386_call_reg(cd, REG_ITMP1);
5210 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
5211 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
5213 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5216 /* we can't use REG_ITMP3 == REG_RESULT2 */
5217 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5218 i386_push_reg(cd, REG_RESULT);
5219 i386_push_reg(cd, REG_RESULT2);
5220 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5221 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP2);
5222 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5223 i386_pop_reg(cd, REG_RESULT2);
5224 i386_pop_reg(cd, REG_RESULT);
5226 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5227 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP2);
5228 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5230 i386_jcc(cd, I386_CC_NE, 1);
5234 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5235 i386_push_reg(cd, REG_ITMP2);
5236 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5237 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5238 i386_pop_reg(cd, REG_ITMP1_XPTR);
5240 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1_XPTR);
5241 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5242 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5244 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP2_XPC);
5245 i386_alu_imm_reg(cd, I386_SUB, 2, REG_ITMP2_XPC);
5247 i386_mov_imm_reg(cd, (s4) asm_handle_nat_exception, REG_ITMP3);
5248 i386_jmp_reg(cd, REG_ITMP3);
5251 codegen_insertmethod(s, cd->mcodeptr);
5261 tmpcd = DNEW(codegendata);
5263 /* there can only be one clinit ref entry */
5264 cref = cd->clinitrefs;
5267 /* Get machine code which is patched back in later. A */
5268 /* `call rel32' is 5 bytes long. */
5269 xcodeptr = cd->mcodebase + cref->branchpos;
5271 mcode = *((u4 *) (xcodeptr + 1));
5273 /* patch in `call rel32' to call the following code */
5274 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5275 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5277 /* Save current stack pointer into a temporary register. */
5278 i386_mov_reg_reg(cd, REG_SP, REG_ITMP1);
5280 /* Push machine code bytes to patch onto the stack. */
5281 i386_push_imm(cd, (u4) xmcode);
5282 i386_push_imm(cd, (u4) mcode);
5284 i386_push_imm(cd, (u4) cref->class);
5286 /* Push previously saved stack pointer onto stack. */
5287 i386_push_reg(cd, REG_ITMP1);
5289 i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP1);
5290 i386_jmp_reg(cd, REG_ITMP1);
5295 dolog_plain("native stubentry: %p, stubsize: %d (for %d params) --", (s4)s,(s4) (cd->mcodeptr - s), m->paramcount);
5296 utf_display(m->name);
5300 #if defined(STATISTICS)
5302 count_nstub_len += NATIVESTUBSIZE;
5305 /* release dump area */
5307 dump_release(dumpsize);
5313 /* function: removenativestub **************************************************
5315 removes a previously created native-stub from memory
5317 *******************************************************************************/
5319 void removenativestub(u1 *stub)
5321 CFREE(stub, NATIVESTUBSIZE);
5326 * These are local overrides for various environment variables in Emacs.
5327 * Please do not remove this and leave it at the end of the file, where
5328 * Emacs will automagically detect them.
5329 * ---------------------------------------------------------------------
5332 * indent-tabs-mode: t