1 /* jit/i386/codegen.c - machine code generator for i386
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 Institut f. Computersprachen, TU Wien
5 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6 S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
9 This file is part of CACAO.
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2, or (at
14 your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Andreas Krall
31 $Id: codegen.c 1453 2004-11-05 14:18:13Z twisti $
41 #include <sys/ucontext.h>
46 #include "exceptions.h"
52 #include "jit/parse.h"
54 #include "jit/i386/codegen.h"
55 #include "jit/i386/emitfuncs.h"
56 /* include independent code generation stuff */
57 #include "jit/codegen.inc"
58 #include "jit/reg.inc"
61 /* register descripton - array ************************************************/
63 /* #define REG_RES 0 reserved register for OS or code generator */
64 /* #define REG_RET 1 return value register */
65 /* #define REG_EXC 2 exception value register (only old jit) */
66 /* #define REG_SAV 3 (callee) saved register */
67 /* #define REG_TMP 4 scratch temporary register (caller saved) */
68 /* #define REG_ARG 5 argument register (caller saved) */
70 /* #define REG_END -1 last entry in tables */
73 we initially try to use %edx as scratch register, it cannot be used if we
74 have one of these ICMDs:
75 LMUL, LMULCONST, IDIV, IREM, LALOAD, AASTORE, LASTORE, IASTORE, CASTORE,
76 SASTORE, BASTORE, INSTANCEOF, CHECKCAST, I2L, F2L, D2L
79 REG_RET, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV,
84 int nregdescfloat[] = {
85 /* rounding problems with callee saved registers */
86 /* REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_RES, REG_RES, */
87 /* REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, */
88 REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
93 void codegen_stubcalled() {
94 log_text("Stub has been called");
97 void codegen_general_stubcalled() {
98 log_text("general exception stub has been called");
102 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
103 void thread_restartcriticalsection(ucontext_t *uc)
106 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL)
107 uc->uc_mcontext.gregs[REG_EIP] = (u4) critical;
112 #define PREPARE_NATIVE_STACKINFO \
113 i386_push_reg(cd, REG_ITMP1); /*save itmp1, needed by some stubs */ \
114 i386_alu_imm_reg(cd, I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \
115 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1); \
116 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/ \
117 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \
118 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/ \
119 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/ \
120 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \
121 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */ \
122 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \
123 i386_mov_membase_reg(cd, REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \
124 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
127 #define REMOVE_NATIVE_STACKINFO \
128 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2); \
129 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3); \
130 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0); \
131 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
134 /* NullPointerException signal handler for hardware null pointer check */
136 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
139 /* long faultaddr; */
141 struct ucontext *_uc = (struct ucontext *) _p;
142 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
143 struct sigaction act;
145 /* Reset signal handler - necessary for SysV, does no harm for BSD */
147 /* instr = *((int*)(sigctx->eip)); */
148 /* faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f]; */
150 /* fprintf(stderr, "null=%d %p addr=%p\n", sig, sigctx, sigctx->eip);*/
152 /* if (faultaddr == 0) { */
153 /* signal(sig, (void *) catch_NullPointerException); */
154 act.sa_sigaction = (void *) catch_NullPointerException;
155 act.sa_flags = SA_SIGINFO;
156 sigaction(sig, &act, NULL); /* reinstall handler */
159 sigaddset(&nsig, sig);
160 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
162 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
163 sigctx->eax = (u4) string_java_lang_NullPointerException;
164 sigctx->eip = (u4) asm_throw_and_handle_exception;
169 /* faultaddr += (long) ((instr << 16) >> 16); */
170 /* fprintf(stderr, "faulting address: 0x%08x\n", faultaddr); */
171 /* panic("Stack overflow"); */
176 /* ArithmeticException signal handler for hardware divide by zero check */
178 void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p)
182 /* void **_p = (void **) &sig; */
183 /* struct sigcontext *sigctx = (struct sigcontext *) ++_p; */
184 struct ucontext *_uc = (struct ucontext *) _p;
185 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
186 struct sigaction act;
188 /* Reset signal handler - necessary for SysV, does no harm for BSD */
190 /* signal(sig, (void *) catch_ArithmeticException); */
191 act.sa_sigaction = (void *) catch_ArithmeticException;
192 act.sa_flags = SA_SIGINFO;
193 sigaction(sig, &act, NULL); /* reinstall handler */
196 sigaddset(&nsig, sig);
197 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
199 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
200 sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
206 void init_exceptions(void)
208 struct sigaction act;
210 /* install signal handlers we need to convert to exceptions */
211 sigemptyset(&act.sa_mask);
215 /* signal(SIGSEGV, (void *) catch_NullPointerException); */
216 act.sa_sigaction = (void *) catch_NullPointerException;
217 act.sa_flags = SA_SIGINFO;
218 sigaction(SIGSEGV, &act, NULL);
222 /* signal(SIGBUS, (void *) catch_NullPointerException); */
223 act.sa_sigaction = (void *) catch_NullPointerException;
224 act.sa_flags = SA_SIGINFO;
225 sigaction(SIGBUS, &act, NULL);
229 /* signal(SIGFPE, (void *) catch_ArithmeticException); */
230 act.sa_sigaction = (void *) catch_ArithmeticException;
231 act.sa_flags = SA_SIGINFO;
232 sigaction(SIGFPE, &act, NULL);
236 /* function codegen ************************************************************
238 generates machine code
240 *******************************************************************************/
242 void codegen(methodinfo *m)
244 int len, s1, s2, s3, d;
254 s4 fpu_st_offset = 0;
260 s4 savedregs_num = 0;
262 /* keep code size smaller */
266 /* space to save used callee saved registers */
268 savedregs_num += (r->savintregcnt - r->maxsavintreguse);
269 savedregs_num += (r->savfltregcnt - r->maxsavfltreguse);
271 parentargs_base = r->maxmemuse + savedregs_num;
273 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
275 if (checksync && (m->flags & ACC_SYNCHRONIZED))
280 /* create method header */
282 (void) dseg_addaddress(m, m); /* MethodPointer */
283 (void) dseg_adds4(m, parentargs_base * 8); /* FrameSize */
285 #if defined(USE_THREADS)
287 /* IsSync contains the offset relative to the stack pointer for the
288 argument of monitor_exit used in the exception handler. Since the
289 offset could be zero and give a wrong meaning of the flag it is
293 if (checksync && (m->flags & ACC_SYNCHRONIZED))
294 (void) dseg_adds4(m, (r->maxmemuse + 1) * 8); /* IsSync */
299 (void) dseg_adds4(m, 0); /* IsSync */
301 (void) dseg_adds4(m, m->isleafmethod); /* IsLeaf */
302 (void) dseg_adds4(m, r->savintregcnt - r->maxsavintreguse); /* IntSave */
303 (void) dseg_adds4(m, r->savfltregcnt - r->maxsavfltreguse); /* FltSave */
305 /* adds a reference for the length of the line number counter. We don't
306 know the size yet, since we evaluate the information during code
307 generation, to save one additional iteration over the whole
308 instructions. During code optimization the position could have changed
309 to the information gotten from the class file */
310 (void) dseg_addlinenumbertablesize(m);
312 (void) dseg_adds4(m, cd->exceptiontablelength); /* ExTableSize */
314 /* create exception table */
316 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
317 dseg_addtarget(m, ex->start);
318 dseg_addtarget(m, ex->end);
319 dseg_addtarget(m, ex->handler);
320 (void) dseg_addaddress(m, ex->catchtype);
324 /* initialize mcode variables */
326 cd->mcodeptr = cd->mcodebase;
327 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
328 MCODECHECK(128 + m->paramcount);
330 /* create stack frame (if necessary) */
332 if (parentargs_base) {
333 i386_alu_imm_reg(cd, I386_SUB, parentargs_base * 8, REG_SP);
336 /* save return address and used callee saved registers */
339 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
340 p--; i386_mov_reg_membase(cd, r->savintregs[i], REG_SP, p * 8);
342 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
343 p--; i386_fld_reg(cd, r->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 8);
346 /* save monitorenter argument */
348 #if defined(USE_THREADS)
349 s4 func_enter = (m->flags & ACC_STATIC) ?
350 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
352 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
353 if (m->flags & ACC_STATIC) {
354 i386_mov_imm_reg(cd, (s4) m->class, REG_ITMP1);
355 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r->maxmemuse * 8);
358 i386_mov_membase_reg(cd, REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
359 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r->maxmemuse * 8);
362 /* call monitorenter function */
364 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
365 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
366 i386_mov_imm_reg(cd, func_enter, REG_ITMP1);
367 i386_call_reg(cd, REG_ITMP1);
368 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
372 /* copy argument registers to stack and call trace function with pointer
373 to arguments on stack.
377 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
379 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
380 t = m->paramtypes[p];
382 if (IS_INT_LNG_TYPE(t)) {
383 if (IS_2_WORD_TYPE(t)) {
384 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
385 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
386 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
387 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
389 /* } else if (t == TYPE_ADR) { */
391 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
392 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
393 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
394 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
397 /* i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
399 /* i386_mov_reg_membase(cd, EAX, REG_SP, p * 8); */
400 /* i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4); */
404 if (!IS_2_WORD_TYPE(t)) {
405 i386_flds_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
406 i386_fstps_membase(cd, REG_SP, p * 8);
407 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
408 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
411 i386_fldl_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
412 i386_fstpl_membase(cd, REG_SP, p * 8);
417 /* fill up the remaining arguments */
418 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
419 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
420 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
421 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
424 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
425 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
426 i386_call_reg(cd, REG_ITMP1);
428 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
431 /* take arguments out of register or stack frame */
433 for (p = 0, l = 0; p < m->paramcount; p++) {
434 t = m->paramtypes[p];
435 var = &(r->locals[l][t]);
437 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
441 if (IS_INT_LNG_TYPE(t)) { /* integer args */
442 if (p < r->intreg_argnum) { /* register arguments */
443 panic("integer register argument");
444 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
445 /* M_INTMOVE (argintregs[p], r); */
447 } else { /* reg arg -> spilled */
448 /* M_LST (argintregs[p], REG_SP, 8 * r); */
450 } else { /* stack arguments */
451 pa = p - r->intreg_argnum;
452 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
453 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, var->regoff); /* + 4 for return address */
454 } else { /* stack arg -> spilled */
455 if (!IS_2_WORD_TYPE(t)) {
456 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
457 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, REG_ITMP1); /* + 4 for return address */
461 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
462 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1); /* + 4 for return address */
463 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8 + 4);
468 } else { /* floating args */
469 if (p < r->fltreg_argnum) { /* register arguments */
470 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
471 panic("There are no float argument registers!");
473 } else { /* reg arg -> spilled */
474 panic("There are no float argument registers!");
477 } else { /* stack arguments */
478 pa = p - r->fltreg_argnum;
479 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
481 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
483 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
487 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
489 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
493 } else { /* stack-arg -> spilled */
494 /* i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
495 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r * 8); */
497 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
498 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
501 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
502 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
511 /* end of header generation */
513 /* walk through all basic blocks */
514 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
516 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
518 if (bptr->flags >= BBREACHED) {
520 /* branch resolving */
523 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
524 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
529 /* copy interface registers to their destination */
534 while (src != NULL) {
536 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
537 if (!IS_2_WORD_TYPE(src->type)) {
538 if (bptr->type == BBTYPE_SBR) {
539 d = reg_of_var(m, src, REG_ITMP1);
541 store_reg_to_var_int(src, d);
543 } else if (bptr->type == BBTYPE_EXH) {
544 d = reg_of_var(m, src, REG_ITMP1);
545 M_INTMOVE(REG_ITMP1, d);
546 store_reg_to_var_int(src, d);
550 panic("copy interface registers: longs have to me in memory (begin 1)");
554 d = reg_of_var(m, src, REG_ITMP1);
555 if ((src->varkind != STACKVAR)) {
557 if (IS_FLT_DBL_TYPE(s2)) {
558 s1 = r->interfaces[len][s2].regoff;
559 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
563 if (s2 == TYPE_FLT) {
564 i386_flds_membase(cd, REG_SP, s1 * 8);
567 i386_fldl_membase(cd, REG_SP, s1 * 8);
570 store_reg_to_var_flt(src, d);
573 s1 = r->interfaces[len][s2].regoff;
574 if (!IS_2_WORD_TYPE(r->interfaces[len][s2].type)) {
575 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
579 i386_mov_membase_reg(cd, REG_SP, s1 * 8, d);
581 store_reg_to_var_int(src, d);
584 if (r->interfaces[len][s2].flags & INMEMORY) {
585 M_LNGMEMMOVE(s1, src->regoff);
588 panic("copy interface registers: longs have to be in memory (begin 2)");
597 /* walk through all instructions */
602 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
603 if (iptr->line != currentline) {
604 dseg_addlinenumber(m, iptr->line, cd->mcodeptr);
605 currentline = iptr->line;
608 MCODECHECK(64); /* an instruction usually needs < 64 words */
611 case ICMD_NOP: /* ... ==> ... */
614 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
615 if (src->flags & INMEMORY) {
616 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
619 i386_test_reg_reg(cd, src->regoff, src->regoff);
621 i386_jcc(cd, I386_CC_E, 0);
622 codegen_addxnullrefs(m, cd->mcodeptr);
625 /* constant operations ************************************************/
627 case ICMD_ICONST: /* ... ==> ..., constant */
628 /* op1 = 0, val.i = constant */
630 d = reg_of_var(m, iptr->dst, REG_ITMP1);
631 if (iptr->dst->flags & INMEMORY) {
632 i386_mov_imm_membase(cd, iptr->val.i, REG_SP, iptr->dst->regoff * 8);
635 if (iptr->val.i == 0) {
636 i386_alu_reg_reg(cd, I386_XOR, d, d);
639 i386_mov_imm_reg(cd, iptr->val.i, d);
644 case ICMD_LCONST: /* ... ==> ..., constant */
645 /* op1 = 0, val.l = constant */
647 d = reg_of_var(m, iptr->dst, REG_ITMP1);
648 if (iptr->dst->flags & INMEMORY) {
649 i386_mov_imm_membase(cd, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
650 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
653 panic("LCONST: longs have to be in memory");
657 case ICMD_FCONST: /* ... ==> ..., constant */
658 /* op1 = 0, val.f = constant */
660 d = reg_of_var(m, iptr->dst, REG_FTMP1);
661 if (iptr->val.f == 0.0) {
666 if (iptr->val.i == 0x80000000) {
670 } else if (iptr->val.f == 1.0) {
674 } else if (iptr->val.f == 2.0) {
681 a = dseg_addfloat(m, iptr->val.f);
682 i386_mov_imm_reg(cd, 0, REG_ITMP1);
683 dseg_adddata(m, cd->mcodeptr);
684 i386_flds_membase(cd, REG_ITMP1, a);
687 store_reg_to_var_flt(iptr->dst, d);
690 case ICMD_DCONST: /* ... ==> ..., constant */
691 /* op1 = 0, val.d = constant */
693 d = reg_of_var(m, iptr->dst, REG_FTMP1);
694 if (iptr->val.d == 0.0) {
699 if (iptr->val.l == 0x8000000000000000LL) {
703 } else if (iptr->val.d == 1.0) {
707 } else if (iptr->val.d == 2.0) {
714 a = dseg_adddouble(m, iptr->val.d);
715 i386_mov_imm_reg(cd, 0, REG_ITMP1);
716 dseg_adddata(m, cd->mcodeptr);
717 i386_fldl_membase(cd, REG_ITMP1, a);
720 store_reg_to_var_flt(iptr->dst, d);
723 case ICMD_ACONST: /* ... ==> ..., constant */
724 /* op1 = 0, val.a = constant */
726 d = reg_of_var(m, iptr->dst, REG_ITMP1);
727 if (iptr->dst->flags & INMEMORY) {
728 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
731 if ((s4) iptr->val.a == 0) {
732 i386_alu_reg_reg(cd, I386_XOR, d, d);
735 i386_mov_imm_reg(cd, (s4) iptr->val.a, d);
741 /* load/store operations **********************************************/
743 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
744 case ICMD_ALOAD: /* op1 = local variable */
746 d = reg_of_var(m, iptr->dst, REG_ITMP1);
747 if ((iptr->dst->varkind == LOCALVAR) &&
748 (iptr->dst->varnum == iptr->op1)) {
751 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
752 if (iptr->dst->flags & INMEMORY) {
753 if (var->flags & INMEMORY) {
754 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, REG_ITMP1);
755 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
758 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
762 if (var->flags & INMEMORY) {
763 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, iptr->dst->regoff);
766 M_INTMOVE(var->regoff, iptr->dst->regoff);
771 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
772 /* op1 = local variable */
774 d = reg_of_var(m, iptr->dst, REG_ITMP1);
775 if ((iptr->dst->varkind == LOCALVAR) &&
776 (iptr->dst->varnum == iptr->op1)) {
779 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
780 if (iptr->dst->flags & INMEMORY) {
781 if (var->flags & INMEMORY) {
782 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
785 panic("LLOAD: longs have to be in memory");
789 panic("LLOAD: longs have to be in memory");
793 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
794 /* op1 = local variable */
796 d = reg_of_var(m, iptr->dst, REG_FTMP1);
797 if ((iptr->dst->varkind == LOCALVAR) &&
798 (iptr->dst->varnum == iptr->op1)) {
801 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
802 if (var->flags & INMEMORY) {
803 i386_flds_membase(cd, REG_SP, var->regoff * 8);
806 i386_fld_reg(cd, var->regoff + fpu_st_offset);
809 store_reg_to_var_flt(iptr->dst, d);
812 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
813 /* op1 = local variable */
815 d = reg_of_var(m, iptr->dst, REG_FTMP1);
816 if ((iptr->dst->varkind == LOCALVAR) &&
817 (iptr->dst->varnum == iptr->op1)) {
820 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
821 if (var->flags & INMEMORY) {
822 i386_fldl_membase(cd, REG_SP, var->regoff * 8);
825 i386_fld_reg(cd, var->regoff + fpu_st_offset);
828 store_reg_to_var_flt(iptr->dst, d);
831 case ICMD_ISTORE: /* ..., value ==> ... */
832 case ICMD_ASTORE: /* op1 = local variable */
834 if ((src->varkind == LOCALVAR) &&
835 (src->varnum == iptr->op1)) {
838 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
839 if (var->flags & INMEMORY) {
840 if (src->flags & INMEMORY) {
841 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
842 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
845 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 8);
849 var_to_reg_int(s1, src, var->regoff);
850 M_INTMOVE(s1, var->regoff);
854 case ICMD_LSTORE: /* ..., value ==> ... */
855 /* op1 = local variable */
857 if ((src->varkind == LOCALVAR) &&
858 (src->varnum == iptr->op1)) {
861 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
862 if (var->flags & INMEMORY) {
863 if (src->flags & INMEMORY) {
864 M_LNGMEMMOVE(src->regoff, var->regoff);
867 panic("LSTORE: longs have to be in memory");
871 panic("LSTORE: longs have to be in memory");
875 case ICMD_FSTORE: /* ..., value ==> ... */
876 /* op1 = local variable */
878 if ((src->varkind == LOCALVAR) &&
879 (src->varnum == iptr->op1)) {
882 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
883 if (var->flags & INMEMORY) {
884 var_to_reg_flt(s1, src, REG_FTMP1);
885 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
888 var_to_reg_flt(s1, src, var->regoff);
889 /* M_FLTMOVE(s1, var->regoff); */
890 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
895 case ICMD_DSTORE: /* ..., value ==> ... */
896 /* op1 = local variable */
898 if ((src->varkind == LOCALVAR) &&
899 (src->varnum == iptr->op1)) {
902 var = &(r->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
903 if (var->flags & INMEMORY) {
904 var_to_reg_flt(s1, src, REG_FTMP1);
905 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
908 var_to_reg_flt(s1, src, var->regoff);
909 /* M_FLTMOVE(s1, var->regoff); */
910 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
916 /* pop/dup/swap operations ********************************************/
918 /* attention: double and longs are only one entry in CACAO ICMDs */
920 case ICMD_POP: /* ..., value ==> ... */
921 case ICMD_POP2: /* ..., value, value ==> ... */
924 case ICMD_DUP: /* ..., a ==> ..., a, a */
925 M_COPY(src, iptr->dst);
928 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
930 M_COPY(src, iptr->dst);
931 M_COPY(src->prev, iptr->dst->prev);
934 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
936 M_COPY(src, iptr->dst);
937 M_COPY(src->prev, iptr->dst->prev);
938 M_COPY(iptr->dst, iptr->dst->prev->prev);
941 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
943 M_COPY(src, iptr->dst);
944 M_COPY(src->prev, iptr->dst->prev);
945 M_COPY(src->prev->prev, iptr->dst->prev->prev);
946 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
949 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
951 M_COPY(src, iptr->dst);
952 M_COPY(src->prev, iptr->dst->prev);
953 M_COPY(src->prev->prev, iptr->dst->prev->prev);
954 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
955 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev);
958 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
960 M_COPY(src, iptr->dst);
961 M_COPY(src->prev, iptr->dst->prev);
962 M_COPY(src->prev->prev, iptr->dst->prev->prev);
963 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
964 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
965 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
968 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
970 M_COPY(src, iptr->dst->prev);
971 M_COPY(src->prev, iptr->dst);
975 /* integer operations *************************************************/
977 case ICMD_INEG: /* ..., value ==> ..., - value */
979 d = reg_of_var(m, iptr->dst, REG_NULL);
980 if (iptr->dst->flags & INMEMORY) {
981 if (src->flags & INMEMORY) {
982 if (src->regoff == iptr->dst->regoff) {
983 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
986 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
987 i386_neg_reg(cd, REG_ITMP1);
988 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
992 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
993 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
997 if (src->flags & INMEMORY) {
998 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
999 i386_neg_reg(cd, iptr->dst->regoff);
1002 M_INTMOVE(src->regoff, iptr->dst->regoff);
1003 i386_neg_reg(cd, iptr->dst->regoff);
1008 case ICMD_LNEG: /* ..., value ==> ..., - value */
1010 d = reg_of_var(m, iptr->dst, REG_NULL);
1011 if (iptr->dst->flags & INMEMORY) {
1012 if (src->flags & INMEMORY) {
1013 if (src->regoff == iptr->dst->regoff) {
1014 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1015 i386_alu_imm_membase(cd, I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1016 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8 + 4);
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);
1022 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1023 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP1);
1024 i386_neg_reg(cd, REG_ITMP1);
1025 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1031 case ICMD_I2L: /* ..., value ==> ..., value */
1033 d = reg_of_var(m, iptr->dst, REG_NULL);
1034 if (iptr->dst->flags & INMEMORY) {
1035 if (src->flags & INMEMORY) {
1036 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, EAX);
1038 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1039 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1042 M_INTMOVE(src->regoff, EAX);
1044 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1045 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1050 case ICMD_L2I: /* ..., value ==> ..., value */
1052 d = reg_of_var(m, iptr->dst, REG_NULL);
1053 if (iptr->dst->flags & INMEMORY) {
1054 if (src->flags & INMEMORY) {
1055 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1056 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1060 if (src->flags & INMEMORY) {
1061 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1066 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1068 d = reg_of_var(m, iptr->dst, REG_NULL);
1069 if (iptr->dst->flags & INMEMORY) {
1070 if (src->flags & INMEMORY) {
1071 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1072 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1073 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1074 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1077 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1078 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1079 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1083 if (src->flags & INMEMORY) {
1084 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1085 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1086 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1089 M_INTMOVE(src->regoff, iptr->dst->regoff);
1090 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1091 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1096 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1098 d = reg_of_var(m, iptr->dst, REG_NULL);
1099 if (iptr->dst->flags & INMEMORY) {
1100 if (src->flags & INMEMORY) {
1101 if (src->regoff == iptr->dst->regoff) {
1102 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1105 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1106 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, REG_ITMP1);
1107 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1111 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1112 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, 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_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1121 M_INTMOVE(src->regoff, iptr->dst->regoff);
1122 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1127 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1129 d = reg_of_var(m, iptr->dst, REG_NULL);
1130 if (iptr->dst->flags & INMEMORY) {
1131 if (src->flags & INMEMORY) {
1132 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1133 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1134 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1135 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1138 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1139 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1140 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1144 if (src->flags & INMEMORY) {
1145 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1146 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1147 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1150 M_INTMOVE(src->regoff, iptr->dst->regoff);
1151 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1152 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1158 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1160 d = reg_of_var(m, iptr->dst, REG_NULL);
1161 i386_emit_ialu(cd, I386_ADD, src, iptr);
1164 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1165 /* val.i = constant */
1167 d = reg_of_var(m, iptr->dst, REG_NULL);
1168 /* should we use a inc optimization for smaller code size? */
1169 i386_emit_ialuconst(cd, I386_ADD, src, iptr);
1172 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1174 d = reg_of_var(m, iptr->dst, REG_NULL);
1175 if (iptr->dst->flags & INMEMORY) {
1176 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1177 if (src->regoff == iptr->dst->regoff) {
1178 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1179 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1180 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1181 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1183 } else if (src->prev->regoff == iptr->dst->regoff) {
1184 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1185 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1186 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1187 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1190 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1191 i386_alu_membase_reg(cd, I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1192 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1193 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1194 i386_alu_membase_reg(cd, I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1195 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1202 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1203 /* val.l = constant */
1205 d = reg_of_var(m, iptr->dst, REG_NULL);
1206 if (iptr->dst->flags & INMEMORY) {
1207 if (src->flags & INMEMORY) {
1208 if (src->regoff == iptr->dst->regoff) {
1209 i386_alu_imm_membase(cd, I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1210 i386_alu_imm_membase(cd, I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1213 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1214 i386_alu_imm_reg(cd, I386_ADD, iptr->val.l, REG_ITMP1);
1215 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1216 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1217 i386_alu_imm_reg(cd, I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1218 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1224 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1226 d = reg_of_var(m, iptr->dst, REG_NULL);
1227 if (iptr->dst->flags & INMEMORY) {
1228 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1229 if (src->prev->regoff == iptr->dst->regoff) {
1230 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1231 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1234 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1235 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1236 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1239 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1240 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1241 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1242 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1244 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1245 if (src->prev->regoff == iptr->dst->regoff) {
1246 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1249 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1250 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1251 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1255 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1256 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1260 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1261 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1262 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1264 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1265 M_INTMOVE(src->prev->regoff, d);
1266 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1268 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1269 /* workaround for reg alloc */
1270 if (src->regoff == iptr->dst->regoff) {
1271 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1272 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1273 M_INTMOVE(REG_ITMP1, d);
1276 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1277 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1281 /* workaround for reg alloc */
1282 if (src->regoff == iptr->dst->regoff) {
1283 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1284 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1285 M_INTMOVE(REG_ITMP1, d);
1288 M_INTMOVE(src->prev->regoff, d);
1289 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1295 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1296 /* val.i = constant */
1298 d = reg_of_var(m, iptr->dst, REG_NULL);
1299 i386_emit_ialuconst(cd, I386_SUB, src, iptr);
1302 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1304 d = reg_of_var(m, iptr->dst, REG_NULL);
1305 if (iptr->dst->flags & INMEMORY) {
1306 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1307 if (src->prev->regoff == iptr->dst->regoff) {
1308 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1309 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1310 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1311 i386_alu_reg_membase(cd, I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1314 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1315 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1316 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1317 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1318 i386_alu_membase_reg(cd, I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1319 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1325 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1326 /* val.l = constant */
1328 d = reg_of_var(m, iptr->dst, REG_NULL);
1329 if (iptr->dst->flags & INMEMORY) {
1330 if (src->flags & INMEMORY) {
1331 if (src->regoff == iptr->dst->regoff) {
1332 i386_alu_imm_membase(cd, I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1333 i386_alu_imm_membase(cd, I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1336 /* TODO: could be size optimized with lea -- see gcc output */
1337 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1338 i386_alu_imm_reg(cd, I386_SUB, iptr->val.l, REG_ITMP1);
1339 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1340 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1341 i386_alu_imm_reg(cd, I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1342 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1348 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1350 d = reg_of_var(m, iptr->dst, REG_NULL);
1351 if (iptr->dst->flags & INMEMORY) {
1352 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1353 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1354 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1355 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1357 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1358 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1359 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1360 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1362 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1363 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1364 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1365 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1368 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1369 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1370 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1374 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1375 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1376 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1378 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1379 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1380 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1382 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1383 M_INTMOVE(src->regoff, iptr->dst->regoff);
1384 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1387 if (src->regoff == iptr->dst->regoff) {
1388 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1391 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1392 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1398 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1399 /* val.i = constant */
1401 d = reg_of_var(m, iptr->dst, REG_NULL);
1402 if (iptr->dst->flags & INMEMORY) {
1403 if (src->flags & INMEMORY) {
1404 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1405 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1408 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1409 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1413 if (src->flags & INMEMORY) {
1414 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1417 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1422 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1424 d = reg_of_var(m, iptr->dst, REG_NULL);
1425 if (iptr->dst->flags & INMEMORY) {
1426 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1427 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX); /* mem -> EAX */
1428 /* optimize move EAX -> REG_ITMP3 is slower??? */
1429 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1430 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1432 /* TODO: optimize move EAX -> REG_ITMP3 */
1433 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); /* mem -> ITMP3 */
1434 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1435 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1437 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP2); /* mem -> ITMP3 */
1438 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1440 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1441 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1442 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1447 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1448 /* val.l = constant */
1450 d = reg_of_var(m, iptr->dst, REG_NULL);
1451 if (iptr->dst->flags & INMEMORY) {
1452 if (src->flags & INMEMORY) {
1453 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1454 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1455 /* TODO: optimize move EAX -> REG_ITMP3 */
1456 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1457 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1459 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1460 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1461 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1463 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1464 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1465 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1470 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1472 d = reg_of_var(m, iptr->dst, REG_NULL);
1473 var_to_reg_int(s1, src, REG_ITMP2);
1475 if (src->prev->flags & INMEMORY) {
1476 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1479 M_INTMOVE(src->prev->regoff, EAX);
1482 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1483 i386_jcc(cd, I386_CC_NE, 3 + 6);
1484 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1485 i386_jcc(cd, I386_CC_E, 1 + 2);
1488 i386_idiv_reg(cd, s1);
1490 if (iptr->dst->flags & INMEMORY) {
1491 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1494 M_INTMOVE(EAX, iptr->dst->regoff);
1498 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1500 d = reg_of_var(m, iptr->dst, REG_NULL);
1501 var_to_reg_int(s1, src, REG_ITMP2);
1503 if (src->prev->flags & INMEMORY) {
1504 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1507 M_INTMOVE(src->prev->regoff, EAX);
1510 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1511 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1512 i386_alu_reg_reg(cd, I386_XOR, EDX, EDX);
1513 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1514 i386_jcc(cd, I386_CC_E, 1 + 2);
1517 i386_idiv_reg(cd, s1);
1519 if (iptr->dst->flags & INMEMORY) {
1520 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8);
1523 M_INTMOVE(EDX, iptr->dst->regoff);
1527 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1528 /* val.i = constant */
1530 /* TODO: optimize for `/ 2' */
1531 var_to_reg_int(s1, src, REG_ITMP1);
1532 d = reg_of_var(m, iptr->dst, REG_ITMP1);
1535 i386_test_reg_reg(cd, d, d);
1537 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1538 i386_jcc(cd, I386_CC_NS, a);
1539 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, d);
1541 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1542 store_reg_to_var_int(iptr->dst, d);
1545 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1546 /* val.i = constant */
1548 d = reg_of_var(m, iptr->dst, REG_NULL);
1549 if (iptr->dst->flags & INMEMORY) {
1550 if (src->flags & INMEMORY) {
1552 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1554 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1555 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1557 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1558 i386_jcc(cd, I386_CC_NS, a);
1559 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1560 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1561 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1562 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1564 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1565 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1570 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1571 /* val.i = constant */
1573 var_to_reg_int(s1, src, REG_ITMP1);
1574 d = reg_of_var(m, iptr->dst, REG_ITMP2);
1576 M_INTMOVE(s1, REG_ITMP1);
1583 CALCIMMEDIATEBYTES(a, iptr->val.i);
1586 /* TODO: optimize */
1588 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1589 i386_test_reg_reg(cd, s1, s1);
1590 i386_jcc(cd, I386_CC_GE, a);
1591 i386_mov_reg_reg(cd, s1, d);
1592 i386_neg_reg(cd, d);
1593 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1594 i386_neg_reg(cd, d);
1596 /* M_INTMOVE(s1, EAX); */
1597 /* i386_cltd(cd); */
1598 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1599 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1600 /* i386_alu_reg_reg(cd, I386_AND, iptr->val.i, EAX); */
1601 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1602 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1603 /* M_INTMOVE(EAX, d); */
1605 /* i386_alu_reg_reg(cd, I386_XOR, d, d); */
1606 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1607 /* i386_shrd_reg_reg(cd, s1, d); */
1608 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1610 store_reg_to_var_int(iptr->dst, d);
1613 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1614 /* val.l = constant */
1616 d = reg_of_var(m, iptr->dst, REG_NULL);
1617 if (iptr->dst->flags & INMEMORY) {
1618 if (src->flags & INMEMORY) {
1619 /* Intel algorithm -- does not work, because constant is wrong */
1620 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1); */
1621 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1623 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1624 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1625 /* i386_jcc(cd, I386_CC_NS, offset); */
1626 /* i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1627 /* i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP3); */
1629 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1630 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1631 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1633 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1635 /* i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1); */
1636 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1637 /* i386_alu_reg_reg(cd, I386_SBB, REG_ITMP3, REG_ITMP2); */
1639 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1640 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1642 /* Alpha algorithm */
1644 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1646 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1652 /* TODO: hmm, don't know if this is always correct */
1654 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1656 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1662 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1663 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1665 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1666 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1667 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1668 i386_jcc(cd, I386_CC_GE, a);
1670 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1671 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1673 i386_neg_reg(cd, REG_ITMP1);
1674 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1675 i386_neg_reg(cd, REG_ITMP2);
1677 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1678 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1680 i386_neg_reg(cd, REG_ITMP1);
1681 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1682 i386_neg_reg(cd, REG_ITMP2);
1684 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1685 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1690 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1692 d = reg_of_var(m, iptr->dst, REG_NULL);
1693 i386_emit_ishift(cd, I386_SHL, src, iptr);
1696 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1697 /* val.i = constant */
1699 d = reg_of_var(m, iptr->dst, REG_NULL);
1700 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1703 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1705 d = reg_of_var(m, iptr->dst, REG_NULL);
1706 i386_emit_ishift(cd, I386_SAR, src, iptr);
1709 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1710 /* val.i = constant */
1712 d = reg_of_var(m, iptr->dst, REG_NULL);
1713 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1716 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1718 d = reg_of_var(m, iptr->dst, REG_NULL);
1719 i386_emit_ishift(cd, I386_SHR, src, iptr);
1722 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1723 /* val.i = constant */
1725 d = reg_of_var(m, iptr->dst, REG_NULL);
1726 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1729 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1731 d = reg_of_var(m, iptr->dst, REG_NULL);
1732 if (iptr->dst->flags & INMEMORY ){
1733 if (src->prev->flags & INMEMORY) {
1734 /* if (src->prev->regoff == iptr->dst->regoff) { */
1735 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1737 /* if (src->flags & INMEMORY) { */
1738 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1740 /* M_INTMOVE(src->regoff, ECX); */
1743 /* i386_test_imm_reg(cd, 32, ECX); */
1744 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1745 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1746 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1); */
1748 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1749 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1752 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1753 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1755 if (src->flags & INMEMORY) {
1756 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1758 M_INTMOVE(src->regoff, ECX);
1761 i386_test_imm_reg(cd, 32, ECX);
1762 i386_jcc(cd, I386_CC_E, 2 + 2);
1763 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1764 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1766 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1767 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1768 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1769 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1775 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1776 /* val.i = constant */
1778 d = reg_of_var(m, iptr->dst, REG_NULL);
1779 if (iptr->dst->flags & INMEMORY ) {
1780 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1781 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1783 if (iptr->val.i & 0x20) {
1784 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1785 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1786 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1789 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1790 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1793 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1794 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1798 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1800 d = reg_of_var(m, iptr->dst, REG_NULL);
1801 if (iptr->dst->flags & INMEMORY ){
1802 if (src->prev->flags & INMEMORY) {
1803 /* if (src->prev->regoff == iptr->dst->regoff) { */
1804 /* TODO: optimize */
1805 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1806 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1808 /* if (src->flags & INMEMORY) { */
1809 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1811 /* M_INTMOVE(src->regoff, ECX); */
1814 /* i386_test_imm_reg(cd, 32, ECX); */
1815 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1816 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1817 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1819 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1820 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1821 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1822 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1825 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1826 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1828 if (src->flags & INMEMORY) {
1829 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1831 M_INTMOVE(src->regoff, ECX);
1834 i386_test_imm_reg(cd, 32, ECX);
1835 i386_jcc(cd, I386_CC_E, 2 + 3);
1836 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1837 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1839 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1840 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1841 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1842 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1848 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1849 /* val.i = constant */
1851 d = reg_of_var(m, iptr->dst, REG_NULL);
1852 if (iptr->dst->flags & INMEMORY ) {
1853 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1854 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1856 if (iptr->val.i & 0x20) {
1857 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1858 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
1859 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1862 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1863 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1866 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1867 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1871 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1873 d = reg_of_var(m, iptr->dst, REG_NULL);
1874 if (iptr->dst->flags & INMEMORY ){
1875 if (src->prev->flags & INMEMORY) {
1876 /* if (src->prev->regoff == iptr->dst->regoff) { */
1877 /* TODO: optimize */
1878 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1879 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1881 /* if (src->flags & INMEMORY) { */
1882 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1884 /* M_INTMOVE(src->regoff, ECX); */
1887 /* i386_test_imm_reg(cd, 32, ECX); */
1888 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1889 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1890 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2); */
1892 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1893 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
1894 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1895 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1898 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1899 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1901 if (src->flags & INMEMORY) {
1902 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1904 M_INTMOVE(src->regoff, ECX);
1907 i386_test_imm_reg(cd, 32, ECX);
1908 i386_jcc(cd, I386_CC_E, 2 + 2);
1909 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1910 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP3, REG_ITMP3);
1912 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1913 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
1914 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1915 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1921 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1922 /* val.l = constant */
1924 d = reg_of_var(m, iptr->dst, REG_NULL);
1925 if (iptr->dst->flags & INMEMORY ) {
1926 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1927 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1929 if (iptr->val.i & 0x20) {
1930 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1931 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
1932 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1935 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1936 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
1939 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1940 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1944 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1946 d = reg_of_var(m, iptr->dst, REG_NULL);
1947 i386_emit_ialu(cd, I386_AND, src, iptr);
1950 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1951 /* val.i = constant */
1953 d = reg_of_var(m, iptr->dst, REG_NULL);
1954 i386_emit_ialuconst(cd, I386_AND, src, iptr);
1957 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1959 d = reg_of_var(m, iptr->dst, REG_NULL);
1960 i386_emit_lalu(cd, I386_AND, src, iptr);
1963 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1964 /* val.l = constant */
1966 d = reg_of_var(m, iptr->dst, REG_NULL);
1967 i386_emit_laluconst(cd, I386_AND, src, iptr);
1970 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1972 d = reg_of_var(m, iptr->dst, REG_NULL);
1973 i386_emit_ialu(cd, I386_OR, src, iptr);
1976 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1977 /* val.i = constant */
1979 d = reg_of_var(m, iptr->dst, REG_NULL);
1980 i386_emit_ialuconst(cd, I386_OR, src, iptr);
1983 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1985 d = reg_of_var(m, iptr->dst, REG_NULL);
1986 i386_emit_lalu(cd, I386_OR, src, iptr);
1989 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1990 /* val.l = constant */
1992 d = reg_of_var(m, iptr->dst, REG_NULL);
1993 i386_emit_laluconst(cd, I386_OR, src, iptr);
1996 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1998 d = reg_of_var(m, iptr->dst, REG_NULL);
1999 i386_emit_ialu(cd, I386_XOR, src, iptr);
2002 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2003 /* val.i = constant */
2005 d = reg_of_var(m, iptr->dst, REG_NULL);
2006 i386_emit_ialuconst(cd, I386_XOR, src, iptr);
2009 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2011 d = reg_of_var(m, iptr->dst, REG_NULL);
2012 i386_emit_lalu(cd, I386_XOR, src, iptr);
2015 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2016 /* val.l = constant */
2018 d = reg_of_var(m, iptr->dst, REG_NULL);
2019 i386_emit_laluconst(cd, I386_XOR, src, iptr);
2022 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2023 /* op1 = variable, val.i = constant */
2025 var = &(r->locals[iptr->op1][TYPE_INT]);
2026 if (var->flags & INMEMORY) {
2027 i386_alu_imm_membase(cd, I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2030 i386_alu_imm_reg(cd, I386_ADD, iptr->val.i, var->regoff);
2035 /* floating operations ************************************************/
2037 #define ROUND_TO_SINGLE \
2038 i386_fstps_membase(cd, REG_SP, -8); \
2039 i386_flds_membase(cd, REG_SP, -8);
2041 #define ROUND_TO_DOUBLE \
2042 i386_fstpl_membase(cd, REG_SP, -8); \
2043 i386_fldl_membase(cd, REG_SP, -8);
2045 #define FPU_SET_24BIT_MODE \
2046 if (!fpu_in_24bit_mode) { \
2047 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2048 fpu_in_24bit_mode = 1; \
2051 #define FPU_SET_53BIT_MODE \
2052 if (fpu_in_24bit_mode) { \
2053 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2054 fpu_in_24bit_mode = 0; \
2057 #define ROUND_TO_SINGLE
2058 #define ROUND_TO_DOUBLE
2059 #define FPU_SET_24BIT_MODE
2060 #define FPU_SET_53BIT_MODE
2062 case ICMD_FNEG: /* ..., value ==> ..., - value */
2065 var_to_reg_flt(s1, src, REG_FTMP1);
2066 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2068 store_reg_to_var_flt(iptr->dst, d);
2071 case ICMD_DNEG: /* ..., value ==> ..., - value */
2074 var_to_reg_flt(s1, src, REG_FTMP1);
2075 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2077 store_reg_to_var_flt(iptr->dst, d);
2080 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2083 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2084 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2085 var_to_reg_flt(s2, src, REG_FTMP2);
2088 store_reg_to_var_flt(iptr->dst, d);
2091 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2094 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2095 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2096 var_to_reg_flt(s2, src, REG_FTMP2);
2099 store_reg_to_var_flt(iptr->dst, d);
2102 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2105 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2106 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2107 var_to_reg_flt(s2, src, REG_FTMP2);
2110 store_reg_to_var_flt(iptr->dst, d);
2113 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2116 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2117 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2118 var_to_reg_flt(s2, src, REG_FTMP2);
2121 store_reg_to_var_flt(iptr->dst, d);
2124 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2127 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2128 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2129 var_to_reg_flt(s2, src, REG_FTMP2);
2133 store_reg_to_var_flt(iptr->dst, d);
2136 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2139 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2140 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2142 /* i386_fldt_mem(cd, subnormal_bias1); */
2143 /* i386_fmulp(cd); */
2145 var_to_reg_flt(s2, src, REG_FTMP2);
2150 /* i386_fldt_mem(cd, subnormal_bias2); */
2151 /* i386_fmulp(cd); */
2153 store_reg_to_var_flt(iptr->dst, d);
2156 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2159 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2160 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2161 var_to_reg_flt(s2, src, REG_FTMP2);
2165 store_reg_to_var_flt(iptr->dst, d);
2168 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2171 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2172 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2174 /* i386_fldt_mem(cd, subnormal_bias1); */
2175 /* i386_fmulp(cd); */
2177 var_to_reg_flt(s2, src, REG_FTMP2);
2182 /* i386_fldt_mem(cd, subnormal_bias2); */
2183 /* i386_fmulp(cd); */
2185 store_reg_to_var_flt(iptr->dst, d);
2188 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2191 /* exchanged to skip fxch */
2192 var_to_reg_flt(s2, src, REG_FTMP2);
2193 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2194 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2195 /* i386_fxch(cd); */
2200 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2201 store_reg_to_var_flt(iptr->dst, d);
2202 i386_ffree_reg(cd, 0);
2207 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2210 /* exchanged to skip fxch */
2211 var_to_reg_flt(s2, src, REG_FTMP2);
2212 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2213 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2214 /* i386_fxch(cd); */
2219 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2220 store_reg_to_var_flt(iptr->dst, d);
2221 i386_ffree_reg(cd, 0);
2226 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2227 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2229 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2230 if (src->flags & INMEMORY) {
2231 i386_fildl_membase(cd, REG_SP, src->regoff * 8);
2235 a = dseg_adds4(m, 0);
2236 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2237 dseg_adddata(m, cd->mcodeptr);
2238 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, a);
2239 i386_fildl_membase(cd, REG_ITMP1, a);
2242 store_reg_to_var_flt(iptr->dst, d);
2245 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2246 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2248 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2249 if (src->flags & INMEMORY) {
2250 i386_fildll_membase(cd, REG_SP, src->regoff * 8);
2254 panic("L2F: longs have to be in memory");
2256 store_reg_to_var_flt(iptr->dst, d);
2259 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2261 var_to_reg_flt(s1, src, REG_FTMP1);
2262 d = reg_of_var(m, iptr->dst, REG_NULL);
2264 a = dseg_adds4(m, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2265 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2266 dseg_adddata(m, cd->mcodeptr);
2267 i386_fldcw_membase(cd, REG_ITMP1, a);
2269 if (iptr->dst->flags & INMEMORY) {
2270 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2273 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2274 i386_fldcw_membase(cd, REG_ITMP1, a);
2276 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2279 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2281 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2284 a = dseg_adds4(m, 0);
2285 i386_fistpl_membase(cd, REG_ITMP1, a);
2287 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2289 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2290 i386_fldcw_membase(cd, REG_ITMP1, a);
2292 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2295 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2296 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2299 i386_jcc(cd, I386_CC_NE, a);
2301 /* XXX: change this when we use registers */
2302 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2303 i386_mov_imm_reg(cd, (s4) asm_builtin_f2i, REG_ITMP1);
2304 i386_call_reg(cd, REG_ITMP1);
2306 if (iptr->dst->flags & INMEMORY) {
2307 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2310 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2314 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2316 var_to_reg_flt(s1, src, REG_FTMP1);
2317 d = reg_of_var(m, iptr->dst, REG_NULL);
2319 a = dseg_adds4(m, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2320 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2321 dseg_adddata(m, cd->mcodeptr);
2322 i386_fldcw_membase(cd, REG_ITMP1, a);
2324 if (iptr->dst->flags & INMEMORY) {
2325 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2328 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2329 i386_fldcw_membase(cd, REG_ITMP1, a);
2331 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2334 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2336 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2339 a = dseg_adds4(m, 0);
2340 i386_fistpl_membase(cd, REG_ITMP1, a);
2342 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2344 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2345 i386_fldcw_membase(cd, REG_ITMP1, a);
2347 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2350 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2351 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2354 i386_jcc(cd, I386_CC_NE, a);
2356 /* XXX: change this when we use registers */
2357 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2358 i386_mov_imm_reg(cd, (s4) asm_builtin_d2i, REG_ITMP1);
2359 i386_call_reg(cd, REG_ITMP1);
2361 if (iptr->dst->flags & INMEMORY) {
2362 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2364 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2368 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2370 var_to_reg_flt(s1, src, REG_FTMP1);
2371 d = reg_of_var(m, iptr->dst, REG_NULL);
2373 a = dseg_adds4(m, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2374 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2375 dseg_adddata(m, cd->mcodeptr);
2376 i386_fldcw_membase(cd, REG_ITMP1, a);
2378 if (iptr->dst->flags & INMEMORY) {
2379 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2382 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2383 i386_fldcw_membase(cd, REG_ITMP1, a);
2385 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2388 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2390 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2393 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2395 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2397 i386_jcc(cd, I386_CC_NE, a);
2399 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2402 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2404 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2406 i386_jcc(cd, I386_CC_NE, a);
2408 /* XXX: change this when we use registers */
2409 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2410 i386_mov_imm_reg(cd, (s4) asm_builtin_f2l, REG_ITMP1);
2411 i386_call_reg(cd, REG_ITMP1);
2412 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2413 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2416 panic("F2L: longs have to be in memory");
2420 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2422 var_to_reg_flt(s1, src, REG_FTMP1);
2423 d = reg_of_var(m, iptr->dst, REG_NULL);
2425 a = dseg_adds4(m, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2426 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2427 dseg_adddata(m, cd->mcodeptr);
2428 i386_fldcw_membase(cd, REG_ITMP1, a);
2430 if (iptr->dst->flags & INMEMORY) {
2431 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2434 a = dseg_adds4(m, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2435 i386_fldcw_membase(cd, REG_ITMP1, a);
2437 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2440 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2442 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2445 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2447 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2449 i386_jcc(cd, I386_CC_NE, a);
2451 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2454 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2456 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2458 i386_jcc(cd, I386_CC_NE, a);
2460 /* XXX: change this when we use registers */
2461 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2462 i386_mov_imm_reg(cd, (s4) asm_builtin_d2l, REG_ITMP1);
2463 i386_call_reg(cd, REG_ITMP1);
2464 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2465 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2468 panic("D2L: longs have to be in memory");
2472 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2474 var_to_reg_flt(s1, src, REG_FTMP1);
2475 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2477 store_reg_to_var_flt(iptr->dst, d);
2480 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2482 var_to_reg_flt(s1, src, REG_FTMP1);
2483 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2485 store_reg_to_var_flt(iptr->dst, d);
2488 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2491 /* exchanged to skip fxch */
2492 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2493 var_to_reg_flt(s1, src, REG_FTMP2);
2494 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2495 /* i386_fxch(cd); */
2499 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2500 i386_jcc(cd, I386_CC_E, 6);
2501 i386_alu_imm_reg(cd, I386_AND, 0x000000ff, EAX);
2503 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2504 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2505 i386_jcc(cd, I386_CC_B, 3 + 5);
2506 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2507 i386_jmp_imm(cd, 3);
2508 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2509 store_reg_to_var_int(iptr->dst, d);
2512 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2515 /* exchanged to skip fxch */
2516 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2517 var_to_reg_flt(s1, src, REG_FTMP2);
2518 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2519 /* i386_fxch(cd); */
2523 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2524 i386_jcc(cd, I386_CC_E, 3);
2525 i386_movb_imm_reg(cd, 1, I386_AH);
2527 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2528 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2529 i386_jcc(cd, I386_CC_B, 3 + 5);
2530 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2531 i386_jmp_imm(cd, 3);
2532 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2533 store_reg_to_var_int(iptr->dst, d);
2537 /* memory operations **************************************************/
2539 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2541 var_to_reg_int(s1, src, REG_ITMP1);
2542 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2543 gen_nullptr_check(s1);
2544 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2545 store_reg_to_var_int(iptr->dst, d);
2548 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2550 var_to_reg_int(s1, src->prev, REG_ITMP1);
2551 var_to_reg_int(s2, src, REG_ITMP2);
2552 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2553 if (iptr->op1 == 0) {
2554 gen_nullptr_check(s1);
2557 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2558 store_reg_to_var_int(iptr->dst, d);
2561 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2563 var_to_reg_int(s1, src->prev, REG_ITMP1);
2564 var_to_reg_int(s2, src, REG_ITMP2);
2565 d = reg_of_var(m, iptr->dst, REG_ITMP3);
2566 if (iptr->op1 == 0) {
2567 gen_nullptr_check(s1);
2571 if (iptr->dst->flags & INMEMORY) {
2572 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2573 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2574 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2575 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2579 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2581 var_to_reg_int(s1, src->prev, REG_ITMP1);
2582 var_to_reg_int(s2, src, REG_ITMP2);
2583 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2584 if (iptr->op1 == 0) {
2585 gen_nullptr_check(s1);
2588 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2589 store_reg_to_var_int(iptr->dst, d);
2592 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2594 var_to_reg_int(s1, src->prev, REG_ITMP1);
2595 var_to_reg_int(s2, src, REG_ITMP2);
2596 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2597 if (iptr->op1 == 0) {
2598 gen_nullptr_check(s1);
2601 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2603 store_reg_to_var_flt(iptr->dst, d);
2606 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2608 var_to_reg_int(s1, src->prev, REG_ITMP1);
2609 var_to_reg_int(s2, src, REG_ITMP2);
2610 d = reg_of_var(m, iptr->dst, REG_FTMP3);
2611 if (iptr->op1 == 0) {
2612 gen_nullptr_check(s1);
2615 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2617 store_reg_to_var_flt(iptr->dst, d);
2620 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2622 var_to_reg_int(s1, src->prev, REG_ITMP1);
2623 var_to_reg_int(s2, src, REG_ITMP2);
2624 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2625 if (iptr->op1 == 0) {
2626 gen_nullptr_check(s1);
2629 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2630 store_reg_to_var_int(iptr->dst, d);
2633 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2635 var_to_reg_int(s1, src->prev, REG_ITMP1);
2636 var_to_reg_int(s2, src, REG_ITMP2);
2637 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2638 if (iptr->op1 == 0) {
2639 gen_nullptr_check(s1);
2642 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2643 store_reg_to_var_int(iptr->dst, d);
2646 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2648 var_to_reg_int(s1, src->prev, REG_ITMP1);
2649 var_to_reg_int(s2, src, REG_ITMP2);
2650 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2651 if (iptr->op1 == 0) {
2652 gen_nullptr_check(s1);
2655 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2656 store_reg_to_var_int(iptr->dst, d);
2660 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2662 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2663 var_to_reg_int(s2, src->prev, REG_ITMP2);
2664 if (iptr->op1 == 0) {
2665 gen_nullptr_check(s1);
2668 var_to_reg_int(s3, src, REG_ITMP3);
2669 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2672 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2674 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2675 var_to_reg_int(s2, src->prev, REG_ITMP2);
2676 if (iptr->op1 == 0) {
2677 gen_nullptr_check(s1);
2681 if (src->flags & INMEMORY) {
2682 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
2683 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2684 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2685 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2689 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2691 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2692 var_to_reg_int(s2, src->prev, REG_ITMP2);
2693 if (iptr->op1 == 0) {
2694 gen_nullptr_check(s1);
2697 var_to_reg_int(s3, src, REG_ITMP3);
2698 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2701 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2703 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2704 var_to_reg_int(s2, src->prev, REG_ITMP2);
2705 if (iptr->op1 == 0) {
2706 gen_nullptr_check(s1);
2709 var_to_reg_flt(s3, src, REG_FTMP1);
2710 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2714 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2716 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2717 var_to_reg_int(s2, src->prev, REG_ITMP2);
2718 if (iptr->op1 == 0) {
2719 gen_nullptr_check(s1);
2722 var_to_reg_flt(s3, src, REG_FTMP1);
2723 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2727 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2729 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2730 var_to_reg_int(s2, src->prev, REG_ITMP2);
2731 if (iptr->op1 == 0) {
2732 gen_nullptr_check(s1);
2735 var_to_reg_int(s3, src, REG_ITMP3);
2736 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2739 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2741 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2742 var_to_reg_int(s2, src->prev, REG_ITMP2);
2743 if (iptr->op1 == 0) {
2744 gen_nullptr_check(s1);
2747 var_to_reg_int(s3, src, REG_ITMP3);
2748 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2751 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2753 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2754 var_to_reg_int(s2, src->prev, REG_ITMP2);
2755 if (iptr->op1 == 0) {
2756 gen_nullptr_check(s1);
2759 var_to_reg_int(s3, src, REG_ITMP3);
2760 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2761 M_INTMOVE(s3, REG_ITMP3);
2764 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2767 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2769 var_to_reg_int(s1, src->prev, REG_ITMP1);
2770 var_to_reg_int(s2, src, REG_ITMP2);
2771 if (iptr->op1 == 0) {
2772 gen_nullptr_check(s1);
2775 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2778 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2780 var_to_reg_int(s1, src->prev, REG_ITMP1);
2781 var_to_reg_int(s2, src, REG_ITMP2);
2782 if (iptr->op1 == 0) {
2783 gen_nullptr_check(s1);
2787 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2788 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2791 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2793 var_to_reg_int(s1, src->prev, REG_ITMP1);
2794 var_to_reg_int(s2, src, REG_ITMP2);
2795 if (iptr->op1 == 0) {
2796 gen_nullptr_check(s1);
2799 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2802 case ICMD_BASTORECONST: /* ..., 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_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2813 case ICMD_CASTORECONST: /* ..., 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);
2821 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2824 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2826 var_to_reg_int(s1, src->prev, REG_ITMP1);
2827 var_to_reg_int(s2, src, REG_ITMP2);
2828 if (iptr->op1 == 0) {
2829 gen_nullptr_check(s1);
2832 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2836 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2837 /* op1 = type, val.a = field address */
2839 /* if class isn't yet initialized, do it */
2840 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2841 /* call helper function which patches this code */
2842 i386_mov_imm_reg(cd, (s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2843 i386_mov_imm_reg(cd, (s4) asm_check_clinit, REG_ITMP2);
2844 i386_call_reg(cd, REG_ITMP2);
2847 a = dseg_addaddress(m, &(((fieldinfo *) iptr->val.a)->value));
2848 /* here it's slightly slower */
2849 i386_mov_imm_reg(cd, 0, REG_ITMP2);
2850 dseg_adddata(m, cd->mcodeptr);
2851 i386_mov_membase_reg(cd, REG_ITMP2, a, REG_ITMP2);
2852 switch (iptr->op1) {
2855 var_to_reg_int(s2, src, REG_ITMP1);
2856 i386_mov_reg_membase(cd, s2, REG_ITMP2, 0);
2859 if (src->flags & INMEMORY) {
2860 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
2861 i386_mov_reg_membase(cd, REG_ITMP1, REG_ITMP2, 0);
2862 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
2863 i386_mov_reg_membase(cd, REG_ITMP1, REG_ITMP2, 0 + 4);
2865 panic("PUTSTATIC: longs have to be in memory");
2869 var_to_reg_flt(s2, src, REG_FTMP1);
2870 i386_fstps_membase(cd, REG_ITMP2, 0);
2874 var_to_reg_flt(s2, src, REG_FTMP1);
2875 i386_fstpl_membase(cd, REG_ITMP2, 0);
2878 default: panic ("internal error");
2882 case ICMD_GETSTATIC: /* ... ==> ..., value */
2883 /* op1 = type, val.a = field address */
2885 /* if class isn't yet initialized, do it */
2886 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2887 /* call helper function which patches this code */
2888 i386_mov_imm_reg(cd, (s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2889 i386_mov_imm_reg(cd, (s4) asm_check_clinit, REG_ITMP2);
2890 i386_call_reg(cd, REG_ITMP2);
2893 a = dseg_addaddress(m, &(((fieldinfo *) iptr->val.a)->value));
2894 i386_mov_imm_reg(cd, 0, REG_ITMP2);
2895 dseg_adddata(m, cd->mcodeptr);
2896 i386_mov_membase_reg(cd, REG_ITMP2, a, REG_ITMP2);
2897 switch (iptr->op1) {
2900 d = reg_of_var(m, iptr->dst, REG_ITMP1);
2901 i386_mov_membase_reg(cd, REG_ITMP2, 0, d);
2902 store_reg_to_var_int(iptr->dst, d);
2905 d = reg_of_var(m, iptr->dst, REG_NULL);
2906 if (iptr->dst->flags & INMEMORY) {
2907 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP1);
2908 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2909 i386_mov_membase_reg(cd, REG_ITMP2, 0 + 4, REG_ITMP1);
2910 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
2912 panic("GETSTATIC: longs have to be in memory");
2916 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2917 i386_flds_membase(cd, REG_ITMP2, 0);
2919 store_reg_to_var_flt(iptr->dst, d);
2922 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2923 i386_fldl_membase(cd, REG_ITMP2, 0);
2925 store_reg_to_var_flt(iptr->dst, d);
2927 default: panic ("internal error");
2931 case ICMD_PUTFIELD: /* ..., value ==> ... */
2932 /* op1 = type, val.i = field offset */
2934 a = ((fieldinfo *)(iptr->val.a))->offset;
2935 switch (iptr->op1) {
2938 var_to_reg_int(s1, src->prev, REG_ITMP1);
2939 var_to_reg_int(s2, src, REG_ITMP2);
2940 gen_nullptr_check(s1);
2941 i386_mov_reg_membase(cd, s2, s1, a);
2944 var_to_reg_int(s1, src->prev, REG_ITMP1);
2945 gen_nullptr_check(s1);
2946 if (src->flags & INMEMORY) {
2947 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);
2948 i386_mov_reg_membase(cd, REG_ITMP2, s1, a);
2949 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2950 i386_mov_reg_membase(cd, REG_ITMP2, s1, a + 4);
2952 panic("PUTFIELD: longs have to be in memory");
2956 var_to_reg_int(s1, src->prev, REG_ITMP1);
2957 var_to_reg_flt(s2, src, REG_FTMP1);
2958 gen_nullptr_check(s1);
2959 i386_fstps_membase(cd, s1, a);
2963 var_to_reg_int(s1, src->prev, REG_ITMP1);
2964 var_to_reg_flt(s2, src, REG_FTMP1);
2965 gen_nullptr_check(s1);
2966 i386_fstpl_membase(cd, s1, a);
2969 default: panic ("internal error");
2973 case ICMD_GETFIELD: /* ... ==> ..., value */
2974 /* op1 = type, val.i = field offset */
2976 a = ((fieldinfo *)(iptr->val.a))->offset;
2977 switch (iptr->op1) {
2980 var_to_reg_int(s1, src, REG_ITMP1);
2981 d = reg_of_var(m, iptr->dst, REG_ITMP2);
2982 gen_nullptr_check(s1);
2983 i386_mov_membase_reg(cd, s1, a, d);
2984 store_reg_to_var_int(iptr->dst, d);
2987 var_to_reg_int(s1, src, REG_ITMP1);
2988 d = reg_of_var(m, iptr->dst, REG_NULL);
2989 gen_nullptr_check(s1);
2990 i386_mov_membase_reg(cd, s1, a, REG_ITMP2);
2991 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
2992 i386_mov_membase_reg(cd, s1, a + 4, REG_ITMP2);
2993 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2996 var_to_reg_int(s1, src, REG_ITMP1);
2997 d = reg_of_var(m, iptr->dst, REG_FTMP1);
2998 gen_nullptr_check(s1);
2999 i386_flds_membase(cd, s1, a);
3001 store_reg_to_var_flt(iptr->dst, d);
3004 var_to_reg_int(s1, src, REG_ITMP1);
3005 d = reg_of_var(m, iptr->dst, REG_FTMP1);
3006 gen_nullptr_check(s1);
3007 i386_fldl_membase(cd, s1, a);
3009 store_reg_to_var_flt(iptr->dst, d);
3011 default: panic ("internal error");
3016 /* branch operations **************************************************/
3019 /* #define ALIGNCODENOP {if((int)((long)cd->mcodeptr&7)){M_NOP;}} */
3020 #define ALIGNCODENOP do {} while (0)
3022 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3024 var_to_reg_int(s1, src, REG_ITMP1);
3025 M_INTMOVE(s1, REG_ITMP1_XPTR);
3027 i386_call_imm(cd, 0); /* passing exception pointer */
3028 i386_pop_reg(cd, REG_ITMP2_XPC);
3030 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
3031 i386_jmp_reg(cd, REG_ITMP3);
3035 case ICMD_GOTO: /* ... ==> ... */
3036 /* op1 = target JavaVM pc */
3038 i386_jmp_imm(cd, 0);
3039 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3043 case ICMD_JSR: /* ... ==> ... */
3044 /* op1 = target JavaVM pc */
3046 i386_call_imm(cd, 0);
3047 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3050 case ICMD_RET: /* ... ==> ... */
3051 /* op1 = local variable */
3053 var = &(r->locals[iptr->op1][TYPE_ADR]);
3054 var_to_reg_int(s1, var, REG_ITMP1);
3055 i386_jmp_reg(cd, s1);
3058 case ICMD_IFNULL: /* ..., value ==> ... */
3059 /* op1 = target JavaVM pc */
3061 if (src->flags & INMEMORY) {
3062 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3065 i386_test_reg_reg(cd, src->regoff, src->regoff);
3067 i386_jcc(cd, I386_CC_E, 0);
3068 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3071 case ICMD_IFNONNULL: /* ..., value ==> ... */
3072 /* op1 = target JavaVM pc */
3074 if (src->flags & INMEMORY) {
3075 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3078 i386_test_reg_reg(cd, src->regoff, src->regoff);
3080 i386_jcc(cd, I386_CC_NE, 0);
3081 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3084 case ICMD_IFEQ: /* ..., value ==> ... */
3085 /* op1 = target JavaVM pc, val.i = constant */
3087 if (src->flags & INMEMORY) {
3088 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3091 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3093 i386_jcc(cd, I386_CC_E, 0);
3094 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3097 case ICMD_IFLT: /* ..., value ==> ... */
3098 /* op1 = target JavaVM pc, val.i = constant */
3100 if (src->flags & INMEMORY) {
3101 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3104 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3106 i386_jcc(cd, I386_CC_L, 0);
3107 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3110 case ICMD_IFLE: /* ..., value ==> ... */
3111 /* op1 = target JavaVM pc, val.i = constant */
3113 if (src->flags & INMEMORY) {
3114 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3117 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3119 i386_jcc(cd, I386_CC_LE, 0);
3120 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3123 case ICMD_IFNE: /* ..., value ==> ... */
3124 /* op1 = target JavaVM pc, val.i = constant */
3126 if (src->flags & INMEMORY) {
3127 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3130 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3132 i386_jcc(cd, I386_CC_NE, 0);
3133 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3136 case ICMD_IFGT: /* ..., value ==> ... */
3137 /* op1 = target JavaVM pc, val.i = constant */
3139 if (src->flags & INMEMORY) {
3140 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3143 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3145 i386_jcc(cd, I386_CC_G, 0);
3146 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3149 case ICMD_IFGE: /* ..., value ==> ... */
3150 /* op1 = target JavaVM pc, val.i = constant */
3152 if (src->flags & INMEMORY) {
3153 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3156 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3158 i386_jcc(cd, I386_CC_GE, 0);
3159 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3162 case ICMD_IF_LEQ: /* ..., value ==> ... */
3163 /* op1 = target JavaVM pc, val.l = constant */
3165 if (src->flags & INMEMORY) {
3166 if (iptr->val.l == 0) {
3167 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3168 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3171 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3172 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3173 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3174 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l, REG_ITMP1);
3175 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3178 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3179 i386_jcc(cd, I386_CC_E, 0);
3180 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3183 case ICMD_IF_LLT: /* ..., value ==> ... */
3184 /* op1 = target JavaVM pc, val.l = constant */
3186 if (src->flags & INMEMORY) {
3187 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3188 i386_jcc(cd, I386_CC_L, 0);
3189 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3192 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3193 CALCIMMEDIATEBYTES(a, iptr->val.l);
3195 i386_jcc(cd, I386_CC_G, a);
3197 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3198 i386_jcc(cd, I386_CC_B, 0);
3199 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3203 case ICMD_IF_LLE: /* ..., value ==> ... */
3204 /* op1 = target JavaVM pc, val.l = constant */
3206 if (src->flags & INMEMORY) {
3207 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3208 i386_jcc(cd, I386_CC_L, 0);
3209 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3212 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3213 CALCIMMEDIATEBYTES(a, iptr->val.l);
3215 i386_jcc(cd, I386_CC_G, a);
3217 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3218 i386_jcc(cd, I386_CC_BE, 0);
3219 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3223 case ICMD_IF_LNE: /* ..., value ==> ... */
3224 /* op1 = target JavaVM pc, val.l = constant */
3226 if (src->flags & INMEMORY) {
3227 if (iptr->val.l == 0) {
3228 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3229 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3232 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3233 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3234 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3235 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3236 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3239 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3240 i386_jcc(cd, I386_CC_NE, 0);
3241 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3244 case ICMD_IF_LGT: /* ..., value ==> ... */
3245 /* op1 = target JavaVM pc, val.l = constant */
3247 if (src->flags & INMEMORY) {
3248 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3249 i386_jcc(cd, I386_CC_G, 0);
3250 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3253 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3254 CALCIMMEDIATEBYTES(a, iptr->val.l);
3256 i386_jcc(cd, I386_CC_L, a);
3258 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3259 i386_jcc(cd, I386_CC_A, 0);
3260 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3264 case ICMD_IF_LGE: /* ..., value ==> ... */
3265 /* op1 = target JavaVM pc, val.l = constant */
3267 if (src->flags & INMEMORY) {
3268 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3269 i386_jcc(cd, I386_CC_G, 0);
3270 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3273 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3274 CALCIMMEDIATEBYTES(a, iptr->val.l);
3276 i386_jcc(cd, I386_CC_L, a);
3278 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3279 i386_jcc(cd, I386_CC_AE, 0);
3280 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3284 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3285 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3287 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3288 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3289 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3291 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3292 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3294 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3295 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3298 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3300 i386_jcc(cd, I386_CC_E, 0);
3301 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3304 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3305 /* op1 = target JavaVM pc */
3307 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3308 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3309 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3310 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3311 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3312 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3313 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3315 i386_jcc(cd, I386_CC_E, 0);
3316 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3319 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3320 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3322 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3323 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3324 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3326 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3327 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3329 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3330 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3333 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3335 i386_jcc(cd, I386_CC_NE, 0);
3336 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3339 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3340 /* op1 = target JavaVM pc */
3342 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3343 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3344 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3345 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3346 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3347 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3348 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3350 i386_jcc(cd, I386_CC_NE, 0);
3351 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3354 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3355 /* op1 = target JavaVM pc */
3357 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3358 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3359 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3361 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3362 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3364 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3365 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3368 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3370 i386_jcc(cd, I386_CC_L, 0);
3371 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3374 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3375 /* op1 = target JavaVM pc */
3377 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3378 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3379 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3380 i386_jcc(cd, I386_CC_L, 0);
3381 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3384 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3385 CALCOFFSETBYTES(a, REG_SP, src->regoff);
3387 i386_jcc(cd, I386_CC_G, a);
3389 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3390 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3391 i386_jcc(cd, I386_CC_B, 0);
3392 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3396 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3397 /* op1 = target JavaVM pc */
3399 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3400 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3401 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3403 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3404 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3406 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3407 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3410 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3412 i386_jcc(cd, I386_CC_G, 0);
3413 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3416 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3417 /* op1 = target JavaVM pc */
3419 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3420 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3421 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3422 i386_jcc(cd, I386_CC_G, 0);
3423 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3426 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3427 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3429 i386_jcc(cd, I386_CC_L, a);
3431 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3432 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3433 i386_jcc(cd, I386_CC_A, 0);
3434 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3438 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3439 /* op1 = target JavaVM pc */
3441 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3442 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3443 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3445 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3446 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3448 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3449 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3452 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3454 i386_jcc(cd, I386_CC_LE, 0);
3455 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3458 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3459 /* op1 = target JavaVM pc */
3461 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3462 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3463 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3464 i386_jcc(cd, I386_CC_L, 0);
3465 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3468 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3469 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3471 i386_jcc(cd, I386_CC_G, a);
3473 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3474 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3475 i386_jcc(cd, I386_CC_BE, 0);
3476 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3480 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3481 /* op1 = target JavaVM pc */
3483 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3484 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3485 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3487 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3488 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3490 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3491 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3494 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3496 i386_jcc(cd, I386_CC_GE, 0);
3497 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3500 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3501 /* op1 = target JavaVM pc */
3503 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3504 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3505 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3506 i386_jcc(cd, I386_CC_G, 0);
3507 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3510 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3511 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3513 i386_jcc(cd, I386_CC_L, a);
3515 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3516 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3517 i386_jcc(cd, I386_CC_AE, 0);
3518 codegen_addreference(m, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3522 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3524 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3527 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3528 /* val.i = constant */
3530 d = reg_of_var(m, iptr->dst, REG_NULL);
3531 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
3534 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3535 /* val.i = constant */
3537 d = reg_of_var(m, iptr->dst, REG_NULL);
3538 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
3541 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3542 /* val.i = constant */
3544 d = reg_of_var(m, iptr->dst, REG_NULL);
3545 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
3548 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3549 /* val.i = constant */
3551 d = reg_of_var(m, iptr->dst, REG_NULL);
3552 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
3555 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3556 /* val.i = constant */
3558 d = reg_of_var(m, iptr->dst, REG_NULL);
3559 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
3562 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3563 /* val.i = constant */
3565 d = reg_of_var(m, iptr->dst, REG_NULL);
3566 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
3570 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3573 var_to_reg_int(s1, src, REG_RESULT);
3574 M_INTMOVE(s1, REG_RESULT);
3576 goto nowperformreturn;
3578 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3580 if (src->flags & INMEMORY) {
3581 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_RESULT);
3582 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3585 panic("LRETURN: longs have to be in memory");
3588 goto nowperformreturn;
3590 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3591 case ICMD_DRETURN: /* ..., retvalue ==> ... */
3593 var_to_reg_flt(s1, src, REG_FRESULT);
3594 /* this may be an early return -- keep the offset correct for the
3598 goto nowperformreturn;
3600 case ICMD_RETURN: /* ... ==> ... */
3606 p = parentargs_base;
3608 /* call trace function */
3610 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3612 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3614 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3615 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3617 i386_fstl_membase(cd, REG_SP, 4 + 8);
3618 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3620 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3621 i386_call_reg(cd, REG_ITMP1);
3623 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3624 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3626 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3629 #if defined(USE_THREADS)
3630 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3631 i386_mov_membase_reg(cd, REG_SP, 8 * r->maxmemuse, REG_ITMP2);
3633 /* we need to save the proper return value */
3634 switch (iptr->opc) {
3637 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, r->maxmemuse * 8);
3641 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, r->maxmemuse * 8);
3642 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, r->maxmemuse * 8 + 4);
3646 i386_fsts_membase(cd, REG_SP, r->maxmemuse * 8);
3650 i386_fstl_membase(cd, REG_SP, r->maxmemuse * 8);
3654 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
3655 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, 0);
3656 i386_mov_imm_reg(cd, (s4) builtin_monitorexit, REG_ITMP1);
3657 i386_call_reg(cd, REG_ITMP1);
3658 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
3660 /* and now restore the proper return value */
3661 switch (iptr->opc) {
3664 i386_mov_membase_reg(cd, REG_SP, r->maxmemuse * 8, REG_RESULT);
3668 i386_mov_membase_reg(cd, REG_SP, r->maxmemuse * 8, REG_RESULT);
3669 i386_mov_membase_reg(cd, REG_SP, r->maxmemuse * 8 + 4, REG_RESULT2);
3673 i386_flds_membase(cd, REG_SP, r->maxmemuse * 8);
3677 i386_fldl_membase(cd, REG_SP, r->maxmemuse * 8);
3683 /* restore saved registers */
3684 for (i = r->savintregcnt - 1; i >= r->maxsavintreguse; i--) {
3686 i386_mov_membase_reg(cd, REG_SP, p * 8, r->savintregs[i]);
3688 for (i = r->savfltregcnt - 1; i >= r->maxsavfltreguse; i--) {
3690 i386_fldl_membase(cd, REG_SP, p * 8);
3692 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3693 i386_fstp_reg(cd, r->savfltregs[i] + fpu_st_offset + 1);
3695 i386_fstp_reg(cd, r->savfltregs[i] + fpu_st_offset);
3700 /* deallocate stack */
3701 if (parentargs_base) {
3702 i386_alu_imm_reg(cd, I386_ADD, parentargs_base * 8, REG_SP);
3711 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3716 tptr = (void **) iptr->target;
3718 s4ptr = iptr->val.a;
3719 l = s4ptr[1]; /* low */
3720 i = s4ptr[2]; /* high */
3722 var_to_reg_int(s1, src, REG_ITMP1);
3723 M_INTMOVE(s1, REG_ITMP1);
3725 i386_alu_imm_reg(cd, I386_SUB, l, REG_ITMP1);
3731 i386_alu_imm_reg(cd, I386_CMP, i - 1, REG_ITMP1);
3732 i386_jcc(cd, I386_CC_A, 0);
3734 /* codegen_addreference(m, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
3735 codegen_addreference(m, (basicblock *) tptr[0], cd->mcodeptr);
3737 /* build jump table top down and use address of lowest entry */
3739 /* s4ptr += 3 + i; */
3743 /* dseg_addtarget(m, BlockPtrOfPC(*--s4ptr)); */
3744 dseg_addtarget(m, (basicblock *) tptr[0]);
3748 /* length of dataseg after last dseg_addtarget is used by load */
3750 i386_mov_imm_reg(cd, 0, REG_ITMP2);
3751 dseg_adddata(m, cd->mcodeptr);
3752 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3753 i386_jmp_reg(cd, REG_ITMP1);
3759 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3761 s4 i, l, val, *s4ptr;
3764 tptr = (void **) iptr->target;
3766 s4ptr = iptr->val.a;
3767 l = s4ptr[0]; /* default */
3768 i = s4ptr[1]; /* count */
3770 MCODECHECK((i<<2)+8);
3771 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3777 i386_alu_imm_reg(cd, I386_CMP, val, s1);
3778 i386_jcc(cd, I386_CC_E, 0);
3779 /* codegen_addreference(m, BlockPtrOfPC(s4ptr[1]), cd->mcodeptr); */
3780 codegen_addreference(m, (basicblock *) tptr[0], cd->mcodeptr);
3783 i386_jmp_imm(cd, 0);
3784 /* codegen_addreference(m, BlockPtrOfPC(l), cd->mcodeptr); */
3786 tptr = (void **) iptr->target;
3787 codegen_addreference(m, (basicblock *) tptr[0], cd->mcodeptr);
3794 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3795 /* op1 = return type, val.a = function pointer*/
3799 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3800 /* op1 = return type, val.a = function pointer*/
3804 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3805 /* op1 = return type, val.a = function pointer*/
3809 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3810 /* op1 = arg count, val.a = method pointer */
3812 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3813 /* op1 = arg count, val.a = method pointer */
3815 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3816 /* op1 = arg count, val.a = method pointer */
3818 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3819 /* op1 = arg count, val.a = method pointer */
3826 MCODECHECK((s3 << 1) + 64);
3828 /* copy arguments to registers or stack location */
3830 for (; --s3 >= 0; src = src->prev) {
3831 if (src->varkind == ARGVAR) {
3835 if (IS_INT_LNG_TYPE(src->type)) {
3836 if (s3 < r->intreg_argnum) {
3837 panic("No integer argument registers available!");
3840 if (!IS_2_WORD_TYPE(src->type)) {
3841 if (src->flags & INMEMORY) {
3842 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3843 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s3 * 8);
3846 i386_mov_reg_membase(cd, src->regoff, REG_SP, s3 * 8);
3850 if (src->flags & INMEMORY) {
3851 M_LNGMEMMOVE(src->regoff, s3);
3854 panic("copy arguments: longs have to be in memory");
3860 if (s3 < r->fltreg_argnum) {
3861 panic("No float argument registers available!");
3864 var_to_reg_flt(d, src, REG_FTMP1);
3865 if (src->type == TYPE_FLT) {
3866 i386_fstps_membase(cd, REG_SP, s3 * 8);
3869 i386_fstpl_membase(cd, REG_SP, s3 * 8);
3876 switch (iptr->opc) {
3883 i386_mov_imm_reg(cd, a, REG_ITMP1);
3884 i386_call_reg(cd, REG_ITMP1);
3887 case ICMD_INVOKESTATIC:
3888 a = (u4) lm->stubroutine;
3891 i386_mov_imm_reg(cd, a, REG_ITMP2);
3892 i386_call_reg(cd, REG_ITMP2);
3895 case ICMD_INVOKESPECIAL:
3896 a = (u4) lm->stubroutine;
3899 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3900 gen_nullptr_check(REG_ITMP1);
3901 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
3903 i386_mov_imm_reg(cd, a, REG_ITMP2);
3904 i386_call_reg(cd, REG_ITMP2);
3907 case ICMD_INVOKEVIRTUAL:
3910 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3911 gen_nullptr_check(REG_ITMP1);
3912 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
3913 i386_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
3915 i386_call_reg(cd, REG_ITMP1);
3918 case ICMD_INVOKEINTERFACE:
3921 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3922 gen_nullptr_check(REG_ITMP1);
3923 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3924 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * lm->class->index, REG_ITMP2);
3925 i386_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - lm->class->methods), REG_ITMP1);
3927 i386_call_reg(cd, REG_ITMP1);
3931 /* d contains return type */
3933 if (d != TYPE_VOID) {
3934 d = reg_of_var(m, iptr->dst, REG_NULL);
3936 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3937 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3938 if (iptr->dst->flags & INMEMORY) {
3939 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3940 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
3943 panic("RETURN: longs have to be in memory");
3947 if (iptr->dst->flags & INMEMORY) {
3948 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3951 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
3956 /* fld from called function -- has other fpu_st_offset counter */
3958 store_reg_to_var_flt(iptr->dst, d);
3965 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3967 /* op1: 0 == array, 1 == class */
3968 /* val.a: (classinfo*) superclass */
3970 /* superclass is an interface:
3972 * return (sub != NULL) &&
3973 * (sub->vftbl->interfacetablelength > super->index) &&
3974 * (sub->vftbl->interfacetable[-super->index] != NULL);
3976 * superclass is a class:
3978 * return ((sub != NULL) && (0
3979 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3980 * super->vftbl->diffvall));
3984 classinfo *super = (classinfo*) iptr->val.a;
3986 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3987 codegen_threadcritrestart(m, cd->mcodeptr - cd->mcodebase);
3989 var_to_reg_int(s1, src, REG_ITMP1);
3990 d = reg_of_var(m, iptr->dst, REG_ITMP3);
3992 M_INTMOVE(s1, REG_ITMP1);
3995 i386_alu_reg_reg(cd, I386_XOR, d, d);
3996 if (iptr->op1) { /* class/interface */
3997 if (super->flags & ACC_INTERFACE) { /* interface */
3998 i386_test_reg_reg(cd, s1, s1);
4000 /* TODO: clean up this calculation */
4002 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4005 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4008 /* CALCOFFSETBYTES(a, super->index); */
4009 CALCIMMEDIATEBYTES(a, super->index);
4015 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4022 i386_jcc(cd, I386_CC_E, a);
4024 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4025 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4026 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4028 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4030 /* TODO: clean up this calculation */
4033 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4040 i386_jcc(cd, I386_CC_LE, a);
4041 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4043 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP1);
4044 /* i386_setcc_reg(cd, I386_CC_A, d); */
4045 /* i386_jcc(cd, I386_CC_BE, 5); */
4046 i386_jcc(cd, I386_CC_E, 5);
4047 i386_mov_imm_reg(cd, 1, d);
4050 } else { /* class */
4051 i386_test_reg_reg(cd, s1, s1);
4053 /* TODO: clean up this calculation */
4055 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4058 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4060 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4063 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4073 i386_jcc(cd, I386_CC_E, a);
4075 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4076 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4077 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4078 codegen_threadcritstart(m, cd->mcodeptr - cd->mcodebase);
4080 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4081 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4082 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4083 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4084 codegen_threadcritstop(m, cd->mcodeptr - cd->mcodebase);
4086 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4087 i386_alu_reg_reg(cd, I386_XOR, d, d);
4089 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4090 i386_jcc(cd, I386_CC_A, 5);
4091 i386_mov_imm_reg(cd, 1, d);
4095 panic ("internal error: no inlined array instanceof");
4097 store_reg_to_var_int(iptr->dst, d);
4100 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4102 /* op1: 0 == array, 1 == class */
4103 /* val.a: (classinfo*) superclass */
4105 /* superclass is an interface:
4107 * OK if ((sub == NULL) ||
4108 * (sub->vftbl->interfacetablelength > super->index) &&
4109 * (sub->vftbl->interfacetable[-super->index] != NULL));
4111 * superclass is a class:
4113 * OK if ((sub == NULL) || (0
4114 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4115 * super->vftbl->diffvall));
4119 classinfo *super = (classinfo*) iptr->val.a;
4121 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4122 codegen_threadcritrestart(m, cd->mcodeptr - cd->mcodebase);
4124 d = reg_of_var(m, iptr->dst, REG_ITMP3);
4125 var_to_reg_int(s1, src, d);
4126 if (iptr->op1) { /* class/interface */
4127 if (super->flags & ACC_INTERFACE) { /* interface */
4128 i386_test_reg_reg(cd, s1, s1);
4130 /* TODO: clean up this calculation */
4132 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4135 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4138 /* CALCOFFSETBYTES(a, super->index); */
4139 CALCIMMEDIATEBYTES(a, super->index);
4145 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4150 i386_jcc(cd, I386_CC_E, a);
4152 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4153 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4154 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4156 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4157 i386_jcc(cd, I386_CC_LE, 0);
4158 codegen_addxcastrefs(m, cd->mcodeptr);
4159 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
4161 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4162 i386_jcc(cd, I386_CC_E, 0);
4163 codegen_addxcastrefs(m, cd->mcodeptr);
4165 } else { /* class */
4166 i386_test_reg_reg(cd, s1, s1);
4168 /* TODO: clean up this calculation */
4170 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4175 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4177 if (d != REG_ITMP3) {
4179 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4182 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4188 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4195 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4202 i386_jcc(cd, I386_CC_E, a);
4204 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4205 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4206 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4207 codegen_threadcritstart(m, cd->mcodeptr - cd->mcodebase);
4209 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4210 if (d != REG_ITMP3) {
4211 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4212 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4213 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4214 codegen_threadcritstop(m, cd->mcodeptr - cd->mcodebase);
4216 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4219 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
4220 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1);
4221 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4222 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4223 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4224 codegen_threadcritstop(m, cd->mcodeptr - cd->mcodebase);
4228 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4229 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
4230 codegen_addxcastrefs(m, cd->mcodeptr);
4234 panic ("internal error: no inlined array checkcast");
4237 store_reg_to_var_int(iptr->dst, d);
4240 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4242 if (src->flags & INMEMORY) {
4243 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4246 i386_test_reg_reg(cd, src->regoff, src->regoff);
4248 i386_jcc(cd, I386_CC_L, 0);
4249 codegen_addxcheckarefs(m, cd->mcodeptr);
4252 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4254 i386_test_reg_reg(cd, REG_RESULT, REG_RESULT);
4255 i386_jcc(cd, I386_CC_E, 0);
4256 codegen_addxexceptionrefs(m, cd->mcodeptr);
4259 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4260 /* op1 = dimension, val.a = array descriptor */
4262 /* check for negative sizes and copy sizes to stack if necessary */
4264 MCODECHECK((iptr->op1 << 1) + 64);
4266 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4267 if (src->flags & INMEMORY) {
4268 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4271 i386_test_reg_reg(cd, src->regoff, src->regoff);
4273 i386_jcc(cd, I386_CC_L, 0);
4274 codegen_addxcheckarefs(m, cd->mcodeptr);
4277 * copy sizes to new stack location, be cause native function
4278 * builtin_nmultianewarray access them as (int *)
4280 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
4281 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);
4283 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
4285 if (src->varkind != ARGVAR) {
4286 if (src->flags & INMEMORY) {
4287 i386_mov_membase_reg(cd, REG_SP, (src->regoff + INT_ARG_CNT) * 8, REG_ITMP1);
4288 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, (s1 + INT_ARG_CNT) * 8);
4291 i386_mov_reg_membase(cd, src->regoff, REG_SP, (s1 + INT_ARG_CNT) * 8);
4295 i386_alu_imm_reg(cd, I386_SUB, iptr->op1 * 4, REG_SP);
4297 /* a0 = dimension count */
4299 /* save stack pointer */
4300 M_INTMOVE(REG_SP, REG_ITMP1);
4302 i386_alu_imm_reg(cd, I386_SUB, 12, REG_SP);
4303 i386_mov_imm_membase(cd, iptr->op1, REG_SP, 0);
4305 /* a1 = arraydescriptor */
4307 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, 4);
4309 /* a2 = pointer to dimensions = stack pointer */
4311 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 8);
4313 i386_mov_imm_reg(cd, (s4) (builtin_nmultianewarray), REG_ITMP1);
4314 i386_call_reg(cd, REG_ITMP1);
4315 i386_alu_imm_reg(cd, I386_ADD, 12 + iptr->op1 * 4, REG_SP);
4317 s1 = reg_of_var(m, iptr->dst, REG_RESULT);
4318 M_INTMOVE(REG_RESULT, s1);
4319 store_reg_to_var_int(iptr->dst, s1);
4323 error ("Unknown pseudo command: %d", iptr->opc);
4326 } /* for instruction */
4328 /* copy values to interface registers */
4330 src = bptr->outstack;
4331 len = bptr->outdepth;
4335 if ((src->varkind != STACKVAR)) {
4337 if (IS_FLT_DBL_TYPE(s2)) {
4338 var_to_reg_flt(s1, src, REG_FTMP1);
4339 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
4340 M_FLTMOVE(s1, r->interfaces[len][s2].regoff);
4343 panic("double store");
4344 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4348 var_to_reg_int(s1, src, REG_ITMP1);
4349 if (!IS_2_WORD_TYPE(r->interfaces[len][s2].type)) {
4350 if (!(r->interfaces[len][s2].flags & INMEMORY)) {
4351 M_INTMOVE(s1, r->interfaces[len][s2].regoff);
4354 i386_mov_reg_membase(cd, s1, REG_SP, r->interfaces[len][s2].regoff * 8);
4358 if (r->interfaces[len][s2].flags & INMEMORY) {
4359 M_LNGMEMMOVE(s1, r->interfaces[len][s2].regoff);
4362 panic("copy interface registers: longs have to be in memory (end)");
4369 } /* if (bptr -> flags >= BBREACHED) */
4370 } /* for basic block */
4372 codegen_createlinenumbertable(m);
4376 /* generate bound check stubs */
4378 u1 *xcodeptr = NULL;
4381 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
4382 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4384 cd->mcodeptr - cd->mcodebase);
4388 /* move index register into REG_ITMP1 */
4389 i386_mov_reg_reg(cd, bref->reg, REG_ITMP1); /* 2 bytes */
4391 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4392 dseg_adddata(m, cd->mcodeptr);
4393 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3); /* 5 bytes */
4394 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4396 if (xcodeptr != NULL) {
4397 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4400 xcodeptr = cd->mcodeptr;
4402 i386_push_reg(cd, REG_ITMP2_XPC);
4404 PREPARE_NATIVE_STACKINFO;
4406 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4407 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 4);
4408 i386_mov_imm_reg(cd, (u4) new_arrayindexoutofboundsexception, REG_ITMP1);
4409 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4410 i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4412 REMOVE_NATIVE_STACKINFO;
4414 i386_pop_reg(cd, REG_ITMP2_XPC);
4416 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4417 i386_jmp_reg(cd, REG_ITMP3);
4421 /* generate negative array size check stubs */
4425 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
4426 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4427 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4429 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4433 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4435 cd->mcodeptr - cd->mcodebase);
4439 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4440 dseg_adddata(m, cd->mcodeptr);
4441 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4442 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4444 if (xcodeptr != NULL) {
4445 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4448 xcodeptr = cd->mcodeptr;
4450 i386_push_reg(cd, REG_ITMP2_XPC);
4452 PREPARE_NATIVE_STACKINFO;
4454 i386_mov_imm_reg(cd, (u4) new_negativearraysizeexception, REG_ITMP1);
4455 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4457 REMOVE_NATIVE_STACKINFO;
4459 i386_pop_reg(cd, REG_ITMP2_XPC);
4461 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4462 i386_jmp_reg(cd, REG_ITMP3);
4466 /* generate cast check stubs */
4470 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
4471 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4472 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4474 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4478 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4480 cd->mcodeptr - cd->mcodebase);
4484 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4485 dseg_adddata(m, cd->mcodeptr);
4486 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4487 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4489 if (xcodeptr != NULL) {
4490 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4493 xcodeptr = cd->mcodeptr;
4495 i386_push_reg(cd, REG_ITMP2_XPC);
4497 PREPARE_NATIVE_STACKINFO;
4499 i386_mov_imm_reg(cd, (u4) new_classcastexception, REG_ITMP1);
4500 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4502 REMOVE_NATIVE_STACKINFO;
4504 i386_pop_reg(cd, REG_ITMP2_XPC);
4506 i386_mov_imm_reg(cd, (u4) asm_handle_exception, REG_ITMP3);
4507 i386_jmp_reg(cd, REG_ITMP3);
4511 /* generate divide by zero check stubs */
4515 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
4516 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4517 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4519 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4523 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4525 cd->mcodeptr - cd->mcodebase);
4529 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4530 dseg_adddata(m, cd->mcodeptr);
4531 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4532 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4534 if (xcodeptr != NULL) {
4535 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4538 xcodeptr = cd->mcodeptr;
4540 i386_push_reg(cd, REG_ITMP2_XPC);
4542 PREPARE_NATIVE_STACKINFO;
4544 i386_mov_imm_reg(cd, (u4) new_arithmeticexception, REG_ITMP1);
4545 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4547 REMOVE_NATIVE_STACKINFO;
4549 i386_pop_reg(cd, REG_ITMP2_XPC);
4551 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4552 i386_jmp_reg(cd, REG_ITMP3);
4556 /* generate exception check stubs */
4560 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
4561 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4562 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4564 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4568 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4570 cd->mcodeptr - cd->mcodebase);
4574 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4575 dseg_adddata(m, cd->mcodeptr);
4576 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4577 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4579 if (xcodeptr != NULL) {
4580 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4583 xcodeptr = cd->mcodeptr;
4585 i386_push_reg(cd, REG_ITMP2_XPC);
4587 PREPARE_NATIVE_STACKINFO;
4589 i386_mov_imm_reg(cd, (s4) codegen_general_stubcalled, REG_ITMP1);
4590 i386_call_reg(cd, REG_ITMP1);
4592 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4593 i386_mov_imm_reg(cd, (s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4594 i386_call_reg(cd, REG_ITMP1);
4595 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP3);
4596 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
4597 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1_XPTR);
4599 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP3);
4600 i386_mov_membase_reg(cd, REG_ITMP3, 0, REG_ITMP1_XPTR);
4601 i386_mov_imm_membase(cd, 0, REG_ITMP3, 0);
4603 i386_push_imm(cd, 0);
4604 i386_push_reg(cd, REG_ITMP1_XPTR);
4606 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4607 java stack at this point*/
4608 i386_mov_membase_reg(cd, REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4609 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, class), REG_ITMP1);
4610 i386_push_imm(cd, (u4) utf_fillInStackTrace_desc);
4611 i386_push_imm(cd, (u4) utf_fillInStackTrace_name);
4612 i386_push_reg(cd, REG_ITMP1);
4613 i386_mov_imm_reg(cd, (s4) class_resolvemethod, REG_ITMP3);
4614 i386_call_reg(cd, REG_ITMP3);
4615 /*cleanup parameters of class_resolvemethod*/
4616 i386_alu_imm_reg(cd, I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4617 /*prepare call to asm_calljavafunction2 */
4618 i386_push_imm(cd, 0);
4619 i386_push_imm(cd, TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
4620 i386_push_reg(cd, REG_SP);
4621 i386_push_imm(cd, sizeof(jni_callblock));
4622 i386_push_imm(cd, 1);
4623 i386_push_reg(cd, REG_RESULT);
4625 i386_mov_imm_reg(cd, (s4) asm_calljavafunction2, REG_ITMP3);
4626 i386_call_reg(cd, REG_ITMP3);
4628 /* check exceptionptr + fail (JOWENN)*/
4630 i386_alu_imm_reg(cd, I386_ADD,6*4,REG_SP);
4632 i386_pop_reg(cd, REG_ITMP1_XPTR);
4633 i386_pop_reg(cd, REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4635 REMOVE_NATIVE_STACKINFO;
4637 i386_pop_reg(cd, REG_ITMP2_XPC);
4639 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4640 i386_jmp_reg(cd, REG_ITMP3);
4644 /* generate null pointer check stubs */
4648 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
4649 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4650 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4652 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4656 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4658 cd->mcodeptr - cd->mcodebase);
4662 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4663 dseg_adddata(m, cd->mcodeptr);
4664 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4665 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4667 if (xcodeptr != NULL) {
4668 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4671 xcodeptr = cd->mcodeptr;
4673 i386_push_reg(cd, REG_ITMP2_XPC);
4675 PREPARE_NATIVE_STACKINFO;
4678 /* create native call block*/
4679 i386_alu_imm_reg(cd, I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4682 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1);
4683 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/
4685 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4686 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
4687 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
4688 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
4689 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4690 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */
4691 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4694 i386_mov_imm_reg(cd, (u4) new_nullpointerexception, REG_ITMP1);
4695 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4697 REMOVE_NATIVE_STACKINFO;
4700 /* restore native call stack */
4701 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2);
4702 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3);
4703 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0);
4704 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
4707 i386_pop_reg(cd, REG_ITMP2_XPC);
4709 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4710 i386_jmp_reg(cd, REG_ITMP3);
4715 codegen_finish(m, (u4) (cd->mcodeptr - cd->mcodebase));
4719 /* function createcompilerstub *************************************************
4721 creates a stub routine which calls the compiler
4723 *******************************************************************************/
4725 #define COMPSTUBSIZE 12
4727 u1 *createcompilerstub(methodinfo *m)
4729 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
4732 /* setup codegendata structure */
4735 cd = m->codegendata;
4738 /* code for the stub */
4739 i386_mov_imm_reg(cd, (u4) m, REG_ITMP1);/* pass method pointer to compiler*/
4741 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
4742 i386_mov_imm_reg(cd, (u4) asm_call_jit_compiler, REG_ITMP3);
4743 i386_jmp_reg(cd, REG_ITMP3); /* jump to compiler */
4745 /* free codegendata memory */
4748 #if defined(STATISTICS)
4750 count_cstub_len += COMPSTUBSIZE;
4757 /* function removecompilerstub *************************************************
4759 deletes a compilerstub from memory (simply by freeing it)
4761 *******************************************************************************/
4763 void removecompilerstub(u1 *stub)
4765 CFREE(stub, COMPSTUBSIZE);
4769 /* function: createnativestub **************************************************
4771 creates a stub routine which calls a native method
4773 *******************************************************************************/
4775 #define NATIVESTUBSIZE 350
4777 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4778 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4781 void i386_native_stub_debug(void **p) {
4782 printf("Pos on stack: %p\n",p);
4783 printf("Return adress should be: %p\n",*p);
4786 void i386_native_stub_debug2(void **p) {
4787 printf("Pos on stack: %p\n",p);
4788 printf("Return for lookup is: %p\n",*p);
4791 void traverseStackInfo() {
4792 void **p=builtin_asm_get_stackframeinfo();
4796 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4797 m=*((methodinfo**)((*p)+8));
4798 utf_display(m->name);
4806 u1 *createnativestub(functionptr f, methodinfo *m)
4808 u1 *s = CNEW(u1, NATIVESTUBSIZE); /* memory to hold the stub */
4812 int stackframesize = 4+12; /* initial 4 bytes is space for jni env,
4813 + 4 byte thread pointer + 4 byte previous pointer + method info*/
4814 int stackframeoffset = 4;
4819 void** callAddrPatchPos=0;
4821 void** jmpInstrPatchPos=0;
4822 /* setup codegendata structure */
4825 cd = m->codegendata;
4828 if (m->flags & ACC_STATIC) {
4829 stackframesize += 4;
4830 stackframeoffset += 4;
4834 descriptor2types(m); /* set paramcount and paramtypes */
4837 /* i386_push_reg(cd, REG_SP);
4838 i386_mov_imm_reg(cd, (s4) i386_native_stub_debug, REG_ITMP1);
4839 i386_call_reg(cd, REG_ITMP1);
4840 i386_pop_reg(cd, REG_ITMP1);*/
4843 /* if function is static, check for initialized */
4845 if (m->flags & ACC_STATIC) {
4846 /* if class isn't yet initialized, do it */
4847 if (!m->class->initialized) {
4848 s4 *header = (s4 *) s;
4849 *header = 0;/*extablesize*/
4851 *header = 0;/*line number table start*/
4853 *header = 0;/*line number table size*/
4855 *header = 0;/*fltsave*/
4857 *header = 0;/*intsave*/
4859 *header = 0;/*isleaf*/
4861 *header = 0;/*issync*/
4863 *header = 0;/*framesize*/
4865 *header = (u4) m;/*methodpointer*/
4867 cd->mcodeptr = s = (u1 *) header;
4870 /* call helper function which patches this code */
4871 i386_mov_imm_reg(cd, (u4) m->class, REG_ITMP1);
4872 i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP2);
4873 i386_call_reg(cd, REG_ITMP2);
4878 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4880 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
4881 t = m->paramtypes[p];
4882 if (IS_INT_LNG_TYPE(t)) {
4883 if (IS_2_WORD_TYPE(t)) {
4884 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4885 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
4886 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4887 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4889 } else if (t == TYPE_ADR) {
4890 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4891 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
4892 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4893 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4896 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
4898 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
4899 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
4903 if (!IS_2_WORD_TYPE(t)) {
4904 i386_flds_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4905 i386_fstps_membase(cd, REG_SP, p * 8);
4906 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
4907 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4910 i386_fldl_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4911 i386_fstpl_membase(cd, REG_SP, p * 8);
4916 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
4917 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
4918 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4919 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
4922 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
4924 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
4925 i386_call_reg(cd, REG_ITMP1);
4927 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4931 * mark the whole fpu stack as free for native functions
4932 * (only for saved register count == 0)
4934 i386_ffree_reg(cd, 0);
4935 i386_ffree_reg(cd, 1);
4936 i386_ffree_reg(cd, 2);
4937 i386_ffree_reg(cd, 3);
4938 i386_ffree_reg(cd, 4);
4939 i386_ffree_reg(cd, 5);
4940 i386_ffree_reg(cd, 6);
4941 i386_ffree_reg(cd, 7);
4943 /* calculate stackframe size for native function */
4944 tptr = m->paramtypes;
4945 for (i = 0; i < m->paramcount; i++) {
4950 stackframesize += 4;
4955 stackframesize += 8;
4959 panic("unknown parameter type in native function");
4963 i386_alu_imm_reg(cd, I386_SUB, stackframesize, REG_SP);
4965 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
4966 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
4967 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
4968 i386_call_reg(cd, REG_ITMP1);
4969 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
4970 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2);
4971 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
4972 i386_mov_reg_reg(cd, REG_SP,REG_ITMP2);
4973 i386_alu_imm_reg(cd, I386_ADD,stackframesize-12,REG_ITMP2);
4974 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0);
4977 /* i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
4978 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
4979 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-12);*/
4981 /* CREATE DYNAMIC STACK INFO -- END*/
4983 /* RESOLVE NATIVE METHOD -- BEGIN*/
4984 #ifndef STATIC_CLASSPATH
4986 log_text("Dynamic classpath: preparing for delayed native function resolving");
4988 jmpInstrPos=cd->mcodeptr-4;
4990 i386_mov_imm_reg(cd,jmpInstrPos,REG_ITMP1);
4991 i386_push_reg(cd,REG_ITMP1);
4993 i386_mov_imm_reg(cd,0,REG_ITMP1);
4994 jmpInstrPatchPos=cd->mcodeptr-4;
4995 i386_push_reg(cd,REG_ITMP1);
4996 /*position of call address to patch*/
4997 i386_mov_imm_reg(cd,0,REG_ITMP1);
4998 callAddrPatchPos=(cd->mcodeptr-4);
4999 i386_push_reg(cd,REG_ITMP1);
5000 /*method info structure*/
5001 i386_mov_imm_reg(cd,(s4) m, REG_ITMP1);
5002 i386_push_reg(cd,REG_ITMP1);
5003 /*call resolve functions*/
5004 i386_mov_imm_reg(cd, (s4)codegen_resolve_native,REG_ITMP1);
5005 i386_call_reg(cd,REG_ITMP1);
5007 i386_pop_reg(cd,REG_ITMP1);
5008 i386_pop_reg(cd,REG_ITMP1);
5009 i386_pop_reg(cd,REG_ITMP1);
5010 i386_pop_reg(cd,REG_ITMP1);
5011 /*fix jmp offset replacement*/
5012 (*jmpInstrPatchPos)=cd->mcodeptr-jmpInstrPos-4;
5013 } else log_text("Dynamic classpath: immediate native function resolution possible");
5015 /* RESOLVE NATIVE METHOD -- END*/
5019 tptr = m->paramtypes;
5020 for (i = 0; i < m->paramcount; i++) {
5025 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5026 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5027 stackframeoffset += 4;
5032 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5033 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5034 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5035 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, stackframeoffset + 4);
5036 stackframeoffset += 8;
5040 panic("unknown parameter type in native function");
5044 if (m->flags & ACC_STATIC) {
5045 /* put class into second argument */
5046 i386_mov_imm_membase(cd, (s4) m->class, REG_SP, 4);
5049 /* put env into first argument */
5050 i386_mov_imm_membase(cd, (s4) &env, REG_SP, 0);
5052 i386_mov_imm_reg(cd, (s4) f, REG_ITMP1);
5053 #ifndef STATIC_CLASSPATH
5055 (*callAddrPatchPos)=(cd->mcodeptr-4);
5057 i386_call_reg(cd, REG_ITMP1);
5059 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5060 i386_push_reg(cd, REG_RESULT2);
5061 i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
5062 i386_mov_membase_reg(cd, REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
5063 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT2,0);
5064 i386_pop_reg(cd, REG_RESULT2);
5065 /*REMOVE DYNAMIC STACK INFO -END */
5067 i386_alu_imm_reg(cd, I386_ADD, stackframesize, REG_SP);
5071 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5073 i386_mov_imm_membase(cd, (u4) m, REG_SP, 0);
5075 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
5076 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
5078 i386_fstl_membase(cd, REG_SP, 4 + 8);
5079 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5081 i386_mov_imm_reg(cd, (u4) builtin_displaymethodstop, REG_ITMP1);
5082 i386_call_reg(cd, REG_ITMP1);
5084 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
5085 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
5087 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5091 /* we can't use REG_ITMP3 == REG_RESULT2 */
5092 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5093 i386_push_reg(cd, REG_RESULT);
5094 i386_push_reg(cd, REG_RESULT2);
5095 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5096 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP2);
5097 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5098 i386_pop_reg(cd, REG_RESULT2);
5099 i386_pop_reg(cd, REG_RESULT);
5101 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5102 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP2);
5103 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5105 i386_jcc(cd, I386_CC_NE, 1);
5109 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5110 i386_push_reg(cd, REG_ITMP2);
5111 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5112 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5113 i386_pop_reg(cd, REG_ITMP1_XPTR);
5115 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1_XPTR);
5116 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5117 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5119 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP2_XPC);
5120 i386_alu_imm_reg(cd, I386_SUB, 2, REG_ITMP2_XPC);
5122 i386_mov_imm_reg(cd, (s4) asm_handle_nat_exception, REG_ITMP3);
5123 i386_jmp_reg(cd, REG_ITMP3);
5126 codegen_insertmethod(s, cd->mcodeptr);
5130 dolog_plain("native stubentry: %p, stubsize: %x (for %d params) --", (s4)s,(s4) (cd->mcodeptr - s), m->paramcount);
5131 utf_display(m->name);
5135 /* free codegendata memory */
5138 #if defined(STATISTICS)
5140 count_nstub_len += NATIVESTUBSIZE;
5147 /* function: removenativestub **************************************************
5149 removes a previously created native-stub from memory
5151 *******************************************************************************/
5153 void removenativestub(u1 *stub)
5155 CFREE(stub, NATIVESTUBSIZE);
5160 * These are local overrides for various environment variables in Emacs.
5161 * Please do not remove this and leave it at the end of the file, where
5162 * Emacs will automagically detect them.
5163 * ---------------------------------------------------------------------
5166 * indent-tabs-mode: t