1 /* vm/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 1641 2004-12-01 13:13:31Z christian $
42 #include "native/jni.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
45 #include "vm/exceptions.h"
46 #include "vm/global.h"
47 #include "vm/loader.h"
48 #include "vm/tables.h"
49 #include "vm/jit/asmpart.h"
50 #include "vm/jit/jit.h"
51 #include "vm/jit/parse.h"
52 #include "vm/jit/reg.h"
53 #include "vm/jit/i386/codegen.h"
54 #include "vm/jit/i386/emitfuncs.h"
55 #include "vm/jit/i386/types.h"
57 /* register descripton - array ************************************************/
59 /* #define REG_RES 0 reserved register for OS or code generator */
60 /* #define REG_RET 1 return value register */
61 /* #define REG_EXC 2 exception value register (only old jit) */
62 /* #define REG_SAV 3 (callee) saved register */
63 /* #define REG_TMP 4 scratch temporary register (caller saved) */
64 /* #define REG_ARG 5 argument register (caller saved) */
66 /* #define REG_END -1 last entry in tables */
68 static int nregdescint[] = {
69 REG_RET, REG_RES, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV,
74 static int nregdescfloat[] = {
75 /* rounding problems with callee saved registers */
76 /* REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_RES, REG_RES, */
77 /* REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, */
78 REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
83 /*******************************************************************************
85 include independent code generation stuff -- include after register
86 descriptions to avoid extern definitions
88 *******************************************************************************/
90 #include "vm/jit/codegen.inc"
91 #include "vm/jit/reg.inc"
93 #include "vm/jit/lsra.inc"
96 void codegen_stubcalled() {
97 log_text("Stub has been called");
100 void codegen_general_stubcalled() {
101 log_text("general exception stub has been called");
105 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
106 void thread_restartcriticalsection(ucontext_t *uc)
109 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL)
110 uc->uc_mcontext.gregs[REG_EIP] = (u4) critical;
115 #define PREPARE_NATIVE_STACKINFO \
116 i386_push_reg(cd, REG_ITMP1); /*save itmp1, needed by some stubs */ \
117 i386_alu_imm_reg(cd, I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \
118 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1); \
119 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/ \
120 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \
121 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/ \
122 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/ \
123 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \
124 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */ \
125 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \
126 i386_mov_membase_reg(cd, REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \
127 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
130 #define REMOVE_NATIVE_STACKINFO \
131 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2); \
132 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3); \
133 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0); \
134 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
137 /* NullPointerException signal handler for hardware null pointer check */
139 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
142 /* long faultaddr; */
144 struct ucontext *_uc = (struct ucontext *) _p;
145 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
146 struct sigaction act;
148 /* Reset signal handler - necessary for SysV, does no harm for BSD */
150 /* instr = *((int*)(sigctx->eip)); */
151 /* faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f]; */
153 /* fprintf(stderr, "null=%d %p addr=%p\n", sig, sigctx, sigctx->eip);*/
155 /* if (faultaddr == 0) { */
156 /* signal(sig, (void *) catch_NullPointerException); */
157 act.sa_sigaction = (functionptr) catch_NullPointerException;
158 act.sa_flags = SA_SIGINFO;
159 sigaction(sig, &act, NULL); /* reinstall handler */
162 sigaddset(&nsig, sig);
163 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
165 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
166 sigctx->eax = (u4) string_java_lang_NullPointerException;
167 sigctx->eip = (u4) asm_throw_and_handle_exception;
172 /* faultaddr += (long) ((instr << 16) >> 16); */
173 /* fprintf(stderr, "faulting address: 0x%08x\n", faultaddr); */
174 /* panic("Stack overflow"); */
179 /* ArithmeticException signal handler for hardware divide by zero check */
181 void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p)
185 /* void **_p = (void **) &sig; */
186 /* struct sigcontext *sigctx = (struct sigcontext *) ++_p; */
187 struct ucontext *_uc = (struct ucontext *) _p;
188 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
189 struct sigaction act;
191 /* Reset signal handler - necessary for SysV, does no harm for BSD */
193 /* signal(sig, (void *) catch_ArithmeticException); */
194 act.sa_sigaction = (functionptr) catch_ArithmeticException;
195 act.sa_flags = SA_SIGINFO;
196 sigaction(sig, &act, NULL); /* reinstall handler */
199 sigaddset(&nsig, sig);
200 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
202 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
203 sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
209 void init_exceptions(void)
211 struct sigaction act;
213 /* install signal handlers we need to convert to exceptions */
214 sigemptyset(&act.sa_mask);
218 /* signal(SIGSEGV, (void *) catch_NullPointerException); */
219 act.sa_sigaction = (functionptr) catch_NullPointerException;
220 act.sa_flags = SA_SIGINFO;
221 sigaction(SIGSEGV, &act, NULL);
225 /* signal(SIGBUS, (void *) catch_NullPointerException); */
226 act.sa_sigaction = (functionptr) catch_NullPointerException;
227 act.sa_flags = SA_SIGINFO;
228 sigaction(SIGBUS, &act, NULL);
232 /* signal(SIGFPE, (void *) catch_ArithmeticException); */
233 act.sa_sigaction = (functionptr) catch_ArithmeticException;
234 act.sa_flags = SA_SIGINFO;
235 sigaction(SIGFPE, &act, NULL);
239 /* function codegen ************************************************************
241 generates machine code
243 *******************************************************************************/
245 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
247 s4 len, s1, s2, s3, d;
255 s4 fpu_st_offset = 0;
261 s4 savedregs_num = 0;
263 /* space to save used callee saved registers */
265 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
266 savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
268 parentargs_base = rd->maxmemuse + savedregs_num;
271 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
273 if (checksync && (m->flags & ACC_SYNCHRONIZED))
278 /* create method header */
280 (void) dseg_addaddress(cd, m); /* MethodPointer */
281 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
283 #if defined(USE_THREADS)
285 /* IsSync contains the offset relative to the stack pointer for the
286 argument of monitor_exit used in the exception handler. Since the
287 offset could be zero and give a wrong meaning of the flag it is
291 if (checksync && (m->flags & ACC_SYNCHRONIZED))
292 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8); /* IsSync */
297 (void) dseg_adds4(cd, 0); /* IsSync */
299 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
300 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
301 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
303 /* adds a reference for the length of the line number counter. We don't
304 know the size yet, since we evaluate the information during code
305 generation, to save one additional iteration over the whole
306 instructions. During code optimization the position could have changed
307 to the information gotten from the class file */
308 (void) dseg_addlinenumbertablesize(cd);
310 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
312 /* create exception table */
314 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
315 dseg_addtarget(cd, ex->start);
316 dseg_addtarget(cd, ex->end);
317 dseg_addtarget(cd, ex->handler);
318 (void) dseg_addaddress(cd, ex->catchtype);
322 /* initialize mcode variables */
324 cd->mcodeptr = cd->mcodebase;
325 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
326 MCODECHECK(128 + m->paramcount);
328 /* create stack frame (if necessary) */
330 if (parentargs_base) {
331 i386_alu_imm_reg(cd, I386_SUB, parentargs_base * 8, REG_SP);
334 /* save return address and used callee saved registers */
337 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
338 p--; i386_mov_reg_membase(cd, rd->savintregs[i], REG_SP, p * 8);
340 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
341 p--; i386_fld_reg(cd, rd->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 8);
344 /* save monitorenter argument */
346 #if defined(USE_THREADS)
347 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
348 s4 func_enter = (m->flags & ACC_STATIC) ?
349 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
351 if (m->flags & ACC_STATIC) {
352 i386_mov_imm_reg(cd, (s4) m->class, REG_ITMP1);
353 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
356 i386_mov_membase_reg(cd, REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
357 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
360 /* call monitorenter function */
362 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
363 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
364 i386_mov_imm_reg(cd, func_enter, REG_ITMP1);
365 i386_call_reg(cd, REG_ITMP1);
366 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
370 /* copy argument registers to stack and call trace function with pointer
371 to arguments on stack.
375 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
377 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
378 t = m->paramtypes[p];
380 if (IS_INT_LNG_TYPE(t)) {
381 if (IS_2_WORD_TYPE(t)) {
382 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
383 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
384 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
385 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
387 /* } else if (t == TYPE_ADR) { */
389 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
390 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
391 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
392 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
395 /* i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
397 /* i386_mov_reg_membase(cd, EAX, REG_SP, p * 8); */
398 /* i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4); */
402 if (!IS_2_WORD_TYPE(t)) {
403 i386_flds_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
404 i386_fstps_membase(cd, REG_SP, p * 8);
405 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
406 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
409 i386_fldl_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
410 i386_fstpl_membase(cd, REG_SP, p * 8);
415 /* fill up the remaining arguments */
416 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
417 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
418 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
419 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
422 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
423 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
424 i386_call_reg(cd, REG_ITMP1);
426 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
429 /* take arguments out of register or stack frame */
431 for (p = 0, l = 0; p < m->paramcount; p++) {
432 t = m->paramtypes[p];
433 var = &(rd->locals[l][t]);
435 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
439 if (IS_INT_LNG_TYPE(t)) { /* integer args */
440 if (p < rd->intreg_argnum) { /* register arguments */
441 panic("integer register argument");
442 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
443 /* M_INTMOVE (argintregs[p], r); */
445 } else { /* reg arg -> spilled */
446 /* M_LST (argintregs[p], REG_SP, 8 * r); */
448 } else { /* stack arguments */
449 pa = p - rd->intreg_argnum;
450 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
451 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, var->regoff); /* + 4 for return address */
452 } else { /* stack arg -> spilled */
453 if (!IS_2_WORD_TYPE(t)) {
454 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
455 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
458 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
459 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
460 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1); /* + 4 for return address */
461 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8 + 4);
466 } else { /* floating args */
467 if (p < rd->fltreg_argnum) { /* register arguments */
468 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
469 panic("There are no float argument registers!");
471 } else { /* reg arg -> spilled */
472 panic("There are no float argument registers!");
475 } else { /* stack arguments */
476 pa = p - rd->fltreg_argnum;
477 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
479 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
481 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
485 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
487 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
491 } else { /* stack-arg -> spilled */
492 /* i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
493 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r * 8); */
495 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
496 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
499 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
500 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
509 /* end of header generation */
511 /* walk through all basic blocks */
512 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
514 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
516 if (bptr->flags >= BBREACHED) {
518 /* branch resolving */
521 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
522 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
527 /* copy interface registers to their destination */
535 while (src != NULL) {
537 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
538 if (!IS_2_WORD_TYPE(src->type)) {
539 if (bptr->type == BBTYPE_SBR) {
540 /* d = reg_of_var(m, src, REG_ITMP1); */
541 if (!(src->flags & INMEMORY))
546 store_reg_to_var_int(src, d);
547 } else if (bptr->type == BBTYPE_EXH) {
548 /* d = reg_of_var(m, src, REG_ITMP1); */
549 if (!(src->flags & INMEMORY))
553 M_INTMOVE(REG_ITMP1, d);
554 store_reg_to_var_int(src, d);
558 panic("copy interface registers(EXH, SBR): longs have to me in memory (begin 1)");
565 while (src != NULL) {
567 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
568 if (!IS_2_WORD_TYPE(src->type)) {
569 if (bptr->type == BBTYPE_SBR) {
570 d = reg_of_var(rd, src, REG_ITMP1);
572 store_reg_to_var_int(src, d);
573 } else if (bptr->type == BBTYPE_EXH) {
574 d = reg_of_var(rd, src, REG_ITMP1);
575 M_INTMOVE(REG_ITMP1, d);
576 store_reg_to_var_int(src, d);
580 panic("copy interface registers: longs have to me in memory (begin 1)");
584 d = reg_of_var(rd, src, REG_ITMP1);
585 if ((src->varkind != STACKVAR)) {
587 if (IS_FLT_DBL_TYPE(s2)) {
588 s1 = rd->interfaces[len][s2].regoff;
589 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
593 if (s2 == TYPE_FLT) {
594 i386_flds_membase(cd, REG_SP, s1 * 8);
597 i386_fldl_membase(cd, REG_SP, s1 * 8);
600 store_reg_to_var_flt(src, d);
603 s1 = rd->interfaces[len][s2].regoff;
604 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
605 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
609 i386_mov_membase_reg(cd, REG_SP, s1 * 8, d);
611 store_reg_to_var_int(src, d);
614 if (rd->interfaces[len][s2].flags & INMEMORY) {
615 M_LNGMEMMOVE(s1, src->regoff);
618 panic("copy interface registers: longs have to be in memory (begin 2)");
630 /* walk through all instructions */
635 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
636 if (iptr->line != currentline) {
637 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
638 currentline = iptr->line;
641 MCODECHECK(64); /* an instruction usually needs < 64 words */
644 case ICMD_NOP: /* ... ==> ... */
647 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
648 if (src->flags & INMEMORY) {
649 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
652 i386_test_reg_reg(cd, src->regoff, src->regoff);
654 i386_jcc(cd, I386_CC_E, 0);
655 codegen_addxnullrefs(cd, cd->mcodeptr);
658 /* constant operations ************************************************/
660 case ICMD_ICONST: /* ... ==> ..., constant */
661 /* op1 = 0, val.i = constant */
663 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
664 if (iptr->dst->flags & INMEMORY) {
665 i386_mov_imm_membase(cd, iptr->val.i, REG_SP, iptr->dst->regoff * 8);
668 if (iptr->val.i == 0) {
669 i386_alu_reg_reg(cd, I386_XOR, d, d);
672 i386_mov_imm_reg(cd, iptr->val.i, d);
677 case ICMD_LCONST: /* ... ==> ..., constant */
678 /* op1 = 0, val.l = constant */
680 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
681 if (iptr->dst->flags & INMEMORY) {
682 i386_mov_imm_membase(cd, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
683 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
686 panic("LCONST: longs have to be in memory");
690 case ICMD_FCONST: /* ... ==> ..., constant */
691 /* op1 = 0, val.f = constant */
693 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
694 if (iptr->val.f == 0.0) {
699 if (iptr->val.i == 0x80000000) {
703 } else if (iptr->val.f == 1.0) {
707 } else if (iptr->val.f == 2.0) {
714 a = dseg_addfloat(cd, iptr->val.f);
715 i386_mov_imm_reg(cd, 0, REG_ITMP1);
716 dseg_adddata(cd, cd->mcodeptr);
717 i386_flds_membase(cd, REG_ITMP1, a);
720 store_reg_to_var_flt(iptr->dst, d);
723 case ICMD_DCONST: /* ... ==> ..., constant */
724 /* op1 = 0, val.d = constant */
726 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
727 if (iptr->val.d == 0.0) {
732 if (iptr->val.l == 0x8000000000000000LL) {
736 } else if (iptr->val.d == 1.0) {
740 } else if (iptr->val.d == 2.0) {
747 a = dseg_adddouble(cd, iptr->val.d);
748 i386_mov_imm_reg(cd, 0, REG_ITMP1);
749 dseg_adddata(cd, cd->mcodeptr);
750 i386_fldl_membase(cd, REG_ITMP1, a);
753 store_reg_to_var_flt(iptr->dst, d);
756 case ICMD_ACONST: /* ... ==> ..., constant */
757 /* op1 = 0, val.a = constant */
759 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
760 if (iptr->dst->flags & INMEMORY) {
761 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
764 if ((s4) iptr->val.a == 0) {
765 i386_alu_reg_reg(cd, I386_XOR, d, d);
768 i386_mov_imm_reg(cd, (s4) iptr->val.a, d);
774 /* load/store operations **********************************************/
776 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
777 case ICMD_ALOAD: /* op1 = local variable */
779 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
780 if ((iptr->dst->varkind == LOCALVAR) &&
781 (iptr->dst->varnum == iptr->op1)) {
784 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
785 if (iptr->dst->flags & INMEMORY) {
786 if (var->flags & INMEMORY) {
787 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, REG_ITMP1);
788 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
791 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
795 if (var->flags & INMEMORY) {
796 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, iptr->dst->regoff);
799 M_INTMOVE(var->regoff, iptr->dst->regoff);
804 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
805 /* op1 = local variable */
807 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
808 if ((iptr->dst->varkind == LOCALVAR) &&
809 (iptr->dst->varnum == iptr->op1)) {
812 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
813 if (iptr->dst->flags & INMEMORY) {
814 if (var->flags & INMEMORY) {
815 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
818 panic("LLOAD: longs have to be in memory");
822 panic("LLOAD: longs have to be in memory");
826 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
827 /* op1 = local variable */
829 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
830 if ((iptr->dst->varkind == LOCALVAR) &&
831 (iptr->dst->varnum == iptr->op1)) {
834 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
835 if (var->flags & INMEMORY) {
836 i386_flds_membase(cd, REG_SP, var->regoff * 8);
839 i386_fld_reg(cd, var->regoff + fpu_st_offset);
842 store_reg_to_var_flt(iptr->dst, d);
845 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
846 /* op1 = local variable */
848 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
849 if ((iptr->dst->varkind == LOCALVAR) &&
850 (iptr->dst->varnum == iptr->op1)) {
853 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
854 if (var->flags & INMEMORY) {
855 i386_fldl_membase(cd, REG_SP, var->regoff * 8);
858 i386_fld_reg(cd, var->regoff + fpu_st_offset);
861 store_reg_to_var_flt(iptr->dst, d);
864 case ICMD_ISTORE: /* ..., value ==> ... */
865 case ICMD_ASTORE: /* op1 = local variable */
867 if ((src->varkind == LOCALVAR) &&
868 (src->varnum == iptr->op1)) {
871 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
872 if (var->flags & INMEMORY) {
873 if (src->flags & INMEMORY) {
874 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
875 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
878 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 8);
882 var_to_reg_int(s1, src, var->regoff);
883 M_INTMOVE(s1, var->regoff);
887 case ICMD_LSTORE: /* ..., value ==> ... */
888 /* op1 = local variable */
890 if ((src->varkind == LOCALVAR) &&
891 (src->varnum == iptr->op1)) {
894 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
895 if (var->flags & INMEMORY) {
896 if (src->flags & INMEMORY) {
897 M_LNGMEMMOVE(src->regoff, var->regoff);
900 panic("LSTORE: longs have to be in memory");
904 panic("LSTORE: longs have to be in memory");
908 case ICMD_FSTORE: /* ..., value ==> ... */
909 /* op1 = local variable */
911 if ((src->varkind == LOCALVAR) &&
912 (src->varnum == iptr->op1)) {
915 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
916 if (var->flags & INMEMORY) {
917 var_to_reg_flt(s1, src, REG_FTMP1);
918 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
921 var_to_reg_flt(s1, src, var->regoff);
922 /* M_FLTMOVE(s1, var->regoff); */
923 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
928 case ICMD_DSTORE: /* ..., value ==> ... */
929 /* op1 = local variable */
931 if ((src->varkind == LOCALVAR) &&
932 (src->varnum == iptr->op1)) {
935 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
936 if (var->flags & INMEMORY) {
937 var_to_reg_flt(s1, src, REG_FTMP1);
938 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
941 var_to_reg_flt(s1, src, var->regoff);
942 /* M_FLTMOVE(s1, var->regoff); */
943 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
949 /* pop/dup/swap operations ********************************************/
951 /* attention: double and longs are only one entry in CACAO ICMDs */
953 case ICMD_POP: /* ..., value ==> ... */
954 case ICMD_POP2: /* ..., value, value ==> ... */
957 case ICMD_DUP: /* ..., a ==> ..., a, a */
958 M_COPY(src, iptr->dst);
961 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
963 M_COPY(src, iptr->dst);
964 M_COPY(src->prev, iptr->dst->prev);
967 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
969 M_COPY(src, iptr->dst);
970 M_COPY(src->prev, iptr->dst->prev);
971 M_COPY(iptr->dst, iptr->dst->prev->prev);
974 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
976 M_COPY(src, iptr->dst);
977 M_COPY(src->prev, iptr->dst->prev);
978 M_COPY(src->prev->prev, iptr->dst->prev->prev);
979 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
982 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
984 M_COPY(src, iptr->dst);
985 M_COPY(src->prev, iptr->dst->prev);
986 M_COPY(src->prev->prev, iptr->dst->prev->prev);
987 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
988 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev);
991 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
993 M_COPY(src, iptr->dst);
994 M_COPY(src->prev, iptr->dst->prev);
995 M_COPY(src->prev->prev, iptr->dst->prev->prev);
996 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
997 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
998 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
1001 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1003 M_COPY(src, iptr->dst->prev);
1004 M_COPY(src->prev, iptr->dst);
1008 /* integer operations *************************************************/
1010 case ICMD_INEG: /* ..., value ==> ..., - value */
1012 d = reg_of_var(rd, iptr->dst, REG_NULL);
1013 if (iptr->dst->flags & INMEMORY) {
1014 if (src->flags & INMEMORY) {
1015 if (src->regoff == iptr->dst->regoff) {
1016 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1019 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1020 i386_neg_reg(cd, REG_ITMP1);
1021 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1025 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1026 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1030 if (src->flags & INMEMORY) {
1031 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1032 i386_neg_reg(cd, iptr->dst->regoff);
1035 M_INTMOVE(src->regoff, iptr->dst->regoff);
1036 i386_neg_reg(cd, iptr->dst->regoff);
1041 case ICMD_LNEG: /* ..., value ==> ..., - value */
1043 d = reg_of_var(rd, iptr->dst, REG_NULL);
1044 if (iptr->dst->flags & INMEMORY) {
1045 if (src->flags & INMEMORY) {
1046 if (src->regoff == iptr->dst->regoff) {
1047 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1048 i386_alu_imm_membase(cd, I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1049 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8 + 4);
1052 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1053 i386_neg_reg(cd, REG_ITMP1);
1054 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1055 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1056 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP1);
1057 i386_neg_reg(cd, REG_ITMP1);
1058 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1064 case ICMD_I2L: /* ..., value ==> ..., value */
1066 d = reg_of_var(rd, iptr->dst, REG_NULL);
1067 if (iptr->dst->flags & INMEMORY) {
1068 if (src->flags & INMEMORY) {
1069 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, EAX);
1071 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1072 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1075 M_INTMOVE(src->regoff, EAX);
1077 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1078 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1083 case ICMD_L2I: /* ..., value ==> ..., value */
1085 d = reg_of_var(rd, iptr->dst, REG_NULL);
1086 if (iptr->dst->flags & INMEMORY) {
1087 if (src->flags & INMEMORY) {
1088 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1089 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1093 if (src->flags & INMEMORY) {
1094 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1099 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1101 d = reg_of_var(rd, iptr->dst, REG_NULL);
1102 if (iptr->dst->flags & INMEMORY) {
1103 if (src->flags & INMEMORY) {
1104 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1105 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1106 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1107 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1110 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1111 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1112 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1116 if (src->flags & INMEMORY) {
1117 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, 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);
1122 M_INTMOVE(src->regoff, iptr->dst->regoff);
1123 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1124 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1129 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1131 d = reg_of_var(rd, iptr->dst, REG_NULL);
1132 if (iptr->dst->flags & INMEMORY) {
1133 if (src->flags & INMEMORY) {
1134 if (src->regoff == iptr->dst->regoff) {
1135 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1138 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1139 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, REG_ITMP1);
1140 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1144 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1145 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1149 if (src->flags & INMEMORY) {
1150 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1151 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1154 M_INTMOVE(src->regoff, iptr->dst->regoff);
1155 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1160 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1162 d = reg_of_var(rd, iptr->dst, REG_NULL);
1163 if (iptr->dst->flags & INMEMORY) {
1164 if (src->flags & INMEMORY) {
1165 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1166 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1167 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1168 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1171 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1172 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1173 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1177 if (src->flags & INMEMORY) {
1178 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, 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);
1183 M_INTMOVE(src->regoff, iptr->dst->regoff);
1184 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1185 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1191 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1193 d = reg_of_var(rd, iptr->dst, REG_NULL);
1194 i386_emit_ialu(cd, I386_ADD, src, iptr);
1197 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1198 /* val.i = constant */
1200 d = reg_of_var(rd, iptr->dst, REG_NULL);
1201 i386_emit_ialuconst(cd, I386_ADD, src, iptr);
1204 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1206 d = reg_of_var(rd, iptr->dst, REG_NULL);
1207 if (iptr->dst->flags & INMEMORY) {
1208 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1209 if (src->regoff == iptr->dst->regoff) {
1210 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1211 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1212 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1213 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1215 } else if (src->prev->regoff == iptr->dst->regoff) {
1216 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1217 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1218 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1219 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1222 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1223 i386_alu_membase_reg(cd, I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1224 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1225 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1226 i386_alu_membase_reg(cd, I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1227 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1234 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1235 /* val.l = constant */
1237 d = reg_of_var(rd, iptr->dst, REG_NULL);
1238 if (iptr->dst->flags & INMEMORY) {
1239 if (src->flags & INMEMORY) {
1240 if (src->regoff == iptr->dst->regoff) {
1241 i386_alu_imm_membase(cd, I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1242 i386_alu_imm_membase(cd, I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1245 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1246 i386_alu_imm_reg(cd, I386_ADD, iptr->val.l, REG_ITMP1);
1247 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1248 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1249 i386_alu_imm_reg(cd, I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1250 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1256 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1258 d = reg_of_var(rd, iptr->dst, REG_NULL);
1259 if (iptr->dst->flags & INMEMORY) {
1260 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1261 if (src->prev->regoff == iptr->dst->regoff) {
1262 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1263 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1266 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1267 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1268 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1271 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1272 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1273 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1274 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1276 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1277 if (src->prev->regoff == iptr->dst->regoff) {
1278 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1281 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1282 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1283 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1287 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1288 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1292 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1293 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1294 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1296 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1297 M_INTMOVE(src->prev->regoff, d);
1298 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1300 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1301 /* workaround for reg alloc */
1302 if (src->regoff == iptr->dst->regoff) {
1303 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1304 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1305 M_INTMOVE(REG_ITMP1, d);
1308 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1309 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1313 /* workaround for reg alloc */
1314 if (src->regoff == iptr->dst->regoff) {
1315 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1316 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1317 M_INTMOVE(REG_ITMP1, d);
1320 M_INTMOVE(src->prev->regoff, d);
1321 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1327 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1328 /* val.i = constant */
1330 d = reg_of_var(rd, iptr->dst, REG_NULL);
1331 i386_emit_ialuconst(cd, I386_SUB, src, iptr);
1334 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1336 d = reg_of_var(rd, iptr->dst, REG_NULL);
1337 if (iptr->dst->flags & INMEMORY) {
1338 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1339 if (src->prev->regoff == iptr->dst->regoff) {
1340 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1341 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1342 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1343 i386_alu_reg_membase(cd, I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1346 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1347 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1348 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1349 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1350 i386_alu_membase_reg(cd, I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1351 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1357 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1358 /* val.l = constant */
1360 d = reg_of_var(rd, iptr->dst, REG_NULL);
1361 if (iptr->dst->flags & INMEMORY) {
1362 if (src->flags & INMEMORY) {
1363 if (src->regoff == iptr->dst->regoff) {
1364 i386_alu_imm_membase(cd, I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1365 i386_alu_imm_membase(cd, I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1368 /* TODO: could be size optimized with lea -- see gcc output */
1369 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1370 i386_alu_imm_reg(cd, I386_SUB, iptr->val.l, REG_ITMP1);
1371 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1372 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1373 i386_alu_imm_reg(cd, I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1374 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1380 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1382 d = reg_of_var(rd, iptr->dst, REG_NULL);
1383 if (iptr->dst->flags & INMEMORY) {
1384 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1385 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1386 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, 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->regoff * 8, REG_ITMP1);
1391 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1392 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1394 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1395 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, 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);
1400 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1401 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1402 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1406 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1407 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1408 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1410 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1411 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1412 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1414 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1415 M_INTMOVE(src->regoff, iptr->dst->regoff);
1416 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1419 if (src->regoff == iptr->dst->regoff) {
1420 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1423 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1424 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1430 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1431 /* val.i = constant */
1433 d = reg_of_var(rd, iptr->dst, REG_NULL);
1434 if (iptr->dst->flags & INMEMORY) {
1435 if (src->flags & INMEMORY) {
1436 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1437 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1440 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1441 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1445 if (src->flags & INMEMORY) {
1446 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1449 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1454 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1456 d = reg_of_var(rd, iptr->dst, REG_NULL);
1457 if (iptr->dst->flags & INMEMORY) {
1458 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1459 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX); /* mem -> EAX */
1460 /* optimize move EAX -> REG_ITMP3 is slower??? */
1461 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1462 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1464 /* TODO: optimize move EAX -> REG_ITMP3 */
1465 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); /* mem -> ITMP3 */
1466 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1467 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1469 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP2); /* mem -> ITMP3 */
1470 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1472 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1473 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1474 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1479 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1480 /* val.l = constant */
1482 d = reg_of_var(rd, iptr->dst, REG_NULL);
1483 if (iptr->dst->flags & INMEMORY) {
1484 if (src->flags & INMEMORY) {
1485 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1486 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1487 /* TODO: optimize move EAX -> REG_ITMP3 */
1488 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1489 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1491 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1492 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1493 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1495 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1496 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1497 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1502 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1504 d = reg_of_var(rd, iptr->dst, REG_NULL);
1505 var_to_reg_int(s1, src, REG_ITMP2);
1507 if (src->prev->flags & INMEMORY) {
1508 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1511 M_INTMOVE(src->prev->regoff, EAX);
1514 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1515 i386_jcc(cd, I386_CC_NE, 3 + 6);
1516 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1517 i386_jcc(cd, I386_CC_E, 1 + 2);
1520 i386_idiv_reg(cd, s1);
1522 if (iptr->dst->flags & INMEMORY) {
1523 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1526 M_INTMOVE(EAX, iptr->dst->regoff);
1530 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1532 d = reg_of_var(rd, iptr->dst, REG_NULL);
1533 var_to_reg_int(s1, src, REG_ITMP2);
1535 if (src->prev->flags & INMEMORY) {
1536 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1539 M_INTMOVE(src->prev->regoff, EAX);
1542 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1543 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1544 i386_alu_reg_reg(cd, I386_XOR, EDX, EDX);
1545 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1546 i386_jcc(cd, I386_CC_E, 1 + 2);
1549 i386_idiv_reg(cd, s1);
1551 if (iptr->dst->flags & INMEMORY) {
1552 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8);
1555 M_INTMOVE(EDX, iptr->dst->regoff);
1559 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1560 /* val.i = constant */
1562 /* TODO: optimize for `/ 2' */
1563 var_to_reg_int(s1, src, REG_ITMP1);
1564 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1567 i386_test_reg_reg(cd, d, d);
1569 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1570 i386_jcc(cd, I386_CC_NS, a);
1571 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, d);
1573 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1574 store_reg_to_var_int(iptr->dst, d);
1577 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1578 /* val.i = constant */
1580 d = reg_of_var(rd, iptr->dst, REG_NULL);
1581 if (iptr->dst->flags & INMEMORY) {
1582 if (src->flags & INMEMORY) {
1584 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1586 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1587 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1589 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1590 i386_jcc(cd, I386_CC_NS, a);
1591 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1592 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1593 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1594 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1596 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1597 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1602 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1603 /* val.i = constant */
1605 var_to_reg_int(s1, src, REG_ITMP1);
1606 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1608 M_INTMOVE(s1, REG_ITMP1);
1615 CALCIMMEDIATEBYTES(a, iptr->val.i);
1618 /* TODO: optimize */
1620 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1621 i386_test_reg_reg(cd, s1, s1);
1622 i386_jcc(cd, I386_CC_GE, a);
1623 i386_mov_reg_reg(cd, s1, d);
1624 i386_neg_reg(cd, d);
1625 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1626 i386_neg_reg(cd, d);
1628 /* M_INTMOVE(s1, EAX); */
1629 /* i386_cltd(cd); */
1630 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1631 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1632 /* i386_alu_reg_reg(cd, I386_AND, iptr->val.i, EAX); */
1633 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1634 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1635 /* M_INTMOVE(EAX, d); */
1637 /* i386_alu_reg_reg(cd, I386_XOR, d, d); */
1638 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1639 /* i386_shrd_reg_reg(cd, s1, d); */
1640 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1642 store_reg_to_var_int(iptr->dst, d);
1645 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1646 /* val.l = constant */
1648 d = reg_of_var(rd, iptr->dst, REG_NULL);
1649 if (iptr->dst->flags & INMEMORY) {
1650 if (src->flags & INMEMORY) {
1651 /* Intel algorithm -- does not work, because constant is wrong */
1652 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1); */
1653 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1655 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1656 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1657 /* i386_jcc(cd, I386_CC_NS, offset); */
1658 /* i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1659 /* i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP3); */
1661 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1662 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1663 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1665 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1667 /* i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1); */
1668 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1669 /* i386_alu_reg_reg(cd, I386_SBB, REG_ITMP3, REG_ITMP2); */
1671 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1672 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1674 /* Alpha algorithm */
1676 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1678 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1684 /* TODO: hmm, don't know if this is always correct */
1686 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1688 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1694 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1695 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1697 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1698 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1699 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1700 i386_jcc(cd, I386_CC_GE, a);
1702 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1703 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1705 i386_neg_reg(cd, REG_ITMP1);
1706 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1707 i386_neg_reg(cd, REG_ITMP2);
1709 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1710 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1712 i386_neg_reg(cd, REG_ITMP1);
1713 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1714 i386_neg_reg(cd, REG_ITMP2);
1716 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1717 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1722 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1724 d = reg_of_var(rd, iptr->dst, REG_NULL);
1725 i386_emit_ishift(cd, I386_SHL, src, iptr);
1728 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1729 /* val.i = constant */
1731 d = reg_of_var(rd, iptr->dst, REG_NULL);
1732 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1735 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1737 d = reg_of_var(rd, iptr->dst, REG_NULL);
1738 i386_emit_ishift(cd, I386_SAR, src, iptr);
1741 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1742 /* val.i = constant */
1744 d = reg_of_var(rd, iptr->dst, REG_NULL);
1745 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1748 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1750 d = reg_of_var(rd, iptr->dst, REG_NULL);
1751 i386_emit_ishift(cd, I386_SHR, src, iptr);
1754 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1755 /* val.i = constant */
1757 d = reg_of_var(rd, iptr->dst, REG_NULL);
1758 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1761 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1763 d = reg_of_var(rd, iptr->dst, REG_NULL);
1764 if (iptr->dst->flags & INMEMORY ){
1765 if (src->prev->flags & INMEMORY) {
1766 /* if (src->prev->regoff == iptr->dst->regoff) { */
1767 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1769 /* if (src->flags & INMEMORY) { */
1770 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1772 /* M_INTMOVE(src->regoff, ECX); */
1775 /* i386_test_imm_reg(cd, 32, ECX); */
1776 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1777 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1778 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1); */
1780 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1781 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1784 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1785 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1787 if (src->flags & INMEMORY) {
1788 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1790 M_INTMOVE(src->regoff, ECX);
1793 i386_test_imm_reg(cd, 32, ECX);
1794 i386_jcc(cd, I386_CC_E, 2 + 2);
1795 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1796 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1798 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1799 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1800 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1801 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1807 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1808 /* val.i = constant */
1810 d = reg_of_var(rd, iptr->dst, REG_NULL);
1811 if (iptr->dst->flags & INMEMORY ) {
1812 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1813 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1815 if (iptr->val.i & 0x20) {
1816 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1817 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1818 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1821 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1822 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1825 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1826 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1830 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1832 d = reg_of_var(rd, iptr->dst, REG_NULL);
1833 if (iptr->dst->flags & INMEMORY ){
1834 if (src->prev->flags & INMEMORY) {
1835 /* if (src->prev->regoff == iptr->dst->regoff) { */
1836 /* TODO: optimize */
1837 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1838 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1840 /* if (src->flags & INMEMORY) { */
1841 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1843 /* M_INTMOVE(src->regoff, ECX); */
1846 /* i386_test_imm_reg(cd, 32, ECX); */
1847 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1848 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1849 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1851 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1852 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1853 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1854 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1857 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1858 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1860 if (src->flags & INMEMORY) {
1861 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1863 M_INTMOVE(src->regoff, ECX);
1866 i386_test_imm_reg(cd, 32, ECX);
1867 i386_jcc(cd, I386_CC_E, 2 + 3);
1868 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1869 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1871 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1872 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1873 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1874 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1880 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1881 /* val.i = constant */
1883 d = reg_of_var(rd, iptr->dst, REG_NULL);
1884 if (iptr->dst->flags & INMEMORY ) {
1885 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1886 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1888 if (iptr->val.i & 0x20) {
1889 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1890 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
1891 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1894 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1895 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1898 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1899 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1903 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1905 d = reg_of_var(rd, iptr->dst, REG_NULL);
1906 if (iptr->dst->flags & INMEMORY ){
1907 if (src->prev->flags & INMEMORY) {
1908 /* if (src->prev->regoff == iptr->dst->regoff) { */
1909 /* TODO: optimize */
1910 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1911 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1913 /* if (src->flags & INMEMORY) { */
1914 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1916 /* M_INTMOVE(src->regoff, ECX); */
1919 /* i386_test_imm_reg(cd, 32, ECX); */
1920 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1921 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1922 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2); */
1924 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1925 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
1926 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1927 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1930 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1931 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1933 if (src->flags & INMEMORY) {
1934 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1936 M_INTMOVE(src->regoff, ECX);
1939 i386_test_imm_reg(cd, 32, ECX);
1940 i386_jcc(cd, I386_CC_E, 2 + 2);
1941 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1942 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP3, REG_ITMP3);
1944 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1945 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
1946 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1947 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1953 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1954 /* val.l = constant */
1956 d = reg_of_var(rd, iptr->dst, REG_NULL);
1957 if (iptr->dst->flags & INMEMORY ) {
1958 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1959 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1961 if (iptr->val.i & 0x20) {
1962 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1963 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
1964 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1967 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1968 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
1971 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1972 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1976 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1978 d = reg_of_var(rd, iptr->dst, REG_NULL);
1979 i386_emit_ialu(cd, I386_AND, src, iptr);
1982 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1983 /* val.i = constant */
1985 d = reg_of_var(rd, iptr->dst, REG_NULL);
1986 i386_emit_ialuconst(cd, I386_AND, src, iptr);
1989 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1991 d = reg_of_var(rd, iptr->dst, REG_NULL);
1992 i386_emit_lalu(cd, I386_AND, src, iptr);
1995 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1996 /* val.l = constant */
1998 d = reg_of_var(rd, iptr->dst, REG_NULL);
1999 i386_emit_laluconst(cd, I386_AND, src, iptr);
2002 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2004 d = reg_of_var(rd, iptr->dst, REG_NULL);
2005 i386_emit_ialu(cd, I386_OR, src, iptr);
2008 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2009 /* val.i = constant */
2011 d = reg_of_var(rd, iptr->dst, REG_NULL);
2012 i386_emit_ialuconst(cd, I386_OR, src, iptr);
2015 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2017 d = reg_of_var(rd, iptr->dst, REG_NULL);
2018 i386_emit_lalu(cd, I386_OR, src, iptr);
2021 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2022 /* val.l = constant */
2024 d = reg_of_var(rd, iptr->dst, REG_NULL);
2025 i386_emit_laluconst(cd, I386_OR, src, iptr);
2028 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2030 d = reg_of_var(rd, iptr->dst, REG_NULL);
2031 i386_emit_ialu(cd, I386_XOR, src, iptr);
2034 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2035 /* val.i = constant */
2037 d = reg_of_var(rd, iptr->dst, REG_NULL);
2038 i386_emit_ialuconst(cd, I386_XOR, src, iptr);
2041 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2043 d = reg_of_var(rd, iptr->dst, REG_NULL);
2044 i386_emit_lalu(cd, I386_XOR, src, iptr);
2047 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2048 /* val.l = constant */
2050 d = reg_of_var(rd, iptr->dst, REG_NULL);
2051 i386_emit_laluconst(cd, I386_XOR, src, iptr);
2054 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2055 /* op1 = variable, val.i = constant */
2057 var = &(rd->locals[iptr->op1][TYPE_INT]);
2058 if (var->flags & INMEMORY) {
2059 i386_alu_imm_membase(cd, I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2062 /* `inc reg' is slower on p4's (regarding to ia32 */
2063 /* optimization reference manual and benchmarks) and as fast */
2065 i386_alu_imm_reg(cd, I386_ADD, iptr->val.i, var->regoff);
2070 /* floating operations ************************************************/
2072 #define ROUND_TO_SINGLE \
2073 i386_fstps_membase(cd, REG_SP, -8); \
2074 i386_flds_membase(cd, REG_SP, -8);
2076 #define ROUND_TO_DOUBLE \
2077 i386_fstpl_membase(cd, REG_SP, -8); \
2078 i386_fldl_membase(cd, REG_SP, -8);
2080 #define FPU_SET_24BIT_MODE \
2081 if (!fpu_in_24bit_mode) { \
2082 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2083 fpu_in_24bit_mode = 1; \
2086 #define FPU_SET_53BIT_MODE \
2087 if (fpu_in_24bit_mode) { \
2088 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2089 fpu_in_24bit_mode = 0; \
2092 #define ROUND_TO_SINGLE
2093 #define ROUND_TO_DOUBLE
2094 #define FPU_SET_24BIT_MODE
2095 #define FPU_SET_53BIT_MODE
2097 case ICMD_FNEG: /* ..., value ==> ..., - value */
2100 var_to_reg_flt(s1, src, REG_FTMP1);
2101 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2103 store_reg_to_var_flt(iptr->dst, d);
2106 case ICMD_DNEG: /* ..., value ==> ..., - value */
2109 var_to_reg_flt(s1, src, REG_FTMP1);
2110 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2112 store_reg_to_var_flt(iptr->dst, d);
2115 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2118 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2119 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2120 var_to_reg_flt(s2, src, REG_FTMP2);
2123 store_reg_to_var_flt(iptr->dst, d);
2126 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2129 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2130 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2131 var_to_reg_flt(s2, src, REG_FTMP2);
2134 store_reg_to_var_flt(iptr->dst, d);
2137 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2140 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2141 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2142 var_to_reg_flt(s2, src, REG_FTMP2);
2145 store_reg_to_var_flt(iptr->dst, d);
2148 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2151 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2152 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2153 var_to_reg_flt(s2, src, REG_FTMP2);
2156 store_reg_to_var_flt(iptr->dst, d);
2159 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2162 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2163 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2164 var_to_reg_flt(s2, src, REG_FTMP2);
2168 store_reg_to_var_flt(iptr->dst, d);
2171 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2174 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2175 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2177 /* i386_fldt_mem(cd, subnormal_bias1); */
2178 /* i386_fmulp(cd); */
2180 var_to_reg_flt(s2, src, REG_FTMP2);
2185 /* i386_fldt_mem(cd, subnormal_bias2); */
2186 /* i386_fmulp(cd); */
2188 store_reg_to_var_flt(iptr->dst, d);
2191 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2194 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2195 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2196 var_to_reg_flt(s2, src, REG_FTMP2);
2200 store_reg_to_var_flt(iptr->dst, d);
2203 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2206 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2207 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2209 /* i386_fldt_mem(cd, subnormal_bias1); */
2210 /* i386_fmulp(cd); */
2212 var_to_reg_flt(s2, src, REG_FTMP2);
2217 /* i386_fldt_mem(cd, subnormal_bias2); */
2218 /* i386_fmulp(cd); */
2220 store_reg_to_var_flt(iptr->dst, d);
2223 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2226 /* exchanged to skip fxch */
2227 var_to_reg_flt(s2, src, REG_FTMP2);
2228 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2229 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2230 /* i386_fxch(cd); */
2235 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2236 store_reg_to_var_flt(iptr->dst, d);
2237 i386_ffree_reg(cd, 0);
2242 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2245 /* exchanged to skip fxch */
2246 var_to_reg_flt(s2, src, REG_FTMP2);
2247 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2248 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2249 /* i386_fxch(cd); */
2254 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2255 store_reg_to_var_flt(iptr->dst, d);
2256 i386_ffree_reg(cd, 0);
2261 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2262 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2264 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2265 if (src->flags & INMEMORY) {
2266 i386_fildl_membase(cd, REG_SP, src->regoff * 8);
2270 a = dseg_adds4(cd, 0);
2271 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2272 dseg_adddata(cd, cd->mcodeptr);
2273 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, a);
2274 i386_fildl_membase(cd, REG_ITMP1, a);
2277 store_reg_to_var_flt(iptr->dst, d);
2280 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2281 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2283 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2284 if (src->flags & INMEMORY) {
2285 i386_fildll_membase(cd, REG_SP, src->regoff * 8);
2289 panic("L2F: longs have to be in memory");
2291 store_reg_to_var_flt(iptr->dst, d);
2294 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2296 var_to_reg_flt(s1, src, REG_FTMP1);
2297 d = reg_of_var(rd, iptr->dst, REG_NULL);
2299 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2300 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2301 dseg_adddata(cd, cd->mcodeptr);
2302 i386_fldcw_membase(cd, REG_ITMP1, a);
2304 if (iptr->dst->flags & INMEMORY) {
2305 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2308 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2309 i386_fldcw_membase(cd, REG_ITMP1, a);
2311 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2314 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2316 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2319 a = dseg_adds4(cd, 0);
2320 i386_fistpl_membase(cd, REG_ITMP1, a);
2322 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2324 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2325 i386_fldcw_membase(cd, REG_ITMP1, a);
2327 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2330 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2331 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2334 i386_jcc(cd, I386_CC_NE, a);
2336 /* XXX: change this when we use registers */
2337 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2338 i386_mov_imm_reg(cd, (s4) asm_builtin_f2i, REG_ITMP1);
2339 i386_call_reg(cd, REG_ITMP1);
2341 if (iptr->dst->flags & INMEMORY) {
2342 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2345 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2349 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2351 var_to_reg_flt(s1, src, REG_FTMP1);
2352 d = reg_of_var(rd, iptr->dst, REG_NULL);
2354 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2355 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2356 dseg_adddata(cd, cd->mcodeptr);
2357 i386_fldcw_membase(cd, REG_ITMP1, a);
2359 if (iptr->dst->flags & INMEMORY) {
2360 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2363 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2364 i386_fldcw_membase(cd, REG_ITMP1, a);
2366 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2369 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2371 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2374 a = dseg_adds4(cd, 0);
2375 i386_fistpl_membase(cd, REG_ITMP1, a);
2377 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2379 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2380 i386_fldcw_membase(cd, REG_ITMP1, a);
2382 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2385 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2386 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2389 i386_jcc(cd, I386_CC_NE, a);
2391 /* XXX: change this when we use registers */
2392 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2393 i386_mov_imm_reg(cd, (s4) asm_builtin_d2i, REG_ITMP1);
2394 i386_call_reg(cd, REG_ITMP1);
2396 if (iptr->dst->flags & INMEMORY) {
2397 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2399 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2403 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2405 var_to_reg_flt(s1, src, REG_FTMP1);
2406 d = reg_of_var(rd, iptr->dst, REG_NULL);
2408 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2409 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2410 dseg_adddata(cd, cd->mcodeptr);
2411 i386_fldcw_membase(cd, REG_ITMP1, a);
2413 if (iptr->dst->flags & INMEMORY) {
2414 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2417 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2418 i386_fldcw_membase(cd, REG_ITMP1, a);
2420 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2423 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2425 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2428 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2430 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2432 i386_jcc(cd, I386_CC_NE, a);
2434 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2437 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2439 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2441 i386_jcc(cd, I386_CC_NE, a);
2443 /* XXX: change this when we use registers */
2444 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2445 i386_mov_imm_reg(cd, (s4) asm_builtin_f2l, REG_ITMP1);
2446 i386_call_reg(cd, REG_ITMP1);
2447 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2448 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2451 panic("F2L: longs have to be in memory");
2455 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2457 var_to_reg_flt(s1, src, REG_FTMP1);
2458 d = reg_of_var(rd, iptr->dst, REG_NULL);
2460 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2461 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2462 dseg_adddata(cd, cd->mcodeptr);
2463 i386_fldcw_membase(cd, REG_ITMP1, a);
2465 if (iptr->dst->flags & INMEMORY) {
2466 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2469 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2470 i386_fldcw_membase(cd, REG_ITMP1, a);
2472 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2475 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2477 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2480 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2482 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2484 i386_jcc(cd, I386_CC_NE, a);
2486 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2489 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2491 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2493 i386_jcc(cd, I386_CC_NE, a);
2495 /* XXX: change this when we use registers */
2496 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2497 i386_mov_imm_reg(cd, (s4) asm_builtin_d2l, REG_ITMP1);
2498 i386_call_reg(cd, REG_ITMP1);
2499 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2500 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2503 panic("D2L: longs have to be in memory");
2507 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2509 var_to_reg_flt(s1, src, REG_FTMP1);
2510 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2512 store_reg_to_var_flt(iptr->dst, d);
2515 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2517 var_to_reg_flt(s1, src, REG_FTMP1);
2518 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2520 store_reg_to_var_flt(iptr->dst, d);
2523 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2526 /* exchanged to skip fxch */
2527 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2528 var_to_reg_flt(s1, src, REG_FTMP2);
2529 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2530 /* i386_fxch(cd); */
2534 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2535 i386_jcc(cd, I386_CC_E, 6);
2536 i386_alu_imm_reg(cd, I386_AND, 0x000000ff, EAX);
2538 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2539 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2540 i386_jcc(cd, I386_CC_B, 3 + 5);
2541 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2542 i386_jmp_imm(cd, 3);
2543 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2544 store_reg_to_var_int(iptr->dst, d);
2547 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2550 /* exchanged to skip fxch */
2551 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2552 var_to_reg_flt(s1, src, REG_FTMP2);
2553 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2554 /* i386_fxch(cd); */
2558 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2559 i386_jcc(cd, I386_CC_E, 3);
2560 i386_movb_imm_reg(cd, 1, I386_AH);
2562 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2563 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2564 i386_jcc(cd, I386_CC_B, 3 + 5);
2565 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2566 i386_jmp_imm(cd, 3);
2567 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2568 store_reg_to_var_int(iptr->dst, d);
2572 /* memory operations **************************************************/
2574 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2576 var_to_reg_int(s1, src, REG_ITMP1);
2577 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2578 gen_nullptr_check(s1);
2579 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2580 store_reg_to_var_int(iptr->dst, d);
2583 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2585 var_to_reg_int(s1, src->prev, REG_ITMP1);
2586 var_to_reg_int(s2, src, REG_ITMP2);
2587 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2588 if (iptr->op1 == 0) {
2589 gen_nullptr_check(s1);
2592 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2593 store_reg_to_var_int(iptr->dst, d);
2596 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2598 var_to_reg_int(s1, src->prev, REG_ITMP1);
2599 var_to_reg_int(s2, src, REG_ITMP2);
2600 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2601 if (iptr->op1 == 0) {
2602 gen_nullptr_check(s1);
2606 if (iptr->dst->flags & INMEMORY) {
2607 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2608 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2609 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2610 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2614 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2616 var_to_reg_int(s1, src->prev, REG_ITMP1);
2617 var_to_reg_int(s2, src, REG_ITMP2);
2618 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2619 if (iptr->op1 == 0) {
2620 gen_nullptr_check(s1);
2623 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2624 store_reg_to_var_int(iptr->dst, d);
2627 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2629 var_to_reg_int(s1, src->prev, REG_ITMP1);
2630 var_to_reg_int(s2, src, REG_ITMP2);
2631 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2632 if (iptr->op1 == 0) {
2633 gen_nullptr_check(s1);
2636 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2638 store_reg_to_var_flt(iptr->dst, d);
2641 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2643 var_to_reg_int(s1, src->prev, REG_ITMP1);
2644 var_to_reg_int(s2, src, REG_ITMP2);
2645 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2646 if (iptr->op1 == 0) {
2647 gen_nullptr_check(s1);
2650 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2652 store_reg_to_var_flt(iptr->dst, d);
2655 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2657 var_to_reg_int(s1, src->prev, REG_ITMP1);
2658 var_to_reg_int(s2, src, REG_ITMP2);
2659 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2660 if (iptr->op1 == 0) {
2661 gen_nullptr_check(s1);
2664 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2665 store_reg_to_var_int(iptr->dst, d);
2668 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2670 var_to_reg_int(s1, src->prev, REG_ITMP1);
2671 var_to_reg_int(s2, src, REG_ITMP2);
2672 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2673 if (iptr->op1 == 0) {
2674 gen_nullptr_check(s1);
2677 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2678 store_reg_to_var_int(iptr->dst, d);
2681 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2683 var_to_reg_int(s1, src->prev, REG_ITMP1);
2684 var_to_reg_int(s2, src, REG_ITMP2);
2685 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2686 if (iptr->op1 == 0) {
2687 gen_nullptr_check(s1);
2690 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2691 store_reg_to_var_int(iptr->dst, d);
2695 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2697 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2698 var_to_reg_int(s2, src->prev, REG_ITMP2);
2699 if (iptr->op1 == 0) {
2700 gen_nullptr_check(s1);
2703 var_to_reg_int(s3, src, REG_ITMP3);
2704 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2707 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2709 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2710 var_to_reg_int(s2, src->prev, REG_ITMP2);
2711 if (iptr->op1 == 0) {
2712 gen_nullptr_check(s1);
2716 if (src->flags & INMEMORY) {
2717 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
2718 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2719 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2720 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2724 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2726 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2727 var_to_reg_int(s2, src->prev, REG_ITMP2);
2728 if (iptr->op1 == 0) {
2729 gen_nullptr_check(s1);
2732 var_to_reg_int(s3, src, REG_ITMP3);
2733 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2736 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2738 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2739 var_to_reg_int(s2, src->prev, REG_ITMP2);
2740 if (iptr->op1 == 0) {
2741 gen_nullptr_check(s1);
2744 var_to_reg_flt(s3, src, REG_FTMP1);
2745 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2749 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2751 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2752 var_to_reg_int(s2, src->prev, REG_ITMP2);
2753 if (iptr->op1 == 0) {
2754 gen_nullptr_check(s1);
2757 var_to_reg_flt(s3, src, REG_FTMP1);
2758 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2762 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2764 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2765 var_to_reg_int(s2, src->prev, REG_ITMP2);
2766 if (iptr->op1 == 0) {
2767 gen_nullptr_check(s1);
2770 var_to_reg_int(s3, src, REG_ITMP3);
2771 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2774 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2776 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2777 var_to_reg_int(s2, src->prev, REG_ITMP2);
2778 if (iptr->op1 == 0) {
2779 gen_nullptr_check(s1);
2782 var_to_reg_int(s3, src, REG_ITMP3);
2783 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2786 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2788 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2789 var_to_reg_int(s2, src->prev, REG_ITMP2);
2790 if (iptr->op1 == 0) {
2791 gen_nullptr_check(s1);
2794 var_to_reg_int(s3, src, REG_ITMP3);
2795 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2796 M_INTMOVE(s3, REG_ITMP3);
2799 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2802 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2804 var_to_reg_int(s1, src->prev, REG_ITMP1);
2805 var_to_reg_int(s2, src, REG_ITMP2);
2806 if (iptr->op1 == 0) {
2807 gen_nullptr_check(s1);
2810 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2813 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2815 var_to_reg_int(s1, src->prev, REG_ITMP1);
2816 var_to_reg_int(s2, src, REG_ITMP2);
2817 if (iptr->op1 == 0) {
2818 gen_nullptr_check(s1);
2822 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2823 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2826 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2828 var_to_reg_int(s1, src->prev, REG_ITMP1);
2829 var_to_reg_int(s2, src, REG_ITMP2);
2830 if (iptr->op1 == 0) {
2831 gen_nullptr_check(s1);
2834 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2837 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2839 var_to_reg_int(s1, src->prev, REG_ITMP1);
2840 var_to_reg_int(s2, src, REG_ITMP2);
2841 if (iptr->op1 == 0) {
2842 gen_nullptr_check(s1);
2845 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2848 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2850 var_to_reg_int(s1, src->prev, REG_ITMP1);
2851 var_to_reg_int(s2, src, REG_ITMP2);
2852 if (iptr->op1 == 0) {
2853 gen_nullptr_check(s1);
2856 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2859 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2861 var_to_reg_int(s1, src->prev, REG_ITMP1);
2862 var_to_reg_int(s2, src, REG_ITMP2);
2863 if (iptr->op1 == 0) {
2864 gen_nullptr_check(s1);
2867 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2871 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2872 /* op1 = type, val.a = field address */
2874 /* If the static fields' class is not yet initialized, we do it */
2875 /* now. The call code is generated later. */
2876 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2877 codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
2879 /* This is just for debugging purposes. Is very difficult to */
2880 /* read patched code. Here we patch the following 5 nop's */
2881 /* so that the real code keeps untouched. */
2882 if (showdisassemble) {
2891 a = (u4) &(((fieldinfo *) iptr->val.a)->value);
2892 switch (iptr->op1) {
2895 var_to_reg_int(s2, src, REG_ITMP1);
2896 i386_mov_reg_mem(cd, s2, a);
2899 if (src->flags & INMEMORY) {
2900 /* Using both REG_ITMP1 and REG_ITMP2 is faster than only */
2901 /* using REG_ITMP1 alternating. */
2903 i386_mov_membase_reg(cd, REG_SP, s2 * 8, REG_ITMP1);
2904 i386_mov_membase_reg(cd, REG_SP, s2 * 8 + 4, REG_ITMP2);
2905 i386_mov_reg_mem(cd, REG_ITMP1, a);
2906 i386_mov_reg_mem(cd, REG_ITMP2, a + 4);
2908 panic("PUTSTATIC: longs have to be in memory");
2912 var_to_reg_flt(s2, src, REG_FTMP1);
2913 i386_fstps_mem(cd, a);
2917 var_to_reg_flt(s2, src, REG_FTMP1);
2918 i386_fstpl_mem(cd, a);
2922 throw_cacao_exception_exit(string_java_lang_InternalError,
2923 "Unknown PUTSTATIC operand type %d",
2928 case ICMD_GETSTATIC: /* ... ==> ..., value */
2929 /* op1 = type, val.a = field address */
2931 /* If the static fields' class is not yet initialized, we do it */
2932 /* now. The call code is generated later. */
2933 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2934 codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
2936 /* This is just for debugging purposes. Is very difficult to */
2937 /* read patched code. Here we patch the following 5 nop's */
2938 /* so that the real code keeps untouched. */
2939 if (showdisassemble) {
2948 a = (u4) &(((fieldinfo *) iptr->val.a)->value);
2949 switch (iptr->op1) {
2952 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2953 i386_mov_mem_reg(cd, a, d);
2954 store_reg_to_var_int(iptr->dst, d);
2957 d = reg_of_var(rd, iptr->dst, REG_NULL);
2958 if (iptr->dst->flags & INMEMORY) {
2959 /* Using both REG_ITMP1 and REG_ITMP2 is faster than only */
2960 /* using REG_ITMP1 alternating. */
2961 i386_mov_mem_reg(cd, a, REG_ITMP1);
2962 i386_mov_mem_reg(cd, a + 4, REG_ITMP2);
2963 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2964 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2966 panic("GETSTATIC: longs have to be in memory");
2970 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2971 i386_flds_mem(cd, a);
2973 store_reg_to_var_flt(iptr->dst, d);
2976 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2977 i386_fldl_mem(cd, a);
2979 store_reg_to_var_flt(iptr->dst, d);
2982 throw_cacao_exception_exit(string_java_lang_InternalError,
2983 "Unknown GETSTATIC operand type %d",
2988 case ICMD_PUTFIELD: /* ..., value ==> ... */
2989 /* op1 = type, val.i = field offset */
2991 a = ((fieldinfo *) (iptr->val.a))->offset;
2992 switch (iptr->op1) {
2995 var_to_reg_int(s1, src->prev, REG_ITMP1);
2996 var_to_reg_int(s2, src, REG_ITMP2);
2997 gen_nullptr_check(s1);
2998 i386_mov_reg_membase(cd, s2, s1, a);
3001 var_to_reg_int(s1, src->prev, REG_ITMP1);
3002 gen_nullptr_check(s1);
3003 if (src->flags & INMEMORY) {
3004 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);
3005 i386_mov_reg_membase(cd, REG_ITMP2, s1, a);
3006 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3007 i386_mov_reg_membase(cd, REG_ITMP2, s1, a + 4);
3009 panic("PUTFIELD: longs have to be in memory");
3013 var_to_reg_int(s1, src->prev, REG_ITMP1);
3014 var_to_reg_flt(s2, src, REG_FTMP1);
3015 gen_nullptr_check(s1);
3016 i386_fstps_membase(cd, s1, a);
3020 var_to_reg_int(s1, src->prev, REG_ITMP1);
3021 var_to_reg_flt(s2, src, REG_FTMP1);
3022 gen_nullptr_check(s1);
3023 i386_fstpl_membase(cd, s1, a);
3027 throw_cacao_exception_exit(string_java_lang_InternalError,
3028 "Unknown PUTFIELD operand type %d",
3033 case ICMD_GETFIELD: /* ... ==> ..., value */
3034 /* op1 = type, val.i = field offset */
3036 a = ((fieldinfo *) (iptr->val.a))->offset;
3037 switch (iptr->op1) {
3040 var_to_reg_int(s1, src, REG_ITMP1);
3041 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3042 gen_nullptr_check(s1);
3043 i386_mov_membase_reg(cd, s1, a, d);
3044 store_reg_to_var_int(iptr->dst, d);
3047 var_to_reg_int(s1, src, REG_ITMP1);
3048 d = reg_of_var(rd, iptr->dst, REG_NULL);
3049 gen_nullptr_check(s1);
3050 i386_mov_membase_reg(cd, s1, a, REG_ITMP2);
3051 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
3052 i386_mov_membase_reg(cd, s1, a + 4, REG_ITMP2);
3053 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
3056 var_to_reg_int(s1, src, REG_ITMP1);
3057 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3058 gen_nullptr_check(s1);
3059 i386_flds_membase(cd, s1, a);
3061 store_reg_to_var_flt(iptr->dst, d);
3064 var_to_reg_int(s1, src, REG_ITMP1);
3065 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3066 gen_nullptr_check(s1);
3067 i386_fldl_membase(cd, s1, a);
3069 store_reg_to_var_flt(iptr->dst, d);
3072 throw_cacao_exception_exit(string_java_lang_InternalError,
3073 "Unknown GETFIELD operand type %d",
3079 /* branch operations **************************************************/
3081 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3083 var_to_reg_int(s1, src, REG_ITMP1);
3084 M_INTMOVE(s1, REG_ITMP1_XPTR);
3086 i386_call_imm(cd, 0); /* passing exception pointer */
3087 i386_pop_reg(cd, REG_ITMP2_XPC);
3089 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
3090 i386_jmp_reg(cd, REG_ITMP3);
3094 case ICMD_GOTO: /* ... ==> ... */
3095 /* op1 = target JavaVM pc */
3097 i386_jmp_imm(cd, 0);
3098 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3102 case ICMD_JSR: /* ... ==> ... */
3103 /* op1 = target JavaVM pc */
3105 i386_call_imm(cd, 0);
3106 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3109 case ICMD_RET: /* ... ==> ... */
3110 /* op1 = local variable */
3112 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3113 var_to_reg_int(s1, var, REG_ITMP1);
3114 i386_jmp_reg(cd, s1);
3117 case ICMD_IFNULL: /* ..., value ==> ... */
3118 /* op1 = target JavaVM pc */
3120 if (src->flags & INMEMORY) {
3121 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3124 i386_test_reg_reg(cd, src->regoff, src->regoff);
3126 i386_jcc(cd, I386_CC_E, 0);
3127 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3130 case ICMD_IFNONNULL: /* ..., value ==> ... */
3131 /* op1 = target JavaVM pc */
3133 if (src->flags & INMEMORY) {
3134 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3137 i386_test_reg_reg(cd, src->regoff, src->regoff);
3139 i386_jcc(cd, I386_CC_NE, 0);
3140 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3143 case ICMD_IFEQ: /* ..., value ==> ... */
3144 /* op1 = target JavaVM pc, val.i = constant */
3146 if (src->flags & INMEMORY) {
3147 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3150 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3152 i386_jcc(cd, I386_CC_E, 0);
3153 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3156 case ICMD_IFLT: /* ..., value ==> ... */
3157 /* op1 = target JavaVM pc, val.i = constant */
3159 if (src->flags & INMEMORY) {
3160 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3163 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3165 i386_jcc(cd, I386_CC_L, 0);
3166 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3169 case ICMD_IFLE: /* ..., value ==> ... */
3170 /* op1 = target JavaVM pc, val.i = constant */
3172 if (src->flags & INMEMORY) {
3173 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3176 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3178 i386_jcc(cd, I386_CC_LE, 0);
3179 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3182 case ICMD_IFNE: /* ..., value ==> ... */
3183 /* op1 = target JavaVM pc, val.i = constant */
3185 if (src->flags & INMEMORY) {
3186 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3189 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3191 i386_jcc(cd, I386_CC_NE, 0);
3192 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3195 case ICMD_IFGT: /* ..., value ==> ... */
3196 /* op1 = target JavaVM pc, val.i = constant */
3198 if (src->flags & INMEMORY) {
3199 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3202 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3204 i386_jcc(cd, I386_CC_G, 0);
3205 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3208 case ICMD_IFGE: /* ..., value ==> ... */
3209 /* op1 = target JavaVM pc, val.i = constant */
3211 if (src->flags & INMEMORY) {
3212 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3215 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3217 i386_jcc(cd, I386_CC_GE, 0);
3218 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3221 case ICMD_IF_LEQ: /* ..., value ==> ... */
3222 /* op1 = target JavaVM pc, val.l = constant */
3224 if (src->flags & INMEMORY) {
3225 if (iptr->val.l == 0) {
3226 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3227 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3230 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3231 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3232 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3233 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l, REG_ITMP1);
3234 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3237 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3238 i386_jcc(cd, I386_CC_E, 0);
3239 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3242 case ICMD_IF_LLT: /* ..., value ==> ... */
3243 /* op1 = target JavaVM pc, val.l = constant */
3245 if (src->flags & INMEMORY) {
3246 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3247 i386_jcc(cd, I386_CC_L, 0);
3248 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3251 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3252 CALCIMMEDIATEBYTES(a, iptr->val.l);
3254 i386_jcc(cd, I386_CC_G, a);
3256 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3257 i386_jcc(cd, I386_CC_B, 0);
3258 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3262 case ICMD_IF_LLE: /* ..., value ==> ... */
3263 /* op1 = target JavaVM pc, val.l = constant */
3265 if (src->flags & INMEMORY) {
3266 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3267 i386_jcc(cd, I386_CC_L, 0);
3268 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3271 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3272 CALCIMMEDIATEBYTES(a, iptr->val.l);
3274 i386_jcc(cd, I386_CC_G, a);
3276 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3277 i386_jcc(cd, I386_CC_BE, 0);
3278 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3282 case ICMD_IF_LNE: /* ..., value ==> ... */
3283 /* op1 = target JavaVM pc, val.l = constant */
3285 if (src->flags & INMEMORY) {
3286 if (iptr->val.l == 0) {
3287 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3288 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3291 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3292 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3293 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3294 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3295 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3298 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3299 i386_jcc(cd, I386_CC_NE, 0);
3300 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3303 case ICMD_IF_LGT: /* ..., value ==> ... */
3304 /* op1 = target JavaVM pc, val.l = constant */
3306 if (src->flags & INMEMORY) {
3307 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3308 i386_jcc(cd, I386_CC_G, 0);
3309 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3312 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3313 CALCIMMEDIATEBYTES(a, iptr->val.l);
3315 i386_jcc(cd, I386_CC_L, a);
3317 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3318 i386_jcc(cd, I386_CC_A, 0);
3319 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3323 case ICMD_IF_LGE: /* ..., value ==> ... */
3324 /* op1 = target JavaVM pc, val.l = constant */
3326 if (src->flags & INMEMORY) {
3327 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3328 i386_jcc(cd, I386_CC_G, 0);
3329 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3332 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3333 CALCIMMEDIATEBYTES(a, iptr->val.l);
3335 i386_jcc(cd, I386_CC_L, a);
3337 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3338 i386_jcc(cd, I386_CC_AE, 0);
3339 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3343 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3344 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3346 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3347 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3348 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3350 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3351 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3353 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3354 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3357 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3359 i386_jcc(cd, I386_CC_E, 0);
3360 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3363 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3364 /* op1 = target JavaVM pc */
3366 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3367 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3368 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3369 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3370 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3371 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3372 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3374 i386_jcc(cd, I386_CC_E, 0);
3375 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3378 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3379 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3381 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3382 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3383 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3385 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3386 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3388 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3389 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3392 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3394 i386_jcc(cd, I386_CC_NE, 0);
3395 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3398 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3399 /* op1 = target JavaVM pc */
3401 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3402 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3403 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3404 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3405 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3406 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3407 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3409 i386_jcc(cd, I386_CC_NE, 0);
3410 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3413 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3414 /* op1 = target JavaVM pc */
3416 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3417 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3418 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3420 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3421 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3423 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3424 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3427 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3429 i386_jcc(cd, I386_CC_L, 0);
3430 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3433 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3434 /* op1 = target JavaVM pc */
3436 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3437 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3438 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3439 i386_jcc(cd, I386_CC_L, 0);
3440 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3443 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3444 CALCOFFSETBYTES(a, REG_SP, src->regoff);
3446 i386_jcc(cd, I386_CC_G, a);
3448 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3449 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3450 i386_jcc(cd, I386_CC_B, 0);
3451 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3455 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3456 /* op1 = target JavaVM pc */
3458 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3459 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3460 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3462 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3463 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3465 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3466 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3469 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3471 i386_jcc(cd, I386_CC_G, 0);
3472 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3475 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3476 /* op1 = target JavaVM pc */
3478 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3479 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3480 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3481 i386_jcc(cd, I386_CC_G, 0);
3482 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3485 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3486 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3488 i386_jcc(cd, I386_CC_L, a);
3490 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3491 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3492 i386_jcc(cd, I386_CC_A, 0);
3493 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3497 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3498 /* op1 = target JavaVM pc */
3500 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3501 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3502 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3504 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3505 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3507 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3508 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3511 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3513 i386_jcc(cd, I386_CC_LE, 0);
3514 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3517 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3518 /* op1 = target JavaVM pc */
3520 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3521 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3522 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3523 i386_jcc(cd, I386_CC_L, 0);
3524 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3527 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3528 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3530 i386_jcc(cd, I386_CC_G, a);
3532 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3533 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3534 i386_jcc(cd, I386_CC_BE, 0);
3535 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3539 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3540 /* op1 = target JavaVM pc */
3542 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3543 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3544 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3546 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3547 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3549 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3550 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3553 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3555 i386_jcc(cd, I386_CC_GE, 0);
3556 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3559 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3560 /* op1 = target JavaVM pc */
3562 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3563 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3564 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3565 i386_jcc(cd, I386_CC_G, 0);
3566 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3569 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3570 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3572 i386_jcc(cd, I386_CC_L, a);
3574 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3575 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3576 i386_jcc(cd, I386_CC_AE, 0);
3577 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3581 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3583 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3586 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3587 /* val.i = constant */
3589 d = reg_of_var(rd, iptr->dst, REG_NULL);
3590 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
3593 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3594 /* val.i = constant */
3596 d = reg_of_var(rd, iptr->dst, REG_NULL);
3597 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
3600 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3601 /* val.i = constant */
3603 d = reg_of_var(rd, iptr->dst, REG_NULL);
3604 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
3607 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3608 /* val.i = constant */
3610 d = reg_of_var(rd, iptr->dst, REG_NULL);
3611 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
3614 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3615 /* val.i = constant */
3617 d = reg_of_var(rd, iptr->dst, REG_NULL);
3618 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
3621 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3622 /* val.i = constant */
3624 d = reg_of_var(rd, iptr->dst, REG_NULL);
3625 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
3629 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3632 var_to_reg_int(s1, src, REG_RESULT);
3633 M_INTMOVE(s1, REG_RESULT);
3635 goto nowperformreturn;
3637 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3639 if (src->flags & INMEMORY) {
3640 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_RESULT);
3641 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3644 panic("LRETURN: longs have to be in memory");
3647 goto nowperformreturn;
3649 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3650 case ICMD_DRETURN: /* ..., retvalue ==> ... */
3652 var_to_reg_flt(s1, src, REG_FRESULT);
3653 /* this may be an early return -- keep the offset correct for the
3657 goto nowperformreturn;
3659 case ICMD_RETURN: /* ... ==> ... */
3665 p = parentargs_base;
3667 /* call trace function */
3669 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3671 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3673 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3674 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3676 i386_fstl_membase(cd, REG_SP, 4 + 8);
3677 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3679 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3680 i386_call_reg(cd, REG_ITMP1);
3682 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3683 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3685 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3688 #if defined(USE_THREADS)
3689 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3690 i386_mov_membase_reg(cd, REG_SP, 8 * rd->maxmemuse, REG_ITMP2);
3692 /* we need to save the proper return value */
3693 switch (iptr->opc) {
3696 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
3700 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
3701 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, rd->maxmemuse * 8 + 4);
3705 i386_fsts_membase(cd, REG_SP, rd->maxmemuse * 8);
3709 i386_fstl_membase(cd, REG_SP, rd->maxmemuse * 8);
3713 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
3714 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, 0);
3715 i386_mov_imm_reg(cd, (s4) builtin_monitorexit, REG_ITMP1);
3716 i386_call_reg(cd, REG_ITMP1);
3717 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
3719 /* and now restore the proper return value */
3720 switch (iptr->opc) {
3723 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
3727 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
3728 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8 + 4, REG_RESULT2);
3732 i386_flds_membase(cd, REG_SP, rd->maxmemuse * 8);
3736 i386_fldl_membase(cd, REG_SP, rd->maxmemuse * 8);
3742 /* restore saved registers */
3743 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
3745 i386_mov_membase_reg(cd, REG_SP, p * 8, rd->savintregs[i]);
3747 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
3749 i386_fldl_membase(cd, REG_SP, p * 8);
3751 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3752 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
3754 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
3759 /* deallocate stack */
3760 if (parentargs_base) {
3761 i386_alu_imm_reg(cd, I386_ADD, parentargs_base * 8, REG_SP);
3770 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3775 tptr = (void **) iptr->target;
3777 s4ptr = iptr->val.a;
3778 l = s4ptr[1]; /* low */
3779 i = s4ptr[2]; /* high */
3781 var_to_reg_int(s1, src, REG_ITMP1);
3782 M_INTMOVE(s1, REG_ITMP1);
3784 i386_alu_imm_reg(cd, I386_SUB, l, REG_ITMP1);
3790 i386_alu_imm_reg(cd, I386_CMP, i - 1, REG_ITMP1);
3791 i386_jcc(cd, I386_CC_A, 0);
3793 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
3794 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3796 /* build jump table top down and use address of lowest entry */
3798 /* s4ptr += 3 + i; */
3802 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
3803 dseg_addtarget(cd, (basicblock *) tptr[0]);
3807 /* length of dataseg after last dseg_addtarget is used by load */
3809 i386_mov_imm_reg(cd, 0, REG_ITMP2);
3810 dseg_adddata(cd, cd->mcodeptr);
3811 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3812 i386_jmp_reg(cd, REG_ITMP1);
3818 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3820 s4 i, l, val, *s4ptr;
3823 tptr = (void **) iptr->target;
3825 s4ptr = iptr->val.a;
3826 l = s4ptr[0]; /* default */
3827 i = s4ptr[1]; /* count */
3829 MCODECHECK((i<<2)+8);
3830 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3836 i386_alu_imm_reg(cd, I386_CMP, val, s1);
3837 i386_jcc(cd, I386_CC_E, 0);
3838 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), cd->mcodeptr); */
3839 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3842 i386_jmp_imm(cd, 0);
3843 /* codegen_addreference(cd, BlockPtrOfPC(l), cd->mcodeptr); */
3845 tptr = (void **) iptr->target;
3846 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3853 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3854 /* op1 = return type, val.a = function pointer*/
3858 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3859 /* op1 = return type, val.a = function pointer*/
3863 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3864 /* op1 = return type, val.a = function pointer*/
3868 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3869 /* op1 = arg count, val.a = method pointer */
3871 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3872 /* op1 = arg count, val.a = method pointer */
3874 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3875 /* op1 = arg count, val.a = method pointer */
3877 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3878 /* op1 = arg count, val.a = method pointer */
3885 MCODECHECK((s3 << 1) + 64);
3887 /* copy arguments to registers or stack location */
3889 for (; --s3 >= 0; src = src->prev) {
3890 if (src->varkind == ARGVAR) {
3894 if (IS_INT_LNG_TYPE(src->type)) {
3895 if (s3 < rd->intreg_argnum) {
3896 panic("No integer argument registers available!");
3899 if (!IS_2_WORD_TYPE(src->type)) {
3900 if (src->flags & INMEMORY) {
3901 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3902 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s3 * 8);
3905 i386_mov_reg_membase(cd, src->regoff, REG_SP, s3 * 8);
3909 if (src->flags & INMEMORY) {
3910 M_LNGMEMMOVE(src->regoff, s3);
3913 panic("copy arguments: longs have to be in memory");
3919 if (s3 < rd->fltreg_argnum) {
3920 panic("No float argument registers available!");
3923 var_to_reg_flt(d, src, REG_FTMP1);
3924 if (src->type == TYPE_FLT) {
3925 i386_fstps_membase(cd, REG_SP, s3 * 8);
3928 i386_fstpl_membase(cd, REG_SP, s3 * 8);
3935 switch (iptr->opc) {
3942 i386_mov_imm_reg(cd, a, REG_ITMP1);
3943 i386_call_reg(cd, REG_ITMP1);
3946 case ICMD_INVOKESTATIC:
3947 a = (u4) lm->stubroutine;
3950 i386_mov_imm_reg(cd, a, REG_ITMP2);
3951 i386_call_reg(cd, REG_ITMP2);
3954 case ICMD_INVOKESPECIAL:
3955 a = (u4) lm->stubroutine;
3958 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3959 gen_nullptr_check(REG_ITMP1);
3960 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
3962 i386_mov_imm_reg(cd, a, REG_ITMP2);
3963 i386_call_reg(cd, REG_ITMP2);
3966 case ICMD_INVOKEVIRTUAL:
3969 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3970 gen_nullptr_check(REG_ITMP1);
3971 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
3972 i386_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
3974 i386_call_reg(cd, REG_ITMP1);
3977 case ICMD_INVOKEINTERFACE:
3980 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3981 gen_nullptr_check(REG_ITMP1);
3982 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3983 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * lm->class->index, REG_ITMP2);
3984 i386_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - lm->class->methods), REG_ITMP1);
3986 i386_call_reg(cd, REG_ITMP1);
3990 /* d contains return type */
3992 if (d != TYPE_VOID) {
3993 d = reg_of_var(rd, iptr->dst, REG_NULL);
3995 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3996 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3997 if (iptr->dst->flags & INMEMORY) {
3998 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3999 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
4002 panic("RETURN: longs have to be in memory");
4006 if (iptr->dst->flags & INMEMORY) {
4007 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
4010 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
4015 /* fld from called function -- has other fpu_st_offset counter */
4017 store_reg_to_var_flt(iptr->dst, d);
4024 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
4026 /* op1: 0 == array, 1 == class */
4027 /* val.a: (classinfo*) superclass */
4029 /* superclass is an interface:
4031 * return (sub != NULL) &&
4032 * (sub->vftbl->interfacetablelength > super->index) &&
4033 * (sub->vftbl->interfacetable[-super->index] != NULL);
4035 * superclass is a class:
4037 * return ((sub != NULL) && (0
4038 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4039 * super->vftbl->diffvall));
4043 classinfo *super = (classinfo*) iptr->val.a;
4045 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4046 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4048 var_to_reg_int(s1, src, REG_ITMP1);
4049 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4051 M_INTMOVE(s1, REG_ITMP1);
4054 i386_alu_reg_reg(cd, I386_XOR, d, d);
4055 if (iptr->op1) { /* class/interface */
4056 if (super->flags & ACC_INTERFACE) { /* interface */
4057 i386_test_reg_reg(cd, s1, s1);
4059 /* TODO: clean up this calculation */
4061 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4064 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4067 /* CALCOFFSETBYTES(a, super->index); */
4068 CALCIMMEDIATEBYTES(a, super->index);
4074 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4081 i386_jcc(cd, I386_CC_E, a);
4083 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4084 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4085 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4087 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4089 /* TODO: clean up this calculation */
4092 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4099 i386_jcc(cd, I386_CC_LE, a);
4100 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4102 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP1);
4103 /* i386_setcc_reg(cd, I386_CC_A, d); */
4104 /* i386_jcc(cd, I386_CC_BE, 5); */
4105 i386_jcc(cd, I386_CC_E, 5);
4106 i386_mov_imm_reg(cd, 1, d);
4109 } else { /* class */
4110 i386_test_reg_reg(cd, s1, s1);
4112 /* TODO: clean up this calculation */
4114 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4117 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4119 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4122 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4132 i386_jcc(cd, I386_CC_E, a);
4134 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4135 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4136 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4137 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4139 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4140 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4141 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4142 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4143 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4145 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4146 i386_alu_reg_reg(cd, I386_XOR, d, d);
4148 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4149 i386_jcc(cd, I386_CC_A, 5);
4150 i386_mov_imm_reg(cd, 1, d);
4154 panic ("internal error: no inlined array instanceof");
4156 store_reg_to_var_int(iptr->dst, d);
4159 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4161 /* op1: 0 == array, 1 == class */
4162 /* val.a: (classinfo*) superclass */
4164 /* superclass is an interface:
4166 * OK if ((sub == NULL) ||
4167 * (sub->vftbl->interfacetablelength > super->index) &&
4168 * (sub->vftbl->interfacetable[-super->index] != NULL));
4170 * superclass is a class:
4172 * OK if ((sub == NULL) || (0
4173 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4174 * super->vftbl->diffvall));
4178 classinfo *super = (classinfo*) iptr->val.a;
4180 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4181 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4183 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4184 var_to_reg_int(s1, src, d);
4185 if (iptr->op1) { /* class/interface */
4186 if (super->flags & ACC_INTERFACE) { /* interface */
4187 i386_test_reg_reg(cd, s1, s1);
4189 /* TODO: clean up this calculation */
4191 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4194 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4197 /* CALCOFFSETBYTES(a, super->index); */
4198 CALCIMMEDIATEBYTES(a, super->index);
4204 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4209 i386_jcc(cd, I386_CC_E, a);
4211 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4212 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4213 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4215 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4216 i386_jcc(cd, I386_CC_LE, 0);
4217 codegen_addxcastrefs(cd, cd->mcodeptr);
4218 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
4220 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4221 i386_jcc(cd, I386_CC_E, 0);
4222 codegen_addxcastrefs(cd, cd->mcodeptr);
4224 } else { /* class */
4225 i386_test_reg_reg(cd, s1, s1);
4227 /* TODO: clean up this calculation */
4229 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4234 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4236 if (d != REG_ITMP3) {
4238 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4241 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4247 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4254 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4261 i386_jcc(cd, I386_CC_E, a);
4263 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4264 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4265 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4266 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4268 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4269 if (d != REG_ITMP3) {
4270 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4271 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4272 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4273 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4275 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4278 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
4279 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1);
4280 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4281 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4282 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4283 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4287 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4288 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
4289 codegen_addxcastrefs(cd, cd->mcodeptr);
4293 panic ("internal error: no inlined array checkcast");
4296 store_reg_to_var_int(iptr->dst, d);
4299 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4301 if (src->flags & INMEMORY) {
4302 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4305 i386_test_reg_reg(cd, src->regoff, src->regoff);
4307 i386_jcc(cd, I386_CC_L, 0);
4308 codegen_addxcheckarefs(cd, cd->mcodeptr);
4311 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4313 i386_test_reg_reg(cd, REG_RESULT, REG_RESULT);
4314 i386_jcc(cd, I386_CC_E, 0);
4315 codegen_addxexceptionrefs(cd, cd->mcodeptr);
4318 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4319 /* op1 = dimension, val.a = array descriptor */
4321 /* check for negative sizes and copy sizes to stack if necessary */
4323 MCODECHECK((iptr->op1 << 1) + 64);
4325 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4326 if (src->flags & INMEMORY) {
4327 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4330 i386_test_reg_reg(cd, src->regoff, src->regoff);
4332 i386_jcc(cd, I386_CC_L, 0);
4333 codegen_addxcheckarefs(cd, cd->mcodeptr);
4336 * copy sizes to new stack location, be cause native function
4337 * builtin_nmultianewarray access them as (int *)
4339 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
4340 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);
4342 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
4344 if (src->varkind != ARGVAR) {
4345 if (src->flags & INMEMORY) {
4346 i386_mov_membase_reg(cd, REG_SP, (src->regoff + INT_ARG_CNT) * 8, REG_ITMP1);
4347 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, (s1 + INT_ARG_CNT) * 8);
4350 i386_mov_reg_membase(cd, src->regoff, REG_SP, (s1 + INT_ARG_CNT) * 8);
4354 i386_alu_imm_reg(cd, I386_SUB, iptr->op1 * 4, REG_SP);
4356 /* a0 = dimension count */
4358 /* save stack pointer */
4359 M_INTMOVE(REG_SP, REG_ITMP1);
4361 i386_alu_imm_reg(cd, I386_SUB, 12, REG_SP);
4362 i386_mov_imm_membase(cd, iptr->op1, REG_SP, 0);
4364 /* a1 = arraydescriptor */
4366 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, 4);
4368 /* a2 = pointer to dimensions = stack pointer */
4370 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 8);
4372 i386_mov_imm_reg(cd, (s4) (builtin_nmultianewarray), REG_ITMP1);
4373 i386_call_reg(cd, REG_ITMP1);
4374 i386_alu_imm_reg(cd, I386_ADD, 12 + iptr->op1 * 4, REG_SP);
4376 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
4377 M_INTMOVE(REG_RESULT, s1);
4378 store_reg_to_var_int(iptr->dst, s1);
4381 case ICMD_INLINE_START:
4382 case ICMD_INLINE_END:
4385 error ("Unknown pseudo command: %d", iptr->opc);
4388 } /* for instruction */
4390 /* copy values to interface registers */
4392 src = bptr->outstack;
4393 len = bptr->outdepth;
4400 if ((src->varkind != STACKVAR)) {
4402 if (IS_FLT_DBL_TYPE(s2)) {
4403 var_to_reg_flt(s1, src, REG_FTMP1);
4404 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4405 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
4408 panic("double store");
4409 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4413 var_to_reg_int(s1, src, REG_ITMP1);
4414 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
4415 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4416 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
4419 i386_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
4423 if (rd->interfaces[len][s2].flags & INMEMORY) {
4424 M_LNGMEMMOVE(s1, rd->interfaces[len][s2].regoff);
4427 panic("copy interface registers: longs have to be in memory (end)");
4434 } /* if (bptr -> flags >= BBREACHED) */
4435 } /* for basic block */
4437 codegen_createlinenumbertable(cd);
4441 /* generate bound check stubs */
4443 u1 *xcodeptr = NULL;
4446 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
4447 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4449 cd->mcodeptr - cd->mcodebase);
4453 /* move index register into REG_ITMP1 */
4454 i386_mov_reg_reg(cd, bref->reg, REG_ITMP1); /* 2 bytes */
4456 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4457 dseg_adddata(cd, cd->mcodeptr);
4458 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3); /* 5 bytes */
4459 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4461 if (xcodeptr != NULL) {
4462 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4465 xcodeptr = cd->mcodeptr;
4467 i386_push_reg(cd, REG_ITMP2_XPC);
4469 PREPARE_NATIVE_STACKINFO;
4471 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4472 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 4);
4473 i386_mov_imm_reg(cd, (u4) new_arrayindexoutofboundsexception, REG_ITMP1);
4474 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4475 i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4477 REMOVE_NATIVE_STACKINFO;
4479 i386_pop_reg(cd, REG_ITMP2_XPC);
4481 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4482 i386_jmp_reg(cd, REG_ITMP3);
4486 /* generate negative array size check stubs */
4490 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
4491 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4492 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4494 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4498 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4500 cd->mcodeptr - cd->mcodebase);
4504 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4505 dseg_adddata(cd, cd->mcodeptr);
4506 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4507 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4509 if (xcodeptr != NULL) {
4510 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4513 xcodeptr = cd->mcodeptr;
4515 i386_push_reg(cd, REG_ITMP2_XPC);
4517 PREPARE_NATIVE_STACKINFO;
4519 i386_mov_imm_reg(cd, (u4) new_negativearraysizeexception, REG_ITMP1);
4520 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4521 /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4524 REMOVE_NATIVE_STACKINFO;
4526 i386_pop_reg(cd, REG_ITMP2_XPC);
4528 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4529 i386_jmp_reg(cd, REG_ITMP3);
4533 /* generate cast check stubs */
4537 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
4538 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4539 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4541 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4545 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4547 cd->mcodeptr - cd->mcodebase);
4551 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4552 dseg_adddata(cd, cd->mcodeptr);
4553 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4554 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4556 if (xcodeptr != NULL) {
4557 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4560 xcodeptr = cd->mcodeptr;
4562 i386_push_reg(cd, REG_ITMP2_XPC);
4564 PREPARE_NATIVE_STACKINFO;
4566 i386_mov_imm_reg(cd, (u4) new_classcastexception, REG_ITMP1);
4567 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4568 /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4571 REMOVE_NATIVE_STACKINFO;
4573 i386_pop_reg(cd, REG_ITMP2_XPC);
4575 i386_mov_imm_reg(cd, (u4) asm_handle_exception, REG_ITMP3);
4576 i386_jmp_reg(cd, REG_ITMP3);
4580 /* generate divide by zero check stubs */
4584 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
4585 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4586 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4588 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4592 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4594 cd->mcodeptr - cd->mcodebase);
4598 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4599 dseg_adddata(cd, cd->mcodeptr);
4600 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4601 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4603 if (xcodeptr != NULL) {
4604 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4607 xcodeptr = cd->mcodeptr;
4609 i386_push_reg(cd, REG_ITMP2_XPC);
4611 PREPARE_NATIVE_STACKINFO;
4613 i386_mov_imm_reg(cd, (u4) new_arithmeticexception, REG_ITMP1);
4614 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4616 REMOVE_NATIVE_STACKINFO;
4618 i386_pop_reg(cd, REG_ITMP2_XPC);
4620 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4621 i386_jmp_reg(cd, REG_ITMP3);
4625 /* generate exception check stubs */
4629 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
4630 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4631 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4633 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4637 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4639 cd->mcodeptr - cd->mcodebase);
4643 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4644 dseg_adddata(cd, cd->mcodeptr);
4645 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4646 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4648 if (xcodeptr != NULL) {
4649 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4652 xcodeptr = cd->mcodeptr;
4654 i386_push_reg(cd, REG_ITMP2_XPC);
4656 PREPARE_NATIVE_STACKINFO;
4658 i386_mov_imm_reg(cd, (s4) codegen_general_stubcalled, REG_ITMP1);
4659 i386_call_reg(cd, REG_ITMP1);
4661 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4662 i386_mov_imm_reg(cd, (s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4663 i386_call_reg(cd, REG_ITMP1);
4664 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP3);
4665 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
4666 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1_XPTR);
4668 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP3);
4669 i386_mov_membase_reg(cd, REG_ITMP3, 0, REG_ITMP1_XPTR);
4670 i386_mov_imm_membase(cd, 0, REG_ITMP3, 0);
4672 i386_push_imm(cd, 0);
4673 i386_push_reg(cd, REG_ITMP1_XPTR);
4675 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4676 java stack at this point*/
4677 i386_mov_membase_reg(cd, REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4678 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, class), REG_ITMP1);
4679 i386_push_imm(cd, (u4) utf_fillInStackTrace_desc);
4680 i386_push_imm(cd, (u4) utf_fillInStackTrace_name);
4681 i386_push_reg(cd, REG_ITMP1);
4682 i386_mov_imm_reg(cd, (s4) class_resolvemethod, REG_ITMP3);
4683 i386_call_reg(cd, REG_ITMP3);
4684 /*cleanup parameters of class_resolvemethod*/
4685 i386_alu_imm_reg(cd, I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4686 /*prepare call to asm_calljavafunction2 */
4687 i386_push_imm(cd, 0);
4688 i386_push_imm(cd, TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
4689 i386_push_reg(cd, REG_SP);
4690 i386_push_imm(cd, sizeof(jni_callblock));
4691 i386_push_imm(cd, 1);
4692 i386_push_reg(cd, REG_RESULT);
4694 i386_mov_imm_reg(cd, (s4) asm_calljavafunction2, REG_ITMP3);
4695 i386_call_reg(cd, REG_ITMP3);
4697 /* check exceptionptr + fail (JOWENN)*/
4699 i386_alu_imm_reg(cd, I386_ADD,6*4,REG_SP);
4701 i386_pop_reg(cd, REG_ITMP1_XPTR);
4702 i386_pop_reg(cd, REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4704 REMOVE_NATIVE_STACKINFO;
4706 i386_pop_reg(cd, REG_ITMP2_XPC);
4708 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4709 i386_jmp_reg(cd, REG_ITMP3);
4713 /* generate null pointer check stubs */
4717 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
4718 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4719 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4721 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4725 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4727 cd->mcodeptr - cd->mcodebase);
4731 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4732 dseg_adddata(cd, cd->mcodeptr);
4733 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4734 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4736 if (xcodeptr != NULL) {
4737 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4740 xcodeptr = cd->mcodeptr;
4742 i386_push_reg(cd, REG_ITMP2_XPC);
4744 PREPARE_NATIVE_STACKINFO;
4747 /* create native call block*/
4748 i386_alu_imm_reg(cd, I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4751 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1);
4752 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/
4754 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4755 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
4756 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
4757 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
4758 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4759 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */
4760 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4763 i386_mov_imm_reg(cd, (u4) new_nullpointerexception, REG_ITMP1);
4764 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4766 REMOVE_NATIVE_STACKINFO;
4769 /* restore native call stack */
4770 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2);
4771 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3);
4772 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0);
4773 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
4776 i386_pop_reg(cd, REG_ITMP2_XPC);
4778 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4779 i386_jmp_reg(cd, REG_ITMP3);
4783 /* generate put/getstatic stub call code */
4791 tmpcd = DNEW(codegendata);
4793 for (cref = cd->clinitrefs; cref != NULL; cref = cref->next) {
4794 /* Get machine code which is patched back in later. A */
4795 /* `call rel32' is 5 bytes long. */
4796 xcodeptr = cd->mcodebase + cref->branchpos;
4798 mcode = *((u4 *) (xcodeptr + 1));
4802 /* patch in `call rel32' to call the following code */
4803 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
4804 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
4806 /* Save current stack pointer into a temporary register. */
4807 i386_mov_reg_reg(cd, REG_SP, REG_ITMP1);
4809 /* Push machine code bytes to patch onto the stack. */
4810 i386_push_imm(cd, (u4) xmcode);
4811 i386_push_imm(cd, (u4) mcode);
4813 i386_push_imm(cd, (u4) cref->class);
4815 /* Push previously saved stack pointer onto stack. */
4816 i386_push_reg(cd, REG_ITMP1);
4818 i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP1);
4819 i386_jmp_reg(cd, REG_ITMP1);
4824 codegen_finish(m, cd, (u4) (cd->mcodeptr - cd->mcodebase));
4828 /* function createcompilerstub *************************************************
4830 creates a stub routine which calls the compiler
4832 *******************************************************************************/
4834 #define COMPSTUBSIZE 12
4836 u1 *createcompilerstub(methodinfo *m)
4838 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
4842 /* mark start of dump memory area */
4844 dumpsize = dump_size();
4846 cd = DNEW(codegendata);
4849 /* code for the stub */
4850 i386_mov_imm_reg(cd, (u4) m, REG_ITMP1);/* pass method pointer to compiler*/
4852 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
4853 i386_mov_imm_reg(cd, (u4) asm_call_jit_compiler, REG_ITMP3);
4854 i386_jmp_reg(cd, REG_ITMP3); /* jump to compiler */
4856 #if defined(STATISTICS)
4858 count_cstub_len += COMPSTUBSIZE;
4861 /* release dump area */
4863 dump_release(dumpsize);
4869 /* function removecompilerstub *************************************************
4871 deletes a compilerstub from memory (simply by freeing it)
4873 *******************************************************************************/
4875 void removecompilerstub(u1 *stub)
4877 CFREE(stub, COMPSTUBSIZE);
4881 /* function: createnativestub **************************************************
4883 creates a stub routine which calls a native method
4885 *******************************************************************************/
4887 #define NATIVESTUBSIZE 370 + 36
4890 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4891 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4894 void i386_native_stub_debug(void **p) {
4895 printf("Pos on stack: %p\n",p);
4896 printf("Return adress should be: %p\n",*p);
4899 void i386_native_stub_debug2(void **p) {
4900 printf("Pos on stack: %p\n",p);
4901 printf("Return for lookup is: %p\n",*p);
4904 void traverseStackInfo() {
4905 void **p=builtin_asm_get_stackframeinfo();
4909 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4910 m=*((methodinfo**)((*p)+8));
4911 utf_display(m->name);
4920 u1 *createnativestub(functionptr f, methodinfo *m)
4922 u1 *s = CNEW(u1, NATIVESTUBSIZE); /* memory to hold the stub */
4925 t_inlining_globals *id;
4931 int stackframesize = 4+12; /* initial 4 bytes is space for jni env,
4932 + 4 byte thread pointer + 4 byte previous pointer + method info*/
4933 int stackframeoffset = 4;
4937 void** callAddrPatchPos=0;
4939 void** jmpInstrPatchPos=0;
4941 /* mark start of dump memory area */
4943 dumpsize = dump_size();
4945 /* allocate required dump memory */
4947 cd = DNEW(codegendata);
4948 rd = DNEW(registerdata);
4949 id = DNEW(t_inlining_globals);
4951 /* setup registers before using it */
4953 inlining_setup(m, id);
4954 reg_setup(m, rd, id);
4956 /* set some required varibles which are normally set by codegen_setup */
4959 cd->clinitrefs = NULL;
4961 if (m->flags & ACC_STATIC) {
4962 stackframesize += 4;
4963 stackframeoffset += 4;
4966 descriptor2types(m); /* set paramcount and paramtypes */
4969 /* i386_push_reg(cd, REG_SP);
4970 i386_mov_imm_reg(cd, (s4) i386_native_stub_debug, REG_ITMP1);
4971 i386_call_reg(cd, REG_ITMP1);
4972 i386_pop_reg(cd, REG_ITMP1);*/
4975 /* if function is static, check for initialized */
4977 if (m->flags & ACC_STATIC) {
4978 /* if class isn't yet initialized, do it */
4979 if (!m->class->initialized) {
4980 s4 *header = (s4 *) s;
4981 *header = 0;/*extablesize*/
4983 *header = 0;/*line number table start*/
4985 *header = 0;/*line number table size*/
4987 *header = 0;/*fltsave*/
4989 *header = 0;/*intsave*/
4991 *header = 0;/*isleaf*/
4993 *header = 0;/*issync*/
4995 *header = 0;/*framesize*/
4997 *header = (u4) m;/*methodpointer*/
5006 codegen_addclinitref(cd, cd->mcodeptr, m->class);
5011 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
5013 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
5014 t = m->paramtypes[p];
5015 if (IS_INT_LNG_TYPE(t)) {
5016 if (IS_2_WORD_TYPE(t)) {
5017 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
5018 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
5019 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5020 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5022 } else if (t == TYPE_ADR) {
5023 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
5024 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
5025 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5026 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5029 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
5031 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
5032 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
5036 if (!IS_2_WORD_TYPE(t)) {
5037 i386_flds_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
5038 i386_fstps_membase(cd, REG_SP, p * 8);
5039 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
5040 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5043 i386_fldl_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
5044 i386_fstpl_membase(cd, REG_SP, p * 8);
5049 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
5050 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
5051 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5052 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
5055 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
5057 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
5058 i386_call_reg(cd, REG_ITMP1);
5060 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
5064 * mark the whole fpu stack as free for native functions
5065 * (only for saved register count == 0)
5067 i386_ffree_reg(cd, 0);
5068 i386_ffree_reg(cd, 1);
5069 i386_ffree_reg(cd, 2);
5070 i386_ffree_reg(cd, 3);
5071 i386_ffree_reg(cd, 4);
5072 i386_ffree_reg(cd, 5);
5073 i386_ffree_reg(cd, 6);
5074 i386_ffree_reg(cd, 7);
5076 /* calculate stackframe size for native function */
5077 tptr = m->paramtypes;
5078 for (i = 0; i < m->paramcount; i++) {
5083 stackframesize += 4;
5088 stackframesize += 8;
5092 panic("unknown parameter type in native function");
5096 i386_alu_imm_reg(cd, I386_SUB, stackframesize, REG_SP);
5098 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
5099 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
5100 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
5101 i386_call_reg(cd, REG_ITMP1);
5102 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
5103 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2);
5104 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
5105 i386_mov_reg_reg(cd, REG_SP,REG_ITMP2);
5106 i386_alu_imm_reg(cd, I386_ADD,stackframesize-12,REG_ITMP2);
5107 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0);
5110 /* i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
5111 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
5112 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-12);*/
5114 /* CREATE DYNAMIC STACK INFO -- END*/
5116 /* RESOLVE NATIVE METHOD -- BEGIN*/
5117 #ifndef STATIC_CLASSPATH
5119 log_text("Dynamic classpath: preparing for delayed native function resolving");
5121 jmpInstrPos=cd->mcodeptr-4;
5123 i386_mov_imm_reg(cd,jmpInstrPos,REG_ITMP1);
5124 i386_push_reg(cd,REG_ITMP1);
5126 i386_mov_imm_reg(cd,0,REG_ITMP1);
5127 jmpInstrPatchPos=cd->mcodeptr-4;
5128 i386_push_reg(cd,REG_ITMP1);
5129 /*position of call address to patch*/
5130 i386_mov_imm_reg(cd,0,REG_ITMP1);
5131 callAddrPatchPos=(cd->mcodeptr-4);
5132 i386_push_reg(cd,REG_ITMP1);
5133 /*method info structure*/
5134 i386_mov_imm_reg(cd,(s4) m, REG_ITMP1);
5135 i386_push_reg(cd,REG_ITMP1);
5136 /*call resolve functions*/
5137 i386_mov_imm_reg(cd, (s4)codegen_resolve_native,REG_ITMP1);
5138 i386_call_reg(cd,REG_ITMP1);
5140 i386_pop_reg(cd,REG_ITMP1);
5141 i386_pop_reg(cd,REG_ITMP1);
5142 i386_pop_reg(cd,REG_ITMP1);
5143 i386_pop_reg(cd,REG_ITMP1);
5144 /*fix jmp offset replacement*/
5145 (*jmpInstrPatchPos)=cd->mcodeptr-jmpInstrPos-4;
5146 } else log_text("Dynamic classpath: immediate native function resolution possible");
5148 /* RESOLVE NATIVE METHOD -- END*/
5152 tptr = m->paramtypes;
5153 for (i = 0; i < m->paramcount; i++) {
5158 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5159 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5160 stackframeoffset += 4;
5165 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5166 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5167 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5168 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, stackframeoffset + 4);
5169 stackframeoffset += 8;
5173 panic("unknown parameter type in native function");
5177 if (m->flags & ACC_STATIC) {
5178 /* put class into second argument */
5179 i386_mov_imm_membase(cd, (s4) m->class, REG_SP, 4);
5182 /* put env into first argument */
5183 i386_mov_imm_membase(cd, (s4) &env, REG_SP, 0);
5185 i386_mov_imm_reg(cd, (s4) f, REG_ITMP1);
5186 #ifndef STATIC_CLASSPATH
5188 (*callAddrPatchPos)=(cd->mcodeptr-4);
5190 i386_call_reg(cd, REG_ITMP1);
5192 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5193 i386_push_reg(cd, REG_RESULT2);
5194 i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
5195 i386_mov_membase_reg(cd, REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
5196 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT2,0);
5197 i386_pop_reg(cd, REG_RESULT2);
5198 /*REMOVE DYNAMIC STACK INFO -END */
5200 i386_alu_imm_reg(cd, I386_ADD, stackframesize, REG_SP);
5204 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5206 i386_mov_imm_membase(cd, (u4) m, REG_SP, 0);
5208 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
5209 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
5211 i386_fstl_membase(cd, REG_SP, 4 + 8);
5212 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5214 i386_mov_imm_reg(cd, (u4) builtin_displaymethodstop, REG_ITMP1);
5215 i386_call_reg(cd, REG_ITMP1);
5217 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
5218 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
5220 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5223 /* we can't use REG_ITMP3 == REG_RESULT2 */
5224 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5225 i386_push_reg(cd, REG_RESULT);
5226 i386_push_reg(cd, REG_RESULT2);
5227 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5228 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP2);
5229 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5230 i386_pop_reg(cd, REG_RESULT2);
5231 i386_pop_reg(cd, REG_RESULT);
5233 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5234 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP2);
5235 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5237 i386_jcc(cd, I386_CC_NE, 1);
5241 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5242 i386_push_reg(cd, REG_ITMP2);
5243 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5244 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5245 i386_pop_reg(cd, REG_ITMP1_XPTR);
5247 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1_XPTR);
5248 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5249 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5251 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP2_XPC);
5252 i386_alu_imm_reg(cd, I386_SUB, 2, REG_ITMP2_XPC);
5254 i386_mov_imm_reg(cd, (s4) asm_handle_nat_exception, REG_ITMP3);
5255 i386_jmp_reg(cd, REG_ITMP3);
5258 codegen_insertmethod(s, cd->mcodeptr);
5268 tmpcd = DNEW(codegendata);
5270 /* there can only be one clinit ref entry */
5271 cref = cd->clinitrefs;
5274 /* Get machine code which is patched back in later. A */
5275 /* `call rel32' is 5 bytes long. */
5276 xcodeptr = cd->mcodebase + cref->branchpos;
5278 mcode = *((u4 *) (xcodeptr + 1));
5280 /* patch in `call rel32' to call the following code */
5281 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5282 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5284 /* Save current stack pointer into a temporary register. */
5285 i386_mov_reg_reg(cd, REG_SP, REG_ITMP1);
5287 /* Push machine code bytes to patch onto the stack. */
5288 i386_push_imm(cd, (u4) xmcode);
5289 i386_push_imm(cd, (u4) mcode);
5291 i386_push_imm(cd, (u4) cref->class);
5293 /* Push previously saved stack pointer onto stack. */
5294 i386_push_reg(cd, REG_ITMP1);
5296 i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP1);
5297 i386_jmp_reg(cd, REG_ITMP1);
5302 dolog_plain("native stubentry: %p, stubsize: %d (for %d params) --", (s4)s,(s4) (cd->mcodeptr - s), m->paramcount);
5303 utf_display(m->name);
5307 #if defined(STATISTICS)
5309 count_nstub_len += NATIVESTUBSIZE;
5312 /* release dump area */
5314 dump_release(dumpsize);
5320 /* function: removenativestub **************************************************
5322 removes a previously created native-stub from memory
5324 *******************************************************************************/
5326 void removenativestub(u1 *stub)
5328 CFREE(stub, NATIVESTUBSIZE);
5333 * These are local overrides for various environment variables in Emacs.
5334 * Please do not remove this and leave it at the end of the file, where
5335 * Emacs will automagically detect them.
5336 * ---------------------------------------------------------------------
5339 * indent-tabs-mode: t